1/* This is the header file of the Parma Polyhedra Library.
2   Copyright (C) 2001-2010 Roberto Bagnara <bagnara@cs.unipr.it>
3   Copyright (C) 2010-2016 BUGSENG srl (http://bugseng.com)
4
5This file is part of the Parma Polyhedra Library (PPL).
6
7The PPL is free software; you can redistribute it and/or modify it
8under the terms of the GNU General Public License as published by the
9Free Software Foundation; either version 3 of the License, or (at your
10option) any later version.
11
12The PPL is distributed in the hope that it will be useful, but WITHOUT
13ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
15for more details.
16
17You should have received a copy of the GNU General Public License
18along with this program; if not, write to the Free Software Foundation,
19Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1307, USA.
20
21For the most up-to-date information see the Parma Polyhedra Library
22site: http://bugseng.com/products/ppl/ . */
23
24#ifndef PPL_ppl_hh
25#define PPL_ppl_hh 1
26
27#ifdef NDEBUG
28# define PPL_SAVE_NDEBUG NDEBUG
29# undef NDEBUG
30#endif
31
32#ifdef __STDC_LIMIT_MACROS
33# define PPL_SAVE_STDC_LIMIT_MACROS __STDC_LIMIT_MACROS
34#endif
35
36/* Automatically generated from PPL source file ../ppl-config.h line 1. */
37/* config.h.  Generated from config.h.in by configure.  */
38/* config.h.in.  Generated from configure.ac by autoheader.  */
39
40
41/* BEGIN ppl-config.h */
42
43#ifndef PPL_ppl_config_h
44#define PPL_ppl_config_h 1
45
46/* Unique (nonzero) code for the IEEE 754 Single Precision
47   floating point format.  */
48#define PPL_FLOAT_IEEE754_SINGLE 1
49
50/* Unique (nonzero) code for the IEEE 754 Double Precision
51   floating point format.  */
52#define PPL_FLOAT_IEEE754_DOUBLE 2
53
54/* Unique (nonzero) code for the IEEE 754 Quad Precision
55   floating point format.  */
56#define PPL_FLOAT_IEEE754_QUAD 3
57
58/* Unique (nonzero) code for the Intel Double-Extended
59   floating point format.  */
60#define PPL_FLOAT_INTEL_DOUBLE_EXTENDED 4
61
62
63/* Define if building universal (internal helper macro) */
64/* #undef AC_APPLE_UNIVERSAL_BUILD */
65
66/* Defined if the C++compiler supports C++11 features. */
67/* #undef PPL_HAVE_CXX11 */
68
69/* Define to 1 if you have the declaration of `ffs', and to 0 if you don't. */
70#define PPL_HAVE_DECL_FFS 1
71
72/* Define to 1 if you have the declaration of `fma', and to 0 if you don't. */
73#define PPL_HAVE_DECL_FMA 1
74
75/* Define to 1 if you have the declaration of `fmaf', and to 0 if you don't.
76   */
77#define PPL_HAVE_DECL_FMAF 1
78
79/* Define to 1 if you have the declaration of `fmal', and to 0 if you don't.
80   */
81#define PPL_HAVE_DECL_FMAL 1
82
83/* Define to 1 if you have the declaration of `getenv', and to 0 if you don't.
84   */
85#define PPL_HAVE_DECL_GETENV 1
86
87/* Define to 1 if you have the declaration of `getrusage', and to 0 if you
88   don't. */
89#define PPL_HAVE_DECL_GETRUSAGE 1
90
91/* Define to 1 if you have the declaration of `rintf', and to 0 if you don't.
92   */
93#define PPL_HAVE_DECL_RINTF 1
94
95/* Define to 1 if you have the declaration of `rintl', and to 0 if you don't.
96   */
97#define PPL_HAVE_DECL_RINTL 1
98
99/* Define to 1 if you have the declaration of `RLIMIT_AS', and to 0 if you
100   don't. */
101#define PPL_HAVE_DECL_RLIMIT_AS 1
102
103/* Define to 1 if you have the declaration of `RLIMIT_DATA', and to 0 if you
104   don't. */
105#define PPL_HAVE_DECL_RLIMIT_DATA 1
106
107/* Define to 1 if you have the declaration of `RLIMIT_RSS', and to 0 if you
108   don't. */
109#define PPL_HAVE_DECL_RLIMIT_RSS 1
110
111/* Define to 1 if you have the declaration of `RLIMIT_VMEM', and to 0 if you
112   don't. */
113#define PPL_HAVE_DECL_RLIMIT_VMEM 0
114
115/* Define to 1 if you have the declaration of `setitimer', and to 0 if you
116   don't. */
117#define PPL_HAVE_DECL_SETITIMER 1
118
119/* Define to 1 if you have the declaration of `setrlimit', and to 0 if you
120   don't. */
121#define PPL_HAVE_DECL_SETRLIMIT 1
122
123/* Define to 1 if you have the declaration of `sigaction', and to 0 if you
124   don't. */
125#define PPL_HAVE_DECL_SIGACTION 1
126
127/* Define to 1 if you have the declaration of `strtod', and to 0 if you don't.
128   */
129#define PPL_HAVE_DECL_STRTOD 1
130
131/* Define to 1 if you have the declaration of `strtof', and to 0 if you don't.
132   */
133#define PPL_HAVE_DECL_STRTOF 1
134
135/* Define to 1 if you have the declaration of `strtold', and to 0 if you
136   don't. */
137#define PPL_HAVE_DECL_STRTOLD 1
138
139/* Define to 1 if you have the declaration of `strtoll', and to 0 if you
140   don't. */
141#define PPL_HAVE_DECL_STRTOLL 1
142
143/* Define to 1 if you have the declaration of `strtoull', and to 0 if you
144   don't. */
145#define PPL_HAVE_DECL_STRTOULL 1
146
147/* Define to 1 if you have the <dlfcn.h> header file. */
148#define PPL_HAVE_DLFCN_H 1
149
150/* Define to 1 if you have the <fenv.h> header file. */
151#define PPL_HAVE_FENV_H 1
152
153/* Define to 1 if you have the <getopt.h> header file. */
154#define PPL_HAVE_GETOPT_H 1
155
156/* Define to 1 if you have the <glpk/glpk.h> header file. */
157/* #undef PPL_HAVE_GLPK_GLPK_H */
158
159/* Define to 1 if you have the <glpk.h> header file. */
160#define PPL_HAVE_GLPK_H 1
161
162/* Define to 1 if you have the <ieeefp.h> header file. */
163/* #undef PPL_HAVE_IEEEFP_H */
164
165/* Define to 1 if you have the <inttypes.h> header file. */
166#define PPL_HAVE_INTTYPES_H 1
167
168/* Define to 1 if the system has the type `int_fast16_t'. */
169#define PPL_HAVE_INT_FAST16_T 1
170
171/* Define to 1 if the system has the type `int_fast32_t'. */
172#define PPL_HAVE_INT_FAST32_T 1
173
174/* Define to 1 if the system has the type `int_fast64_t'. */
175#define PPL_HAVE_INT_FAST64_T 1
176
177/* Define to 1 if you have the <memory.h> header file. */
178#define PPL_HAVE_MEMORY_H 1
179
180/* Define to 1 if the system has the type `siginfo_t'. */
181#define PPL_HAVE_SIGINFO_T 1
182
183/* Define to 1 if you have the <signal.h> header file. */
184#define PPL_HAVE_SIGNAL_H 1
185
186/* Define to 1 if you have the <stdint.h> header file. */
187#define PPL_HAVE_STDINT_H 1
188
189/* Define to 1 if you have the <stdlib.h> header file. */
190#define PPL_HAVE_STDLIB_H 1
191
192/* Define to 1 if you have the <strings.h> header file. */
193#define PPL_HAVE_STRINGS_H 1
194
195/* Define to 1 if you have the <string.h> header file. */
196#define PPL_HAVE_STRING_H 1
197
198/* Define to 1 if you have the <sys/resource.h> header file. */
199#define PPL_HAVE_SYS_RESOURCE_H 1
200
201/* Define to 1 if you have the <sys/stat.h> header file. */
202#define PPL_HAVE_SYS_STAT_H 1
203
204/* Define to 1 if you have the <sys/time.h> header file. */
205#define PPL_HAVE_SYS_TIME_H 1
206
207/* Define to 1 if you have the <sys/types.h> header file. */
208#define PPL_HAVE_SYS_TYPES_H 1
209
210/* Define to 1 if the system has the type `timeval'. */
211#define PPL_HAVE_TIMEVAL 1
212
213/* Define to 1 if typeof works with your compiler. */
214#define PPL_HAVE_TYPEOF 1
215
216/* Define to 1 if the system has the type `uintptr_t'. */
217#define PPL_HAVE_UINTPTR_T 1
218
219/* Define to 1 if the system has the type `uint_fast16_t'. */
220#define PPL_HAVE_UINT_FAST16_T 1
221
222/* Define to 1 if the system has the type `uint_fast32_t'. */
223#define PPL_HAVE_UINT_FAST32_T 1
224
225/* Define to 1 if the system has the type `uint_fast64_t'. */
226#define PPL_HAVE_UINT_FAST64_T 1
227
228/* Define to 1 if you have the <unistd.h> header file. */
229#define PPL_HAVE_UNISTD_H 1
230
231/* Define to 1 if `_mp_alloc' is a member of `__mpz_struct'. */
232#define PPL_HAVE___MPZ_STRUCT__MP_ALLOC 1
233
234/* Define to 1 if `_mp_d' is a member of `__mpz_struct'. */
235#define PPL_HAVE___MPZ_STRUCT__MP_D 1
236
237/* Define to 1 if `_mp_size' is a member of `__mpz_struct'. */
238#define PPL_HAVE___MPZ_STRUCT__MP_SIZE 1
239
240/* Define to the sub-directory in which libtool stores uninstalled libraries.
241   */
242#define LT_OBJDIR ".libs/"
243
244/* Define to the address where bug reports for this package should be sent. */
245#define PPL_PACKAGE_BUGREPORT "ppl-devel@cs.unipr.it"
246
247/* Define to the full name of this package. */
248#define PPL_PACKAGE_NAME "the Parma Polyhedra Library"
249
250/* Define to the full name and version of this package. */
251#define PPL_PACKAGE_STRING "the Parma Polyhedra Library 1.2"
252
253/* Define to the one symbol short name of this package. */
254#define PPL_PACKAGE_TARNAME "ppl"
255
256/* Define to the home page for this package. */
257#define PACKAGE_URL ""
258
259/* Define to the version of this package. */
260#define PPL_PACKAGE_VERSION "1.2"
261
262/* ABI-breaking extra assertions are enabled when this is defined. */
263/* #undef PPL_ABI_BREAKING_EXTRA_DEBUG */
264
265/* Not zero if the FPU can be controlled. */
266#define PPL_CAN_CONTROL_FPU 1
267
268/* Defined if the integral type to be used for coefficients is a checked one.
269   */
270/* #undef PPL_CHECKED_INTEGERS */
271
272/* The number of bits of coefficients; 0 if unbounded. */
273#define PPL_COEFFICIENT_BITS 0
274
275/* The integral type used to represent coefficients. */
276#define PPL_COEFFICIENT_TYPE mpz_class
277
278/* This contains the options with which `configure' was invoked. */
279#define PPL_CONFIGURE_OPTIONS " '--with-java=/usr/lib/jvm/java-7-openjdk-amd64'"
280
281/* The unique code of the binary format of C++ doubles, if supported;
282   undefined otherwise. */
283#define PPL_CXX_DOUBLE_BINARY_FORMAT PPL_FLOAT_IEEE754_DOUBLE
284
285/* The binary format of C++ floats, if supported; undefined otherwise. */
286#define PPL_CXX_FLOAT_BINARY_FORMAT PPL_FLOAT_IEEE754_SINGLE
287
288/* The unique code of the binary format of C++ long doubles, if supported;
289   undefined otherwise. */
290#define PPL_CXX_LONG_DOUBLE_BINARY_FORMAT PPL_FLOAT_INTEL_DOUBLE_EXTENDED
291
292/* Not zero if the the plain char type is signed. */
293#define PPL_CXX_PLAIN_CHAR_IS_SIGNED 1
294
295/* Not zero if the C++ compiler provides long double numbers that have bigger
296   range or precision than double. */
297#define PPL_CXX_PROVIDES_PROPER_LONG_DOUBLE 1
298
299/* Not zero if the C++ compiler supports __attribute__ ((weak)). */
300#define PPL_CXX_SUPPORTS_ATTRIBUTE_WEAK 1
301
302/* Not zero if the the IEEE inexact flag is supported in C++. */
303#define PPL_CXX_SUPPORTS_IEEE_INEXACT_FLAG 1
304
305/* Not zero if it is possible to limit memory using setrlimit(). */
306#define PPL_CXX_SUPPORTS_LIMITING_MEMORY 1
307
308/* Not zero if the C++ compiler supports zero_length arrays. */
309#define PPL_CXX_SUPPORTS_ZERO_LENGTH_ARRAYS 1
310
311/* Defined if floating point arithmetic may use the 387 unit. */
312#define PPL_FPMATH_MAY_USE_387 1
313
314/* Defined if floating point arithmetic may use the SSE instruction set. */
315#define PPL_FPMATH_MAY_USE_SSE 1
316
317/* Defined if GLPK provides glp_term_hook(). */
318#define PPL_GLPK_HAS_GLP_TERM_HOOK 1
319
320/* Defined if GLPK provides glp_term_out(). */
321#define PPL_GLPK_HAS_GLP_TERM_OUT 1
322
323/* Defined if GLPK provides lib_set_print_hook(). */
324/* #undef PPL_GLPK_HAS_LIB_SET_PRINT_HOOK */
325
326/* Defined if GLPK provides _glp_lib_print_hook(). */
327/* #undef PPL_GLPK_HAS__GLP_LIB_PRINT_HOOK */
328
329/* Defined if the integral type to be used for coefficients is GMP's one. */
330#define PPL_GMP_INTEGERS 1
331
332/* Not zero if GMP has been compiled with support for exceptions. */
333#define PPL_GMP_SUPPORTS_EXCEPTIONS 1
334
335/* Defined if the integral type to be used for coefficients is a native one.
336   */
337/* #undef PPL_NATIVE_INTEGERS */
338
339/* Assertions are disabled when this is defined. */
340#define PPL_NDEBUG 1
341
342/* Not zero if doubles are supported. */
343#define PPL_SUPPORTED_DOUBLE 1
344
345/* Not zero if floats are supported. */
346#define PPL_SUPPORTED_FLOAT 1
347
348/* Not zero if long doubles are supported. */
349#define PPL_SUPPORTED_LONG_DOUBLE 1
350
351/* The size of `char', as computed by sizeof. */
352#define PPL_SIZEOF_CHAR 1
353
354/* The size of `double', as computed by sizeof. */
355#define PPL_SIZEOF_DOUBLE 8
356
357/* The size of `float', as computed by sizeof. */
358#define PPL_SIZEOF_FLOAT 4
359
360/* The size of `fp', as computed by sizeof. */
361#define PPL_SIZEOF_FP 8
362
363/* The size of `int', as computed by sizeof. */
364#define PPL_SIZEOF_INT 4
365
366/* The size of `int*', as computed by sizeof. */
367#define PPL_SIZEOF_INTP 8
368
369/* The size of `long', as computed by sizeof. */
370#define PPL_SIZEOF_LONG 8
371
372/* The size of `long double', as computed by sizeof. */
373#define PPL_SIZEOF_LONG_DOUBLE 16
374
375/* The size of `long long', as computed by sizeof. */
376#define PPL_SIZEOF_LONG_LONG 8
377
378/* The size of `mp_limb_t', as computed by sizeof. */
379#define PPL_SIZEOF_MP_LIMB_T 8
380
381/* The size of `short', as computed by sizeof. */
382#define PPL_SIZEOF_SHORT 2
383
384/* The size of `size_t', as computed by sizeof. */
385#define PPL_SIZEOF_SIZE_T 8
386
387/* Define to 1 if you have the ANSI C header files. */
388#define PPL_STDC_HEADERS 1
389
390/* Define PPL_WORDS_BIGENDIAN to 1 if your processor stores words with the most
391   significant byte first (like Motorola and SPARC, unlike Intel). */
392#if defined AC_APPLE_UNIVERSAL_BUILD
393# if defined __BIG_ENDIAN__
394#  define PPL_WORDS_BIGENDIAN 1
395# endif
396#else
397# ifndef PPL_WORDS_BIGENDIAN
398/* #  undef PPL_WORDS_BIGENDIAN */
399# endif
400#endif
401
402/* When defined and libstdc++ is used, it is used in debug mode. */
403/* #undef _GLIBCXX_DEBUG */
404
405/* When defined and libstdc++ is used, it is used in pedantic debug mode. */
406/* #undef _GLIBCXX_DEBUG_PEDANTIC */
407
408/* Define to empty if `const' does not conform to ANSI C. */
409/* #undef const */
410
411/* Define to `__inline__' or `__inline' if that's what the C compiler
412   calls it, or to nothing if 'inline' is not supported under any name.  */
413#ifndef __cplusplus
414/* #undef inline */
415#endif
416
417/* Define to __typeof__ if your compiler spells it that way. */
418/* #undef typeof */
419
420/* Define to the type of an unsigned integer type wide enough to hold a
421   pointer, if such a type exists, and if the system does not define it. */
422/* #undef uintptr_t */
423
424
425#if defined(PPL_NDEBUG) && !defined(NDEBUG)
426# define NDEBUG PPL_NDEBUG
427#endif
428
429/* In order for the definition of `int64_t' to be seen by Comeau C/C++,
430   we must make sure <stdint.h> is included before <sys/types.hh> is
431   (even indirectly) included.  Moreover we need to define
432   __STDC_LIMIT_MACROS before the first inclusion of <stdint.h>
433   in order to have the macros defined also in C++.  */
434
435#ifdef PPL_HAVE_STDINT_H
436# ifndef __STDC_LIMIT_MACROS
437#  define __STDC_LIMIT_MACROS 1
438# endif
439# include <stdint.h>
440#endif
441
442#ifdef PPL_HAVE_INTTYPES_H
443# include <inttypes.h>
444#endif
445
446#define PPL_U(x) x
447
448#endif /* !defined(PPL_ppl_config_h) */
449
450/* END ppl-config.h */
451
452/* Automatically generated from PPL source file ../src/version.hh line 1. */
453/* Declaration of macros and functions providing version  -*- C++ -*-
454   and licensing information.
455*/
456
457
458//! The major number of the PPL version.
459/*! \ingroup PPL_CXX_interface */
460#define PPL_VERSION_MAJOR 1
461
462//! The minor number of the PPL version.
463/*! \ingroup PPL_CXX_interface */
464#define PPL_VERSION_MINOR 2
465
466//! The revision number of the PPL version.
467/*! \ingroup PPL_CXX_interface */
468#define PPL_VERSION_REVISION 0
469
470/*! \brief
471  The beta number of the PPL version.  This is zero for official
472  releases and nonzero for development snapshots.
473  \ingroup PPL_CXX_interface
474*/
475#define PPL_VERSION_BETA 0
476
477//! A string containing the PPL version.
478/*! \ingroup PPL_CXX_interface
479  Let <CODE>M</CODE> and <CODE>m</CODE> denote the numbers associated
480  to PPL_VERSION_MAJOR and PPL_VERSION_MINOR, respectively.  The
481  format of PPL_VERSION is <CODE>M "." m</CODE> if both
482  PPL_VERSION_REVISION (<CODE>r</CODE>) and PPL_VERSION_BETA
483  (<CODE>b</CODE>)are zero, <CODE>M "." m "pre" b</CODE> if
484  PPL_VERSION_REVISION is zero and PPL_VERSION_BETA is not zero,
485  <CODE>M "." m "." r</CODE> if PPL_VERSION_REVISION is not zero and
486  PPL_VERSION_BETA is zero, <CODE>M "." m "." r "pre" b</CODE> if
487  neither PPL_VERSION_REVISION nor PPL_VERSION_BETA are zero.
488*/
489#define PPL_VERSION "1.2"
490
491namespace Parma_Polyhedra_Library {
492
493//! \name Library Version Control Functions
494//@{
495
496//! Returns the major number of the PPL version.
497unsigned
498version_major();
499
500//! Returns the minor number of the PPL version.
501unsigned
502version_minor();
503
504//! Returns the revision number of the PPL version.
505unsigned
506version_revision();
507
508//! Returns the beta number of the PPL version.
509unsigned
510version_beta();
511
512//! Returns a character string containing the PPL version.
513const char* version();
514
515//! Returns a character string containing the PPL banner.
516/*!
517  The banner provides information about the PPL version, the licensing,
518  the lack of any warranty whatsoever, the C++ compiler used to build
519  the library, where to report bugs and where to look for further
520  information.
521*/
522const char* banner();
523
524//@} // Library Version Control Functions
525
526} // namespace Parma_Polyhedra_Library
527
528/* Automatically generated from PPL source file ../src/namespaces.hh line 1. */
529/* Documentation for used namespaces.
530*/
531
532
533//! The entire library is confined to this namespace.
534namespace Parma_Polyhedra_Library {
535
536//! All input/output operators are confined to this namespace.
537/*! \ingroup PPL_CXX_interface
538  This is done so that the library's input/output operators
539  do not interfere with those the user might want to define.
540  In fact, it is highly unlikely that any predefined I/O
541  operator will suit the needs of a client application.
542  On the other hand, those applications for which the PPL
543  I/O operator are enough can easily obtain access to them.
544  For example, a directive like
545  \code
546    using namespace Parma_Polyhedra_Library::IO_Operators;
547  \endcode
548  would suffice for most uses.
549  In more complex situations, such as
550  \code
551    const Constraint_System& cs = ...;
552    copy(cs.begin(), cs.end(),
553         ostream_iterator<Constraint>(cout, "\n"));
554  \endcode
555  the Parma_Polyhedra_Library namespace must be suitably extended.
556  This can be done as follows:
557  \code
558    namespace Parma_Polyhedra_Library {
559      // Import all the output operators into the main PPL namespace.
560      using IO_Operators::operator<<;
561    }
562  \endcode
563*/
564namespace IO_Operators {
565} // namespace IO_Operators
566
567#ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
568//! Types and functions implementing checked numbers.
569/*! \ingroup PPL_CXX_interface */
570#endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
571namespace Checked {
572} // namespace Checked
573
574#ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
575//! %Implementation related data and functions.
576/*! \ingroup PPL_CXX_interface */
577#endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
578namespace Implementation {
579} // namespace Implementation
580
581#ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
582//! Data and functions related to language interfaces.
583#endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
584namespace Interfaces {
585
586#ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
587//! Data and functions related to the C language interface.
588/*! \ingroup PPL_C_interface */
589#endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
590namespace C {
591
592} // namespace C
593
594#ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
595//! Data and functions related to the Java language interface.
596/*! \ingroup PPL_Java_interface */
597#endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
598namespace Java {
599
600} // namespace Java
601
602#ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
603//! Data and functions related to the OCaml language interface.
604/*! \ingroup PPL_OCaml_interface */
605#endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
606namespace OCaml {
607
608} // namespace OCaml
609
610#ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
611//! Data and functions related to the Prolog language interfaces.
612/*! \ingroup PPL_Prolog_interface */
613#endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
614namespace Prolog {
615
616#ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
617//! Data and functions related to the Ciao Prolog language interface.
618/*! \ingroup PPL_Prolog_interface */
619#endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
620namespace Ciao {
621
622} // namespace Ciao
623
624#ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
625//! Data and functions related to the GNU Prolog language interface.
626/*! \ingroup PPL_Prolog_interface */
627#endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
628namespace GNU {
629
630} // namespace GNU
631
632#ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
633//! Data and functions related to the SICStus language interface.
634/*! \ingroup PPL_Prolog_interface */
635#endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
636namespace SICStus {
637
638} // namespace SICStus
639
640#ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
641//! Data and functions related to the SWI-Prolog language interface.
642/*! \ingroup PPL_Prolog_interface */
643#endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
644namespace SWI {
645
646} // namespace SWI
647
648#ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
649//! Data and functions related to the XSB language interface.
650/*! \ingroup PPL_Prolog_interface */
651#endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
652namespace XSB {
653
654} // namespace XSB
655
656#ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
657//! Data and functions related to the YAP language interface.
658/*! \ingroup PPL_Prolog_interface */
659#endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
660namespace YAP {
661
662} // namespace YAP
663
664} // namespace Prolog
665
666} // namespace Interfaces
667
668} // namespace Parma_Polyhedra_Library
669
670
671//! The standard C++ namespace.
672/*! \ingroup PPL_CXX_interface
673  The Parma Polyhedra Library conforms to the C++ standard and,
674  in particular, as far as reserved names are concerned (17.4.3.1,
675  [lib.reserved.names]).  The PPL, however, defines several
676  template specializations for the standard library class template
677  <CODE>numeric_limits</CODE> (18.2.1, [lib.limits]).
678
679  \note
680  The PPL provides the specializations of the class template
681  <CODE>numeric_limits</CODE> not only for PPL-specific numeric types,
682  but also for the GMP types <CODE>mpz_class</CODE> and
683  <CODE>mpq_class</CODE>. These specializations will be removed
684  as soon as they will be provided by the C++ interface of GMP.
685*/
686namespace std {
687} // namespace std
688
689
690/* Automatically generated from PPL source file ../src/Interval_Info_types.hh line 1. */
691
692
693namespace Parma_Polyhedra_Library {
694
695template <typename Policy>
696class Interval_Info_Null;
697
698template <typename T, typename Policy>
699class Interval_Info_Bitset;
700
701} // namespace Parma_Polyhedra_Library
702
703/* Automatically generated from PPL source file ../src/checked_numeric_limits.hh line 1. */
704/* Specializations of std::numeric_limits for "checked" types.
705*/
706
707
708/* Automatically generated from PPL source file ../src/Checked_Number_defs.hh line 1. */
709/* Checked_Number class declaration.
710*/
711
712
713/* Automatically generated from PPL source file ../src/Checked_Number_types.hh line 1. */
714
715
716/* Automatically generated from PPL source file ../src/Coefficient_traits_template.hh line 1. */
717/* Coefficient_traits_template class declaration.
718*/
719
720
721namespace Parma_Polyhedra_Library {
722
723#ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
724//! Coefficient traits.
725/*! \ingroup PPL_CXX_interface */
726#endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
727template <typename Coefficient>
728struct Coefficient_traits_template {
729};
730
731} // namespace Parma_Polyhedra_Library
732
733/* Automatically generated from PPL source file ../src/Checked_Number_types.hh line 17. */
734
735namespace Parma_Polyhedra_Library {
736
737struct Extended_Number_Policy;
738
739template <typename T, typename Policy>
740class Checked_Number;
741
742} // namespace Parma_Polyhedra_Library
743
744/* Automatically generated from PPL source file ../src/checked_defs.hh line 1. */
745/* Abstract checked arithmetic function container.
746*/
747
748
749/* Automatically generated from PPL source file ../src/mp_std_bits_defs.hh line 1. */
750/* Declarations of specializations of std:: objects for
751   multi-precision types.
752*/
753
754
755#include <gmpxx.h>
756#include <limits>
757
758#ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
759//! Swaps \p x with \p y.
760#endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
761void swap(mpz_class& x, mpz_class& y);
762
763#ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
764//! Swaps \p x with \p y.
765#endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
766void swap(mpq_class& x, mpq_class& y);
767
768#if __GNU_MP_VERSION < 5 \
769  || (__GNU_MP_VERSION == 5 && __GNU_MP_VERSION_MINOR < 1)
770
771namespace std {
772
773#ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
774//! Specialization of std::numeric_limits.
775#endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
776template <>
777class numeric_limits<mpz_class> {
778private:
779  typedef mpz_class Type;
780
781public:
782  static const bool is_specialized = true;
783  static const int digits = 0;
784  static const int digits10 = 0;
785  static const bool is_signed = true;
786  static const bool is_integer = true;
787  static const bool is_exact = true;
788  static const int radix = 2;
789  static const int min_exponent = 0;
790  static const int min_exponent10 = 0;
791  static const int max_exponent = 0;
792  static const int max_exponent10 = 0;
793  static const bool has_infinity = false;
794  static const bool has_quiet_NaN =  false;
795  static const bool has_signaling_NaN = false;
796  static const float_denorm_style has_denorm = denorm_absent;
797  static const bool has_denorm_loss = false;
798  static const bool is_iec559 = false;
799  static const bool is_bounded = false;
800  static const bool is_modulo = false;
801  static const bool traps = false;
802  static const bool tinyness_before = false;
803  static const float_round_style round_style = round_toward_zero;
804
805  static Type min() {
806    return static_cast<Type>(0);
807  }
808
809  static Type max() {
810    return static_cast<Type>(0);
811  }
812
813  static Type epsilon() {
814    return static_cast<Type>(0);
815  }
816
817  static Type round_error() {
818    return static_cast<Type>(0);
819  }
820
821  static Type infinity() {
822    return static_cast<Type>(0);
823  }
824
825  static Type quiet_NaN() {
826    return static_cast<Type>(0);
827  }
828
829  static Type denorm_min() {
830    return static_cast<Type>(1);
831  }
832};
833
834#ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
835//! Specialization of std::numeric_limits.
836#endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
837template <>
838class numeric_limits<mpq_class> {
839private:
840  typedef mpq_class Type;
841
842public:
843  static const bool is_specialized = true;
844  static const int digits = 0;
845  static const int digits10 = 0;
846  static const bool is_signed = true;
847  static const bool is_integer = false;
848  static const bool is_exact = true;
849  static const int radix = 2;
850  static const int min_exponent = 0;
851  static const int min_exponent10 = 0;
852  static const int max_exponent = 0;
853  static const int max_exponent10 = 0;
854  static const bool has_infinity = false;
855  static const bool has_quiet_NaN =  false;
856  static const bool has_signaling_NaN = false;
857  static const float_denorm_style has_denorm = denorm_absent;
858  static const bool has_denorm_loss = false;
859  static const bool is_iec559 = false;
860  static const bool is_bounded = false;
861  static const bool is_modulo = false;
862  static const bool traps = false;
863  static const bool tinyness_before = false;
864  static const float_round_style round_style = round_toward_zero;
865
866  static Type min() {
867    return static_cast<Type>(0);
868  }
869
870  static Type max() {
871    return static_cast<Type>(0);
872  }
873
874  static Type epsilon() {
875    return static_cast<Type>(0);
876  }
877
878  static Type round_error() {
879    return static_cast<Type>(0);
880  }
881
882  static Type infinity() {
883    return static_cast<Type>(0);
884  }
885
886  static Type quiet_NaN() {
887    return static_cast<Type>(0);
888  }
889
890  static Type denorm_min() {
891    return static_cast<Type>(0);
892  }
893};
894
895} // namespace std
896
897#endif // __GNU_MP_VERSION < 5
898       // || (__GNU_MP_VERSION == 5 && __GNU_MP_VERSION_MINOR < 1)
899
900/* Automatically generated from PPL source file ../src/mp_std_bits_inlines.hh line 1. */
901/* Definitions of specializations of std:: functions and methods for
902   multi-precision types.
903*/
904
905
906inline void
907swap(mpz_class& x, mpz_class& y) {
908  mpz_swap(x.get_mpz_t(), y.get_mpz_t());
909}
910
911inline void
912swap(mpq_class& x, mpq_class& y) {
913  mpq_swap(x.get_mpq_t(), y.get_mpq_t());
914}
915
916/* Automatically generated from PPL source file ../src/mp_std_bits_defs.hh line 174. */
917
918/* Automatically generated from PPL source file ../src/Temp_defs.hh line 1. */
919/* Temp_* classes declarations.
920*/
921
922
923/* Automatically generated from PPL source file ../src/meta_programming.hh line 1. */
924/* Metaprogramming utilities.
925*/
926
927
928#include <gmpxx.h>
929
930namespace Parma_Polyhedra_Library {
931
932#ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
933/*! \brief
934  Declares a per-class constant of type <CODE>bool</CODE>, called \p name
935  and with value \p value.
936
937  \ingroup PPL_CXX_interface
938  Differently from static constants, \p name needs not (and cannot) be
939  defined (for static constants, the need for a further definition is
940  mandated by Section 9.4.2/4 of the C++ standard).
941*/
942#endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
943#define const_bool_nodef(name, value)           \
944  enum const_bool_value_ ## name { PPL_U(name) = (value) }
945
946#ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
947/*! \brief
948  Declares a per-class constant of type <CODE>int</CODE>, called \p name
949  and with value \p value.
950
951  \ingroup PPL_CXX_interface
952  Differently from static constants, \p name needs not (and cannot) be
953  defined (for static constants, the need for a further definition is
954  mandated by Section 9.4.2/4 of the C++ standard).
955*/
956#endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
957#define const_int_nodef(name, value) \
958  enum anonymous_enum_ ## name { PPL_U(name) = (value) }
959
960#ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
961/*! \brief
962  Declares a per-class constant of type \p type, called \p name
963  and with value \p value.  The value of the constant is accessible
964  by means of the syntax <CODE>name()</CODE>.
965
966  \ingroup PPL_CXX_interface
967  Differently from static constants, \p name needs not (and cannot) be
968  defined (for static constants, the need for a further definition is
969  mandated by Section 9.4.2/4 of the C++ standard).
970*/
971#endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
972#define const_value_nodef(type, name, value)    \
973  static type PPL_U(name)() {                   \
974    return (value);                             \
975  }
976
977#ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
978/*! \brief
979  Declares a per-class constant of type \p type, called \p name
980  and with value \p value.  A constant reference to the constant
981  is accessible by means of the syntax <CODE>name()</CODE>.
982
983  \ingroup PPL_CXX_interface
984  Differently from static constants, \p name needs not (and cannot) be
985  defined (for static constants, the need for a further definition is
986  mandated by Section 9.4.2/4 of the C++ standard).
987*/
988#endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
989#define const_ref_nodef(type, name, value)                              \
990  static const type& PPL_U(name)() {                                    \
991    static type PPL_U(name) = (value);                                       \
992    return (name);                                                      \
993  }
994
995#ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
996/*! \brief
997  A class that is only defined if \p b evaluates to <CODE>true</CODE>.
998
999  \ingroup PPL_CXX_interface
1000  This is the non-specialized case, so the class is declared but not defined.
1001*/
1002#endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
1003template <bool b>
1004struct Compile_Time_Check;
1005
1006#ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
1007/*! \brief
1008  A class that is only defined if \p b evaluates to <CODE>true</CODE>.
1009
1010  \ingroup PPL_CXX_interface
1011  This is the specialized case with \p b equal to <CODE>true</CODE>,
1012  so the class is declared and (trivially) defined.
1013*/
1014#endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
1015template <>
1016struct Compile_Time_Check<true> {
1017};
1018
1019#define PPL_COMPILE_TIME_CHECK_NAME(suffix) compile_time_check_ ## suffix
1020#define PPL_COMPILE_TIME_CHECK_AUX(e, suffix)                           \
1021  enum anonymous_enum_compile_time_check_ ## suffix {                   \
1022    /* If e evaluates to false, then the sizeof cannot be compiled. */  \
1023    PPL_COMPILE_TIME_CHECK_NAME(suffix)                                 \
1024      = sizeof(Parma_Polyhedra_Library::Compile_Time_Check<(e)>)        \
1025  }
1026
1027#ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
1028/*! \brief
1029  Produces a compilation error if the compile-time constant \p e does
1030  not evaluate to <CODE>true</CODE>
1031  \ingroup PPL_CXX_interface
1032*/
1033#endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
1034#define PPL_COMPILE_TIME_CHECK(e, msg) PPL_COMPILE_TIME_CHECK_AUX(e, __LINE__)
1035
1036#ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
1037/*! \brief
1038  A class holding a constant called <CODE>value</CODE> that evaluates
1039  to \p b.
1040  \ingroup PPL_CXX_interface
1041*/
1042#endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
1043template <bool b>
1044struct Bool {
1045  enum const_bool_value {
1046    value = b
1047  };
1048};
1049
1050#ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
1051/*! \brief
1052  A class holding a constant called <CODE>value</CODE> that evaluates
1053  to <CODE>true</CODE>.
1054  \ingroup PPL_CXX_interface
1055*/
1056#endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
1057struct True : public Bool<true> {
1058};
1059
1060#ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
1061/*! \brief
1062  A class holding a constant called <CODE>value</CODE> that evaluates
1063  to <CODE>false</CODE>.
1064  \ingroup PPL_CXX_interface
1065*/
1066#endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
1067struct False : public Bool<false> {
1068};
1069
1070#ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
1071/*! \brief
1072  A class holding a constant called <CODE>value</CODE> that evaluates
1073  to <CODE>true</CODE> if and only if \p T1 is the same type as \p T2.
1074
1075  \ingroup PPL_CXX_interface
1076  This is the non-specialized case, in which \p T1 and \p T2 can be different.
1077*/
1078#endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
1079template <typename T1, typename T2>
1080struct Is_Same : public False {
1081};
1082
1083#ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
1084/*! \brief
1085  A class holding a constant called <CODE>value</CODE> that evaluates
1086  to <CODE>true</CODE> if and only if \p T1 is the same type as \p T2.
1087
1088  \ingroup PPL_CXX_interface
1089  This is the specialization in which \p T1 and \p T2 are equal.
1090*/
1091#endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
1092template <typename T>
1093struct Is_Same<T, T> : public True {
1094};
1095
1096#ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
1097/*! \brief
1098  A class holding a constant called <CODE>value</CODE> that evaluates
1099  to <CODE>true</CODE> if and only if \p Base is the same type as \p Derived
1100  or \p Derived is a class derived from \p Base.
1101
1102  \ingroup PPL_CXX_interface
1103  \note
1104  Care must be taken to use this predicate with template classes.
1105  Suppose we have
1106  \code
1107  template <typename T> struct B;
1108  template <typename T> struct D : public B<T>;
1109  \endcode
1110  Of course, we cannot test if, for some type variable <CODE>U</CODE>, we have
1111  <CODE>Is_Same_Or_Derived<B<U>, Type>:: const_bool_value:: value == true</CODE>.
1112  But we can do as follows:
1113  \code
1114  struct B_Base {
1115  };
1116
1117  template <typename T> struct B : public B_Base;
1118  \endcode
1119  This enables us to inquire
1120  <CODE>Is_Same_Or_Derived<B_Base, Type>:: const_bool_value:: value</CODE>.
1121*/
1122#endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
1123template <typename Base, typename Derived>
1124struct Is_Same_Or_Derived {
1125
1126#ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
1127  //! A class that is constructible from just anything.
1128#endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
1129  struct Any {
1130    //! The universal constructor.
1131    template <typename T>
1132    Any(const T&);
1133  };
1134
1135  //! Overloading with \p Base.
1136  static char func(const Base&);
1137
1138  //! Overloading with \p Any.
1139  static double func(Any);
1140
1141  //! A function obtaining a const reference to a \p Derived object.
1142  static const Derived& derived_object();
1143
1144  PPL_COMPILE_TIME_CHECK(sizeof(char) != sizeof(double),
1145                         "architecture with sizeof(char) == sizeof(double)"
1146                         " (!?)");
1147
1148  enum const_bool_value {
1149    /*!
1150      Assuming <CODE>sizeof(char) != sizeof(double)</CODE>, the C++
1151      overload resolution mechanism guarantees that <CODE>value</CODE>
1152      evaluates to <CODE>true</CODE> if and only if <CODE>Base</CODE>
1153      is the same type as <CODE>Derived</CODE> or <CODE>Derived</CODE>
1154      is a class derived from <CODE>Base</CODE>.
1155    */
1156    value = (sizeof(func(derived_object())) == sizeof(char))
1157  };
1158};
1159
1160#ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
1161/*! \brief
1162  A class that provides a type member called <CODE>type</CODE> equivalent
1163  to \p T if and only if \p b is <CODE>true</CODE>.
1164
1165  \ingroup PPL_CXX_interface
1166  This is the non-specialized case, in which the <CODE>type</CODE> member
1167  is not present.
1168*/
1169#endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
1170template <bool b, typename T = void>
1171struct Enable_If {
1172};
1173
1174template <typename Type, Type, typename T = void>
1175struct Enable_If_Is {
1176  typedef T type;
1177};
1178
1179#ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
1180/*! \brief
1181  A class that provides a type member called <CODE>type</CODE> equivalent
1182  to \p T if and only if \p b is <CODE>true</CODE>.
1183
1184  \ingroup PPL_CXX_interface
1185  This is the specialization in which the <CODE>type</CODE> member
1186  is present.
1187
1188  \note
1189  Let <CODE>T</CODE>, <CODE>T1</CODE> and <CODE>T2</CODE> be any type
1190  expressions and suppose we have some template function
1191  <CODE>T f(T1, T2)</CODE>.  If we want to declare a specialization
1192  that is enabled only if some compile-time checkable condition holds,
1193  we simply declare the specialization by
1194  \code
1195  template ...
1196  typename Enable_If<condition, T>::type
1197  foo(T1 x, T2 y);
1198  \endcode
1199  For all the instantiations of the template parameters that cause
1200  <CODE>condition</CODE> to evaluate to <CODE>false</CODE>,
1201  the <CODE>Enable_If<condition, T>::type</CODE> member will not be defined.
1202  Hence, for that instantiations, the specialization will not be eligible.
1203*/
1204#endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
1205template <typename T>
1206struct Enable_If<true, T> {
1207  typedef T type;
1208};
1209
1210template <typename T>
1211struct Is_Native : public False {
1212};
1213
1214template <> struct Is_Native<char> : public True { };
1215template <> struct Is_Native<signed char> : public True { };
1216template <> struct Is_Native<signed short> : public True { };
1217template <> struct Is_Native<signed int> : public True { };
1218template <> struct Is_Native<signed long> : public True { };
1219template <> struct Is_Native<signed long long> : public True { };
1220template <> struct Is_Native<unsigned char> : public True { };
1221template <> struct Is_Native<unsigned short> : public True { };
1222template <> struct Is_Native<unsigned int> : public True { };
1223template <> struct Is_Native<unsigned long> : public True { };
1224template <> struct Is_Native<unsigned long long> : public True { };
1225
1226#if PPL_SUPPORTED_FLOAT
1227template <> struct Is_Native<float> : public True { };
1228#endif
1229#if PPL_SUPPORTED_DOUBLE
1230template <> struct Is_Native<double> : public True { };
1231#endif
1232#if PPL_SUPPORTED_LONG_DOUBLE
1233template <> struct Is_Native<long double> : public True { };
1234#endif
1235
1236template <> struct Is_Native<mpz_class> : public True { };
1237
1238template <> struct Is_Native<mpq_class> : public True { };
1239
1240} // namespace Parma_Polyhedra_Library
1241
1242/* Automatically generated from PPL source file ../src/Slow_Copy.hh line 1. */
1243/* Basic Slow_Copy classes declarations.
1244*/
1245
1246
1247/* Automatically generated from PPL source file ../src/Slow_Copy.hh line 28. */
1248#include <gmpxx.h>
1249
1250namespace Parma_Polyhedra_Library {
1251
1252#ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
1253/*! \ingroup PPL_CXX_interface
1254  Copies are not slow by default.
1255*/
1256#endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
1257template <typename T>
1258struct Slow_Copy : public False {
1259};
1260
1261#ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
1262/*! \ingroup PPL_CXX_interface
1263  Copies are slow for mpz_class objects.
1264*/
1265#endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
1266template <>
1267struct Slow_Copy<mpz_class> : public True {
1268};
1269
1270#ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
1271/*! \ingroup PPL_CXX_interface
1272  Copies are slow for mpq_class objects.
1273*/
1274#endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
1275template <>
1276struct Slow_Copy<mpq_class> : public True {
1277};
1278
1279} // namespace Parma_Polyhedra_Library
1280
1281/* Automatically generated from PPL source file ../src/Temp_defs.hh line 29. */
1282
1283namespace Parma_Polyhedra_Library {
1284
1285#ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
1286//! A pool of temporary items of type \p T.
1287#endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
1288template <typename T>
1289class Temp_Item {
1290public:
1291  //! Obtains a reference to a temporary item.
1292  static Temp_Item& obtain();
1293
1294  //! Releases the temporary item \p p.
1295  static void release(Temp_Item& p);
1296
1297  //! Returns a reference to the encapsulated item.
1298  T& item();
1299
1300private:
1301  //! The encapsulated item.
1302  T item_;
1303
1304  //! Pointer to the next item in the free list.
1305  Temp_Item* next;
1306
1307  class Free_List {
1308  public:
1309    Free_List();
1310    ~Free_List();
1311    Temp_Item* head_ptr;
1312  private:
1313    Free_List(const Free_List&); // Not implemented.
1314    Free_List& operator=(const Free_List&); // Not implemented.
1315  }; // class Free_List
1316
1317  friend class Free_List;
1318
1319  //! Head of the free list.
1320  static Temp_Item*& free_list_ref();
1321
1322  //! Default constructor.
1323  Temp_Item();
1324
1325  //! Copy constructor: private and intentionally not implemented.
1326  Temp_Item(const Temp_Item&);
1327
1328  //! Assignment operator: private and intentionally not implemented.
1329  Temp_Item& operator=(const Temp_Item&);
1330};
1331
1332#ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
1333//! An holder for a reference to a temporary object.
1334#endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
1335template <typename T>
1336class Temp_Reference_Holder {
1337public:
1338  //! Constructs an holder holding a dirty temp.
1339  Temp_Reference_Holder();
1340
1341  //! Destructor.
1342  ~Temp_Reference_Holder();
1343
1344  //! Returns a reference to the held item.
1345  T& item();
1346
1347private:
1348  //! Copy constructor: private and intentionally not implemented.
1349  Temp_Reference_Holder(const Temp_Reference_Holder&);
1350
1351  //! Assignment operator: private and intentionally not implemented.
1352  Temp_Reference_Holder& operator=(const Temp_Reference_Holder&);
1353
1354  //! The held item, encapsulated.
1355  Temp_Item<T>& held;
1356};
1357
1358#ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
1359//! An (fake) holder for the value of a temporary object.
1360#endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
1361template <typename T>
1362class Temp_Value_Holder {
1363public:
1364  //! Constructs a fake holder.
1365  Temp_Value_Holder();
1366
1367  //! Returns the value of the held item.
1368  T& item();
1369
1370private:
1371  //! Copy constructor: private and intentionally not implemented.
1372  Temp_Value_Holder(const Temp_Value_Holder&);
1373
1374  //! Assignment operator: private and intentionally not implemented.
1375  Temp_Value_Holder& operator=(const Temp_Value_Holder&);
1376
1377  //! The held item.
1378  T item_;
1379};
1380
1381#ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
1382//! A structure for the efficient handling of temporaries.
1383#endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
1384template <typename T, typename Enable = void>
1385class Dirty_Temp;
1386
1387#ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
1388//! Specialization for the handling of temporaries with a free list.
1389#endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
1390template <typename T>
1391class Dirty_Temp<T, typename Enable_If<Slow_Copy<T>::value>::type>
1392  : public Temp_Reference_Holder<T> {
1393};
1394
1395#ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
1396//! Specialization for the handling of temporaries with local variables.
1397#endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
1398template <typename T>
1399class Dirty_Temp<T, typename Enable_If<!Slow_Copy<T>::value>::type>
1400  : public Temp_Value_Holder<T> {
1401};
1402
1403} // namespace Parma_Polyhedra_Library
1404
1405/* Automatically generated from PPL source file ../src/Temp_inlines.hh line 1. */
1406/* Temp_* classes implementation: inline functions.
1407*/
1408
1409
1410/* Automatically generated from PPL source file ../src/Temp_inlines.hh line 28. */
1411
1412namespace Parma_Polyhedra_Library {
1413
1414template <typename T>
1415inline
1416Temp_Item<T>::Temp_Item()
1417  : item_() {
1418}
1419
1420template <typename T>
1421inline T&
1422Temp_Item<T>::item() {
1423    return item_;
1424}
1425
1426template <typename T>
1427inline
1428Temp_Item<T>::Free_List::Free_List()
1429  : head_ptr(0) {
1430}
1431
1432template <typename T>
1433inline Temp_Item<T>*&
1434Temp_Item<T>::free_list_ref() {
1435  static Free_List free_list;
1436  return free_list.head_ptr;
1437}
1438
1439template <typename T>
1440inline Temp_Item<T>&
1441Temp_Item<T>::obtain() {
1442  Temp_Item* const p = free_list_ref();
1443  if (p != 0) {
1444    free_list_ref() = p->next;
1445    return *p;
1446  }
1447  else {
1448    return *new Temp_Item();
1449  }
1450}
1451
1452template <typename T>
1453inline void
1454Temp_Item<T>::release(Temp_Item& p) {
1455  p.next = free_list_ref();
1456  free_list_ref() = &p;
1457}
1458
1459template <typename T>
1460inline
1461Temp_Reference_Holder<T>::Temp_Reference_Holder()
1462  : held(Temp_Item<T>::obtain()) {
1463}
1464
1465template <typename T>
1466inline
1467Temp_Reference_Holder<T>::~Temp_Reference_Holder() {
1468  Temp_Item<T>::release(held);
1469}
1470
1471template <typename T>
1472inline T&
1473Temp_Reference_Holder<T>::item() {
1474  return held.item();
1475}
1476
1477template <typename T>
1478inline
1479Temp_Value_Holder<T>::Temp_Value_Holder() {
1480}
1481
1482template <typename T>
1483inline T&
1484Temp_Value_Holder<T>::item() {
1485  return item_;
1486}
1487
1488} // namespace Parma_Polyhedra_Library
1489
1490#define PPL_DIRTY_TEMP(T, id)                                           \
1491  Parma_Polyhedra_Library::Dirty_Temp<PPL_U(T)> holder_ ## id;          \
1492  PPL_U(T)& PPL_U(id) = holder_ ## id.item()
1493
1494/* Automatically generated from PPL source file ../src/Temp_templates.hh line 1. */
1495/* Temp_* classes implementation: non-inline template members.
1496*/
1497
1498
1499namespace Parma_Polyhedra_Library {
1500
1501template <typename T>
1502Temp_Item<T>::Free_List::~Free_List() {
1503  while (head_ptr != 0) {
1504    Temp_Item* const p = head_ptr;
1505    head_ptr = head_ptr->next;
1506    delete p;
1507  }
1508}
1509
1510} // namespace Parma_Polyhedra_Library
1511
1512/* Automatically generated from PPL source file ../src/Temp_defs.hh line 154. */
1513
1514/* Automatically generated from PPL source file ../src/Rounding_Dir_defs.hh line 1. */
1515/* Declaration of Rounding_Dir and related functions.
1516*/
1517
1518
1519/* Automatically generated from PPL source file ../src/Result_defs.hh line 1. */
1520/* Result enum and supporting function declarations.
1521*/
1522
1523
1524namespace Parma_Polyhedra_Library {
1525
1526enum Result_Class {
1527  //! \hideinitializer Representable number result class.
1528  VC_NORMAL = 0U << 4,
1529
1530  //! \hideinitializer Negative infinity result class.
1531  VC_MINUS_INFINITY = 1U << 4,
1532
1533  //! \hideinitializer Positive infinity result class.
1534  VC_PLUS_INFINITY = 2U << 4,
1535
1536  //! \hideinitializer Not a number result class.
1537  VC_NAN = 3U << 4,
1538
1539  VC_MASK = VC_NAN
1540};
1541
1542// This must be kept in sync with Relation_Symbol
1543enum Result_Relation {
1544  //! \hideinitializer No values satisfies the relation.
1545  VR_EMPTY = 0U,
1546
1547  //! \hideinitializer Equal. This need to be accompanied by a value.
1548  VR_EQ = 1U,
1549
1550  //! \hideinitializer Less than. This need to be accompanied by a value.
1551  VR_LT = 2U,
1552
1553  //! \hideinitializer Greater than. This need to be accompanied by a value.
1554  VR_GT = 4U,
1555
1556  //! \hideinitializer Not equal. This need to be accompanied by a value.
1557  VR_NE = VR_LT | VR_GT,
1558
1559  //! \hideinitializer Less or equal. This need to be accompanied by a value.
1560  VR_LE = VR_EQ | VR_LT,
1561
1562  //! \hideinitializer Greater or equal. This need to be accompanied by a value.
1563  VR_GE = VR_EQ | VR_GT,
1564
1565  //! \hideinitializer All values satisfy the relation.
1566  VR_LGE = VR_LT | VR_EQ | VR_GT,
1567
1568  VR_MASK = VR_LGE
1569};
1570
1571//! Possible outcomes of a checked arithmetic computation.
1572/*! \ingroup PPL_CXX_interface */
1573enum Result {
1574  //! \hideinitializer The exact result is not comparable.
1575  V_EMPTY = VR_EMPTY,
1576
1577  //! \hideinitializer The computed result is exact.
1578  V_EQ = static_cast<unsigned>(VR_EQ),
1579
1580  //! \hideinitializer The computed result is inexact and rounded up.
1581  V_LT = static_cast<unsigned>(VR_LT),
1582
1583  //! \hideinitializer The computed result is inexact and rounded down.
1584  V_GT = static_cast<unsigned>(VR_GT),
1585
1586  //! \hideinitializer The computed result is inexact.
1587  V_NE = VR_NE,
1588
1589  //! \hideinitializer The computed result may be inexact and rounded up.
1590  V_LE = VR_LE,
1591
1592  //! \hideinitializer The computed result may be inexact and rounded down.
1593  V_GE = VR_GE,
1594
1595  //! \hideinitializer The computed result may be inexact.
1596  V_LGE = VR_LGE,
1597
1598  //! \hideinitializer The exact result is a number out of finite bounds.
1599  V_OVERFLOW = 1U << 6,
1600
1601  //! \hideinitializer A negative integer overflow occurred (rounding up).
1602  V_LT_INF = V_LT | V_OVERFLOW,
1603
1604  //! \hideinitializer A positive integer overflow occurred (rounding down).
1605  V_GT_SUP = V_GT | V_OVERFLOW,
1606
1607  //! \hideinitializer A positive integer overflow occurred (rounding up).
1608  V_LT_PLUS_INFINITY = V_LT | static_cast<unsigned>(VC_PLUS_INFINITY),
1609
1610  //! \hideinitializer A negative integer overflow occurred (rounding down).
1611  V_GT_MINUS_INFINITY = V_GT | static_cast<unsigned>(VC_MINUS_INFINITY),
1612
1613  //! \hideinitializer Negative infinity result.
1614  V_EQ_MINUS_INFINITY = V_EQ | static_cast<unsigned>(VC_MINUS_INFINITY),
1615
1616  //! \hideinitializer Positive infinity result.
1617  V_EQ_PLUS_INFINITY = V_EQ | static_cast<unsigned>(VC_PLUS_INFINITY),
1618
1619  //! \hideinitializer Not a number result.
1620  V_NAN = static_cast<unsigned>(VC_NAN),
1621
1622  //! \hideinitializer Converting from unknown string.
1623  V_CVT_STR_UNK = V_NAN | (1U << 8),
1624
1625  //! \hideinitializer Dividing by zero.
1626  V_DIV_ZERO = V_NAN | (2U << 8),
1627
1628  //! \hideinitializer Adding two infinities having opposite signs.
1629  V_INF_ADD_INF = V_NAN | (3U << 8),
1630
1631  //! \hideinitializer Dividing two infinities.
1632  V_INF_DIV_INF = V_NAN | (4U << 8),
1633
1634  //! \hideinitializer Taking the modulus of an infinity.
1635  V_INF_MOD = V_NAN | (5U << 8),
1636
1637  //! \hideinitializer Multiplying an infinity by zero.
1638  V_INF_MUL_ZERO = V_NAN | (6U << 8),
1639
1640  //! \hideinitializer Subtracting two infinities having the same sign.
1641  V_INF_SUB_INF = V_NAN | (7U << 8),
1642
1643  //! \hideinitializer Computing a remainder modulo zero.
1644  V_MOD_ZERO = V_NAN | (8U << 8),
1645
1646  //! \hideinitializer Taking the square root of a negative number.
1647  V_SQRT_NEG = V_NAN | (9U << 8),
1648
1649  //! \hideinitializer Unknown result due to intermediate negative overflow.
1650  V_UNKNOWN_NEG_OVERFLOW = V_NAN | (10U << 8),
1651
1652  //! \hideinitializer Unknown result due to intermediate positive overflow.
1653  V_UNKNOWN_POS_OVERFLOW = V_NAN | (11U << 8),
1654
1655  //! \hideinitializer The computed result is not representable.
1656  V_UNREPRESENTABLE = 1U << 7
1657
1658};
1659
1660//! \name Functions Inspecting and/or Combining Result Values
1661//@{
1662
1663/*! \ingroup PPL_CXX_interface */
1664Result operator&(Result x, Result y);
1665
1666/*! \ingroup PPL_CXX_interface */
1667Result operator|(Result x, Result y);
1668
1669/*! \ingroup PPL_CXX_interface */
1670Result operator-(Result x, Result y);
1671
1672/*! \ingroup PPL_CXX_interface \brief
1673  Extracts the value class part of \p r (representable number,
1674  unrepresentable minus/plus infinity or nan).
1675*/
1676Result_Class result_class(Result r);
1677
1678/*! \ingroup PPL_CXX_interface \brief
1679  Extracts the relation part of \p r.
1680*/
1681Result_Relation result_relation(Result r);
1682
1683/*! \ingroup PPL_CXX_interface */
1684Result result_relation_class(Result r);
1685
1686//@} // Functions Inspecting and/or Combining Result Values
1687
1688} // namespace Parma_Polyhedra_Library
1689
1690/* Automatically generated from PPL source file ../src/Result_inlines.hh line 1. */
1691/* Result supporting functions implementation: inline functions.
1692*/
1693
1694
1695/* Automatically generated from PPL source file ../src/assertions.hh line 1. */
1696/* Implementation of PPL assert-like macros.
1697*/
1698
1699
1700// The PPL_UNREACHABLE_MSG macro flags a program point as unreachable.
1701// Argument `msg__' is added to output when assertions are turned on.
1702#if defined(NDEBUG)
1703#define PPL_UNREACHABLE_MSG(msg__) Parma_Polyhedra_Library::ppl_unreachable()
1704#else
1705#define PPL_UNREACHABLE_MSG(msg__) Parma_Polyhedra_Library:: \
1706  ppl_unreachable_msg(msg__, __FILE__, __LINE__, __func__)
1707#endif
1708
1709// The PPL_UNREACHABLE macro flags a program point as unreachable.
1710#define PPL_UNREACHABLE PPL_UNREACHABLE_MSG("unreachable")
1711
1712// The PPL_ASSERTION_FAILED macro is used to output a message after
1713// an assertion failure and then cause program termination.
1714// (It is meant to be used only when assertions are turned on.)
1715#define PPL_ASSERTION_FAILED(msg__) Parma_Polyhedra_Library:: \
1716  ppl_assertion_failed(msg__, __FILE__, __LINE__, __func__)
1717
1718// Helper macro PPL_ASSERT_IMPL_: do not use it directly.
1719#if defined(NDEBUG)
1720#define PPL_ASSERT_IMPL_(cond__) ((void) 0)
1721#else
1722#define PPL_STRING_(s) #s
1723#define PPL_ASSERT_IMPL_(cond__) \
1724  ((cond__) ? (void) 0 : PPL_ASSERTION_FAILED(PPL_STRING_(cond__)))
1725#endif
1726
1727
1728// Non zero to detect use of PPL_ASSERT instead of PPL_ASSERT_HEAVY
1729// Note: flag does not affect code built with NDEBUG defined.
1730#define PPL_DEBUG_PPL_ASSERT 1
1731
1732// The PPL_ASSERT macro states that Boolean condition cond__ should hold.
1733// This is meant to replace uses of C assert().
1734#if defined(NDEBUG) || (!PPL_DEBUG_PPL_ASSERT)
1735#define PPL_ASSERT(cond__) PPL_ASSERT_IMPL_(cond__)
1736#else
1737// Note: here we have assertions enabled and PPL_DEBUG_PPL_ASSERT is 1.
1738// Check if the call to PPL_ASSERT should be replaced by PPL_ASSERT_HEAVY
1739// (i.e., if the former may interfere with computational weights).
1740#define PPL_ASSERT(cond__)                                        \
1741  do {                                                            \
1742    typedef Parma_Polyhedra_Library::Weightwatch_Traits W_Traits; \
1743    W_Traits::Threshold old_weight__ = W_Traits::weight;          \
1744    PPL_ASSERT_IMPL_(cond__);                                     \
1745    PPL_ASSERT_IMPL_(old_weight__ == W_Traits::weight             \
1746                     && ("PPL_ASSERT_HEAVY has to be used here" != 0)); \
1747  } while (false)
1748#endif // !defined(NDEBUG) && PPL_DEBUG_PPL_ASSERT
1749
1750
1751// Macro PPL_ASSERT_HEAVY is meant to be used when the evaluation of
1752// the assertion may change computational weights (via WEIGHT_ADD).
1753#if defined(NDEBUG)
1754#define PPL_ASSERT_HEAVY(cond__) PPL_ASSERT_IMPL_(cond__)
1755#else
1756#define PPL_ASSERT_HEAVY(cond__)                                \
1757  do {                                                          \
1758    Parma_Polyhedra_Library::In_Assert guard;                   \
1759    PPL_ASSERT_IMPL_(cond__);                                   \
1760  } while (false)
1761#endif // !defined(NDEBUG)
1762
1763
1764// Macro PPL_EXPECT (resp., PPL_EXPECT_HEAVY) should be used rather than
1765// PPL_ASSERT (resp., PPL_ASSERT_HEAVY) when the condition is assumed to
1766// hold but it is not under library control (typically, it depends on
1767// user provided input).
1768#define PPL_EXPECT(cond__) PPL_ASSERT(cond__)
1769#define PPL_EXPECT_HEAVY(cond__) PPL_ASSERT_HEAVY(cond__)
1770
1771
1772namespace Parma_Polyhedra_Library {
1773
1774#if PPL_CXX_SUPPORTS_ATTRIBUTE_WEAK
1775#define PPL_WEAK_NORETURN __attribute__((weak, noreturn))
1776#else
1777#define PPL_WEAK_NORETURN __attribute__((noreturn))
1778#endif
1779
1780#ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
1781//! Helper function causing program termination by calling \c abort.
1782#endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
1783void ppl_unreachable() PPL_WEAK_NORETURN;
1784
1785#ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
1786/*! \brief
1787  Helper function printing message on \c std::cerr and causing program
1788  termination by calling \c abort.
1789*/
1790#endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
1791void ppl_unreachable_msg(const char* msg,
1792                         const char* file, unsigned int line,
1793                         const char* function) PPL_WEAK_NORETURN;
1794
1795#ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
1796/*! \brief
1797  Helper function printing an assertion failure message on \c std::cerr
1798  and causing program termination by calling \c abort.
1799*/
1800#endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
1801void ppl_assertion_failed(const char* assertion_text,
1802                          const char* file, unsigned int line,
1803                          const char* function) PPL_WEAK_NORETURN;
1804
1805
1806#ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
1807/*! \brief
1808  Returns \c true if and only if \p x_copy contains \p y_copy.
1809
1810  \note
1811  This is a helper function for debugging purposes, to be used in assertions.
1812  The two arguments are meant to be passed by value, i.e., <em>copied</em>,
1813  so that their representations will not be affected by the containment check.
1814*/
1815#endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
1816template <typename T>
1817bool copy_contains(T x_copy, T y_copy) {
1818  return x_copy.contains(y_copy);
1819}
1820
1821} // namespace Parma_Polyhedra_Library
1822
1823/* Automatically generated from PPL source file ../src/Result_inlines.hh line 28. */
1824
1825namespace Parma_Polyhedra_Library {
1826
1827/*! \ingroup PPL_CXX_interface */
1828inline Result
1829operator&(Result x, Result y) {
1830  const unsigned res = static_cast<unsigned>(x) & static_cast<unsigned>(y);
1831  return static_cast<Result>(res);
1832}
1833
1834/*! \ingroup PPL_CXX_interface */
1835inline Result
1836operator|(Result x, Result y) {
1837  const unsigned res = static_cast<unsigned>(x) | static_cast<unsigned>(y);
1838  return static_cast<Result>(res);
1839}
1840
1841/*! \ingroup PPL_CXX_interface */
1842inline Result
1843operator-(Result x, Result y) {
1844  const Result y_neg = static_cast<Result>(~static_cast<unsigned>(y));
1845  return x & y_neg;
1846}
1847
1848/*! \ingroup PPL_CXX_interface */
1849inline Result_Class
1850result_class(Result r) {
1851  const Result rc = r & static_cast<Result>(VC_MASK);
1852  return static_cast<Result_Class>(rc);
1853}
1854
1855/*! \ingroup PPL_CXX_interface */
1856inline Result_Relation
1857result_relation(Result r) {
1858  const Result rc = r & static_cast<Result>(VR_MASK);
1859  return static_cast<Result_Relation>(rc);
1860}
1861
1862/*! \ingroup PPL_CXX_interface */
1863inline Result
1864result_relation_class(Result r) {
1865  return r & (static_cast<Result>(VR_MASK) | static_cast<Result>(VC_MASK));
1866}
1867
1868inline int
1869result_overflow(Result r) {
1870  switch (result_class(r)) {
1871  case VC_NORMAL:
1872    switch (r) {
1873    case V_LT_INF:
1874      return -1;
1875    case V_GT_SUP:
1876      return 1;
1877    default:
1878      break;
1879    }
1880    break;
1881  case VC_MINUS_INFINITY:
1882    return -1;
1883  case VC_PLUS_INFINITY:
1884    return 1;
1885  default:
1886    break;
1887  }
1888  return 0;
1889}
1890
1891inline bool
1892result_representable(Result r) {
1893  return (r & V_UNREPRESENTABLE) != V_UNREPRESENTABLE;
1894}
1895
1896} // namespace Parma_Polyhedra_Library
1897
1898/* Automatically generated from PPL source file ../src/Result_defs.hh line 194. */
1899
1900/* Automatically generated from PPL source file ../src/fpu_defs.hh line 1. */
1901/* Floating point unit related functions.
1902*/
1903
1904
1905/* Automatically generated from PPL source file ../src/fpu_types.hh line 1. */
1906
1907
1908#ifdef PPL_HAVE_IEEEFP_H
1909#include <ieeefp.h>
1910#endif
1911
1912namespace Parma_Polyhedra_Library {
1913
1914enum fpu_rounding_direction_type {};
1915enum fpu_rounding_control_word_type {};
1916
1917} // namespace Parma_Polyhedra_Library
1918
1919/* Automatically generated from PPL source file ../src/compiler.hh line 1. */
1920/* C++ compiler related stuff.
1921*/
1922
1923
1924#include <cstddef>
1925#include <climits>
1926#include <cassert>
1927
1928namespace Parma_Polyhedra_Library {
1929
1930#ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
1931/*! \brief
1932  No-op macro that allows to avoid unused variable warnings from
1933  the compiler.
1934*/
1935#endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
1936#define PPL_USED(v) (void)(v)
1937
1938#ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
1939/*! \brief
1940  No-op function that force the compiler to store the argument and
1941  to reread it from memory if needed (thus preventing CSE).
1942*/
1943#endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
1944template <typename T>
1945inline void
1946PPL_CC_FLUSH(const T& x) {
1947#if defined(__GNUC__) || defined(__INTEL_COMPILER)
1948  __asm__ __volatile__ ("" : "+m" (const_cast<T&>(x)));
1949#else
1950  // FIXME: is it possible to achieve the same effect in a portable way?
1951  PPL_USED(x);
1952#endif
1953}
1954
1955#ifndef PPL_SUPPRESS_UNINIT_WARNINGS
1956#define PPL_SUPPRESS_UNINIT_WARNINGS 1
1957#endif
1958
1959#ifndef PPL_SUPPRESS_UNINITIALIZED_WARNINGS
1960#define PPL_SUPPRESS_UNINITIALIZED_WARNINGS 1
1961#endif
1962
1963#if PPL_SUPPRESS_UNINITIALIZED_WARNINGS
1964template <typename T>
1965struct Suppress_Uninitialized_Warnings_Type {
1966  typedef T synonym;
1967};
1968
1969#define PPL_UNINITIALIZED(type, name)                                   \
1970  PPL_U(type) PPL_U(name)                                               \
1971  = Suppress_Uninitialized_Warnings_Type<PPL_U(type)>::synonym()
1972#else
1973#define PPL_UNINITIALIZED(type, name)           \
1974  PPL_U(type) name
1975#endif
1976
1977#define sizeof_to_bits(size)                    \
1978  ((size) * static_cast<std::size_t>(CHAR_BIT))
1979
1980#if !defined(__GNUC__)
1981
1982inline unsigned int
1983clz32(uint32_t w) {
1984  unsigned int r = 31;
1985  if ((w & 0xffff0000U) != 0) {
1986    w >>= 16;
1987    r -= 16;
1988  }
1989  if ((w & 0xff00U) != 0) {
1990    w >>= 8;
1991    r -= 8;
1992  }
1993  if ((w & 0xf0U) != 0) {
1994    w >>= 4;
1995    r -= 4;
1996  }
1997  if ((w & 0xcU) != 0) {
1998    w >>= 2;
1999    r -= 2;
2000  }
2001  if ((w & 0x2U) != 0) {
2002    r -= 1;
2003  }
2004  return r;
2005}
2006
2007inline unsigned int
2008clz64(uint64_t w) {
2009  if ((w & 0xffffffff00000000ULL) == 0) {
2010    return clz32(static_cast<uint32_t>(w)) + 32;
2011  }
2012  else {
2013    return clz32(static_cast<uint32_t>(w >> 32));
2014  }
2015}
2016
2017inline unsigned int
2018ctz32(uint32_t w) {
2019  static const unsigned int mod37_table[] = {
2020    32, 0, 1, 26, 2, 23, 27, 0, 3, 16, 24, 30, 28, 11, 0, 13,
2021    4, 7, 17, 0, 25, 22, 31, 15, 29, 10, 12, 6, 0, 21, 14, 9,
2022    5, 20, 8, 19, 18
2023  };
2024  return mod37_table[(w & -w) % 37];
2025}
2026
2027inline unsigned int
2028ctz64(uint64_t w) {
2029  if ((w & 0x00000000ffffffffULL) == 0) {
2030    return ctz32(static_cast<uint32_t>(w >> 32)) + 32;
2031  }
2032  else {
2033    return ctz32(static_cast<uint32_t>(w));
2034  }
2035}
2036
2037#endif
2038
2039inline unsigned int
2040clz(unsigned int u) {
2041  assert(u != 0);
2042#if defined(__GNUC__)
2043  return static_cast<unsigned int>(__builtin_clz(u));
2044#elif PPL_SIZEOF_INT == 4
2045  return clz32(u);
2046#elif PPL_SIZEOF_INT == 8
2047  return clz64(u);
2048#else
2049  #error "Unsupported unsigned int size"
2050#endif
2051}
2052
2053inline unsigned int
2054clz(unsigned long ul) {
2055  assert(ul != 0);
2056#if defined(__GNUC__)
2057  return static_cast<unsigned int>(__builtin_clzl(ul));
2058#elif PPL_SIZEOF_LONG == 4
2059  return clz32(ul);
2060#elif PPL_SIZEOF_LONG == 8
2061  return clz64(ul);
2062#else
2063  #error "Unsupported unsigned long size"
2064#endif
2065}
2066
2067inline unsigned int
2068clz(unsigned long long ull) {
2069  assert(ull != 0);
2070#if defined(__GNUC__)
2071  return static_cast<unsigned int>(__builtin_clzll(ull));
2072#elif PPL_SIZEOF_LONG_LONG == 4
2073  return clz32(ull);
2074#elif PPL_SIZEOF_LONG_LONG == 8
2075  return clz64(ull);
2076#else
2077  #error "Unsupported unsigned long long size"
2078#endif
2079}
2080
2081
2082inline unsigned int
2083ctz(unsigned int u) {
2084  assert(u != 0);
2085#if defined(__GNUC__)
2086  return static_cast<unsigned int>(__builtin_ctz(u));
2087#elif PPL_SIZEOF_INT == 4
2088  return ctz32(u);
2089#elif PPL_SIZEOF_INT == 8
2090  return ctz64(u);
2091#else
2092  #error "Unsupported unsigned int size"
2093#endif
2094}
2095
2096inline unsigned int
2097ctz(unsigned long ul) {
2098  assert(ul != 0);
2099#if defined(__GNUC__)
2100  return static_cast<unsigned int>(__builtin_ctzl(ul));
2101#elif PPL_SIZEOF_LONG == 4
2102  return ctz32(ul);
2103#elif PPL_SIZEOF_LONG == 8
2104  return ctz64(ul);
2105#else
2106  #error "Unsupported unsigned long size"
2107#endif
2108}
2109
2110inline unsigned int
2111ctz(unsigned long long ull) {
2112  assert(ull != 0);
2113#if defined(__GNUC__)
2114  return static_cast<unsigned int>(__builtin_ctzll(ull));
2115#elif PPL_SIZEOF_LONG_LONG == 4
2116  return ctz32(ull);
2117#elif PPL_SIZEOF_LONG_LONG == 8
2118  return ctz64(ull);
2119#else
2120  #error "Unsupported unsigned long long size"
2121#endif
2122}
2123
2124} // namespace Parma_Polyhedra_Library
2125
2126/* Automatically generated from PPL source file ../src/fpu_defs.hh line 29. */
2127
2128namespace Parma_Polyhedra_Library {
2129
2130//! \name Functions Controlling Floating Point Unit
2131//@{
2132
2133//! Initializes the FPU control functions.
2134void
2135fpu_initialize_control_functions();
2136
2137//! Returns the current FPU rounding direction.
2138fpu_rounding_direction_type
2139fpu_get_rounding_direction();
2140
2141//! Sets the FPU rounding direction to \p dir.
2142void
2143fpu_set_rounding_direction(fpu_rounding_direction_type dir);
2144
2145/*! \brief
2146  Sets the FPU rounding direction to \p dir and returns the rounding
2147  control word previously in use.
2148*/
2149fpu_rounding_control_word_type
2150fpu_save_rounding_direction(fpu_rounding_direction_type dir);
2151
2152/*! \brief
2153  Sets the FPU rounding direction to \p dir, clears the <EM>inexact
2154  computation</EM> status, and returns the rounding control word
2155  previously in use.
2156*/
2157fpu_rounding_control_word_type
2158fpu_save_rounding_direction_reset_inexact(fpu_rounding_direction_type dir);
2159
2160//! Restores the FPU rounding rounding control word to \p cw.
2161void
2162fpu_restore_rounding_direction(fpu_rounding_control_word_type w);
2163
2164//! Clears the <EM>inexact computation</EM> status.
2165void
2166fpu_reset_inexact();
2167
2168/*! \brief
2169  Queries the <EM>inexact computation</EM> status.
2170
2171  Returns 0 if the computation was definitely exact, 1 if it was
2172  definitely inexact, -1 if definite exactness information is unavailable.
2173*/
2174int
2175fpu_check_inexact();
2176
2177//@} // Functions Controlling Floating Point Unit
2178
2179} // namespace Parma_Polyhedra_Library
2180
2181#if PPL_CAN_CONTROL_FPU
2182
2183#if defined(__i386__) && (defined(__GNUC__) || defined(__INTEL_COMPILER))
2184/* Automatically generated from PPL source file ../src/fpu-ia32_inlines.hh line 1. */
2185/* IA-32 floating point unit inline related functions.
2186*/
2187
2188
2189#include <csetjmp>
2190#include <csignal>
2191
2192#define FPU_INVALID       0x01
2193#define FPU_DIVBYZERO     0x04
2194#define FPU_OVERFLOW      0x08
2195#define FPU_UNDERFLOW     0x10
2196#define FPU_INEXACT       0x20
2197
2198#define FPU_ALL_EXCEPT \
2199  (FPU_INEXACT | FPU_DIVBYZERO | FPU_UNDERFLOW | FPU_OVERFLOW | FPU_INVALID)
2200
2201#define PPL_FPU_TONEAREST     0
2202#define PPL_FPU_DOWNWARD      0x400
2203#define PPL_FPU_UPWARD        0x800
2204#define PPL_FPU_TOWARDZERO    0xc00
2205
2206#define FPU_ROUNDING_MASK 0xc00
2207
2208#define SSE_INEXACT       0x20
2209
2210#define PPL_FPU_CONTROL_DEFAULT_BASE 0x37f
2211#define PPL_SSE_CONTROL_DEFAULT_BASE 0x1f80
2212
2213// This MUST be congruent with the definition of ROUND_DIRECT
2214#define PPL_FPU_CONTROL_DEFAULT \
2215  (PPL_FPU_CONTROL_DEFAULT_BASE | PPL_FPU_UPWARD)
2216#define PPL_SSE_CONTROL_DEFAULT \
2217  (PPL_SSE_CONTROL_DEFAULT_BASE | (PPL_FPU_UPWARD << 3))
2218
2219namespace Parma_Polyhedra_Library {
2220
2221typedef struct {
2222  unsigned short control_word;
2223  unsigned short unused1;
2224  unsigned short status_word;
2225  unsigned short unused2;
2226  unsigned short tags;
2227  unsigned short unused3;
2228  unsigned int eip;
2229  unsigned short cs_selector;
2230  unsigned int opcode:11;
2231  unsigned int unused4:5;
2232  unsigned int data_offset;
2233  unsigned short data_selector;
2234  unsigned short unused5;
2235} ia32_fenv_t;
2236
2237inline int
2238fpu_get_control() {
2239  unsigned short cw;
2240  __asm__ __volatile__ ("fnstcw %0" : "=m" (*&cw) : : "memory");
2241  return cw;
2242}
2243
2244inline void
2245fpu_set_control(int c) {
2246  unsigned short cw = static_cast<unsigned short>(c);
2247  __asm__ __volatile__ ("fldcw %0" : : "m" (*&cw) : "memory");
2248}
2249
2250inline int
2251fpu_get_status() {
2252  unsigned short sw;
2253  __asm__ __volatile__ ("fnstsw %0" : "=a" (sw) : : "memory");
2254  return sw;
2255}
2256
2257inline void
2258fpu_clear_status(unsigned short bits) {
2259  /* There is no fldsw instruction */
2260  ia32_fenv_t env;
2261  __asm__ __volatile__ ("fnstenv %0" : "=m" (env));
2262  env.status_word = static_cast<unsigned short>(env.status_word & ~bits);
2263  __asm__ __volatile__ ("fldenv %0" : : "m" (env) : "memory");
2264}
2265
2266inline void
2267fpu_clear_exceptions() {
2268  __asm__ __volatile__ ("fnclex" : /* No outputs.  */ : : "memory");
2269}
2270
2271#ifdef PPL_FPMATH_MAY_USE_SSE
2272inline void
2273sse_set_control(unsigned int cw) {
2274  __asm__ __volatile__ ("ldmxcsr %0" : : "m" (*&cw) : "memory");
2275}
2276
2277inline unsigned int
2278sse_get_control() {
2279  unsigned int cw;
2280  __asm__ __volatile__ ("stmxcsr %0" : "=m" (*&cw) : : "memory");
2281  return cw;
2282}
2283#endif
2284
2285inline void
2286fpu_initialize_control_functions() {
2287#ifdef PPL_FPMATH_MAY_USE_SSE
2288  extern void detect_sse_unit();
2289  detect_sse_unit();
2290#endif
2291}
2292
2293inline fpu_rounding_direction_type
2294fpu_get_rounding_direction() {
2295  return static_cast<fpu_rounding_direction_type>(fpu_get_control() & FPU_ROUNDING_MASK);
2296}
2297
2298inline void
2299fpu_set_rounding_direction(fpu_rounding_direction_type dir) {
2300#ifdef PPL_FPMATH_MAY_USE_387
2301  fpu_set_control(PPL_FPU_CONTROL_DEFAULT_BASE | dir);
2302#endif
2303#ifdef PPL_FPMATH_MAY_USE_SSE
2304  extern bool have_sse_unit;
2305  if (have_sse_unit)
2306    sse_set_control(PPL_SSE_CONTROL_DEFAULT_BASE | (dir << 3));
2307#endif
2308}
2309
2310inline fpu_rounding_control_word_type
2311fpu_save_rounding_direction(fpu_rounding_direction_type dir) {
2312#ifdef PPL_FPMATH_MAY_USE_387
2313  fpu_set_control(PPL_FPU_CONTROL_DEFAULT_BASE | dir);
2314#endif
2315#ifdef PPL_FPMATH_MAY_USE_SSE
2316  extern bool have_sse_unit;
2317  if (have_sse_unit)
2318    sse_set_control(PPL_SSE_CONTROL_DEFAULT_BASE | (dir << 3));
2319#endif
2320  return static_cast<fpu_rounding_control_word_type>(0);
2321}
2322
2323inline void
2324fpu_reset_inexact() {
2325#ifdef PPL_FPMATH_MAY_USE_387
2326  fpu_clear_exceptions();
2327#endif
2328#ifdef PPL_FPMATH_MAY_USE_SSE
2329  // NOTE: on entry to this function the current rounding mode
2330  // has to be the default one.
2331  extern bool have_sse_unit;
2332  if (have_sse_unit) {
2333    sse_set_control(PPL_SSE_CONTROL_DEFAULT);
2334  }
2335#endif
2336}
2337
2338inline void
2339fpu_restore_rounding_direction(fpu_rounding_control_word_type) {
2340#ifdef PPL_FPMATH_MAY_USE_387
2341  fpu_set_control(PPL_FPU_CONTROL_DEFAULT);
2342#endif
2343#ifdef PPL_FPMATH_MAY_USE_SSE
2344  extern bool have_sse_unit;
2345  if (have_sse_unit) {
2346    sse_set_control(PPL_SSE_CONTROL_DEFAULT);
2347  }
2348#endif
2349}
2350
2351inline int
2352fpu_check_inexact() {
2353#ifdef PPL_FPMATH_MAY_USE_387
2354  if (fpu_get_status() & FPU_INEXACT) {
2355    return 1;
2356  }
2357#endif
2358#ifdef PPL_FPMATH_MAY_USE_SSE
2359  extern bool have_sse_unit;
2360  if (have_sse_unit && (sse_get_control() & SSE_INEXACT)) {
2361    return 1;
2362  }
2363#endif
2364  return 0;
2365}
2366
2367} // namespace Parma_Polyhedra_Library
2368
2369/* Automatically generated from PPL source file ../src/fpu_defs.hh line 87. */
2370#elif defined(PPL_HAVE_IEEEFP_H)                                        \
2371  && (defined(__sparc)                                                  \
2372      || defined(sparc)                                                 \
2373      || defined(__sparc__))
2374/* Automatically generated from PPL source file ../src/fpu-sparc_inlines.hh line 1. */
2375/* SPARC floating point unit related functions.
2376*/
2377
2378
2379#ifdef PPL_HAVE_IEEEFP_H
2380#include <ieeefp.h>
2381
2382#define PPL_FPU_TONEAREST  ((int) FP_RN)
2383#define PPL_FPU_UPWARD     ((int) FP_RP)
2384#define PPL_FPU_DOWNWARD   ((int) FP_RM)
2385#define PPL_FPU_TOWARDZERO ((int) FP_RZ)
2386
2387namespace Parma_Polyhedra_Library {
2388
2389inline void
2390fpu_initialize_control_functions() {
2391}
2392
2393inline fpu_rounding_direction_type
2394fpu_get_rounding_direction() {
2395  return static_cast<fpu_rounding_direction_type>(fpgetround());
2396}
2397
2398inline void
2399fpu_set_rounding_direction(fpu_rounding_direction_type dir) {
2400  fpsetround((fp_rnd) dir);
2401}
2402
2403inline fpu_rounding_control_word_type
2404fpu_save_rounding_direction(fpu_rounding_direction_type dir) {
2405  return static_cast<fpu_rounding_control_word_type>(fpsetround((fp_rnd) dir));
2406}
2407
2408inline void
2409fpu_reset_inexact() {
2410  fp_except except = fpgetmask();
2411  except &= ~FP_X_IMP;
2412  fpsetmask(except);
2413}
2414
2415inline void
2416fpu_restore_rounding_direction(fpu_rounding_control_word_type w) {
2417  fpsetround((fp_rnd) w);
2418}
2419
2420inline int
2421fpu_check_inexact() {
2422  return (fpgetmask() & FP_X_IMP) ? 1 : 0;
2423}
2424
2425} // namespace Parma_Polyhedra_Library
2426
2427#endif // !defined(PPL_HAVE_IEEEFP_H)
2428
2429/* Automatically generated from PPL source file ../src/fpu_defs.hh line 92. */
2430#elif defined(PPL_HAVE_FENV_H)
2431/* Automatically generated from PPL source file ../src/fpu-c99_inlines.hh line 1. */
2432/* C99 Floating point unit related functions.
2433*/
2434
2435
2436#ifdef PPL_HAVE_FENV_H
2437#include <fenv.h>
2438#include <stdexcept>
2439
2440#ifdef FE_TONEAREST
2441#define PPL_FPU_TONEAREST FE_TONEAREST
2442#endif
2443#ifdef FE_UPWARD
2444#define PPL_FPU_UPWARD FE_UPWARD
2445#endif
2446#ifdef FE_DOWNWARD
2447#define PPL_FPU_DOWNWARD FE_DOWNWARD
2448#endif
2449#ifdef FE_TOWARDZERO
2450#define PPL_FPU_TOWARDZERO FE_TOWARDZERO
2451#endif
2452
2453namespace Parma_Polyhedra_Library {
2454
2455inline void
2456fpu_initialize_control_functions() {
2457  const int old = fegetround();
2458  if (fesetround(PPL_FPU_DOWNWARD) != 0
2459      || fesetround(PPL_FPU_UPWARD) != 0
2460      || fesetround(old) != 0) {
2461    throw std::logic_error("PPL configuration error:"
2462                           " PPL_CAN_CONTROL_FPU evaluates to true,"
2463                           " but fesetround() returns nonzero.");
2464  }
2465}
2466
2467inline fpu_rounding_direction_type
2468fpu_get_rounding_direction() {
2469  return static_cast<fpu_rounding_direction_type>(fegetround());
2470}
2471
2472inline void
2473fpu_set_rounding_direction(fpu_rounding_direction_type dir) {
2474  fesetround(dir);
2475}
2476
2477inline fpu_rounding_control_word_type
2478fpu_save_rounding_direction(fpu_rounding_direction_type dir) {
2479  const fpu_rounding_control_word_type old
2480    = static_cast<fpu_rounding_control_word_type>(fegetround());
2481  fesetround(dir);
2482  return old;
2483}
2484
2485inline void
2486fpu_reset_inexact() {
2487#if PPL_CXX_SUPPORTS_IEEE_INEXACT_FLAG
2488  feclearexcept(FE_INEXACT);
2489#endif
2490}
2491
2492inline void
2493fpu_restore_rounding_direction(fpu_rounding_control_word_type w) {
2494  fesetround(w);
2495}
2496
2497inline int
2498fpu_check_inexact() {
2499#if PPL_CXX_SUPPORTS_IEEE_INEXACT_FLAG
2500  return fetestexcept(FE_INEXACT) != 0 ? 1 : 0;
2501#else
2502  return -1;
2503#endif
2504}
2505
2506} // namespace Parma_Polyhedra_Library
2507
2508#endif // !defined(PPL_HAVE_FENV_H)
2509
2510/* Automatically generated from PPL source file ../src/fpu_defs.hh line 94. */
2511#else
2512#error "PPL_CAN_CONTROL_FPU evaluates to true: why?"
2513#endif
2514
2515#else // !PPL_CAN_CONTROL_FPU
2516
2517/* Automatically generated from PPL source file ../src/fpu-none_inlines.hh line 1. */
2518/* Null floating point unit related functions.
2519*/
2520
2521
2522#include <stdexcept>
2523
2524namespace Parma_Polyhedra_Library {
2525
2526inline void
2527fpu_initialize_control_functions() {
2528  throw std::logic_error("PPL::fpu_initialize_control_functions():"
2529                         " cannot control the FPU");
2530}
2531
2532inline fpu_rounding_direction_type
2533fpu_get_rounding_direction() {
2534  throw std::logic_error("PPL::fpu_get_rounding_direction():"
2535                         " cannot control the FPU");
2536}
2537
2538inline void
2539fpu_set_rounding_direction(int) {
2540  throw std::logic_error("PPL::fpu_set_rounding_direction():"
2541                         " cannot control the FPU");
2542}
2543
2544inline int
2545fpu_save_rounding_direction(int) {
2546  throw std::logic_error("PPL::fpu_save_rounding_direction():"
2547                         " cannot control the FPU");
2548}
2549
2550inline void
2551fpu_reset_inexact() {
2552  throw std::logic_error("PPL::fpu_reset_inexact():"
2553                         " cannot control the FPU");
2554}
2555
2556inline void
2557fpu_restore_rounding_direction(int) {
2558  throw std::logic_error("PPL::fpu_restore_rounding_direction():"
2559                         " cannot control the FPU");
2560}
2561
2562inline int
2563fpu_check_inexact() {
2564  throw std::logic_error("PPL::fpu_check_inexact():"
2565                         " cannot control the FPU");
2566}
2567
2568} // namespace Parma_Polyhedra_Library
2569
2570/* Automatically generated from PPL source file ../src/fpu_defs.hh line 101. */
2571
2572#endif // !PPL_CAN_CONTROL_FPU
2573
2574/* Automatically generated from PPL source file ../src/Rounding_Dir_defs.hh line 29. */
2575
2576namespace Parma_Polyhedra_Library {
2577
2578//! Rounding directions for arithmetic computations.
2579/*! \ingroup PPL_CXX_interface */
2580enum Rounding_Dir {
2581  /*! \hideinitializer
2582    Round toward \f$-\infty\f$.
2583  */
2584  ROUND_DOWN = 0U,
2585
2586  /*! \hideinitializer
2587    Round toward \f$+\infty\f$.
2588  */
2589  ROUND_UP = 1U,
2590
2591  /*! \hideinitializer
2592    Rounding is delegated to lower level. Result info is evaluated lazily.
2593  */
2594  ROUND_IGNORE = 6U,
2595  ROUND_NATIVE = ROUND_IGNORE,
2596
2597  /*! \hideinitializer
2598    Rounding is not needed: client code must ensure that the operation
2599    result is exact and representable in the destination type.
2600    Result info is evaluated lazily.
2601  */
2602  ROUND_NOT_NEEDED = 7U,
2603
2604  ROUND_DIRECT = ROUND_UP,
2605  ROUND_INVERSE = ROUND_DOWN,
2606
2607  ROUND_DIR_MASK = 7U,
2608
2609  /*! \hideinitializer
2610    The client code is willing to pay an extra price to know the exact
2611    relation between the exact result and the computed one.
2612   */
2613  ROUND_STRICT_RELATION = 8U,
2614
2615  ROUND_CHECK = ROUND_DIRECT | ROUND_STRICT_RELATION
2616};
2617
2618//! \name Functions Inspecting and/or Combining Rounding_Dir Values
2619//@{
2620
2621/*! \ingroup PPL_CXX_interface */
2622Rounding_Dir operator&(Rounding_Dir x, Rounding_Dir y);
2623
2624/*! \ingroup PPL_CXX_interface */
2625Rounding_Dir operator|(Rounding_Dir x, Rounding_Dir y);
2626
2627/*! \ingroup PPL_CXX_interface \brief
2628  Returns the inverse rounding mode of \p dir,
2629  <CODE>ROUND_IGNORE</CODE> being the inverse of itself.
2630*/
2631Rounding_Dir inverse(Rounding_Dir dir);
2632
2633/*! \ingroup PPL_CXX_interface */
2634Rounding_Dir round_dir(Rounding_Dir dir);
2635
2636/*! \ingroup PPL_CXX_interface */
2637bool round_down(Rounding_Dir dir);
2638
2639/*! \ingroup PPL_CXX_interface */
2640bool round_up(Rounding_Dir dir);
2641
2642/*! \ingroup PPL_CXX_interface */
2643bool round_ignore(Rounding_Dir dir);
2644
2645/*! \ingroup PPL_CXX_interface */
2646bool round_not_needed(Rounding_Dir dir);
2647
2648/*! \ingroup PPL_CXX_interface */
2649bool round_not_requested(Rounding_Dir dir);
2650
2651/*! \ingroup PPL_CXX_interface */
2652bool round_direct(Rounding_Dir dir);
2653
2654/*! \ingroup PPL_CXX_interface */
2655bool round_inverse(Rounding_Dir dir);
2656
2657/*! \ingroup PPL_CXX_interface */
2658bool round_strict_relation(Rounding_Dir dir);
2659
2660/*! \ingroup PPL_CXX_interface */
2661fpu_rounding_direction_type round_fpu_dir(Rounding_Dir dir);
2662
2663//@} // Functions Inspecting and/or Combining Rounding_Dir Values
2664
2665} // namespace Parma_Polyhedra_Library
2666
2667/* Automatically generated from PPL source file ../src/Rounding_Dir_inlines.hh line 1. */
2668/* Inline functions operating on enum Rounding_Dir values.
2669*/
2670
2671
2672/* Automatically generated from PPL source file ../src/Rounding_Dir_inlines.hh line 28. */
2673
2674namespace Parma_Polyhedra_Library {
2675
2676/*! \ingroup PPL_CXX_interface */
2677inline Rounding_Dir
2678operator&(Rounding_Dir x, Rounding_Dir y) {
2679  const unsigned res = static_cast<unsigned>(x) & static_cast<unsigned>(y);
2680  return static_cast<Rounding_Dir>(res);
2681}
2682
2683/*! \ingroup PPL_CXX_interface */
2684inline Rounding_Dir
2685operator|(Rounding_Dir x, Rounding_Dir y) {
2686  const unsigned res = static_cast<unsigned>(x) | static_cast<unsigned>(y);
2687  return static_cast<Rounding_Dir>(res);
2688}
2689
2690/*! \ingroup PPL_CXX_interface */
2691inline Rounding_Dir
2692round_dir(Rounding_Dir dir) {
2693  return dir & ROUND_DIR_MASK;
2694}
2695
2696/*! \ingroup PPL_CXX_interface */
2697inline bool
2698round_down(Rounding_Dir dir) {
2699  return round_dir(dir) == ROUND_DOWN;
2700}
2701
2702/*! \ingroup PPL_CXX_interface */
2703inline bool
2704round_up(Rounding_Dir dir) {
2705  return round_dir(dir) == ROUND_UP;
2706}
2707
2708/*! \ingroup PPL_CXX_interface */
2709inline bool
2710round_ignore(Rounding_Dir dir) {
2711  return round_dir(dir) == ROUND_IGNORE;
2712}
2713
2714/*! \ingroup PPL_CXX_interface */
2715inline bool
2716round_not_needed(Rounding_Dir dir) {
2717  return round_dir(dir) == ROUND_NOT_NEEDED;
2718}
2719
2720/*! \ingroup PPL_CXX_interface */
2721inline bool
2722round_not_requested(Rounding_Dir dir) {
2723  return round_dir(dir) == ROUND_IGNORE || round_dir(dir) == ROUND_NOT_NEEDED;
2724}
2725
2726/*! \ingroup PPL_CXX_interface */
2727inline bool
2728round_direct(Rounding_Dir dir) {
2729  return round_dir(dir) == ROUND_DIRECT;
2730}
2731
2732/*! \ingroup PPL_CXX_interface */
2733inline bool
2734round_inverse(Rounding_Dir dir) {
2735  return round_dir(dir) == ROUND_INVERSE;
2736}
2737
2738/*! \ingroup PPL_CXX_interface */
2739inline bool
2740round_strict_relation(Rounding_Dir dir) {
2741  return (dir & ROUND_STRICT_RELATION) == ROUND_STRICT_RELATION;
2742}
2743
2744#if PPL_CAN_CONTROL_FPU
2745
2746/*! \ingroup PPL_CXX_interface */
2747inline fpu_rounding_direction_type
2748round_fpu_dir(Rounding_Dir dir) {
2749  switch (round_dir(dir)) {
2750  case ROUND_UP:
2751    return static_cast<fpu_rounding_direction_type>(PPL_FPU_UPWARD);
2752  case ROUND_DOWN:
2753    return static_cast<fpu_rounding_direction_type>(PPL_FPU_DOWNWARD);
2754  case ROUND_IGNORE: // Fall through.
2755  default:
2756    PPL_UNREACHABLE;
2757    return static_cast<fpu_rounding_direction_type>(PPL_FPU_UPWARD);
2758  }
2759}
2760
2761#undef PPL_FPU_DOWNWARD
2762#undef PPL_FPU_TONEAREST
2763#undef PPL_FPU_TOWARDZERO
2764#undef PPL_FPU_UPWARD
2765
2766#endif
2767
2768/*! \ingroup PPL_CXX_interface */
2769inline Rounding_Dir
2770inverse(Rounding_Dir dir) {
2771  switch (round_dir(dir)) {
2772  case ROUND_UP:
2773    return ROUND_DOWN | (dir & ROUND_STRICT_RELATION);
2774  case ROUND_DOWN:
2775    return ROUND_UP | (dir & ROUND_STRICT_RELATION);
2776  case ROUND_IGNORE:
2777    return dir;
2778  default:
2779    PPL_UNREACHABLE;
2780    return dir;
2781  }
2782}
2783
2784} // namespace Parma_Polyhedra_Library
2785
2786/* Automatically generated from PPL source file ../src/Rounding_Dir_defs.hh line 122. */
2787
2788
2789/* Automatically generated from PPL source file ../src/Numeric_Format_defs.hh line 1. */
2790/* Numeric format.
2791*/
2792
2793
2794/* Automatically generated from PPL source file ../src/Numeric_Format_defs.hh line 29. */
2795
2796namespace Parma_Polyhedra_Library {
2797
2798class Numeric_Format {
2799};
2800
2801} // namespace Parma_Polyhedra_Library
2802
2803
2804/* Automatically generated from PPL source file ../src/Float_defs.hh line 1. */
2805/* IEC 559 floating point format related functions.
2806*/
2807
2808
2809/* Automatically generated from PPL source file ../src/globals_types.hh line 1. */
2810
2811
2812#include <cstddef>
2813
2814namespace Parma_Polyhedra_Library {
2815
2816//! An unsigned integral type for representing space dimensions.
2817/*! \ingroup PPL_CXX_interface */
2818typedef size_t dimension_type;
2819
2820//! An unsigned integral type for representing memory size in bytes.
2821/*! \ingroup PPL_CXX_interface */
2822typedef size_t memory_size_type;
2823
2824//! Kinds of degenerate abstract elements.
2825/*! \ingroup PPL_CXX_interface */
2826enum Degenerate_Element {
2827  //! The universe element, i.e., the whole vector space.
2828  UNIVERSE,
2829  //! The empty element, i.e., the empty set.
2830  EMPTY
2831};
2832
2833//! Relation symbols.
2834/*! \ingroup PPL_CXX_interface */
2835// This must be kept in sync with Result
2836enum Relation_Symbol {
2837  //! \hideinitializer Equal to.
2838  EQUAL = 1U,
2839  //! \hideinitializer Less than.
2840  LESS_THAN = 2U,
2841  //! \hideinitializer Less than or equal to.
2842  LESS_OR_EQUAL = LESS_THAN | EQUAL,
2843  //! \hideinitializer Greater than.
2844  GREATER_THAN = 4U,
2845  //! \hideinitializer Greater than or equal to.
2846  GREATER_OR_EQUAL = GREATER_THAN | EQUAL,
2847  //! \hideinitializer Not equal to.
2848  NOT_EQUAL = LESS_THAN | GREATER_THAN
2849};
2850
2851//! Complexity pseudo-classes.
2852/*! \ingroup PPL_CXX_interface */
2853enum Complexity_Class {
2854  //! Worst-case polynomial complexity.
2855  POLYNOMIAL_COMPLEXITY,
2856  //! Worst-case exponential complexity but typically polynomial behavior.
2857  SIMPLEX_COMPLEXITY,
2858  //! Any complexity.
2859  ANY_COMPLEXITY
2860};
2861
2862//! Possible optimization modes.
2863/*! \ingroup PPL_CXX_interface */
2864enum Optimization_Mode {
2865  //! Minimization is requested.
2866  MINIMIZATION,
2867  //! Maximization is requested.
2868  MAXIMIZATION
2869};
2870
2871/*! \ingroup PPL_CXX_interface \brief
2872  Widths of bounded integer types.
2873
2874  See the section on
2875  \ref Approximating_Bounded_Integers "approximating bounded integers".
2876*/
2877enum Bounded_Integer_Type_Width {
2878  //! \hideinitializer 8 bits.
2879  BITS_8 = 8,
2880
2881  //! \hideinitializer 16 bits.
2882  BITS_16 = 16,
2883
2884  //! \hideinitializer 32 bits.
2885  BITS_32 = 32,
2886
2887  //! \hideinitializer 64 bits.
2888  BITS_64 = 64,
2889
2890  //! \hideinitializer 128 bits.
2891  BITS_128 = 128
2892};
2893
2894/*! \ingroup PPL_CXX_interface \brief
2895  Representation of bounded integer types.
2896
2897  See the section on
2898  \ref Approximating_Bounded_Integers "approximating bounded integers".
2899*/
2900enum Bounded_Integer_Type_Representation {
2901  //! Unsigned binary.
2902  UNSIGNED,
2903
2904  /*! \brief
2905    Signed binary where negative values are represented by the two's
2906    complement of the absolute value.
2907  */
2908  SIGNED_2_COMPLEMENT
2909};
2910
2911/*! \ingroup PPL_CXX_interface \brief
2912  Overflow behavior of bounded integer types.
2913
2914  See the section on
2915  \ref Approximating_Bounded_Integers "approximating bounded integers".
2916*/
2917enum Bounded_Integer_Type_Overflow {
2918  /*! \brief
2919    On overflow, wrapping takes place.
2920
2921    This means that, for a \f$w\f$-bit bounded integer, the computation
2922    happens modulo \f$2^w\f$.
2923  */
2924  OVERFLOW_WRAPS,
2925
2926  /*! \brief
2927    On overflow, the result is undefined.
2928
2929    This simply means that the result of the operation resulting in an
2930    overflow can take any value.
2931
2932    \note
2933    Even though something more serious can happen in the system
2934    being analyzed ---due to, e.g., C's undefined behavior---, here we
2935    are only concerned with the results of arithmetic operations.
2936    It is the responsibility of the analyzer to ensure that other
2937    manifestations of undefined behavior are conservatively approximated.
2938  */
2939  OVERFLOW_UNDEFINED,
2940
2941  /*! \brief
2942    Overflow is impossible.
2943
2944    This is for the analysis of languages where overflow is trapped
2945    before it affects the state, for which, thus, any indication that
2946    an overflow may have affected the state is necessarily due to
2947    the imprecision of the analysis.
2948  */
2949  OVERFLOW_IMPOSSIBLE
2950};
2951
2952/*! \ingroup PPL_CXX_interface \brief
2953  Possible representations of coefficient sequences (i.e. linear expressions
2954  and more complex objects containing linear expressions, e.g. Constraints,
2955  Generators, etc.).
2956*/
2957enum Representation {
2958  /*! \brief
2959    Dense representation: the coefficient sequence is represented as a vector
2960    of coefficients, including the zero coefficients.
2961    If there are only a few nonzero coefficients, this representation is
2962    faster and also uses a bit less memory.
2963  */
2964  DENSE,
2965
2966  /*! \brief
2967    Sparse representation: only the nonzero coefficient are stored.
2968    If there are many nonzero coefficients, this improves memory consumption
2969    and run time (both because there is less data to process in O(n)
2970    operations and because finding zeroes/nonzeroes is much faster since
2971    zeroes are not stored at all, so any stored coefficient is nonzero).
2972  */
2973  SPARSE
2974};
2975
2976/*! \ingroup PPL_CXX_interface \brief
2977  Floating point formats known to the library.
2978
2979  The parameters of each format are defined by a specific struct
2980  in file Float_defs.hh.  See the section on \ref floating_point
2981  "Analysis of floating point computations" for more information.
2982*/
2983enum Floating_Point_Format {
2984  //! IEEE 754 half precision, 16 bits (5 exponent, 10 mantissa).
2985  IEEE754_HALF,
2986
2987  //! IEEE 754 single precision, 32 bits (8 exponent, 23 mantissa).
2988  IEEE754_SINGLE,
2989
2990  //! IEEE 754 double precision, 64 bits (11 exponent, 52 mantissa).
2991  IEEE754_DOUBLE,
2992
2993  //! IEEE 754 quad precision, 128 bits (15 exponent, 112 mantissa).
2994  IEEE754_QUAD,
2995
2996  //! Intel double extended precision, 80 bits (15 exponent, 64 mantissa)
2997  INTEL_DOUBLE_EXTENDED,
2998
2999  //! IBM single precision, 32 bits (7 exponent, 24 mantissa).
3000  IBM_SINGLE,
3001
3002  //! IBM double precision, 64 bits (7 exponent, 56 mantissa).
3003  IBM_DOUBLE
3004};
3005
3006struct Weightwatch_Traits;
3007
3008} // namespace Parma_Polyhedra_Library
3009
3010/* Automatically generated from PPL source file ../src/Concrete_Expression_types.hh line 1. */
3011
3012
3013namespace Parma_Polyhedra_Library {
3014
3015/*
3016  NOTE: Doxygen seems to ignore documentation blocks attached to
3017  template class declarations that are not provided with a definition.
3018  This justifies (here below) the explicit use of Doxygen command \class.
3019*/
3020
3021/*! \brief The base class of all concrete expressions.
3022  \class Parma_Polyhedra_Library::Concrete_Expression
3023*/
3024template <typename Target>
3025class Concrete_Expression;
3026
3027/*! \brief A binary operator applied to two concrete expressions.
3028  \class Parma_Polyhedra_Library::Binary_Operator
3029*/
3030template <typename Target>
3031class Binary_Operator;
3032
3033/*! \brief A unary operator applied to one concrete expression.
3034  \class Parma_Polyhedra_Library::Unary_Operator
3035*/
3036template <typename Target>
3037class Unary_Operator;
3038
3039/*! \brief A cast operator converting one concrete expression to some type.
3040  \class Parma_Polyhedra_Library::Cast_Operator
3041*/
3042template <typename Target>
3043class Cast_Operator;
3044
3045/*! \brief An integer constant concrete expression.
3046  \class Parma_Polyhedra_Library::Integer_Constant
3047*/
3048template <typename Target>
3049class Integer_Constant;
3050
3051/*! \brief A floating-point constant concrete expression.
3052  \class Parma_Polyhedra_Library::Floating_Point_Constant
3053*/
3054template <typename Target>
3055class Floating_Point_Constant;
3056
3057/*! \brief A concrete expression representing a reference to some approximable.
3058  \class Parma_Polyhedra_Library::Approximable_Reference
3059*/
3060template <typename Target>
3061class Approximable_Reference;
3062
3063class Concrete_Expression_Type;
3064
3065/*! \brief
3066  Encodes the kind of concrete expression.
3067
3068  The values should be defined by the particular instance
3069  and uniquely identify one of: Binary_Operator, Unary_Operator,
3070  Cast_Operator, Integer_Constant, Floating_Point_Constant, or
3071  Approximable_Reference.  For example, the Binary_Operator kind
3072  integer constant should be defined by an instance as the member
3073  <CODE>Binary_Operator\<T\>::%KIND</CODE>.
3074*/
3075typedef int Concrete_Expression_Kind;
3076
3077/*! \brief
3078  Encodes a binary operator of concrete expressions.
3079
3080  The values should be uniquely defined by the particular instance and
3081  named: ADD, SUB, MUL, DIV, REM, BAND, BOR, BXOR, LSHIFT, RSHIFT.
3082*/
3083typedef int Concrete_Expression_BOP;
3084
3085/*! \brief
3086  Encodes a unary operator of concrete expressions.
3087
3088  The values should be uniquely defined by the particular instance and
3089  named: PLUS, MINUS, BNOT.
3090*/
3091typedef int Concrete_Expression_UOP;
3092
3093} // namespace Parma_Polyhedra_Library
3094
3095/* Automatically generated from PPL source file ../src/Variable_types.hh line 1. */
3096
3097
3098namespace Parma_Polyhedra_Library {
3099
3100class Variable;
3101
3102} // namespace Parma_Polyhedra_Library
3103
3104/* Automatically generated from PPL source file ../src/Linear_Form_types.hh line 1. */
3105
3106
3107namespace Parma_Polyhedra_Library {
3108
3109template <typename C>
3110class Linear_Form;
3111
3112} // namespace Parma_Polyhedra_Library
3113
3114/* Automatically generated from PPL source file ../src/Float_defs.hh line 33. */
3115#include <set>
3116#include <cmath>
3117#include <map>
3118#include <gmp.h>
3119
3120#ifdef NAN
3121#define PPL_NAN NAN
3122#else
3123#define PPL_NAN (HUGE_VAL - HUGE_VAL)
3124#endif
3125
3126namespace Parma_Polyhedra_Library {
3127
3128#ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
3129/*! \ingroup PPL_CXX_interface */
3130#endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
3131struct float_ieee754_half {
3132  uint16_t word;
3133  static const uint16_t SGN_MASK = 0x8000U;
3134  static const uint16_t EXP_MASK = 0xfc00U;
3135  static const uint16_t WRD_MAX = 0x7bffU;
3136  static const uint16_t POS_INF = 0x7c00U;
3137  static const uint16_t NEG_INF = 0xfc00U;
3138  static const uint16_t POS_ZERO = 0x0000U;
3139  static const uint16_t NEG_ZERO = 0x8000U;
3140  static const unsigned int BASE = 2;
3141  static const unsigned int EXPONENT_BITS = 5;
3142  static const unsigned int MANTISSA_BITS = 10;
3143  static const int EXPONENT_MAX = (1 << (EXPONENT_BITS - 1)) - 1;
3144  static const int EXPONENT_BIAS = EXPONENT_MAX;
3145  static const int EXPONENT_MIN = -EXPONENT_MAX + 1;
3146  static const int EXPONENT_MIN_DENORM = EXPONENT_MIN
3147                                        - static_cast<int>(MANTISSA_BITS);
3148  static const Floating_Point_Format floating_point_format = IEEE754_HALF;
3149  int inf_sign() const;
3150  bool is_nan() const;
3151  int zero_sign() const;
3152  bool sign_bit() const;
3153  void negate();
3154  void dec();
3155  void inc();
3156  void set_max(bool negative);
3157  void build(bool negative, mpz_t mantissa, int exponent);
3158
3159};
3160
3161#ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
3162/*! \ingroup PPL_CXX_interface */
3163#endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
3164struct float_ieee754_single {
3165  uint32_t word;
3166  static const uint32_t SGN_MASK = 0x80000000U;
3167  static const uint32_t EXP_MASK = 0x7f800000U;
3168  static const uint32_t WRD_MAX = 0x7f7fffffU;
3169  static const uint32_t POS_INF = 0x7f800000U;
3170  static const uint32_t NEG_INF = 0xff800000U;
3171  static const uint32_t POS_ZERO = 0x00000000U;
3172  static const uint32_t NEG_ZERO = 0x80000000U;
3173  static const unsigned int BASE = 2;
3174  static const unsigned int EXPONENT_BITS = 8;
3175  static const unsigned int MANTISSA_BITS = 23;
3176  static const int EXPONENT_MAX = (1 << (EXPONENT_BITS - 1)) - 1;
3177  static const int EXPONENT_BIAS = EXPONENT_MAX;
3178  static const int EXPONENT_MIN = -EXPONENT_MAX + 1;
3179  static const int EXPONENT_MIN_DENORM = EXPONENT_MIN
3180                                        - static_cast<int>(MANTISSA_BITS);
3181  static const Floating_Point_Format floating_point_format = IEEE754_SINGLE;
3182  int inf_sign() const;
3183  bool is_nan() const;
3184  int zero_sign() const;
3185  bool sign_bit() const;
3186  void negate();
3187  void dec();
3188  void inc();
3189  void set_max(bool negative);
3190  void build(bool negative, mpz_t mantissa, int exponent);
3191};
3192
3193#ifdef WORDS_BIGENDIAN
3194#ifndef PPL_WORDS_BIGENDIAN
3195#define PPL_WORDS_BIGENDIAN
3196#endif
3197#endif
3198
3199#ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
3200/*! \ingroup PPL_CXX_interface */
3201#endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
3202struct float_ieee754_double {
3203#ifdef PPL_WORDS_BIGENDIAN
3204  uint32_t msp;
3205  uint32_t lsp;
3206#else
3207  uint32_t lsp;
3208  uint32_t msp;
3209#endif
3210  static const uint32_t MSP_SGN_MASK = 0x80000000U;
3211  static const uint32_t MSP_POS_INF = 0x7ff00000U;
3212  static const uint32_t MSP_NEG_INF = 0xfff00000U;
3213  static const uint32_t MSP_POS_ZERO = 0x00000000U;
3214  static const uint32_t MSP_NEG_ZERO = 0x80000000U;
3215  static const uint32_t LSP_INF = 0;
3216  static const uint32_t LSP_ZERO = 0;
3217  static const uint32_t MSP_MAX = 0x7fefffffU;
3218  static const uint32_t LSP_MAX = 0xffffffffU;
3219  static const unsigned int BASE = 2;
3220  static const unsigned int EXPONENT_BITS = 11;
3221  static const unsigned int MANTISSA_BITS = 52;
3222  static const int EXPONENT_MAX = (1 << (EXPONENT_BITS - 1)) - 1;
3223  static const int EXPONENT_BIAS = EXPONENT_MAX;
3224  static const int EXPONENT_MIN = -EXPONENT_MAX + 1;
3225  static const int EXPONENT_MIN_DENORM = EXPONENT_MIN
3226                                        - static_cast<int>(MANTISSA_BITS);
3227  static const Floating_Point_Format floating_point_format = IEEE754_DOUBLE;
3228  int inf_sign() const;
3229  bool is_nan() const;
3230  int zero_sign() const;
3231  bool sign_bit() const;
3232  void negate();
3233  void dec();
3234  void inc();
3235  void set_max(bool negative);
3236  void build(bool negative, mpz_t mantissa, int exponent);
3237};
3238
3239#ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
3240/*! \ingroup PPL_CXX_interface */
3241#endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
3242struct float_ibm_single {
3243  uint32_t word;
3244  static const uint32_t SGN_MASK = 0x80000000U;
3245  static const uint32_t EXP_MASK = 0x7f000000U;
3246  static const uint32_t WRD_MAX = 0x7fffffffU;
3247  static const uint32_t POS_INF = 0x7f000000U;
3248  static const uint32_t NEG_INF = 0xff000000U;
3249  static const uint32_t POS_ZERO = 0x00000000U;
3250  static const uint32_t NEG_ZERO = 0x80000000U;
3251  static const unsigned int BASE = 16;
3252  static const unsigned int EXPONENT_BITS = 7;
3253  static const unsigned int MANTISSA_BITS = 24;
3254  static const int EXPONENT_BIAS = 64;
3255  static const int EXPONENT_MAX = (1 << (EXPONENT_BITS - 1)) - 1;
3256  static const int EXPONENT_MIN = -EXPONENT_MAX + 1;
3257  static const int EXPONENT_MIN_DENORM = EXPONENT_MIN
3258                                        - static_cast<int>(MANTISSA_BITS);
3259  static const Floating_Point_Format floating_point_format = IBM_SINGLE;
3260  int inf_sign() const;
3261  bool is_nan() const;
3262  int zero_sign() const;
3263  bool sign_bit() const;
3264  void negate();
3265  void dec();
3266  void inc();
3267  void set_max(bool negative);
3268  void build(bool negative, mpz_t mantissa, int exponent);
3269};
3270
3271#ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
3272/*! \ingroup PPL_CXX_interface */
3273#endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
3274struct float_ibm_double {
3275  static const unsigned int BASE = 16;
3276  static const unsigned int EXPONENT_BITS = 7;
3277  static const unsigned int MANTISSA_BITS = 56;
3278  static const int EXPONENT_BIAS = 64;
3279};
3280
3281#ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
3282/*! \ingroup PPL_CXX_interface */
3283#endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
3284struct float_intel_double_extended {
3285#ifdef PPL_WORDS_BIGENDIAN
3286  uint32_t msp;
3287  uint64_t lsp;
3288#else
3289  uint64_t lsp;
3290  uint32_t msp;
3291#endif
3292  static const uint32_t MSP_SGN_MASK = 0x00008000U;
3293  static const uint32_t MSP_POS_INF = 0x00007fffU;
3294  static const uint32_t MSP_NEG_INF = 0x0000ffffU;
3295  static const uint32_t MSP_POS_ZERO = 0x00000000U;
3296  static const uint32_t MSP_NEG_ZERO = 0x00008000U;
3297  static const uint64_t LSP_INF = static_cast<uint64_t>(0x8000000000000000ULL);
3298  static const uint64_t LSP_ZERO = 0;
3299  static const uint32_t MSP_MAX = 0x00007ffeU;
3300  static const uint64_t LSP_DMAX = static_cast<uint64_t>(0x7fffffffffffffffULL);
3301  static const uint64_t LSP_NMAX = static_cast<uint64_t>(0xffffffffffffffffULL);
3302  static const unsigned int BASE = 2;
3303  static const unsigned int EXPONENT_BITS = 15;
3304  static const unsigned int MANTISSA_BITS = 63;
3305  static const int EXPONENT_MAX = (1 << (EXPONENT_BITS - 1)) - 1;
3306  static const int EXPONENT_BIAS = EXPONENT_MAX;
3307  static const int EXPONENT_MIN = -EXPONENT_MAX + 1;
3308  static const int EXPONENT_MIN_DENORM = EXPONENT_MIN
3309                                        - static_cast<int>(MANTISSA_BITS);
3310  static const Floating_Point_Format floating_point_format =
3311                                     INTEL_DOUBLE_EXTENDED;
3312  int inf_sign() const;
3313  bool is_nan() const;
3314  int zero_sign() const;
3315  bool sign_bit() const;
3316  void negate();
3317  void dec();
3318  void inc();
3319  void set_max(bool negative);
3320  void build(bool negative, mpz_t mantissa, int exponent);
3321};
3322
3323#ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
3324/*! \ingroup PPL_CXX_interface */
3325#endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
3326struct float_ieee754_quad {
3327#ifdef PPL_WORDS_BIGENDIAN
3328  uint64_t msp;
3329  uint64_t lsp;
3330#else
3331  uint64_t lsp;
3332  uint64_t msp;
3333#endif
3334  static const uint64_t MSP_SGN_MASK = static_cast<uint64_t>(0x8000000000000000ULL);
3335  static const uint64_t MSP_POS_INF = static_cast<uint64_t>(0x7fff000000000000ULL);
3336  static const uint64_t MSP_NEG_INF = static_cast<uint64_t>(0xffff000000000000ULL);
3337  static const uint64_t MSP_POS_ZERO = static_cast<uint64_t>(0x0000000000000000ULL);
3338  static const uint64_t MSP_NEG_ZERO = static_cast<uint64_t>(0x8000000000000000ULL);
3339  static const uint64_t LSP_INF = 0;
3340  static const uint64_t LSP_ZERO = 0;
3341  static const uint64_t MSP_MAX = static_cast<uint64_t>(0x7ffeffffffffffffULL);
3342  static const uint64_t LSP_MAX = static_cast<uint64_t>(0xffffffffffffffffULL);
3343  static const unsigned int BASE = 2;
3344  static const unsigned int EXPONENT_BITS = 15;
3345  static const unsigned int MANTISSA_BITS = 112;
3346  static const int EXPONENT_MAX = (1 << (EXPONENT_BITS - 1)) - 1;
3347  static const int EXPONENT_BIAS = EXPONENT_MAX;
3348  static const int EXPONENT_MIN = -EXPONENT_MAX + 1;
3349  static const int EXPONENT_MIN_DENORM = EXPONENT_MIN
3350                                        - static_cast<int>(MANTISSA_BITS);
3351  static const Floating_Point_Format floating_point_format = IEEE754_QUAD;
3352  int inf_sign() const;
3353  bool is_nan() const;
3354  int zero_sign() const;
3355  bool sign_bit() const;
3356  void negate();
3357  void dec();
3358  void inc();
3359  void set_max(bool negative);
3360  void build(bool negative, mpz_t mantissa, int exponent);
3361};
3362
3363#ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
3364/*! \ingroup PPL_CXX_interface */
3365#endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
3366template <typename T>
3367class Float : public False { };
3368
3369#if PPL_SUPPORTED_FLOAT
3370template <>
3371class Float<float> : public True {
3372public:
3373#if PPL_CXX_FLOAT_BINARY_FORMAT == PPL_FLOAT_IEEE754_HALF
3374  typedef float_ieee754_half Binary;
3375#elif PPL_CXX_FLOAT_BINARY_FORMAT == PPL_FLOAT_IEEE754_SINGLE
3376  typedef float_ieee754_single Binary;
3377#elif PPL_CXX_FLOAT_BINARY_FORMAT == PPL_FLOAT_IEEE754_DOUBLE
3378  typedef float_ieee754_double Binary;
3379#elif PPL_CXX_FLOAT_BINARY_FORMAT == PPL_FLOAT_IBM_SINGLE
3380  typedef float_ibm_single Binary;
3381#elif PPL_CXX_FLOAT_BINARY_FORMAT == PPL_FLOAT_IEEE754_QUAD
3382  typedef float_ieee754_quad Binary;
3383#elif PPL_CXX_FLOAT_BINARY_FORMAT == PPL_FLOAT_INTEL_DOUBLE_EXTENDED
3384  typedef float_intel_double_extended Binary;
3385#else
3386#error "Invalid value for PPL_CXX_FLOAT_BINARY_FORMAT"
3387#endif
3388  union {
3389    float number;
3390    Binary binary;
3391  } u;
3392  Float();
3393  Float(float v);
3394  float value();
3395};
3396#endif
3397
3398#if PPL_SUPPORTED_DOUBLE
3399template <>
3400class Float<double> : public True {
3401public:
3402#if PPL_CXX_DOUBLE_BINARY_FORMAT == PPL_FLOAT_IEEE754_HALF
3403  typedef float_ieee754_half Binary;
3404#elif PPL_CXX_DOUBLE_BINARY_FORMAT == PPL_FLOAT_IEEE754_SINGLE
3405  typedef float_ieee754_single Binary;
3406#elif PPL_CXX_DOUBLE_BINARY_FORMAT == PPL_FLOAT_IEEE754_DOUBLE
3407  typedef float_ieee754_double Binary;
3408#elif PPL_CXX_DOUBLE_BINARY_FORMAT == PPL_FLOAT_IBM_SINGLE
3409  typedef float_ibm_single Binary;
3410#elif PPL_CXX_DOUBLE_BINARY_FORMAT == PPL_FLOAT_IEEE754_QUAD
3411  typedef float_ieee754_quad Binary;
3412#elif PPL_CXX_DOUBLE_BINARY_FORMAT == PPL_FLOAT_INTEL_DOUBLE_EXTENDED
3413  typedef float_intel_double_extended Binary;
3414#else
3415#error "Invalid value for PPL_CXX_DOUBLE_BINARY_FORMAT"
3416#endif
3417  union {
3418    double number;
3419    Binary binary;
3420  } u;
3421  Float();
3422  Float(double v);
3423  double value();
3424};
3425#endif
3426
3427#if PPL_SUPPORTED_LONG_DOUBLE
3428template <>
3429class Float<long double> : public True {
3430public:
3431#if PPL_CXX_LONG_DOUBLE_BINARY_FORMAT == PPL_FLOAT_IEEE754_HALF
3432  typedef float_ieee754_half Binary;
3433#elif PPL_CXX_LONG_DOUBLE_BINARY_FORMAT == PPL_FLOAT_IEEE754_SINGLE
3434  typedef float_ieee754_single Binary;
3435#elif PPL_CXX_LONG_DOUBLE_BINARY_FORMAT == PPL_FLOAT_IEEE754_DOUBLE
3436  typedef float_ieee754_double Binary;
3437#elif PPL_CXX_LONG_DOUBLE_BINARY_FORMAT == PPL_FLOAT_IBM_SINGLE
3438  typedef float_ibm_single Binary;
3439#elif PPL_CXX_LONG_DOUBLE_BINARY_FORMAT == PPL_FLOAT_IEEE754_QUAD
3440  typedef float_ieee754_quad Binary;
3441#elif PPL_CXX_LONG_DOUBLE_BINARY_FORMAT == PPL_FLOAT_INTEL_DOUBLE_EXTENDED
3442  typedef float_intel_double_extended Binary;
3443#else
3444#error "Invalid value for PPL_CXX_LONG_DOUBLE_BINARY_FORMAT"
3445#endif
3446  union {
3447    long double number;
3448    Binary binary;
3449  } u;
3450  Float();
3451  Float(long double v);
3452  long double value();
3453};
3454#endif
3455
3456// FIXME: is this the right place for this function?
3457#ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
3458/*! \brief
3459  If \p v is nonzero, returns the position of the most significant bit
3460  in \p a.
3461
3462  The behavior is undefined if \p v is zero.
3463*/
3464#endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
3465unsigned int msb_position(unsigned long long v);
3466
3467/*! \brief
3468  An abstract class to be implemented by an external analyzer such
3469  as ECLAIR in order to provide to the PPL the necessary information
3470  for performing the analysis of floating point computations.
3471
3472  \par Template type parameters
3473
3474  - The class template parameter \p Target specifies the implementation
3475  of Concrete_Expression to be used.
3476  - The class template parameter \p FP_Interval_Type represents the type
3477  of the intervals used in the abstract domain. The interval bounds
3478  should have a floating point type.
3479*/
3480template <typename Target, typename FP_Interval_Type>
3481class FP_Oracle {
3482public:
3483  /*
3484    FIXME: the const qualifiers on expressions may raise CLANG
3485    compatibility issues. It may be necessary to omit them.
3486  */
3487
3488  /*! \brief
3489    Asks the external analyzer for an interval that correctly
3490    approximates the floating point entity referenced by \p dim.
3491    Result is stored into \p result.
3492
3493    \return <CODE>true</CODE> if the analyzer was able to find a correct
3494    approximation, <CODE>false</CODE> otherwise.
3495  */
3496  virtual bool get_interval(dimension_type dim, FP_Interval_Type& result) const
3497    = 0;
3498
3499  /*! \brief
3500    Asks the external analyzer for an interval that correctly
3501    approximates the value of floating point constant \p expr.
3502    Result is stored into \p result.
3503
3504    \return <CODE>true</CODE> if the analyzer was able to find a correct
3505    approximation, <CODE>false</CODE> otherwise.
3506  */
3507  virtual bool get_fp_constant_value(
3508               const Floating_Point_Constant<Target>& expr,
3509                     FP_Interval_Type& result) const = 0;
3510
3511  /*! \brief
3512    Asks the external analyzer for an interval that correctly approximates
3513    the value of \p expr, which must be of integer type.
3514    Result is stored into \p result.
3515
3516    \return <CODE>true</CODE> if the analyzer was able to find a correct
3517    approximation, <CODE>false</CODE> otherwise.
3518  */
3519  virtual bool get_integer_expr_value(const Concrete_Expression<Target>& expr,
3520                                      FP_Interval_Type& result) const = 0;
3521
3522  /*! \brief
3523    Asks the external analyzer for the possible space dimensions that
3524    are associated to the approximable reference \p expr.
3525    Result is stored into \p result.
3526
3527    \return <CODE>true</CODE> if the analyzer was able to return
3528    the (possibly empty!) set, <CODE>false</CODE> otherwise.
3529
3530    The resulting set MUST NOT contain <CODE>not_a_dimension()</CODE>.
3531  */
3532  virtual bool get_associated_dimensions(
3533          const Approximable_Reference<Target>& expr,
3534          std::set<dimension_type>& result) const = 0;
3535
3536};
3537
3538/* FIXME: some of the following  documentation should probably be
3539   under PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS */
3540
3541/*! \brief \relates Float
3542  Returns <CODE>true</CODE> if and only if there is some floating point
3543  number that is representable by \p f2 but not by \p f1.
3544*/
3545bool is_less_precise_than(Floating_Point_Format f1, Floating_Point_Format f2);
3546
3547/*! \brief \relates Float
3548  Computes the absolute error of floating point computations.
3549
3550  \par Template type parameters
3551
3552  - The class template parameter \p FP_Interval_Type represents the type
3553  of the intervals used in the abstract domain. The interval bounds
3554  should have a floating point type.
3555
3556  \param analyzed_format The floating point format used by the analyzed
3557  program.
3558
3559  \return The interval \f$[-\omega, \omega]\f$ where \f$\omega\f$ is the
3560  smallest non-zero positive number in the less precise floating point
3561  format between the analyzer format and the analyzed format.
3562*/
3563template <typename FP_Interval_Type>
3564const FP_Interval_Type&
3565compute_absolute_error(Floating_Point_Format analyzed_format);
3566
3567/*! \brief \relates Linear_Form
3568  Discards all linear forms containing variable \p var from the
3569  linear form abstract store \p lf_store.
3570*/
3571template <typename FP_Interval_Type>
3572void
3573discard_occurrences(std::map<dimension_type,
3574                             Linear_Form<FP_Interval_Type> >& lf_store,
3575                    Variable var);
3576
3577/*! \brief \relates Linear_Form
3578  Assigns the linear form \p lf to \p var in the linear form abstract
3579  store \p lf_store, then discards all occurrences of \p var from it.
3580*/
3581template <typename FP_Interval_Type>
3582void
3583affine_form_image(std::map<dimension_type,
3584                           Linear_Form<FP_Interval_Type> >& lf_store,
3585                  Variable var,
3586                  const Linear_Form<FP_Interval_Type>& lf);
3587
3588/*! \brief \relates Linear_Form
3589  Discards from \p ls1 all linear forms but those that are associated
3590  to the same variable in \p ls2.
3591*/
3592template <typename FP_Interval_Type>
3593void
3594upper_bound_assign(std::map<dimension_type,
3595                            Linear_Form<FP_Interval_Type> >& ls1,
3596                   const std::map<dimension_type,
3597                                  Linear_Form<FP_Interval_Type> >& ls2);
3598
3599} // namespace Parma_Polyhedra_Library
3600
3601/* Automatically generated from PPL source file ../src/Float_inlines.hh line 1. */
3602/* IEC 559 floating point format related functions.
3603*/
3604
3605
3606/* Automatically generated from PPL source file ../src/Variable_defs.hh line 1. */
3607/* Variable class declaration.
3608*/
3609
3610
3611/* Automatically generated from PPL source file ../src/Init_types.hh line 1. */
3612
3613
3614namespace Parma_Polyhedra_Library {
3615
3616class Init;
3617
3618} // namespace Parma_Polyhedra_Library
3619
3620/* Automatically generated from PPL source file ../src/Variable_defs.hh line 30. */
3621#include <iosfwd>
3622#include <set>
3623
3624namespace Parma_Polyhedra_Library {
3625
3626namespace IO_Operators {
3627
3628//! Output operator.
3629/*! \relates Parma_Polyhedra_Library::Variable */
3630std::ostream&
3631operator<<(std::ostream& s, const Variable v);
3632
3633} // namespace IO_Operators
3634
3635//! Defines a total ordering on variables.
3636/*! \relates Variable */
3637bool less(Variable v, Variable w);
3638
3639/*! \relates Variable */
3640void
3641swap(Variable& x, Variable& y);
3642
3643} // namespace Parma_Polyhedra_Library
3644
3645//! A dimension of the vector space.
3646/*! \ingroup PPL_CXX_interface
3647  An object of the class Variable represents a dimension of the space,
3648  that is one of the Cartesian axes.
3649  Variables are used as basic blocks in order to build
3650  more complex linear expressions.
3651  Each variable is identified by a non-negative integer,
3652  representing the index of the corresponding Cartesian axis
3653  (the first axis has index 0).
3654  The space dimension of a variable is the dimension of the vector space
3655  made by all the Cartesian axes having an index less than or equal to
3656  that of the considered variable; thus, if a variable has index \f$i\f$,
3657  its space dimension is \f$i+1\f$.
3658
3659  Note that the ``meaning'' of an object of the class Variable
3660  is completely specified by the integer index provided to its
3661  constructor:
3662  be careful not to be mislead by C++ language variable names.
3663  For instance, in the following example the linear expressions
3664  <CODE>e1</CODE> and <CODE>e2</CODE> are equivalent,
3665  since the two variables <CODE>x</CODE> and <CODE>z</CODE> denote
3666  the same Cartesian axis.
3667  \code
3668  Variable x(0);
3669  Variable y(1);
3670  Variable z(0);
3671  Linear_Expression e1 = x + y;
3672  Linear_Expression e2 = y + z;
3673  \endcode
3674
3675*/
3676class Parma_Polyhedra_Library::Variable {
3677
3678public:
3679  //! Builds the variable corresponding to the Cartesian axis of index \p i.
3680  /*!
3681    \exception std::length_error
3682    Thrown if <CODE>i+1</CODE> exceeds
3683    <CODE>Variable::max_space_dimension()</CODE>.
3684  */
3685  explicit Variable(dimension_type i);
3686
3687  //! Returns the index of the Cartesian axis associated to the variable.
3688  dimension_type id() const;
3689
3690  //! Returns the maximum space dimension a Variable can handle.
3691  static dimension_type max_space_dimension();
3692
3693  //! Returns the dimension of the vector space enclosing \p *this.
3694  /*!
3695    The returned value is <CODE>id()+1</CODE>.
3696  */
3697  dimension_type space_dimension() const;
3698
3699  //! Returns the total size in bytes of the memory occupied by \p *this.
3700  memory_size_type total_memory_in_bytes() const;
3701
3702  //! Returns the size in bytes of the memory managed by \p *this.
3703  memory_size_type external_memory_in_bytes() const;
3704
3705  //! Checks if all the invariants are satisfied.
3706  bool OK() const;
3707
3708  //! Type of output functions.
3709  typedef void output_function_type(std::ostream& s, const Variable v);
3710
3711  //! The default output function.
3712  static void default_output_function(std::ostream& s, const Variable v);
3713
3714  //! Sets the output function to be used for printing Variable objects.
3715  static void set_output_function(output_function_type* p);
3716
3717  //! Returns the pointer to the current output function.
3718  static output_function_type* get_output_function();
3719
3720  //! Binary predicate defining the total ordering on variables.
3721  /*! \ingroup PPL_CXX_interface */
3722  struct Compare {
3723    //! Returns <CODE>true</CODE> if and only if \p x comes before \p y.
3724    bool operator()(Variable x, Variable y) const;
3725  };
3726
3727  //! Swaps *this and v.
3728  void m_swap(Variable& v);
3729
3730private:
3731  //! The index of the Cartesian axis.
3732  dimension_type varid;
3733
3734  // The initialization class needs to set the default output function.
3735  friend class Init;
3736
3737  friend std::ostream&
3738  Parma_Polyhedra_Library::IO_Operators::operator<<(std::ostream& s,
3739                                                    const Variable v);
3740
3741  //! Pointer to the current output function.
3742  static output_function_type* current_output_function;
3743
3744};
3745
3746/* Automatically generated from PPL source file ../src/Variable_inlines.hh line 1. */
3747/* Variable class implementation: inline functions.
3748*/
3749
3750
3751/* Automatically generated from PPL source file ../src/globals_defs.hh line 1. */
3752/* Declarations of global objects.
3753*/
3754
3755
3756/* Automatically generated from PPL source file ../src/C_Integer.hh line 1. */
3757/* C integers info.
3758*/
3759
3760
3761/* Automatically generated from PPL source file ../src/C_Integer.hh line 28. */
3762#include <climits>
3763
3764// C99 defines LLONG_MIN, LLONG_MAX and ULLONG_MAX, but this part of
3765// C99 is not yet included into the C++ standard.
3766// GCC defines LONG_LONG_MIN, LONG_LONG_MAX and ULONG_LONG_MAX.
3767// Some compilers (such as Comeau C++ up to and including version 4.3.3)
3768// define nothing.  In this last case we make a reasonable guess.
3769#ifndef LLONG_MIN
3770#if defined(LONG_LONG_MIN)
3771#define LLONG_MIN LONG_LONG_MIN
3772#elif PPL_SIZEOF_LONG_LONG == 8
3773#define LLONG_MIN 0x8000000000000000LL
3774#endif
3775#endif
3776
3777#ifndef LLONG_MAX
3778#if defined(LONG_LONG_MAX)
3779#define LLONG_MAX LONG_LONG_MAX
3780#elif PPL_SIZEOF_LONG_LONG == 8
3781#define LLONG_MAX 0x7fffffffffffffffLL
3782#endif
3783#endif
3784
3785#ifndef ULLONG_MAX
3786#if defined(ULONG_LONG_MAX)
3787#define ULLONG_MAX ULONG_LONG_MAX
3788#elif PPL_SIZEOF_LONG_LONG == 8
3789#define ULLONG_MAX 0xffffffffffffffffULL
3790#endif
3791#endif
3792
3793namespace Parma_Polyhedra_Library {
3794
3795template <typename T>
3796struct C_Integer : public False { };
3797
3798template <>
3799struct C_Integer<char> : public True {
3800  enum const_bool_value {
3801#if PPL_CXX_PLAIN_CHAR_IS_SIGNED
3802    is_signed = true
3803#else
3804    is_signed = false
3805#endif
3806  };
3807  typedef void smaller_type;
3808  typedef void smaller_signed_type;
3809  typedef void smaller_unsigned_type;
3810#if PPL_CXX_PLAIN_CHAR_IS_SIGNED
3811  typedef unsigned char other_type;
3812#else
3813  typedef signed char other_type;
3814#endif
3815  static const char min = static_cast<char>(CHAR_MIN);
3816  static const char max = static_cast<char>(CHAR_MAX);
3817};
3818
3819template <>
3820struct C_Integer<signed char> : public True {
3821  enum const_bool_value {
3822    is_signed = true
3823  };
3824  typedef void smaller_type;
3825  typedef void smaller_signed_type;
3826  typedef void smaller_unsigned_type;
3827  typedef unsigned char other_type;
3828  static const signed char min = static_cast<signed char>(SCHAR_MIN);
3829  static const signed char max = static_cast<signed char>(SCHAR_MAX);
3830};
3831
3832template <>
3833struct C_Integer<signed short> : public True {
3834  enum const_bool_value {
3835    is_signed = true
3836  };
3837  typedef signed char smaller_type;
3838  typedef signed char smaller_signed_type;
3839  typedef unsigned char smaller_unsigned_type;
3840  typedef unsigned short other_type;
3841  static const signed short min = static_cast<signed short>(SHRT_MIN);
3842  static const signed short max = static_cast<signed short>(SHRT_MAX);
3843};
3844
3845template <>
3846struct C_Integer<signed int> : public True {
3847  enum const_bool_value {
3848    is_signed = true
3849  };
3850  typedef signed short smaller_type;
3851  typedef signed short smaller_signed_type;
3852  typedef unsigned short smaller_unsigned_type;
3853  typedef unsigned int other_type;
3854  static const signed int min = INT_MIN;
3855  static const signed int max = INT_MAX;
3856};
3857
3858template <>
3859struct C_Integer<signed long> : public True {
3860  enum const_bool_value {
3861    is_signed = true
3862  };
3863  typedef signed int smaller_type;
3864  typedef signed int smaller_signed_type;
3865  typedef unsigned int smaller_unsigned_type;
3866  typedef unsigned long other_type;
3867  static const signed long min = LONG_MIN;
3868  static const signed long max = LONG_MAX;
3869};
3870
3871template <>
3872struct C_Integer<signed long long> : public True {
3873  enum const_bool_value {
3874    is_signed = true
3875  };
3876  typedef signed long smaller_type;
3877  typedef signed long smaller_signed_type;
3878  typedef unsigned long smaller_unsigned_type;
3879  typedef unsigned long long other_type;
3880  static const signed long long min = LLONG_MIN;
3881  static const signed long long max = LLONG_MAX;
3882};
3883
3884template <>
3885struct C_Integer<unsigned char> : public True {
3886  enum const_bool_value {
3887    is_signed = false
3888  };
3889  typedef void smaller_type;
3890  typedef void smaller_signed_type;
3891  typedef void smaller_unsigned_type;
3892  typedef signed char other_type;
3893  static const unsigned char min = static_cast<unsigned char>(0U);
3894  static const unsigned char max = static_cast<unsigned char>(UCHAR_MAX);
3895};
3896
3897template <>
3898struct C_Integer<unsigned short> : public True {
3899  enum const_bool_value {
3900    is_signed = false
3901  };
3902  typedef unsigned char smaller_type;
3903  typedef signed char smaller_signed_type;
3904  typedef unsigned char smaller_unsigned_type;
3905  typedef signed short other_type;
3906  static const unsigned short min = static_cast<unsigned short>(0U);
3907  static const unsigned short max = static_cast<unsigned short>(USHRT_MAX);
3908};
3909
3910template <>
3911struct C_Integer<unsigned int> : public True {
3912  enum const_bool_value {
3913    is_signed = false
3914  };
3915  typedef unsigned short smaller_type;
3916  typedef signed short smaller_signed_type;
3917  typedef unsigned short smaller_unsigned_type;
3918  typedef signed int other_type;
3919  static const unsigned int min = 0U;
3920  static const unsigned int max = UINT_MAX;
3921};
3922
3923template <>
3924struct C_Integer<unsigned long> : public True {
3925  enum const_bool_value {
3926    is_signed = false
3927  };
3928  typedef unsigned int smaller_type;
3929  typedef signed int smaller_signed_type;
3930  typedef unsigned int smaller_unsigned_type;
3931  typedef signed long other_type;
3932  static const unsigned long min = 0UL;
3933  static const unsigned long max = ULONG_MAX;
3934};
3935
3936template <>
3937struct C_Integer<unsigned long long> : public True {
3938  enum const_bool_value {
3939    is_signed = false
3940  };
3941  typedef unsigned long smaller_type;
3942  typedef signed long smaller_signed_type;
3943  typedef unsigned long smaller_unsigned_type;
3944  typedef signed long long other_type;
3945  static const unsigned long long min = 0ULL;
3946  static const unsigned long long max = ULLONG_MAX;
3947};
3948
3949} // namespace Parma_Polyhedra_Library
3950
3951/* Automatically generated from PPL source file ../src/globals_defs.hh line 32. */
3952#include <exception>
3953#include <gmpxx.h>
3954
3955#ifndef PPL_PROFILE_ADD_WEIGHT
3956#define PPL_PROFILE_ADD_WEIGHT 0
3957#endif
3958
3959#if defined(NDEBUG) && PPL_PROFILE_ADD_WEIGHT
3960/* Automatically generated from PPL source file ../src/Weight_Profiler_defs.hh line 1. */
3961/* Weight_Profiler class declaration.
3962*/
3963
3964#ifndef Weight_Profiler_defs_hh
3965#define Weight_Profiler_defs_hh 1
3966
3967#include <cassert>
3968
3969namespace Parma_Polyhedra_Library {
3970
3971class Weight_Profiler {
3972private:
3973  enum { DISCARDED = 0, VALID = 1 };
3974
3975public:
3976  Weight_Profiler(const char* file, int line,
3977                  Weightwatch_Traits::Delta delta,
3978                  double min_threshold = 0, double max_threshold = 0)
3979    : file(file), line(line), delta(delta),
3980      min_threshold(min_threshold), max_threshold(max_threshold) {
3981    for (int i = 0; i < 2; ++i) {
3982      stat[i].samples = 0;
3983      stat[i].count = 0;
3984      stat[i].sum = 0;
3985      stat[i].squares_sum = 0;
3986      stat[i].min = 0;
3987      stat[i].max = 0;
3988    }
3989  }
3990
3991  ~Weight_Profiler() {
3992    output_stats();
3993  }
3994
3995  void output_stats();
3996
3997  static void begin() {
3998#ifndef NDEBUG
3999    int r = clock_gettime(CLOCK_THREAD_CPUTIME_ID, &stamp);
4000    assert(r >= 0);
4001#else
4002    clock_gettime(CLOCK_THREAD_CPUTIME_ID, &stamp);
4003#endif
4004  }
4005
4006  void end(unsigned int factor = 1) {
4007    Weightwatch_Traits::weight
4008      += (Weightwatch_Traits::Threshold) delta * factor;
4009    struct timespec start = stamp;
4010    begin();
4011    double elapsed;
4012    if (stamp.tv_nsec >= start.tv_nsec) {
4013      elapsed = (stamp.tv_nsec - start.tv_nsec)
4014        + (stamp.tv_sec - start.tv_sec) * 1e9;
4015    }
4016    else {
4017      elapsed = (1000000000 - start.tv_nsec + stamp.tv_nsec )
4018        + (stamp.tv_sec - start.tv_sec - 1) * 1e9;
4019    }
4020    elapsed -= adjustment;
4021    double elapsed1 = elapsed / factor;
4022    int i = (elapsed1 < min_threshold
4023             || (max_threshold > 0 && elapsed1 > max_threshold))
4024      ? DISCARDED
4025      : VALID;
4026    ++stat[i].samples;
4027    if (stat[i].count == 0) {
4028      stat[i].min = stat[i].max = elapsed1;
4029    }
4030    else if (stat[i].min > elapsed1) {
4031      stat[i].min = elapsed1;
4032    }
4033    else if (stat[i].max < elapsed1) {
4034      stat[i].max = elapsed1;
4035    }
4036    stat[i].sum += elapsed;
4037    stat[i].squares_sum += elapsed * elapsed1;
4038    stat[i].count += factor;
4039  }
4040
4041  static double tune_adjustment();
4042
4043 private:
4044  //! File of this profiling point.
4045  const char *file;
4046
4047  //! Line of this profiling point.
4048  int line;
4049
4050  //! Computational weight to be added at each iteration.
4051  Weightwatch_Traits::Delta delta;
4052
4053  //! Times less than this value are discarded.
4054  double min_threshold;
4055
4056  //! Times greater than this value are discarded.
4057  double max_threshold;
4058
4059  //! Statistical data for samples (both DISCARDED and VALID)
4060  struct {
4061    //! Number of collected samples.
4062    unsigned int samples;
4063
4064    /*! \brief
4065      Number of collected iterations.
4066
4067      \note
4068      Multiple iterations are possibly collected for each sample.
4069    */
4070    unsigned int count;
4071
4072    //! Sum of the measured times.
4073    double sum;
4074
4075    //! Sum of the squares of the measured times (to compute variance).
4076    double squares_sum;
4077
4078    //! Minimum measured time.
4079    double min;
4080
4081    //! Maximum measured time.
4082    double max;
4083  } stat[2];
4084
4085  //! Holds the time corresponding to last time begin() was called.
4086  static struct timespec stamp;
4087
4088  /*! \brief
4089    Time quantity used to adjust the elapsed times so as not to take
4090    into account the time spent by the measurement infrastructure.
4091  */
4092  static double adjustment;
4093};
4094
4095}
4096
4097#endif // Weight_Profiler_defs_hh
4098/* Automatically generated from PPL source file ../src/globals_defs.hh line 41. */
4099#endif
4100
4101#if defined(NDEBUG)
4102
4103#if PPL_PROFILE_ADD_WEIGHT
4104
4105#define WEIGHT_BEGIN() Weight_Profiler::begin()
4106
4107#define WEIGHT_ADD(delta)                                     \
4108  do {                                                        \
4109    static Weight_Profiler wp__(__FILE__, __LINE__, delta);   \
4110    wp__.end();                                               \
4111  } while (false)
4112
4113#define WEIGHT_ADD_MUL(delta, factor)                                   \
4114  do {                                                                  \
4115    static Weight_Profiler wp__(__FILE__, __LINE__, delta);             \
4116    wp__.end(factor);                                                   \
4117  } while (false)
4118
4119#else // !PPL_PROFILE_ADD_WEIGHT
4120
4121#define WEIGHT_BEGIN()                          \
4122  do {                                          \
4123  } while (false)
4124
4125#define WEIGHT_ADD(delta)                       \
4126  do {                                          \
4127    Weightwatch_Traits::weight += (delta);      \
4128  } while (false)
4129
4130#define WEIGHT_ADD_MUL(delta, factor)                   \
4131  do {                                                  \
4132    Weightwatch_Traits::weight += (delta)*(factor);     \
4133  } while (false)
4134
4135#endif // !PPL_PROFILE_ADD_WEIGHT
4136
4137#else // !defined(NDEBUG)
4138
4139#define WEIGHT_BEGIN()
4140
4141#define WEIGHT_ADD(delta)                       \
4142  do {                                          \
4143    if (!In_Assert::asserting()) {              \
4144      Weightwatch_Traits::weight += delta;      \
4145    }                                           \
4146  } while (false)
4147
4148#define WEIGHT_ADD_MUL(delta, factor)                   \
4149  do {                                                  \
4150    if (!In_Assert::asserting()) {                      \
4151      Weightwatch_Traits::weight += delta * factor;     \
4152    }                                                   \
4153  } while (false)
4154
4155#endif // !defined(NDEBUG)
4156
4157
4158namespace Parma_Polyhedra_Library {
4159
4160//! Returns a value that does not designate a valid dimension.
4161dimension_type
4162not_a_dimension();
4163
4164#ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
4165//! Returns the hash code for space dimension \p dim.
4166#endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
4167int32_t
4168hash_code_from_dimension(dimension_type dim);
4169
4170#ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
4171/*! \brief
4172  Make sure swap() is specialized when needed.
4173
4174  This will cause a compile-time error whenever a specialization for \p T
4175  is beneficial but missing.
4176*/
4177#endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
4178template <typename T>
4179inline typename Enable_If<Slow_Copy<T>::value, void>::type
4180swap(T&, T&) {
4181  PPL_COMPILE_TIME_CHECK(!Slow_Copy<T>::value, "missing swap specialization");
4182}
4183
4184/*! \brief
4185  Declare a local variable named \p id, of type Coefficient, and containing
4186  an unknown initial value.
4187
4188  Use of this macro to declare temporaries of type Coefficient results
4189  in decreased memory allocation overhead and in better locality.
4190*/
4191#define PPL_DIRTY_TEMP_COEFFICIENT(id) \
4192PPL_DIRTY_TEMP(Parma_Polyhedra_Library::Coefficient, id)
4193
4194#ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
4195//! Speculative allocation function.
4196/*!
4197  \return
4198  The actual capacity to be allocated.
4199
4200  \param requested_size
4201  The number of elements we need.
4202
4203  \param maximum_size
4204  The maximum number of elements to be allocated. It is assumed
4205  to be no less than \p requested_size.
4206
4207  Computes a capacity given a requested size.
4208  Allows for speculative allocation aimed at reducing the number of
4209  reallocations enough to guarantee amortized constant insertion time
4210  for our vector-like data structures. In all cases, the speculative
4211  allocation will not exceed \p maximum_size.
4212*/
4213#endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
4214dimension_type
4215compute_capacity(dimension_type requested_size,
4216                 dimension_type maximum_size);
4217
4218
4219#ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
4220//! Traits class for the deterministic timeout mechanism.
4221/*! \ingroup PPL_CXX_interface
4222  This abstract base class should be instantiated by those users
4223  willing to provide a polynomial upper bound to the time spent
4224  by any invocation of a library operator.
4225*/
4226#endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
4227struct Weightwatch_Traits {
4228  //! The type used to specify thresholds for computational weight.
4229  typedef unsigned long long Threshold;
4230
4231  //! The type used to specify increments of computational weight.
4232  typedef unsigned long long Delta;
4233
4234  //! Returns the current computational weight.
4235  static const Threshold& get();
4236
4237  //! Compares the two weights \p a and \p b.
4238  static bool less_than(const Threshold& a, const Threshold& b);
4239
4240  //! Computes a \c Delta value from \p unscaled and \p scale.
4241  /*!
4242    \return
4243    \f$u \cdot 2^s\f$, where \f$u\f$ is the value of \p unscaled and
4244    \f$s\f$ is the value of \p scale.
4245
4246    \param unscaled
4247    The value of delta before scaling.
4248
4249    \param scale
4250    The scaling to be applied to \p unscaled.
4251  */
4252  static Delta compute_delta(unsigned long unscaled, unsigned scale);
4253
4254  //! Sets \p threshold to be \p delta units bigger than the current weight.
4255  static void from_delta(Threshold& threshold, const Delta& delta);
4256
4257  //! The current computational weight.
4258  static Threshold weight;
4259
4260  /*! \brief
4261    A pointer to the function that has to be called when checking
4262    the reaching of thresholds.
4263
4264    The pointer can be null if no thresholds are set.
4265  */
4266  static void (*check_function)(void);
4267};
4268
4269
4270#ifndef NDEBUG
4271
4272class In_Assert {
4273private:
4274  //! Non zero during evaluation of PPL_ASSERT expression.
4275  static unsigned int count;
4276public:
4277  In_Assert() {
4278    ++count;
4279  }
4280  ~In_Assert() {
4281    --count;
4282  }
4283  static bool asserting() {
4284    return count != 0;
4285  }
4286};
4287
4288#endif
4289
4290
4291//! User objects the PPL can throw.
4292/*! \ingroup PPL_CXX_interface
4293  This abstract base class should be instantiated by those users
4294  willing to provide a polynomial upper bound to the time spent
4295  by any invocation of a library operator.
4296*/
4297class Throwable {
4298public:
4299  //! Throws the user defined exception object.
4300  virtual void throw_me() const = 0;
4301
4302  //! Virtual destructor.
4303  virtual ~Throwable();
4304};
4305
4306/*! \brief
4307  A pointer to an exception object.
4308
4309  \ingroup PPL_CXX_interface
4310  This pointer, which is initialized to zero, is repeatedly checked
4311  along any super-linear (i.e., computationally expensive) computation
4312  path in the library.
4313  When it is found nonzero the exception it points to is thrown.
4314  In other words, making this pointer point to an exception (and
4315  leaving it in this state) ensures that the library will return
4316  control to the client application, possibly by throwing the given
4317  exception, within a time that is a linear function of the size
4318  of the representation of the biggest object (powerset of polyhedra,
4319  polyhedron, system of constraints or generators) on which the library
4320  is operating upon.
4321
4322  \note
4323  The only sensible way to assign to this pointer is from within a
4324  signal handler or from a parallel thread.  For this reason, the
4325  library, apart from ensuring that the pointer is initially set to zero,
4326  never assigns to it.  In particular, it does not zero it again when
4327  the exception is thrown: it is the client's responsibility to do so.
4328*/
4329extern const Throwable* volatile abandon_expensive_computations;
4330
4331#ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
4332/*! \brief
4333  If the pointer abandon_expensive_computations is found
4334  to be nonzero, the exception it points to is thrown.
4335
4336  \relates Throwable
4337*/
4338#endif
4339void
4340maybe_abandon();
4341
4342//! A tag class.
4343/*! \ingroup PPL_CXX_interface
4344  Tag class to distinguish those constructors that recycle the data
4345  structures of their arguments, instead of taking a copy.
4346*/
4347struct Recycle_Input {
4348};
4349
4350// Turn s into a string: PPL_STR(x + y) => "x + y".
4351#define PPL_STR(s) #s
4352// Turn the expansion of s into a string: PPL_XSTR(x) => "x expanded".
4353#define PPL_XSTR(s) PPL_STR(s)
4354
4355#define PPL_OUTPUT_DECLARATIONS                                         \
4356  /*! \brief Writes to \c std::cerr an ASCII representation of \p *this. */ \
4357  void ascii_dump() const;                                              \
4358  /*! \brief Writes to \p s an ASCII representation of \p *this. */     \
4359  void ascii_dump(std::ostream& s) const;                               \
4360  /*! \brief Prints \p *this to \c std::cerr using \c operator<<. */    \
4361  void print() const;
4362
4363#define PPL_OUTPUT_DEFINITIONS(class_name)                      \
4364  void                                                          \
4365  Parma_Polyhedra_Library::class_name::ascii_dump() const {     \
4366    ascii_dump(std::cerr);                                      \
4367  }                                                             \
4368                                                                \
4369  void                                                          \
4370  Parma_Polyhedra_Library::class_name::print() const {          \
4371    using IO_Operators::operator<<;                             \
4372    std::cerr << *this;                                         \
4373  }
4374
4375#define PPL_OUTPUT_DEFINITIONS_ASCII_ONLY(class_name)                   \
4376  void                                                                  \
4377  Parma_Polyhedra_Library::class_name::ascii_dump() const {             \
4378    ascii_dump(std::cerr);                                              \
4379  }                                                                     \
4380                                                                        \
4381  void                                                                  \
4382  Parma_Polyhedra_Library::class_name::print() const {                  \
4383    std::cerr << "No user level output operator defined "               \
4384              << "for class " PPL_XSTR(class_name) << "." << std::endl; \
4385  }
4386
4387#define PPL_OUTPUT_TEMPLATE_DEFINITIONS(type_symbol, class_prefix)      \
4388  template <typename type_symbol>                                       \
4389  void                                                                  \
4390  class_prefix::ascii_dump() const {                             \
4391    ascii_dump(std::cerr);                                              \
4392  }                                                                     \
4393                                                                        \
4394  template <typename type_symbol>                                       \
4395  void                                                                  \
4396  class_prefix::print() const {                                  \
4397    using IO_Operators::operator<<;                                     \
4398    std::cerr << *this;                                                 \
4399  }
4400
4401#define PPL_OUTPUT_2_PARAM_TEMPLATE_DEFINITIONS(type_symbol1,           \
4402                                                type_symbol2,           \
4403                                                class_prefix)           \
4404  template <typename type_symbol1, typename type_symbol2>               \
4405  void                                                                  \
4406  PPL_U(class_prefix)<PPL_U(type_symbol1), PPL_U(type_symbol2)>         \
4407  ::ascii_dump() const {                                                \
4408    ascii_dump(std::cerr);                                              \
4409  }                                                                     \
4410                                                                        \
4411  template <typename type_symbol1, typename type_symbol2>               \
4412  void                                                                  \
4413  PPL_U(class_prefix)<PPL_U(type_symbol1), PPL_U(type_symbol2)>         \
4414  ::print() const {                                                     \
4415    using IO_Operators::operator<<;                                     \
4416    std::cerr << *this;                                                 \
4417  }
4418
4419#define PPL_OUTPUT_3_PARAM_TEMPLATE_DEFINITIONS(type_symbol1,           \
4420                                                type_symbol2,           \
4421                                                type_symbol3,           \
4422                                                class_prefix)           \
4423  template <typename type_symbol1, typename type_symbol2,               \
4424            typename type_symbol3>                                      \
4425  void                                                                  \
4426  PPL_U(class_prefix)<PPL_U(type_symbol1), type_symbol2,                \
4427                      PPL_U(type_symbol3)>::ascii_dump()                \
4428    const {                                                             \
4429    ascii_dump(std::cerr);                                              \
4430  }                                                                     \
4431                                                                        \
4432    template <typename type_symbol1, typename type_symbol2,             \
4433              typename type_symbol3>                                    \
4434    void                                                                \
4435    PPL_U(class_prefix)<PPL_U(type_symbol1), type_symbol2,              \
4436                        PPL_U(type_symbol3)>::print()                   \
4437      const {                                                           \
4438      using IO_Operators::operator<<;                                   \
4439      std::cerr << *this;                                               \
4440    }
4441
4442#define PPL_OUTPUT_TEMPLATE_DEFINITIONS_ASCII_ONLY(type_symbol, class_prefix) \
4443  template <typename type_symbol>                                       \
4444  void                                                                  \
4445  class_prefix::ascii_dump() const {                                    \
4446    ascii_dump(std::cerr);                                              \
4447  }                                                                     \
4448                                                                        \
4449  template <typename type_symbol>                                       \
4450  void                                                                  \
4451  class_prefix::print() const {                                         \
4452    std::cerr << "No user level output operator defined "               \
4453              << "for " PPL_XSTR(class_prefix) << "." << std::endl;     \
4454  }
4455
4456#ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
4457//! Returns <CODE>true</CODE> if \p c is any kind of space character.
4458#endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
4459bool is_space(char c);
4460
4461template <typename T, long long v, typename Enable = void>
4462struct Fit : public False {
4463};
4464
4465template <typename T, long long v>
4466struct Fit<T, v, typename Enable_If<C_Integer<T>::value>::type>  {
4467  enum {
4468    value = (v >= static_cast<long long>(C_Integer<T>::min)
4469             && v <= static_cast<long long>(C_Integer<T>::max))
4470  };
4471};
4472
4473template <typename T, T v>
4474struct TConstant {
4475  static const T value = v;
4476};
4477
4478
4479template <typename T, T v>
4480const T TConstant<T, v>::value;
4481
4482template <typename T, long long v, bool prefer_signed = true,
4483          typename Enable = void>
4484struct Constant_ : public TConstant<T, v> {
4485};
4486
4487//! \cond
4488// Keep Doxygen off until it learns how to deal properly with `||'.
4489
4490template <typename T, long long v, bool prefer_signed>
4491struct Constant_<T, v, prefer_signed,
4492                 typename Enable_If<(Fit<typename C_Integer<T>::smaller_signed_type, v>::value
4493                                     && (prefer_signed
4494                                         || !Fit<typename C_Integer<T>::smaller_unsigned_type, v>::value))>::type>
4495  : public Constant_<typename C_Integer<T>::smaller_signed_type, v, prefer_signed> {
4496};
4497
4498template <typename T, long long v, bool prefer_signed>
4499struct Constant_<T, v, prefer_signed,
4500                 typename Enable_If<(Fit<typename C_Integer<T>::smaller_unsigned_type, v>::value
4501                                     && (!prefer_signed
4502                                         || !Fit<typename C_Integer<T>::smaller_signed_type, v>::value))>::type>
4503  : public Constant_<typename C_Integer<T>::smaller_unsigned_type, v, prefer_signed> {
4504};
4505
4506//! \endcond
4507
4508template <long long v, bool prefer_signed = true>
4509struct Constant : public Constant_<long long, v, prefer_signed> {
4510};
4511
4512#ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
4513//! \name Memory Size Inspection Functions
4514//@{
4515#endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
4516
4517#ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
4518/*! \brief
4519  For native types, returns the total size in bytes of the memory
4520  occupied by the type of the (unused) parameter, i.e., 0.
4521*/
4522#endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
4523template <typename T>
4524typename Enable_If<Is_Native<T>::value, memory_size_type>::type
4525total_memory_in_bytes(const T&);
4526
4527#ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
4528/*! \brief
4529  For native types, returns the size in bytes of the memory managed
4530  by the type of the (unused) parameter, i.e., 0.
4531*/
4532#endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
4533template <typename T>
4534typename Enable_If<Is_Native<T>::value, memory_size_type>::type
4535external_memory_in_bytes(const T&);
4536
4537#ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
4538//! Returns the total size in bytes of the memory occupied by \p x.
4539#endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
4540memory_size_type
4541total_memory_in_bytes(const mpz_class& x);
4542
4543#ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
4544//! Returns the size in bytes of the memory managed by \p x.
4545#endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
4546memory_size_type
4547external_memory_in_bytes(const mpz_class& x);
4548
4549#ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
4550//! Returns the total size in bytes of the memory occupied by \p x.
4551#endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
4552memory_size_type
4553total_memory_in_bytes(const mpq_class& x);
4554
4555#ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
4556//! Returns the size in bytes of the memory managed by \p x.
4557#endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
4558memory_size_type
4559external_memory_in_bytes(const mpq_class& x);
4560
4561#ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
4562//@} // Memory Size Inspection Functions
4563#endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
4564
4565
4566template <typename T, typename Enable = void>
4567struct Has_OK : public False { };
4568
4569template <typename T>
4570struct Has_OK<T, typename Enable_If_Is<bool (T::*)() const, &T::OK>::type>
4571  : public True {
4572};
4573
4574template <typename T>
4575inline typename Enable_If<Has_OK<T>::value, bool>::type
4576f_OK(const T& to) {
4577  return to.OK();
4578}
4579
4580#define FOK(T) inline bool f_OK(const T&) { return true; }
4581
4582FOK(char)
4583FOK(signed char)
4584FOK(unsigned char)
4585FOK(signed short)
4586FOK(unsigned short)
4587FOK(signed int)
4588FOK(unsigned int)
4589FOK(signed long)
4590FOK(unsigned long)
4591FOK(signed long long)
4592FOK(unsigned long long)
4593FOK(float)
4594FOK(double)
4595FOK(long double)
4596FOK(mpz_class)
4597FOK(mpq_class)
4598
4599void ascii_dump(std::ostream& s, Representation r);
4600bool ascii_load(std::istream& s, Representation& r);
4601
4602dimension_type
4603check_space_dimension_overflow(dimension_type dim,
4604                               dimension_type max,
4605                               const char* domain,
4606                               const char* method,
4607                               const char* reason);
4608
4609template <typename RA_Container>
4610typename RA_Container::iterator
4611nth_iter(RA_Container& cont, dimension_type n);
4612
4613template <typename RA_Container>
4614typename RA_Container::const_iterator
4615nth_iter(const RA_Container& cont, dimension_type n);
4616
4617dimension_type
4618least_significant_one_mask(dimension_type i);
4619
4620} // namespace Parma_Polyhedra_Library
4621
4622// By default, use sparse matrices both for MIP_Problem and PIP_Problem.
4623#ifndef PPL_USE_SPARSE_MATRIX
4624#define PPL_USE_SPARSE_MATRIX 1
4625#endif
4626
4627/* Automatically generated from PPL source file ../src/globals_inlines.hh line 1. */
4628/* Implementation of global objects: inline functions.
4629*/
4630
4631
4632/* Automatically generated from PPL source file ../src/globals_inlines.hh line 28. */
4633#include <limits>
4634#include <cassert>
4635#include <istream>
4636#include <ostream>
4637#include <cctype>
4638#include <stdexcept>
4639
4640namespace Parma_Polyhedra_Library {
4641
4642inline dimension_type
4643not_a_dimension() {
4644  return std::numeric_limits<dimension_type>::max();
4645}
4646
4647inline int32_t
4648hash_code_from_dimension(dimension_type dim) {
4649  const dimension_type divisor = 1U << (32 - 1);
4650  dim = dim % divisor;
4651  return static_cast<int32_t>(dim);
4652}
4653
4654inline const Weightwatch_Traits::Threshold&
4655Weightwatch_Traits::get() {
4656  return weight;
4657}
4658
4659inline bool
4660Weightwatch_Traits::less_than(const Threshold& a, const Threshold& b) {
4661  return b - a < (1ULL << (sizeof_to_bits(sizeof(Threshold)) - 1));
4662}
4663
4664inline Weightwatch_Traits::Delta
4665Weightwatch_Traits::compute_delta(unsigned long unscaled, unsigned scale) {
4666  if ((std::numeric_limits<Delta>::max() >> scale) < unscaled) {
4667    throw std::invalid_argument("PPL::Weightwatch_Traits::"
4668                                "compute_delta(u, s):\n"
4669                                "values of u and s cause wrap around.");
4670  }
4671  return static_cast<Delta>(unscaled) << scale;
4672}
4673
4674inline void
4675Weightwatch_Traits::from_delta(Threshold& threshold, const Delta& delta) {
4676  threshold = weight + delta;
4677}
4678
4679inline void
4680maybe_abandon() {
4681#ifndef NDEBUG
4682  if (In_Assert::asserting()) {
4683    return;
4684  }
4685#endif
4686  if (Weightwatch_Traits::check_function != 0) {
4687    Weightwatch_Traits::check_function();
4688  }
4689  if (const Throwable* const p = abandon_expensive_computations) {
4690    p->throw_me();
4691  }
4692}
4693
4694inline dimension_type
4695compute_capacity(const dimension_type requested_size,
4696                 const dimension_type maximum_size) {
4697  assert(requested_size <= maximum_size);
4698  // Speculation factor 2.
4699  return (requested_size < maximum_size/2)
4700    ? (2*(requested_size + 1))
4701    : maximum_size;
4702  // Speculation factor 1.5.
4703  // return (maximum_size - requested_size > requested_size/2)
4704  //   ? requested_size + requested_size/2 + 1
4705  //   : maximum_size;
4706}
4707
4708template <typename T>
4709inline typename
4710Enable_If<Is_Native<T>::value, memory_size_type>::type
4711external_memory_in_bytes(const T&) {
4712  return 0;
4713}
4714
4715template <typename T>
4716inline typename
4717Enable_If<Is_Native<T>::value, memory_size_type>::type
4718total_memory_in_bytes(const T&) {
4719  return sizeof(T);
4720}
4721
4722inline memory_size_type
4723external_memory_in_bytes(const mpz_class& x) {
4724  return static_cast<memory_size_type>(x.get_mpz_t()[0]._mp_alloc)
4725    * PPL_SIZEOF_MP_LIMB_T;
4726}
4727
4728inline memory_size_type
4729total_memory_in_bytes(const mpz_class& x) {
4730  return sizeof(x) + external_memory_in_bytes(x);
4731}
4732
4733inline memory_size_type
4734external_memory_in_bytes(const mpq_class& x) {
4735  return external_memory_in_bytes(x.get_num())
4736    + external_memory_in_bytes(x.get_den());
4737}
4738
4739inline memory_size_type
4740total_memory_in_bytes(const mpq_class& x) {
4741  return sizeof(x) + external_memory_in_bytes(x);
4742}
4743
4744inline void
4745ascii_dump(std::ostream& s, Representation r) {
4746  if (r == DENSE) {
4747    s << "DENSE";
4748  }
4749  else {
4750    s << "SPARSE";
4751  }
4752}
4753
4754inline bool
4755ascii_load(std::istream& is, Representation& r) {
4756  std::string s;
4757  if (!(is >> s)) {
4758    return false;
4759  }
4760
4761  if (s == "DENSE")  {
4762    r = DENSE;
4763    return true;
4764  }
4765  if (s == "SPARSE")  {
4766    r = SPARSE;
4767    return true;
4768  }
4769  return false;
4770}
4771
4772inline bool
4773is_space(char c) {
4774  return isspace(c) != 0;
4775}
4776
4777template <typename RA_Container>
4778inline typename RA_Container::iterator
4779nth_iter(RA_Container& cont, dimension_type n) {
4780  typedef typename RA_Container::difference_type diff_t;
4781  return cont.begin() + static_cast<diff_t>(n);
4782}
4783
4784template <typename RA_Container>
4785inline typename RA_Container::const_iterator
4786nth_iter(const RA_Container& cont, dimension_type n) {
4787  typedef typename RA_Container::difference_type diff_t;
4788  return cont.begin() + static_cast<diff_t>(n);
4789}
4790
4791inline dimension_type
4792least_significant_one_mask(const dimension_type i) {
4793  return i & (~i + 1U);
4794}
4795
4796} // namespace Parma_Polyhedra_Library
4797
4798/* Automatically generated from PPL source file ../src/globals_defs.hh line 570. */
4799
4800/* Automatically generated from PPL source file ../src/Variable_inlines.hh line 28. */
4801#include <stdexcept>
4802
4803namespace Parma_Polyhedra_Library {
4804
4805inline dimension_type
4806Variable::max_space_dimension() {
4807  return not_a_dimension() - 1;
4808}
4809
4810inline
4811Variable::Variable(dimension_type i)
4812  : varid((i < max_space_dimension())
4813          ? i
4814          : (throw std::length_error("PPL::Variable::Variable(i):\n"
4815                                     "i exceeds the maximum allowed "
4816                                     "variable identifier."), i)) {
4817}
4818
4819inline dimension_type
4820Variable::id() const {
4821  return varid;
4822}
4823
4824inline dimension_type
4825Variable::space_dimension() const {
4826  return varid + 1;
4827}
4828
4829inline memory_size_type
4830Variable::external_memory_in_bytes() const {
4831  return 0;
4832}
4833
4834inline memory_size_type
4835Variable::total_memory_in_bytes() const {
4836  return sizeof(*this) + external_memory_in_bytes();
4837}
4838
4839inline void
4840Variable::set_output_function(output_function_type* p) {
4841  current_output_function = p;
4842}
4843
4844inline Variable::output_function_type*
4845Variable::get_output_function() {
4846  return current_output_function;
4847}
4848
4849/*! \relates Variable */
4850inline bool
4851less(const Variable v, const Variable w) {
4852  return v.id() < w.id();
4853}
4854
4855inline bool
4856Variable::Compare::operator()(const Variable x, const Variable y) const {
4857  return less(x, y);
4858}
4859
4860inline void
4861Variable::m_swap(Variable& v) {
4862  using std::swap;
4863  swap(varid, v.varid);
4864}
4865
4866inline void
4867swap(Variable& x, Variable& y) {
4868  x.m_swap(y);
4869}
4870
4871} // namespace Parma_Polyhedra_Library
4872
4873/* Automatically generated from PPL source file ../src/Variable_defs.hh line 156. */
4874
4875/* Automatically generated from PPL source file ../src/Linear_Form_defs.hh line 1. */
4876/* Linear_Form class declaration.
4877*/
4878
4879
4880/* Automatically generated from PPL source file ../src/Linear_Expression_types.hh line 1. */
4881
4882
4883namespace Parma_Polyhedra_Library {
4884
4885class Linear_Expression;
4886
4887} // namespace Parma_Polyhedra_Library
4888
4889/* Automatically generated from PPL source file ../src/Box_types.hh line 1. */
4890
4891
4892namespace Parma_Polyhedra_Library {
4893
4894template <typename Interval>
4895class Box;
4896
4897class Box_Helpers;
4898
4899} // namespace Parma_Polyhedra_Library
4900
4901/* Automatically generated from PPL source file ../src/Linear_Form_defs.hh line 32. */
4902#include <vector>
4903
4904namespace Parma_Polyhedra_Library {
4905
4906//! Swaps \p x with \p y.
4907/*! \relates Linear_Form */
4908template <typename C>
4909void swap(Linear_Form<C>& x, Linear_Form<C>& y);
4910
4911// Put them in the namespace here to declare them friend later.
4912
4913//! Returns the linear form \p f1 + \p f2.
4914/*! \relates Linear_Form */
4915template <typename C>
4916Linear_Form<C>
4917operator+(const Linear_Form<C>& f1, const Linear_Form<C>& f2);
4918
4919//! Returns the linear form \p v + \p f.
4920/*! \relates Linear_Form */
4921template <typename C>
4922Linear_Form<C>
4923operator+(Variable v, const Linear_Form<C>& f);
4924
4925//! Returns the linear form \p f + \p v.
4926/*! \relates Linear_Form */
4927template <typename C>
4928Linear_Form<C>
4929operator+(const Linear_Form<C>& f, Variable v);
4930
4931//! Returns the linear form \p n + \p f.
4932/*! \relates Linear_Form */
4933template <typename C>
4934Linear_Form<C>
4935operator+(const C& n, const Linear_Form<C>& f);
4936
4937//! Returns the linear form \p f + \p n.
4938/*! \relates Linear_Form */
4939template <typename C>
4940Linear_Form<C>
4941operator+(const Linear_Form<C>& f, const C& n);
4942
4943//! Returns the linear form \p f.
4944/*! \relates Linear_Form */
4945template <typename C>
4946Linear_Form<C>
4947operator+(const Linear_Form<C>& f);
4948
4949//! Returns the linear form - \p f.
4950/*! \relates Linear_Form */
4951template <typename C>
4952Linear_Form<C>
4953operator-(const Linear_Form<C>& f);
4954
4955//! Returns the linear form \p f1 - \p f2.
4956/*! \relates Linear_Form */
4957template <typename C>
4958Linear_Form<C>
4959operator-(const Linear_Form<C>& f1, const Linear_Form<C>& f2);
4960
4961//! Returns the linear form \p v - \p f.
4962/*! \relates Linear_Form */
4963template <typename C>
4964Linear_Form<C>
4965operator-(Variable v, const Linear_Form<C>& f);
4966
4967//! Returns the linear form \p f - \p v.
4968/*! \relates Linear_Form */
4969template <typename C>
4970Linear_Form<C>
4971operator-(const Linear_Form<C>& f, Variable v);
4972
4973//! Returns the linear form \p n - \p f.
4974/*! \relates Linear_Form */
4975template <typename C>
4976Linear_Form<C>
4977operator-(const C& n, const Linear_Form<C>& f);
4978
4979//! Returns the linear form \p f - \p n.
4980/*! \relates Linear_Form */
4981template <typename C>
4982Linear_Form<C>
4983operator-(const Linear_Form<C>& f, const C& n);
4984
4985//! Returns the linear form \p n * \p f.
4986/*! \relates Linear_Form */
4987template <typename C>
4988Linear_Form<C>
4989operator*(const C& n, const Linear_Form<C>& f);
4990
4991//! Returns the linear form \p f * \p n.
4992/*! \relates Linear_Form */
4993template <typename C>
4994Linear_Form<C>
4995operator*(const Linear_Form<C>& f, const C& n);
4996
4997//! Returns the linear form \p f1 + \p f2 and assigns it to \p e1.
4998/*! \relates Linear_Form */
4999template <typename C>
5000Linear_Form<C>&
5001operator+=(Linear_Form<C>& f1, const Linear_Form<C>& f2);
5002
5003//! Returns the linear form \p f + \p v and assigns it to \p f.
5004/*! \relates Linear_Form
5005  \exception std::length_error
5006  Thrown if the space dimension of \p v exceeds
5007  <CODE>Linear_Form::max_space_dimension()</CODE>.
5008 */
5009template <typename C>
5010Linear_Form<C>&
5011operator+=(Linear_Form<C>& f, Variable v);
5012
5013//! Returns the linear form \p f + \p n and assigns it to \p f.
5014/*! \relates Linear_Form */
5015template <typename C>
5016Linear_Form<C>&
5017operator+=(Linear_Form<C>& f, const C& n);
5018
5019//! Returns the linear form \p f1 - \p f2 and assigns it to \p f1.
5020/*! \relates Linear_Form */
5021template <typename C>
5022Linear_Form<C>&
5023operator-=(Linear_Form<C>& f1, const Linear_Form<C>& f2);
5024
5025//! Returns the linear form \p f - \p v and assigns it to \p f.
5026/*! \relates Linear_Form
5027  \exception std::length_error
5028  Thrown if the space dimension of \p v exceeds
5029  <CODE>Linear_Form::max_space_dimension()</CODE>.
5030 */
5031template <typename C>
5032Linear_Form<C>&
5033operator-=(Linear_Form<C>& f, Variable v);
5034
5035//! Returns the linear form \p f - \p n and assigns it to \p f.
5036/*! \relates Linear_Form */
5037template <typename C>
5038Linear_Form<C>&
5039operator-=(Linear_Form<C>& f, const C& n);
5040
5041//! Returns the linear form \p n * \p f and assigns it to \p f.
5042/*! \relates Linear_Form */
5043template <typename C>
5044Linear_Form<C>&
5045operator*=(Linear_Form<C>& f, const C& n);
5046
5047//! Returns the linear form \p f / \p n and assigns it to \p f.
5048/*!
5049   \relates Linear_Form
5050   Performs the division of a linear form by a scalar. It is up to the user to
5051   ensure that division by 0 is not performed.
5052*/
5053template <typename C>
5054Linear_Form<C>&
5055operator/=(Linear_Form<C>& f, const C& n);
5056
5057//! Returns <CODE>true</CODE> if and only if \p x and \p y are equal.
5058/*! \relates Linear_Form */
5059template <typename C>
5060bool
5061operator==(const Linear_Form<C>& x, const Linear_Form<C>& y);
5062
5063//! Returns <CODE>true</CODE> if and only if \p x and \p y are different.
5064/*! \relates Linear_Form */
5065template <typename C>
5066bool
5067operator!=(const Linear_Form<C>& x, const Linear_Form<C>& y);
5068
5069namespace IO_Operators {
5070
5071//! Output operator.
5072/*! \relates Parma_Polyhedra_Library::Linear_Form */
5073template <typename C>
5074std::ostream& operator<<(std::ostream& s, const Linear_Form<C>& f);
5075
5076} // namespace IO_Operators
5077
5078} // namespace Parma_Polyhedra_Library
5079
5080//! A linear form with interval coefficients.
5081/*! \ingroup PPL_CXX_interface
5082  An object of the class Linear_Form represents the interval linear form
5083  \f[
5084    \sum_{i=0}^{n-1} a_i x_i + b
5085  \f]
5086  where \f$n\f$ is the dimension of the vector space,
5087  each \f$a_i\f$ is the coefficient
5088  of the \f$i\f$-th variable \f$x_i\f$
5089  and \f$b\f$ is the inhomogeneous term.
5090  The coefficients and the inhomogeneous term of the linear form
5091  have the template parameter \p C as their type. \p C must be the
5092  type of an Interval.
5093
5094  \par How to build a linear form.
5095  A full set of functions is defined in order to provide a convenient
5096  interface for building complex linear forms starting from simpler ones
5097  and from objects of the classes Variable and \p C. Available operators
5098  include binary addition and subtraction, as well as multiplication and
5099  division by a coefficient.
5100  The space dimension of a linear form is defined as
5101  the highest variable dimension among variables that have a nonzero
5102  coefficient in the linear form, or zero if no such variable exists.
5103  The space dimension for each variable \f$x_i\f$ is given by \f$i + 1\f$.
5104
5105  \par Example
5106  Given the type \p T of an Interval with floating point coefficients (though
5107  any integral type may also be used), the following code builds the interval
5108  linear form \f$lf = x_5 - x_2 + 1\f$ with space dimension 6:
5109  \code
5110  Variable x5(5);
5111  Variable x2(2);
5112  T x5_coefficient;
5113  x5_coefficient.lower() = 2.0;
5114  x5_coefficient.upper() = 3.0;
5115  T inhomogeneous_term;
5116  inhomogeneous_term.lower() = 4.0;
5117  inhomogeneous_term.upper() = 8.0;
5118  Linear_Form<T> lf(x2);
5119  lf = -lf;
5120  lf += Linear_Form<T>(x2);
5121  Linear_Form<T> lf_x5(x5);
5122  lf_x5 *= x5_coefficient;
5123  lf += lf_x5;
5124  \endcode
5125  Note that \c lf_x5 is created with space dimension 6, while \c lf is
5126  created with space dimension 0 and then extended first to space
5127  dimension 2 when \c x2 is subtracted and finally to space dimension
5128  6 when \c lf_x5 is added.
5129*/
5130template <typename C>
5131class Parma_Polyhedra_Library::Linear_Form {
5132public:
5133  //! Default constructor: returns a copy of Linear_Form::zero().
5134  Linear_Form();
5135
5136  //! Ordinary copy constructor.
5137  Linear_Form(const Linear_Form& f);
5138
5139  //! Destructor.
5140  ~Linear_Form();
5141
5142  //! Builds the linear form corresponding to the inhomogeneous term \p n.
5143  explicit Linear_Form(const C& n);
5144
5145  //! Builds the linear form corresponding to the variable \p v.
5146  /*!
5147    \exception std::length_error
5148    Thrown if the space dimension of \p v exceeds
5149    <CODE>Linear_Form::max_space_dimension()</CODE>.
5150  */
5151  Linear_Form(Variable v);
5152
5153  //! Builds a linear form approximating the linear expression \p e.
5154  Linear_Form(const Linear_Expression& e);
5155
5156  //! Returns the maximum space dimension a Linear_Form can handle.
5157  static dimension_type max_space_dimension();
5158
5159  //! Returns the dimension of the vector space enclosing \p *this.
5160  dimension_type space_dimension() const;
5161
5162  //! Returns the coefficient of \p v in \p *this.
5163  const C& coefficient(Variable v) const;
5164
5165  //! Returns the inhomogeneous term of \p *this.
5166  const C& inhomogeneous_term() const;
5167
5168  //! Negates all the coefficients of \p *this.
5169  void negate();
5170
5171  /*! \brief
5172    Returns a lower bound to the total size in bytes of the memory
5173    occupied by \p *this.
5174  */
5175  memory_size_type total_memory_in_bytes() const;
5176
5177  //! Returns the size in bytes of the memory managed by \p *this.
5178  memory_size_type external_memory_in_bytes() const;
5179
5180  PPL_OUTPUT_DECLARATIONS
5181
5182  /*! \brief
5183    Loads from \p s an ASCII representation (as produced by
5184    ascii_dump(std::ostream&) const) and sets \p *this accordingly.
5185    Returns <CODE>true</CODE> if successful, <CODE>false</CODE> otherwise.
5186  */
5187  bool ascii_load(std::istream& s);
5188
5189  //! Checks if all the invariants are satisfied.
5190  bool OK() const;
5191
5192  //! Swaps \p *this with \p y.
5193  void m_swap(Linear_Form& y);
5194
5195  // Floating point analysis related methods.
5196
5197  /*! \brief
5198    Verifies if the linear form overflows.
5199
5200    \return
5201    Returns <CODE>false</CODE> if all coefficients in \p lf are bounded,
5202    <CODE>true</CODE> otherwise.
5203
5204    \p T must be the type of possibly unbounded quantities.
5205  */
5206  bool overflows() const;
5207
5208  /*! \brief
5209    Computes the relative error associated to floating point computations
5210    that operate on a quantity that is overapproximated by \p *this.
5211
5212    \param analyzed_format The floating point format used by the analyzed
5213    program.
5214    \param result Becomes the linear form corresponding to the relative
5215    error committed.
5216
5217    This method makes <CODE>result</CODE> become a linear form
5218    obtained by evaluating the function \f$\varepsilon_{\mathbf{f}}(l)\f$
5219    on the linear form. This function is defined as:
5220    \f[
5221    \varepsilon_{\mathbf{f}}\left([a, b]+\sum_{v \in \cV}[a_{v}, b_{v}]v\right)
5222    \defeq
5223    (\textrm{max}(|a|, |b|) \amifp [-\beta^{-\textrm{p}}, \beta^{-\textrm{p}}])
5224    +
5225    \sum_{v \in \cV}(\textrm{max}(|a_{v}|,|b_{v}|)
5226    \amifp
5227    [-\beta^{-\textrm{p}}, \beta^{-\textrm{p}}])v
5228    \f]
5229    where p is the fraction size in bits for the format \f$\mathbf{f}\f$ and
5230    \f$\beta\f$ the base.
5231
5232    The result is undefined if \p T is not the type of an interval with
5233    floating point boundaries.
5234  */
5235  void relative_error(Floating_Point_Format analyzed_format,
5236                      Linear_Form& result) const;
5237
5238  /*! \brief
5239    Makes \p result become an interval that overapproximates all the
5240    possible values of \p *this.
5241
5242    \param oracle The FP_Oracle to be queried.
5243    \param result The linear form that will store the result.
5244
5245    \return <CODE>true</CODE> if the operation was successful,
5246    <CODE>false</CODE> otherwise (the possibility of failure
5247    depends on the oracle's implementation).
5248
5249    \par Template type parameters
5250
5251    - The class template parameter \p Target specifies the implementation
5252    of Concrete_Expression to be used.
5253
5254    This method makes <CODE>result</CODE> become
5255    \f$\iota(lf)\rho^{\#}\f$, that is an interval defined as:
5256    \f[
5257    \iota\left(i + \sum_{v \in \cV}i_{v}v\right)\rho^{\#}
5258    \defeq
5259    i \asifp \left(\bigoplus_{v \in \cV}{}^{\#}i_{v} \amifp
5260    \rho^{\#}(v)\right)
5261    \f]
5262    where \f$\rho^{\#}(v)\f$ is an interval (provided by the oracle)
5263    that correctly approximates the value of \f$v\f$.
5264
5265    The result is undefined if \p C is not the type of an interval with
5266    floating point boundaries.
5267  */
5268  template <typename Target>
5269  bool intervalize(const FP_Oracle<Target,C>& oracle, C& result) const;
5270
5271private:
5272  //! The generic coefficient equal to the singleton zero.
5273  static C zero;
5274
5275  //! Type of the container vector.
5276  typedef std::vector<C> vec_type;
5277
5278  //! The container vector.
5279  vec_type vec;
5280
5281  //! Implementation sizing constructor.
5282  /*!
5283    The bool parameter is just to avoid problems with
5284    the constructor Linear_Form(const C& n).
5285  */
5286  Linear_Form(dimension_type sz, bool);
5287
5288  /*! \brief
5289    Builds the linear form corresponding to the difference of
5290    \p v and \p w.
5291
5292    \exception std::length_error
5293    Thrown if the space dimension of \p v or the one of \p w exceed
5294    <CODE>Linear_Form::max_space_dimension()</CODE>.
5295  */
5296  Linear_Form(Variable v, Variable w);
5297
5298  //! Gives the number of generic coefficients currently in use.
5299  dimension_type size() const;
5300
5301  //! Extends the vector of \p *this to size \p sz.
5302  void extend(dimension_type sz);
5303
5304  //! Returns a reference to \p vec[i].
5305  C& operator[](dimension_type i);
5306
5307  //! Returns a const reference to \p vec[i].
5308  const C& operator[](dimension_type i) const;
5309
5310  friend Linear_Form<C>
5311  operator+<C>(const Linear_Form<C>& f1, const Linear_Form<C>& f2);
5312  friend Linear_Form<C>
5313  operator+<C>(const C& n, const Linear_Form<C>& f);
5314  friend Linear_Form<C>
5315  operator+<C>(const Linear_Form<C>& f, const C& n);
5316  friend Linear_Form<C>
5317  operator+<C>(Variable v, const Linear_Form<C>& f);
5318
5319  friend Linear_Form<C>
5320  operator-<C>(const Linear_Form<C>& f);
5321
5322  friend Linear_Form<C>
5323  operator-<C>(const Linear_Form<C>& f1, const Linear_Form<C>& f2);
5324  friend Linear_Form<C>
5325  operator-<C>(const C& n, const Linear_Form<C>& f);
5326  friend Linear_Form<C>
5327  operator-<C>(const Linear_Form<C>& f, const C& n);
5328  friend Linear_Form<C>
5329  operator-<C>(Variable v, const Linear_Form<C>& f);
5330  friend Linear_Form<C>
5331  operator-<C>(const Linear_Form<C>& f, Variable v);
5332
5333  friend Linear_Form<C>
5334  operator*<C>(const C& n, const Linear_Form<C>& f);
5335  friend Linear_Form<C>
5336  operator*<C>(const Linear_Form<C>& f, const C& n);
5337
5338  friend Linear_Form<C>&
5339  operator+=<C>(Linear_Form<C>& f1, const Linear_Form<C>& f2);
5340  friend Linear_Form<C>&
5341  operator+=<C>(Linear_Form<C>& f, Variable v);
5342  friend Linear_Form<C>&
5343  operator+=<C>(Linear_Form<C>& f, const C& n);
5344
5345  friend Linear_Form<C>&
5346  operator-=<C>(Linear_Form<C>& f1, const Linear_Form<C>& f2);
5347  friend Linear_Form<C>&
5348  operator-=<C>(Linear_Form<C>& f, Variable v);
5349  friend Linear_Form<C>&
5350  operator-=<C>(Linear_Form<C>& f, const C& n);
5351
5352  friend Linear_Form<C>&
5353  operator*=<C>(Linear_Form<C>& f, const C& n);
5354
5355  friend Linear_Form<C>&
5356  operator/=<C>(Linear_Form<C>& f, const C& n);
5357
5358  friend bool
5359  operator==<C>(const Linear_Form<C>& x, const Linear_Form<C>& y);
5360
5361  friend std::ostream&
5362  Parma_Polyhedra_Library::IO_Operators
5363  ::operator<<<C>(std::ostream& s, const Linear_Form<C>& f);
5364};
5365
5366/* Automatically generated from PPL source file ../src/Linear_Form_inlines.hh line 1. */
5367/* Linear_Form class implementation: inline functions.
5368*/
5369
5370
5371/* Automatically generated from PPL source file ../src/Linear_Form_inlines.hh line 28. */
5372#include <iostream>
5373#include <stdexcept>
5374
5375namespace Parma_Polyhedra_Library {
5376
5377template <typename C>
5378inline dimension_type
5379Linear_Form<C>::max_space_dimension() {
5380  return vec_type().max_size() - 1;
5381}
5382
5383template <typename C>
5384inline
5385Linear_Form<C>::Linear_Form()
5386  : vec(1, zero) {
5387  vec.reserve(compute_capacity(1, vec_type().max_size()));
5388}
5389
5390template <typename C>
5391inline
5392Linear_Form<C>::Linear_Form(dimension_type sz, bool)
5393  : vec(sz, zero) {
5394  vec.reserve(compute_capacity(sz, vec_type().max_size()));
5395}
5396
5397template <typename C>
5398inline
5399Linear_Form<C>::Linear_Form(const Linear_Form& f)
5400  : vec(f.vec) {
5401}
5402
5403template <typename C>
5404inline
5405Linear_Form<C>::~Linear_Form() {
5406}
5407
5408template <typename C>
5409inline dimension_type
5410Linear_Form<C>::size() const {
5411  return vec.size();
5412}
5413
5414template <typename C>
5415inline void
5416Linear_Form<C>::extend(dimension_type sz) {
5417  assert(sz > size());
5418  vec.reserve(compute_capacity(sz, vec_type().max_size()));
5419  vec.resize(sz, zero);
5420}
5421
5422template <typename C>
5423inline
5424Linear_Form<C>::Linear_Form(const C& n)
5425  : vec(1, n) {
5426  vec.reserve(compute_capacity(1, vec_type().max_size()));
5427}
5428
5429template <typename C>
5430inline dimension_type
5431Linear_Form<C>::space_dimension() const {
5432  return size() - 1;
5433}
5434
5435template <typename C>
5436inline const C&
5437Linear_Form<C>::coefficient(Variable v) const {
5438  if (v.space_dimension() > space_dimension()) {
5439    return zero;
5440  }
5441  return vec[v.id()+1];
5442}
5443
5444template <typename C>
5445inline C&
5446Linear_Form<C>::operator[](dimension_type i) {
5447  assert(i < size());
5448  return vec[i];
5449}
5450
5451template <typename C>
5452inline const C&
5453Linear_Form<C>::operator[](dimension_type i) const {
5454  assert(i < size());
5455  return vec[i];
5456}
5457
5458template <typename C>
5459inline const C&
5460Linear_Form<C>::inhomogeneous_term() const {
5461  return vec[0];
5462}
5463
5464template <typename C>
5465inline memory_size_type
5466Linear_Form<C>::total_memory_in_bytes() const {
5467  return sizeof(*this) + external_memory_in_bytes();
5468}
5469
5470/*! \relates Linear_Form */
5471template <typename C>
5472inline Linear_Form<C>
5473operator+(const Linear_Form<C>& f) {
5474  return f;
5475}
5476
5477/*! \relates Linear_Form */
5478template <typename C>
5479inline Linear_Form<C>
5480operator+(const Linear_Form<C>& f, const C& n) {
5481  return n + f;
5482}
5483
5484/*! \relates Linear_Form */
5485template <typename C>
5486inline Linear_Form<C>
5487operator+(const Linear_Form<C>& f, const Variable v) {
5488  return v + f;
5489}
5490
5491/*! \relates Linear_Form */
5492template <typename C>
5493inline Linear_Form<C>
5494operator-(const Linear_Form<C>& f, const C& n) {
5495  return -n + f;
5496}
5497
5498/*! \relates Linear_Form */
5499template <typename C>
5500inline Linear_Form<C>
5501operator-(const Variable v, const Variable w) {
5502  return Linear_Form<C>(v, w);
5503}
5504
5505/*! \relates Linear_Form */
5506template <typename C>
5507inline Linear_Form<C>
5508operator*(const Linear_Form<C>& f, const C& n) {
5509  return n * f;
5510}
5511
5512/*! \relates Linear_Form */
5513template <typename C>
5514inline Linear_Form<C>&
5515operator+=(Linear_Form<C>& f, const C& n) {
5516  f[0] += n;
5517  return f;
5518}
5519
5520/*! \relates Linear_Form */
5521template <typename C>
5522inline Linear_Form<C>&
5523operator-=(Linear_Form<C>& f, const C& n) {
5524  f[0] -= n;
5525  return f;
5526}
5527
5528/*! \relates Linear_Form */
5529template <typename C>
5530inline bool
5531operator!=(const Linear_Form<C>& x, const Linear_Form<C>& y) {
5532  return !(x == y);
5533}
5534
5535template <typename C>
5536inline void
5537Linear_Form<C>::m_swap(Linear_Form& y) {
5538  using std::swap;
5539  swap(vec, y.vec);
5540}
5541
5542template <typename C>
5543inline void
5544Linear_Form<C>::ascii_dump(std::ostream& s) const {
5545  using namespace IO_Operators;
5546  dimension_type space_dim = space_dimension();
5547  s << space_dim << "\n";
5548  for (dimension_type i = 0; i <= space_dim; ++i) {
5549    const char separator = ' ';
5550    s << vec[i] << separator;
5551  }
5552  s << "\n";
5553}
5554
5555template <typename C>
5556inline bool
5557Linear_Form<C>::ascii_load(std::istream& s) {
5558  using namespace IO_Operators;
5559  dimension_type new_dim;
5560  if (!(s >> new_dim)) {
5561    return false;
5562  }
5563
5564  vec.resize(new_dim + 1, zero);
5565  for (dimension_type i = 0; i <= new_dim; ++i) {
5566    if (!(s >> vec[i])) {
5567      return false;
5568    }
5569  }
5570
5571  PPL_ASSERT(OK());
5572  return true;
5573}
5574
5575// Floating point analysis related methods.
5576template <typename C>
5577inline bool
5578Linear_Form<C>::overflows() const {
5579  if (!inhomogeneous_term().is_bounded()) {
5580    return true;
5581  }
5582  for (dimension_type i = space_dimension(); i-- > 0; ) {
5583    if (!coefficient(Variable(i)).is_bounded()) {
5584      return true;
5585    }
5586  }
5587
5588  return false;
5589}
5590
5591/*! \relates Linear_Form */
5592template <typename C>
5593inline void
5594swap(Linear_Form<C>& x, Linear_Form<C>& y) {
5595  x.m_swap(y);
5596}
5597
5598} // namespace Parma_Polyhedra_Library
5599
5600/* Automatically generated from PPL source file ../src/Linear_Form_defs.hh line 497. */
5601// Linear_Form_templates.hh is not included here on purpose.
5602
5603/* Automatically generated from PPL source file ../src/Float_inlines.hh line 30. */
5604#include <climits>
5605
5606namespace Parma_Polyhedra_Library {
5607
5608inline int
5609float_ieee754_half::inf_sign() const {
5610  if (word == NEG_INF) {
5611    return -1;
5612  }
5613  if (word == POS_INF) {
5614    return 1;
5615  }
5616  return 0;
5617}
5618
5619inline bool
5620float_ieee754_half::is_nan() const {
5621  return (word & ~SGN_MASK) > POS_INF;
5622}
5623
5624inline int
5625float_ieee754_half::zero_sign() const {
5626  if (word == NEG_ZERO) {
5627    return -1;
5628  }
5629  if (word == POS_ZERO) {
5630    return 1;
5631  }
5632  return 0;
5633}
5634
5635inline void
5636float_ieee754_half::negate() {
5637  word ^= SGN_MASK;
5638}
5639
5640inline bool
5641float_ieee754_half::sign_bit() const {
5642  return (word & SGN_MASK) != 0;
5643}
5644
5645inline void
5646float_ieee754_half::dec() {
5647  --word;
5648}
5649
5650inline void
5651float_ieee754_half::inc() {
5652  ++word;
5653}
5654
5655inline void
5656float_ieee754_half::set_max(bool negative) {
5657  word = WRD_MAX;
5658  if (negative) {
5659    word |= SGN_MASK;
5660  }
5661}
5662
5663inline void
5664float_ieee754_half::build(bool negative, mpz_t mantissa, int exponent) {
5665  word = static_cast<uint16_t>(mpz_get_ui(mantissa)
5666                               & ((1UL << MANTISSA_BITS) - 1));
5667  if (negative) {
5668    word |= SGN_MASK;
5669  }
5670  const int exponent_repr = exponent + EXPONENT_BIAS;
5671  PPL_ASSERT(exponent_repr >= 0 && exponent_repr < (1 << EXPONENT_BITS));
5672  word |= static_cast<uint16_t>(exponent_repr) << MANTISSA_BITS;
5673}
5674
5675inline int
5676float_ieee754_single::inf_sign() const {
5677  if (word == NEG_INF) {
5678    return -1;
5679  }
5680  if (word == POS_INF) {
5681    return 1;
5682  }
5683  return 0;
5684}
5685
5686inline bool
5687float_ieee754_single::is_nan() const {
5688  return (word & ~SGN_MASK) > POS_INF;
5689}
5690
5691inline int
5692float_ieee754_single::zero_sign() const {
5693  if (word == NEG_ZERO) {
5694    return -1;
5695  }
5696  if (word == POS_ZERO) {
5697    return 1;
5698  }
5699  return 0;
5700}
5701
5702inline void
5703float_ieee754_single::negate() {
5704  word ^= SGN_MASK;
5705}
5706
5707inline bool
5708float_ieee754_single::sign_bit() const {
5709  return (word & SGN_MASK) != 0;
5710}
5711
5712inline void
5713float_ieee754_single::dec() {
5714  --word;
5715}
5716
5717inline void
5718float_ieee754_single::inc() {
5719  ++word;
5720}
5721
5722inline void
5723float_ieee754_single::set_max(bool negative) {
5724  word = WRD_MAX;
5725  if (negative) {
5726    word |= SGN_MASK;
5727  }
5728}
5729
5730inline void
5731float_ieee754_single::build(bool negative, mpz_t mantissa, int exponent) {
5732  word = static_cast<uint32_t>(mpz_get_ui(mantissa)
5733                               & ((1UL << MANTISSA_BITS) - 1));
5734  if (negative) {
5735    word |= SGN_MASK;
5736  }
5737  const int exponent_repr = exponent + EXPONENT_BIAS;
5738  PPL_ASSERT(exponent_repr >= 0 && exponent_repr < (1 << EXPONENT_BITS));
5739  word |= static_cast<uint32_t>(exponent_repr) << MANTISSA_BITS;
5740}
5741
5742inline int
5743float_ieee754_double::inf_sign() const {
5744  if (lsp != LSP_INF) {
5745    return 0;
5746  }
5747  if (msp == MSP_NEG_INF) {
5748    return -1;
5749  }
5750  if (msp == MSP_POS_INF) {
5751    return 1;
5752  }
5753  return 0;
5754}
5755
5756inline bool
5757float_ieee754_double::is_nan() const {
5758  const uint32_t a = msp & ~MSP_SGN_MASK;
5759  return a > MSP_POS_INF || (a == MSP_POS_INF && lsp != LSP_INF);
5760}
5761
5762inline int
5763float_ieee754_double::zero_sign() const {
5764  if (lsp != LSP_ZERO) {
5765    return 0;
5766  }
5767  if (msp == MSP_NEG_ZERO) {
5768    return -1;
5769  }
5770  if (msp == MSP_POS_ZERO) {
5771    return 1;
5772  }
5773  return 0;
5774}
5775
5776inline void
5777float_ieee754_double::negate() {
5778  msp ^= MSP_SGN_MASK;
5779}
5780
5781inline bool
5782float_ieee754_double::sign_bit() const {
5783  return (msp & MSP_SGN_MASK) != 0;
5784}
5785
5786inline void
5787float_ieee754_double::dec() {
5788  if (lsp == 0) {
5789    --msp;
5790    lsp = LSP_MAX;
5791  }
5792  else {
5793    --lsp;
5794  }
5795}
5796
5797inline void
5798float_ieee754_double::inc() {
5799  if (lsp == LSP_MAX) {
5800    ++msp;
5801    lsp = 0;
5802  }
5803  else {
5804    ++lsp;
5805  }
5806}
5807
5808inline void
5809float_ieee754_double::set_max(bool negative) {
5810  msp = MSP_MAX;
5811  lsp = LSP_MAX;
5812  if (negative) {
5813    msp |= MSP_SGN_MASK;
5814  }
5815}
5816
5817inline void
5818float_ieee754_double::build(bool negative, mpz_t mantissa, int exponent) {
5819  unsigned long m;
5820#if ULONG_MAX == 0xffffffffUL
5821  lsp = mpz_get_ui(mantissa);
5822  mpz_tdiv_q_2exp(mantissa, mantissa, 32);
5823  m = mpz_get_ui(mantissa);
5824#else
5825  m = mpz_get_ui(mantissa);
5826  lsp = static_cast<uint32_t>(m & LSP_MAX);
5827  m >>= 32;
5828#endif
5829  msp = static_cast<uint32_t>(m & ((1UL << (MANTISSA_BITS - 32)) - 1));
5830  if (negative) {
5831    msp |= MSP_SGN_MASK;
5832  }
5833  const int exponent_repr = exponent + EXPONENT_BIAS;
5834  PPL_ASSERT(exponent_repr >= 0 && exponent_repr < (1 << EXPONENT_BITS));
5835  msp |= static_cast<uint32_t>(exponent_repr) << (MANTISSA_BITS - 32);
5836}
5837
5838inline int
5839float_ibm_single::inf_sign() const {
5840  if (word == NEG_INF) {
5841    return -1;
5842  }
5843  if (word == POS_INF) {
5844    return 1;
5845  }
5846  return 0;
5847}
5848
5849inline bool
5850float_ibm_single::is_nan() const {
5851  return (word & ~SGN_MASK) > POS_INF;
5852}
5853
5854inline int
5855float_ibm_single::zero_sign() const {
5856  if (word == NEG_ZERO) {
5857    return -1;
5858  }
5859  if (word == POS_ZERO) {
5860    return 1;
5861  }
5862  return 0;
5863}
5864
5865inline void
5866float_ibm_single::negate() {
5867  word ^= SGN_MASK;
5868}
5869
5870inline bool
5871float_ibm_single::sign_bit() const {
5872  return (word & SGN_MASK) != 0;
5873}
5874
5875inline void
5876float_ibm_single::dec() {
5877  --word;
5878}
5879
5880inline void
5881float_ibm_single::inc() {
5882  ++word;
5883}
5884
5885inline void
5886float_ibm_single::set_max(bool negative) {
5887  word = WRD_MAX;
5888  if (negative) {
5889    word |= SGN_MASK;
5890  }
5891}
5892
5893inline void
5894float_ibm_single::build(bool negative, mpz_t mantissa, int exponent) {
5895  word = static_cast<uint32_t>(mpz_get_ui(mantissa)
5896                               & ((1UL << MANTISSA_BITS) - 1));
5897  if (negative) {
5898    word |= SGN_MASK;
5899  }
5900  const int exponent_repr = exponent + EXPONENT_BIAS;
5901  PPL_ASSERT(exponent_repr >= 0 && exponent_repr < (1 << EXPONENT_BITS));
5902  word |= static_cast<uint32_t>(exponent_repr) << MANTISSA_BITS;
5903}
5904
5905inline int
5906float_intel_double_extended::inf_sign() const {
5907  if (lsp != LSP_INF) {
5908    return 0;
5909  }
5910  const uint32_t a = msp & MSP_NEG_INF;
5911  if (a == MSP_NEG_INF) {
5912    return -1;
5913  }
5914  if (a == MSP_POS_INF) {
5915    return 1;
5916  }
5917  return 0;
5918}
5919
5920inline bool
5921float_intel_double_extended::is_nan() const {
5922  return (msp & MSP_POS_INF) == MSP_POS_INF
5923    && lsp != LSP_INF;
5924}
5925
5926inline int
5927float_intel_double_extended::zero_sign() const {
5928  if (lsp != LSP_ZERO) {
5929    return 0;
5930  }
5931  const uint32_t a = msp & MSP_NEG_INF;
5932  if (a == MSP_NEG_ZERO) {
5933    return -1;
5934  }
5935  if (a == MSP_POS_ZERO) {
5936    return 1;
5937  }
5938  return 0;
5939}
5940
5941inline void
5942float_intel_double_extended::negate() {
5943  msp ^= MSP_SGN_MASK;
5944}
5945
5946inline bool
5947float_intel_double_extended::sign_bit() const {
5948  return (msp & MSP_SGN_MASK) != 0;
5949}
5950
5951inline void
5952float_intel_double_extended::dec() {
5953  if ((lsp & LSP_DMAX) == 0) {
5954    --msp;
5955    lsp = ((msp & MSP_NEG_INF) == 0) ? LSP_DMAX : LSP_NMAX;
5956  }
5957  else {
5958    --lsp;
5959  }
5960}
5961
5962inline void
5963float_intel_double_extended::inc() {
5964  if ((lsp & LSP_DMAX) == LSP_DMAX) {
5965    ++msp;
5966    lsp = LSP_DMAX + 1;
5967  }
5968  else {
5969    ++lsp;
5970  }
5971}
5972
5973inline void
5974float_intel_double_extended::set_max(bool negative) {
5975  msp = MSP_MAX;
5976  lsp = LSP_NMAX;
5977  if (negative) {
5978    msp |= MSP_SGN_MASK;
5979  }
5980}
5981
5982inline void
5983float_intel_double_extended::build(bool negative,
5984                                   mpz_t mantissa, int exponent) {
5985#if ULONG_MAX == 0xffffffffUL
5986  mpz_export(&lsp, 0, -1, sizeof(lsp), 0, 0, mantissa);
5987#else
5988  lsp = mpz_get_ui(mantissa);
5989#endif
5990  msp = (negative ? MSP_SGN_MASK : 0);
5991  const int exponent_repr = exponent + EXPONENT_BIAS;
5992  PPL_ASSERT(exponent_repr >= 0 && exponent_repr < (1 << EXPONENT_BITS));
5993  msp |= static_cast<uint32_t>(exponent_repr);
5994}
5995
5996inline int
5997float_ieee754_quad::inf_sign() const {
5998  if (lsp != LSP_INF) {
5999    return 0;
6000  }
6001  if (msp == MSP_NEG_INF) {
6002    return -1;
6003  }
6004  if (msp == MSP_POS_INF) {
6005    return 1;
6006  }
6007  return 0;
6008}
6009
6010inline bool
6011float_ieee754_quad::is_nan() const {
6012  return (msp & ~MSP_SGN_MASK) == MSP_POS_INF
6013    && lsp != LSP_INF;
6014}
6015
6016inline int
6017float_ieee754_quad::zero_sign() const {
6018  if (lsp != LSP_ZERO) {
6019    return 0;
6020  }
6021  if (msp == MSP_NEG_ZERO) {
6022    return -1;
6023  }
6024  if (msp == MSP_POS_ZERO) {
6025    return 1;
6026  }
6027  return 0;
6028}
6029
6030inline void
6031float_ieee754_quad::negate() {
6032  msp ^= MSP_SGN_MASK;
6033}
6034
6035inline bool
6036float_ieee754_quad::sign_bit() const {
6037  return (msp & MSP_SGN_MASK) != 0;
6038}
6039
6040inline void
6041float_ieee754_quad::dec() {
6042  if (lsp == 0) {
6043    --msp;
6044    lsp = LSP_MAX;
6045  }
6046  else {
6047    --lsp;
6048  }
6049}
6050
6051inline void
6052float_ieee754_quad::inc() {
6053  if (lsp == LSP_MAX) {
6054    ++msp;
6055    lsp = 0;
6056  }
6057  else {
6058    ++lsp;
6059  }
6060}
6061
6062inline void
6063float_ieee754_quad::set_max(bool negative) {
6064  msp = MSP_MAX;
6065  lsp = LSP_MAX;
6066  if (negative) {
6067    msp |= MSP_SGN_MASK;
6068  }
6069}
6070
6071inline void
6072float_ieee754_quad::build(bool negative, mpz_t mantissa, int exponent) {
6073  uint64_t parts[2];
6074  mpz_export(parts, 0, -1, sizeof(parts[0]), 0, 0, mantissa);
6075  lsp = parts[0];
6076  msp = parts[1];
6077  msp &= ((static_cast<uint64_t>(1) << (MANTISSA_BITS - 64)) - 1);
6078  if (negative) {
6079    msp |= MSP_SGN_MASK;
6080  }
6081  const int exponent_repr = exponent + EXPONENT_BIAS;
6082  PPL_ASSERT(exponent_repr >= 0 && exponent_repr < (1 << EXPONENT_BITS));
6083  msp |= static_cast<uint64_t>(exponent_repr) << (MANTISSA_BITS - 64);
6084}
6085
6086inline bool
6087is_less_precise_than(Floating_Point_Format f1, Floating_Point_Format f2) {
6088  return f1 < f2;
6089}
6090
6091inline unsigned int
6092msb_position(unsigned long long v) {
6093  return static_cast<unsigned int>(sizeof_to_bits(sizeof(v))) - 1U - clz(v);
6094}
6095
6096template <typename FP_Interval_Type>
6097inline void
6098affine_form_image(std::map<dimension_type,
6099                           Linear_Form<FP_Interval_Type> >& lf_store,
6100                  const Variable var,
6101                  const Linear_Form<FP_Interval_Type>& lf) {
6102  // Assign the new linear form for var.
6103  lf_store[var.id()] = lf;
6104  // Now invalidate all linear forms in which var occurs.
6105  discard_occurrences(lf_store, var);
6106}
6107
6108#if PPL_SUPPORTED_FLOAT
6109inline
6110Float<float>::Float() {
6111}
6112
6113inline
6114Float<float>::Float(float v) {
6115  u.number = v;
6116}
6117
6118inline float
6119Float<float>::value() {
6120  return u.number;
6121}
6122#endif
6123
6124#if PPL_SUPPORTED_DOUBLE
6125inline
6126Float<double>::Float() {
6127}
6128
6129inline
6130Float<double>::Float(double v) {
6131  u.number = v;
6132}
6133
6134inline double
6135Float<double>::value() {
6136  return u.number;
6137}
6138#endif
6139
6140#if PPL_SUPPORTED_LONG_DOUBLE
6141inline
6142Float<long double>::Float() {
6143}
6144
6145inline
6146Float<long double>::Float(long double v) {
6147  u.number = v;
6148}
6149
6150inline long double
6151Float<long double>::value() {
6152  return u.number;
6153}
6154#endif
6155
6156} // namespace Parma_Polyhedra_Library
6157
6158/* Automatically generated from PPL source file ../src/Float_templates.hh line 1. */
6159/* IEC 559 floating point format related functions:
6160   non-inline template functions.
6161*/
6162
6163
6164/* Automatically generated from PPL source file ../src/Float_templates.hh line 30. */
6165#include <cmath>
6166
6167namespace Parma_Polyhedra_Library {
6168
6169template <typename FP_Interval_Type>
6170const FP_Interval_Type& compute_absolute_error(
6171                        const Floating_Point_Format analyzed_format) {
6172  typedef typename FP_Interval_Type::boundary_type analyzer_format;
6173
6174  // FIXME: check if initializing caches with EMPTY is better.
6175  static const FP_Interval_Type ZERO_INTERVAL = FP_Interval_Type(0);
6176  // Cached results for each different analyzed format.
6177  static FP_Interval_Type ieee754_half_result = ZERO_INTERVAL;
6178  static FP_Interval_Type ieee754_single_result = ZERO_INTERVAL;
6179  static FP_Interval_Type ieee754_double_result = ZERO_INTERVAL;
6180  static FP_Interval_Type ibm_single_result = ZERO_INTERVAL;
6181  static FP_Interval_Type ieee754_quad_result = ZERO_INTERVAL;
6182  static FP_Interval_Type intel_double_extended_result = ZERO_INTERVAL;
6183
6184  FP_Interval_Type* to_compute = NULL;
6185  // Get the necessary information on the analyzed's format.
6186  unsigned int f_base;
6187  int f_exponent_bias;
6188  unsigned int f_mantissa_bits;
6189  switch (analyzed_format) {
6190    case IEEE754_HALF:
6191      if (ieee754_half_result != ZERO_INTERVAL) {
6192        return ieee754_half_result;
6193      }
6194      to_compute = &ieee754_half_result;
6195      f_base = float_ieee754_half::BASE;
6196      f_exponent_bias = float_ieee754_half::EXPONENT_BIAS;
6197      f_mantissa_bits = float_ieee754_half::MANTISSA_BITS;
6198      break;
6199    case IEEE754_SINGLE:
6200      if (ieee754_single_result != ZERO_INTERVAL) {
6201        return ieee754_single_result;
6202      }
6203
6204      to_compute = &ieee754_single_result;
6205      f_base = float_ieee754_single::BASE;
6206      f_exponent_bias = float_ieee754_single::EXPONENT_BIAS;
6207      f_mantissa_bits = float_ieee754_single::MANTISSA_BITS;
6208      break;
6209    case IEEE754_DOUBLE:
6210      if (ieee754_double_result != ZERO_INTERVAL) {
6211        return ieee754_double_result;
6212      }
6213
6214      to_compute = &ieee754_double_result;
6215      f_base = float_ieee754_double::BASE;
6216      f_exponent_bias = float_ieee754_double::EXPONENT_BIAS;
6217      f_mantissa_bits = float_ieee754_double::MANTISSA_BITS;
6218      break;
6219    case IBM_SINGLE:
6220      if (ibm_single_result != ZERO_INTERVAL) {
6221        return ibm_single_result;
6222      }
6223
6224      to_compute = &ibm_single_result;
6225      f_base = float_ibm_single::BASE;
6226      f_exponent_bias = float_ibm_single::EXPONENT_BIAS;
6227      f_mantissa_bits = float_ibm_single::MANTISSA_BITS;
6228      break;
6229    case IEEE754_QUAD:
6230      if (ieee754_quad_result != ZERO_INTERVAL) {
6231        return ieee754_quad_result;
6232      }
6233
6234      to_compute = &ieee754_quad_result;
6235      f_base = float_ieee754_quad::BASE;
6236      f_exponent_bias = float_ieee754_quad::EXPONENT_BIAS;
6237      f_mantissa_bits = float_ieee754_quad::MANTISSA_BITS;
6238      break;
6239    case INTEL_DOUBLE_EXTENDED:
6240      if (intel_double_extended_result != ZERO_INTERVAL) {
6241        return intel_double_extended_result;
6242      }
6243
6244      to_compute = &intel_double_extended_result;
6245      f_base = float_intel_double_extended::BASE;
6246      f_exponent_bias = float_intel_double_extended::EXPONENT_BIAS;
6247      f_mantissa_bits = float_intel_double_extended::MANTISSA_BITS;
6248      break;
6249    default:
6250      PPL_UNREACHABLE;
6251      break;
6252  }
6253
6254  PPL_ASSERT(to_compute != NULL);
6255
6256  // We assume that f_base is a power of 2.
6257  analyzer_format omega;
6258  int power = static_cast<int>(msb_position(f_base))
6259    * ((1 - f_exponent_bias) - static_cast<int>(f_mantissa_bits));
6260  omega = std::max(static_cast<analyzer_format>(ldexp(1.0, power)),
6261                   std::numeric_limits<analyzer_format>::denorm_min());
6262
6263  to_compute->build(i_constraint(GREATER_OR_EQUAL, -omega),
6264                    i_constraint(LESS_OR_EQUAL, omega));
6265  return *to_compute;
6266}
6267
6268template <typename FP_Interval_Type>
6269void
6270discard_occurrences(std::map<dimension_type,
6271                             Linear_Form<FP_Interval_Type> >& lf_store,
6272                    Variable var) {
6273  typedef Linear_Form<FP_Interval_Type> FP_Linear_Form;
6274  typedef typename std::map<dimension_type, FP_Linear_Form>::iterator Iter;
6275  for (Iter i = lf_store.begin(); i != lf_store.end(); ) {
6276    if ((i->second).coefficient(var) != 0) {
6277      i = lf_store.erase(i);
6278    }
6279    else {
6280      ++i;
6281    }
6282  }
6283}
6284
6285/* FIXME: improve efficiency by adding the list of potentially conflicting
6286   variables as an argument. */
6287template <typename FP_Interval_Type>
6288void upper_bound_assign(std::map<dimension_type,
6289                                 Linear_Form<FP_Interval_Type> >& ls1,
6290                        const std::map<dimension_type,
6291                                       Linear_Form<FP_Interval_Type> >& ls2) {
6292  typedef Linear_Form<FP_Interval_Type> FP_Linear_Form;
6293  typedef typename std::map<dimension_type, FP_Linear_Form>::iterator Iter;
6294  typedef typename std::map<dimension_type,
6295                            FP_Linear_Form>::const_iterator Const_Iter;
6296
6297  Const_Iter i2_end = ls2.end();
6298  for (Iter i1 = ls1.begin(), i1_end = ls1.end(); i1 != i1_end; ) {
6299    Const_Iter i2 = ls2.find(i1->first);
6300    if ((i2 == i2_end) || (i1->second != i2->second)) {
6301      i1 = ls1.erase(i1);
6302    }
6303    else {
6304      ++i1;
6305    }
6306  }
6307}
6308
6309} // namespace Parma_Polyhedra_Library
6310
6311/* Automatically generated from PPL source file ../src/Float_defs.hh line 521. */
6312
6313/* Automatically generated from PPL source file ../src/checked_defs.hh line 32. */
6314#include <cassert>
6315#include <iostream>
6316#include <gmpxx.h>
6317
6318namespace Parma_Polyhedra_Library {
6319
6320namespace Checked {
6321
6322
6323// It is a pity that function partial specialization is not permitted
6324// by C++.  To (partly) overcome this limitation, we use class
6325// encapsulated functions and partial specialization of containing
6326// classes.
6327
6328#define PPL_FUNCTION_CLASS(name) name ## _function_struct
6329
6330#define PPL_DECLARE_FUN1_0_0(name, ret_type, qual, type)                \
6331  template <typename Policy, typename type>                             \
6332  struct PPL_FUNCTION_CLASS(name);                                      \
6333  template <typename Policy, typename type>                             \
6334  inline ret_type PPL_U(name)(PPL_U(qual) PPL_U(type)& arg) {           \
6335    return PPL_FUNCTION_CLASS(name)<Policy, PPL_U(type)>::function(arg); \
6336  }
6337
6338#define PPL_DECLARE_FUN1_0_1(name, ret_type, qual, type, after1)        \
6339  template <typename Policy, typename type>                             \
6340  struct PPL_FUNCTION_CLASS(name);                                      \
6341  template <typename Policy, typename type>                             \
6342  inline ret_type PPL_U(name)(PPL_U(qual) PPL_U(type)& arg, PPL_U(after1) a1) { \
6343    return                                                              \
6344      PPL_FUNCTION_CLASS(name)<Policy, PPL_U(type)>::function(arg, a1); \
6345  }
6346
6347#define PPL_DECLARE_FUN1_0_2(name, ret_type, qual, type, after1, after2) \
6348  template <typename Policy, typename type>                             \
6349  struct PPL_FUNCTION_CLASS(name);                                      \
6350  template <typename Policy, typename type>                             \
6351  inline ret_type PPL_U(name)(PPL_U(qual) PPL_U(type)& arg, PPL_U(after1) a1, \
6352                       PPL_U(after2) a2) {                              \
6353    return                                                              \
6354      PPL_FUNCTION_CLASS(name)<Policy, PPL_U(type)>::function(arg,      \
6355                                                              a1, a2);  \
6356  }
6357
6358#define PPL_DECLARE_FUN1_0_3(name, ret_type, qual, type,                \
6359                             after1, after2, after3)                    \
6360  template <typename Policy, typename type>                             \
6361  struct PPL_FUNCTION_CLASS(name);                                      \
6362  template <typename Policy, typename type>                             \
6363  inline ret_type PPL_U(name)(PPL_U(qual) PPL_U(type)& arg,             \
6364                       PPL_U(after1) a1, PPL_U(after2) a2,              \
6365                       PPL_U(after3) a3) {                              \
6366    return                                                              \
6367      PPL_FUNCTION_CLASS(name)<Policy, PPL_U(type)>::function(arg,      \
6368                                                              a1, a2,   \
6369                                                              a3);      \
6370  }
6371
6372#define PPL_DECLARE_FUN1_1_1(name, ret_type, before1, qual, type, after1) \
6373  template <typename Policy, typename type>                             \
6374  struct PPL_FUNCTION_CLASS(name);                                      \
6375  template <typename Policy, typename type>                             \
6376  inline ret_type PPL_U(name)(PPL_U(before1) b1, PPL_U(qual) PPL_U(type)& arg, \
6377                       PPL_U(after1) a1) {                              \
6378    return                                                              \
6379      PPL_FUNCTION_CLASS(name)<Policy, PPL_U(type)>::function(b1, arg,  \
6380                                                              a1);      \
6381  }
6382
6383#define PPL_DECLARE_FUN1_1_2(name, ret_type, before1, qual, type,       \
6384                             after1, after2)                            \
6385  template <typename Policy, typename type>                             \
6386  struct PPL_FUNCTION_CLASS(name);                                      \
6387  template <typename Policy, typename type>                             \
6388  inline ret_type PPL_U(name)(PPL_U(before1) b1, PPL_U(qual) PPL_U(type)& arg, \
6389                       PPL_U(after1) a1, PPL_U(after2) a2) {            \
6390    return                                                              \
6391      PPL_FUNCTION_CLASS(name)<Policy, PPL_U(type)>::function(b1, arg,  \
6392                                                              a1, a2);  \
6393  }
6394
6395#define PPL_DECLARE_FUN1_2_2(name, ret_type, before1, before2, qual, type, \
6396                             after1, after2)                            \
6397  template <typename Policy, typename type>                             \
6398  struct PPL_FUNCTION_CLASS(name);                                      \
6399  template <typename Policy, typename type>                             \
6400  inline ret_type PPL_U(name)(PPL_U(before1) b1, PPL_U(before2) b2,     \
6401                       PPL_U(qual) PPL_U(type)& arg,                    \
6402                       PPL_U(after1) a1, PPL_U(after2) a2) {            \
6403    return                                                              \
6404      PPL_FUNCTION_CLASS(name)<Policy, PPL_U(type)>::function(b1, b2,   \
6405                                                              arg,      \
6406                                                              a1, a2);  \
6407  }
6408
6409#define PPL_DECLARE_FUN2_0_0(name, ret_type, qual1, type1, qual2, type2) \
6410  template <typename Policy1, typename Policy2,                         \
6411            typename type1, typename type2>                             \
6412  struct PPL_FUNCTION_CLASS(name);                                      \
6413  template <typename Policy1, typename Policy2,                         \
6414            typename type1, typename type2>                             \
6415  inline ret_type PPL_U(name)(PPL_U(qual1) PPL_U(type1)& arg1,          \
6416                       PPL_U(qual2) PPL_U(type2)& arg2) {               \
6417    return PPL_FUNCTION_CLASS(name)<Policy1, Policy2,                   \
6418      type1, PPL_U(type2)>::function(arg1, arg2);                       \
6419  }
6420
6421#define PPL_DECLARE_FUN2_0_1(name, ret_type, qual1, type1,      \
6422                             qual2, type2, after1)              \
6423  template <typename Policy1, typename Policy2,                 \
6424            typename type1, typename type2>                     \
6425  struct PPL_FUNCTION_CLASS(name);                              \
6426  template <typename Policy1, typename Policy2,                 \
6427            typename type1, typename type2>                     \
6428  inline ret_type PPL_U(name)(PPL_U(qual1) PPL_U(type1)& arg1,  \
6429                       PPL_U(qual2) PPL_U(type2)& arg2,         \
6430                       PPL_U(after1) a1) {                      \
6431    return PPL_FUNCTION_CLASS(name)<Policy1, Policy2,           \
6432      type1, PPL_U(type2)>::function(arg1, arg2, a1);           \
6433  }
6434
6435#define PPL_DECLARE_FUN2_0_2(name, ret_type, qual1, type1, qual2, type2, \
6436                             after1, after2)                            \
6437  template <typename Policy1, typename Policy2,                         \
6438            typename type1, typename type2>                             \
6439  struct PPL_FUNCTION_CLASS(name);                                      \
6440  template <typename Policy1, typename Policy2,                         \
6441            typename type1, typename type2>                             \
6442  inline ret_type PPL_U(name)(PPL_U(qual1) PPL_U(type1)& arg1,          \
6443                       PPL_U(qual2) PPL_U(type2)& arg2,                 \
6444                       PPL_U(after1) a1, PPL_U(after2) a2) {            \
6445    return PPL_FUNCTION_CLASS(name)<Policy1, Policy2,                   \
6446      type1, PPL_U(type2)>::function(arg1, arg2, a1, a2);               \
6447  }
6448
6449#define PPL_DECLARE_FUN3_0_1(name, ret_type, qual1, type1,              \
6450                             qual2, type2, qual3, type3, after1)        \
6451  template <typename Policy1, typename Policy2, typename Policy3,       \
6452            typename type1, typename type2, typename type3>             \
6453  struct PPL_FUNCTION_CLASS(name);                                      \
6454  template <typename Policy1, typename Policy2, typename Policy3,       \
6455            typename type1, typename type2, typename type3>             \
6456  inline ret_type PPL_U(name)(PPL_U(qual1) PPL_U(type1)& arg1,          \
6457                       PPL_U(qual2) PPL_U(type2)& arg2,                 \
6458                       PPL_U(qual3) PPL_U(type3)& arg3,                 \
6459                       PPL_U(after1) a1) {                              \
6460    return PPL_FUNCTION_CLASS(name)<Policy1, Policy2, Policy3,          \
6461      type1, type2, PPL_U(type3)>                                       \
6462      ::function(arg1, arg2, arg3, a1);                                 \
6463  }
6464
6465#define PPL_DECLARE_FUN5_0_1(name, ret_type,                            \
6466                             qual1, type1, qual2, type2, qual3, type3,  \
6467                             qual4, type4, qual5, type5,                \
6468                             after1)                                    \
6469  template <typename Policy1, typename Policy2, typename Policy3,       \
6470            typename Policy4,typename Policy5,                          \
6471            typename type1, typename type2, typename type3,             \
6472            typename type4, typename type5>                             \
6473  struct PPL_FUNCTION_CLASS(name);                                      \
6474  template <typename Policy1, typename Policy2, typename Policy3,       \
6475            typename Policy4,typename Policy5,                          \
6476            typename type1, typename type2, typename type3,             \
6477            typename type4, typename type5>                             \
6478  inline ret_type PPL_U(name)(PPL_U(qual1) PPL_U(type1)& arg1, PPL_U(qual2) \
6479                       PPL_U(type2)& arg2,                              \
6480                       PPL_U(qual3) PPL_U(type3)& arg3, PPL_U(qual4)    \
6481                       PPL_U(type4)& arg4,                              \
6482                       PPL_U(qual5) PPL_U(type5)& arg5,                 \
6483                       PPL_U(after1) a1) {                              \
6484    return PPL_FUNCTION_CLASS(name)<Policy1, Policy2, Policy3,          \
6485      Policy4, Policy5,                                                 \
6486      type1, type2,                                                     \
6487      type3, type4,                                                     \
6488      PPL_U(type5)>                                                     \
6489      ::function(arg1, arg2, arg3, arg4, arg5, a1);                     \
6490  }
6491
6492#define PPL_SPECIALIZE_FUN1_0_0(name, func, ret_type, qual, type)       \
6493  template <typename Policy>                                            \
6494  struct PPL_FUNCTION_CLASS(name)<Policy, PPL_U(type)> {                \
6495    static inline ret_type function(PPL_U(qual) PPL_U(type)& arg) {     \
6496      return PPL_U(func)<Policy>(arg);                                  \
6497    }                                                                   \
6498  };
6499
6500#define PPL_SPECIALIZE_FUN1_0_1(name, func, ret_type, qual, type, after1) \
6501  template <typename Policy>                                            \
6502  struct PPL_FUNCTION_CLASS(name)<Policy, PPL_U(type)> {                \
6503    static inline ret_type function(PPL_U(qual) PPL_U(type)& arg,       \
6504                                    PPL_U(after1) a1) {                 \
6505      return PPL_U(func)<Policy>(arg, a1);                              \
6506    }                                                                   \
6507  };
6508
6509#define PPL_SPECIALIZE_FUN1_0_2(name, func, ret_type, qual, type,       \
6510                                after1, after2)                         \
6511  template <typename Policy>                                            \
6512  struct PPL_FUNCTION_CLASS(name)<Policy, PPL_U(type)> {                \
6513    static inline ret_type function(PPL_U(qual) PPL_U(type)& arg,       \
6514                                    PPL_U(after1) a1, PPL_U(after2) a2) \
6515    {                                                                   \
6516      return PPL_U(func)<Policy>(arg, a1, a2);                          \
6517    }                                                                   \
6518  };
6519
6520#define PPL_SPECIALIZE_FUN1_0_3(name, func, ret_type, qual, type,       \
6521                                after1, after2, after3)                 \
6522  template <typename Policy>                                            \
6523  struct PPL_FUNCTION_CLASS(name)<Policy, PPL_U(type)> {                \
6524    static inline ret_type function(PPL_U(qual) PPL_U(type)& arg,       \
6525                                    PPL_U(after1) a1, PPL_U(after2) a2, \
6526                                    PPL_U(after3) a3) {                 \
6527      return PPL_U(func)<Policy>(arg, a1, a2, a3);                      \
6528    }                                                                   \
6529  };
6530
6531#define PPL_SPECIALIZE_FUN1_1_1(name, func, ret_type, before1,          \
6532                                qual, type, after1)                     \
6533  template <typename Policy>                                            \
6534  struct PPL_FUNCTION_CLASS(name)<Policy, PPL_U(type)> {                \
6535    static inline ret_type function(PPL_U(before1) b1, PPL_U(qual)      \
6536                                    PPL_U(type)& arg,                   \
6537                                    PPL_U(after1) a1) {                 \
6538      return PPL_U(func)<Policy>(b1, arg, a1);                          \
6539    }                                                                   \
6540  };
6541
6542#define PPL_SPECIALIZE_FUN1_1_2(name, func, ret_type, before1,          \
6543                                qual, type, after1, after2)             \
6544  template <typename Policy>                                            \
6545  struct PPL_FUNCTION_CLASS(name)<Policy, PPL_U(type)> {                \
6546    static inline ret_type function(PPL_U(before1) b1, PPL_U(qual)      \
6547                                    PPL_U(type)& arg,                   \
6548                                    PPL_U(after1) a1, PPL_U(after2) a2) \
6549    {                                                                   \
6550      return PPL_U(func)<Policy>(b1, arg, a1, a2);                      \
6551    }                                                                   \
6552  };
6553
6554#define PPL_SPECIALIZE_FUN1_2_2(name, func, ret_type, before1, before2, \
6555                                qual, type, after1, after2)             \
6556  template <typename Policy>                                            \
6557  struct PPL_FUNCTION_CLASS(name)<Policy, PPL_U(type)> {                \
6558    static inline ret_type function(PPL_U(before1) b1, PPL_U(before2) b2, \
6559                                    PPL_U(qual) PPL_U(type)& arg,       \
6560                                    PPL_U(after1) a1, PPL_U(after2) a2) \
6561    {                                                                   \
6562      return PPL_U(func)<Policy>(b1, b2, arg, a1, a2);                  \
6563    }                                                                   \
6564  };
6565
6566#define PPL_SPECIALIZE_FUN2_0_0(name, func, ret_type, qual1, type1,     \
6567                                qual2, type2)                           \
6568  template <typename Policy1, typename Policy2>                         \
6569  struct PPL_FUNCTION_CLASS(name)<Policy1, Policy2, type1,              \
6570                                  PPL_U(type2)> {                       \
6571    static inline ret_type function(PPL_U(qual1) PPL_U(type1)& arg1,    \
6572                                    PPL_U(qual2) PPL_U(type2) &arg2) {  \
6573      return PPL_U(func)<Policy1, Policy2>(arg1, arg2);                 \
6574    }                                                                   \
6575  };
6576
6577#define PPL_SPECIALIZE_FUN2_0_1(name, func, ret_type, qual1, type1,     \
6578                                qual2, type2, after1)                   \
6579  template <typename Policy1, typename Policy2>                         \
6580  struct PPL_FUNCTION_CLASS(name)<Policy1, Policy2, type1,              \
6581                                  PPL_U(type2)> {                       \
6582    static inline ret_type function(PPL_U(qual1) PPL_U(type1)& arg1,    \
6583                                    PPL_U(qual2) PPL_U(type2) &arg2,    \
6584                                    PPL_U(after1) a1) {                 \
6585      return PPL_U(func)<Policy1, Policy2>(arg1, arg2, a1);             \
6586    }                                                                   \
6587  };
6588
6589#define PPL_SPECIALIZE_FUN2_0_2(name, func, ret_type, qual1, type1,     \
6590                                qual2, type2, after1, after2)           \
6591  template <typename Policy1, typename Policy2>                         \
6592  struct PPL_FUNCTION_CLASS(name)<Policy1, Policy2, type1,              \
6593                                  PPL_U(type2)> {                       \
6594    static inline ret_type function(PPL_U(qual1) PPL_U(type1)& arg1,    \
6595                                    PPL_U(qual2) PPL_U(type2) &arg2,    \
6596                                    PPL_U(after1) a1, PPL_U(after2) a2) \
6597    {                                                                   \
6598      return PPL_U(func)<Policy1, Policy2>(arg1, arg2, a1, a2);         \
6599    }                                                                   \
6600  };
6601
6602#define PPL_SPECIALIZE_FUN3_0_1(name, func, ret_type, qual1, type1,     \
6603                                qual2, type2, qual3, type3, after1)     \
6604  template <typename Policy1, typename Policy2, typename Policy3>       \
6605  struct PPL_FUNCTION_CLASS(name) <Policy1, Policy2, Policy3,           \
6606                                   type1, type2,                        \
6607                                   PPL_U(type3)> {                      \
6608    static inline Result function(PPL_U(qual1) PPL_U(type1)& arg1,      \
6609                                  PPL_U(qual2) PPL_U(type2) &arg2,      \
6610                                  PPL_U(qual3) PPL_U(type3) &arg3,      \
6611                                  PPL_U(after1) a1) {                   \
6612      return PPL_U(func)<Policy1, Policy2, Policy3>(arg1, arg2, arg3,   \
6613                                                    a1);                \
6614    }                                                                   \
6615  };
6616
6617#define PPL_SPECIALIZE_FUN5_0_1(name, func, ret_type,                   \
6618                                qual1, type1, qual2, type2,             \
6619                                qual3, type3,                           \
6620                                qual4, type4, qual5, type5, after1)     \
6621  template <typename Policy1, typename Policy2, typename Policy3,       \
6622            typename Policy4, typename Policy5>                         \
6623  struct PPL_FUNCTION_CLASS(name) <Policy1, Policy2, Policy3, Policy4,  \
6624                                   Policy5,                             \
6625                                   type1, type2,                        \
6626                                   type3, type4,                        \
6627                                   PPL_U(type5)> {                      \
6628    static inline Result                                                \
6629      function(PPL_U(qual1) PPL_U(type1)& arg1, PPL_U(qual2)            \
6630               PPL_U(type2) &arg2,                                      \
6631               PPL_U(qual3) PPL_U(type3) &arg3, PPL_U(qual4)            \
6632               PPL_U(type4) &arg4,                                      \
6633               PPL_U(qual5) PPL_U(type5) &arg5, PPL_U(after1) a1) {     \
6634      return PPL_U(func)<Policy1, Policy2, Policy3, Policy4,            \
6635        Policy5>(arg1, arg2, arg3, arg4, arg5, a1);                     \
6636    }                                                                   \
6637  };
6638
6639// The `nonconst' macro helps readability of the sequel.
6640#ifdef nonconst
6641#define PPL_SAVED_nonconst nonconst
6642#undef nonconst
6643#endif
6644#define nonconst
6645
6646#define PPL_SPECIALIZE_COPY(func, Type)                                 \
6647  PPL_SPECIALIZE_FUN2_0_0(copy, func, void, nonconst, Type, const, Type)
6648#define PPL_SPECIALIZE_SGN(func, From)                                  \
6649  PPL_SPECIALIZE_FUN1_0_0(sgn, func, Result_Relation, const, From)
6650#define PPL_SPECIALIZE_CMP(func, Type1, Type2)                          \
6651  PPL_SPECIALIZE_FUN2_0_0(cmp, func, Result_Relation, const, Type1, const, Type2)
6652#define PPL_SPECIALIZE_CLASSIFY(func, Type)                             \
6653  PPL_SPECIALIZE_FUN1_0_3(classify, func, Result, const, Type, bool, bool, bool)
6654#define PPL_SPECIALIZE_IS_NAN(func, Type)                       \
6655  PPL_SPECIALIZE_FUN1_0_0(is_nan, func, bool, const, Type)
6656#define PPL_SPECIALIZE_IS_MINF(func, Type)                      \
6657  PPL_SPECIALIZE_FUN1_0_0(is_minf, func, bool, const, Type)
6658#define PPL_SPECIALIZE_IS_PINF(func, Type)                      \
6659  PPL_SPECIALIZE_FUN1_0_0(is_pinf, func, bool, const, Type)
6660#define PPL_SPECIALIZE_IS_INT(func, Type)                       \
6661  PPL_SPECIALIZE_FUN1_0_0(is_int, func, bool, const, Type)
6662#define PPL_SPECIALIZE_ASSIGN_SPECIAL(func, Type)                       \
6663  PPL_SPECIALIZE_FUN1_0_2(assign_special, func, Result,                 \
6664                          nonconst, Type, Result_Class, Rounding_Dir)
6665#define PPL_SPECIALIZE_CONSTRUCT_SPECIAL(func, Type)                    \
6666  PPL_SPECIALIZE_FUN1_0_2(construct_special, func, Result, nonconst,    \
6667                          Type, Result_Class, Rounding_Dir)
6668#define PPL_SPECIALIZE_CONSTRUCT(func, To, From)                        \
6669  PPL_SPECIALIZE_FUN2_0_1(construct, func, Result, nonconst, To,        \
6670                          const, From, Rounding_Dir)
6671#define PPL_SPECIALIZE_ASSIGN(func, To, From)                   \
6672  PPL_SPECIALIZE_FUN2_0_1(assign, func, Result, nonconst, To,   \
6673                          const, From, Rounding_Dir)
6674#define PPL_SPECIALIZE_FLOOR(func, To, From)                    \
6675  PPL_SPECIALIZE_FUN2_0_1(floor, func, Result, nonconst, To,    \
6676                          const, From, Rounding_Dir)
6677#define PPL_SPECIALIZE_CEIL(func, To, From)                     \
6678  PPL_SPECIALIZE_FUN2_0_1(ceil, func, Result, nonconst, To,     \
6679                          const, From, Rounding_Dir)
6680#define PPL_SPECIALIZE_TRUNC(func, To, From)                    \
6681  PPL_SPECIALIZE_FUN2_0_1(trunc, func, Result, nonconst, To,    \
6682                          const, From, Rounding_Dir)
6683#define PPL_SPECIALIZE_NEG(func, To, From)                      \
6684  PPL_SPECIALIZE_FUN2_0_1(neg, func, Result, nonconst, To,      \
6685                          const, From, Rounding_Dir)
6686#define PPL_SPECIALIZE_ABS(func, To, From)                      \
6687  PPL_SPECIALIZE_FUN2_0_1(abs, func, Result, nonconst, To,      \
6688                          const, From, Rounding_Dir)
6689#define PPL_SPECIALIZE_SQRT(func, To, From)                     \
6690  PPL_SPECIALIZE_FUN2_0_1(sqrt, func, Result, nonconst, To,     \
6691                          const, From, Rounding_Dir)
6692#define PPL_SPECIALIZE_ADD(func, To, From1, From2)                      \
6693  PPL_SPECIALIZE_FUN3_0_1(add, func, Result, nonconst, To,              \
6694                          const, From1, const, From2, Rounding_Dir)
6695#define PPL_SPECIALIZE_SUB(func, To, From1, From2)                      \
6696  PPL_SPECIALIZE_FUN3_0_1(sub, func, Result, nonconst, To,              \
6697                          const, From1, const, From2, Rounding_Dir)
6698#define PPL_SPECIALIZE_MUL(func, To, From1, From2)                      \
6699  PPL_SPECIALIZE_FUN3_0_1(mul, func, Result, nonconst, To,              \
6700                          const, From1, const, From2, Rounding_Dir)
6701#define PPL_SPECIALIZE_DIV(func, To, From1, From2)                      \
6702  PPL_SPECIALIZE_FUN3_0_1(div, func, Result, nonconst, To,              \
6703                          const, From1, const, From2, Rounding_Dir)
6704#define PPL_SPECIALIZE_REM(func, To, From1, From2)                      \
6705  PPL_SPECIALIZE_FUN3_0_1(rem, func, Result, nonconst, To,              \
6706                          const, From1, const, From2, Rounding_Dir)
6707#define PPL_SPECIALIZE_IDIV(func, To, From1, From2)                     \
6708  PPL_SPECIALIZE_FUN3_0_1(idiv, func, Result, nonconst, To,             \
6709                          const, From1, const, From2, Rounding_Dir)
6710#define PPL_SPECIALIZE_ADD_2EXP(func, To, From)                         \
6711  PPL_SPECIALIZE_FUN2_0_2(add_2exp, func, Result, nonconst, To,         \
6712                          const, From, unsigned int, Rounding_Dir)
6713#define PPL_SPECIALIZE_SUB_2EXP(func, To, From)                         \
6714  PPL_SPECIALIZE_FUN2_0_2(sub_2exp, func, Result, nonconst, To,         \
6715                          const, From, unsigned int, Rounding_Dir)
6716#define PPL_SPECIALIZE_MUL_2EXP(func, To, From)                         \
6717  PPL_SPECIALIZE_FUN2_0_2(mul_2exp, func, Result, nonconst, To,         \
6718                          const, From, unsigned int, Rounding_Dir)
6719#define PPL_SPECIALIZE_DIV_2EXP(func, To, From)                         \
6720  PPL_SPECIALIZE_FUN2_0_2(div_2exp, func, Result, nonconst, To,         \
6721                          const, From, unsigned int, Rounding_Dir)
6722#define PPL_SPECIALIZE_SMOD_2EXP(func, To, From)                        \
6723  PPL_SPECIALIZE_FUN2_0_2(smod_2exp, func, Result, nonconst, To,        \
6724                          const, From, unsigned int, Rounding_Dir)
6725#define PPL_SPECIALIZE_UMOD_2EXP(func, To, From)                        \
6726  PPL_SPECIALIZE_FUN2_0_2(umod_2exp, func, Result, nonconst, To,        \
6727                          const, From, unsigned int, Rounding_Dir)
6728#define PPL_SPECIALIZE_ADD_MUL(func, To, From1, From2)                  \
6729  PPL_SPECIALIZE_FUN3_0_1(add_mul, func, Result, nonconst, To,          \
6730                          const, From1, const, From2, Rounding_Dir)
6731#define PPL_SPECIALIZE_SUB_MUL(func, To, From1, From2)                  \
6732  PPL_SPECIALIZE_FUN3_0_1(sub_mul, func, Result, nonconst, To,          \
6733                          const, From1, const, From2, Rounding_Dir)
6734#define PPL_SPECIALIZE_GCD(func, To, From1, From2)                      \
6735  PPL_SPECIALIZE_FUN3_0_1(gcd, func, Result, nonconst, To,              \
6736                          const, From1, const, From2, Rounding_Dir)
6737#define PPL_SPECIALIZE_GCDEXT(func, To1, From1, From2, To2, To3)        \
6738  PPL_SPECIALIZE_FUN5_0_1(gcdext, func, Result, nonconst, To1,          \
6739                          nonconst, To2, nonconst, To3,                 \
6740                          const, From1, const, From2, Rounding_Dir)
6741#define PPL_SPECIALIZE_LCM(func, To, From1, From2)                      \
6742  PPL_SPECIALIZE_FUN3_0_1(lcm, func, Result, nonconst, To,              \
6743                          const, From1, const, From2, Rounding_Dir)
6744#define PPL_SPECIALIZE_INPUT(func, Type)                        \
6745  PPL_SPECIALIZE_FUN1_0_2(input, func, Result, nonconst, Type,  \
6746                          std::istream&, Rounding_Dir)
6747#define PPL_SPECIALIZE_OUTPUT(func, Type)                       \
6748  PPL_SPECIALIZE_FUN1_1_2(output, func, Result, std::ostream&,  \
6749                          const, Type,                          \
6750                          const Numeric_Format&, Rounding_Dir)
6751
6752
6753PPL_DECLARE_FUN2_0_0(copy,
6754                     void, nonconst, Type1, const, Type2)
6755PPL_DECLARE_FUN1_0_0(sgn,
6756                     Result_Relation, const, From)
6757PPL_DECLARE_FUN2_0_0(cmp,
6758                     Result_Relation, const, Type1, const, Type2)
6759PPL_DECLARE_FUN1_0_3(classify,
6760                     Result, const, Type, bool, bool, bool)
6761PPL_DECLARE_FUN1_0_0(is_nan,
6762                     bool, const, Type)
6763PPL_DECLARE_FUN1_0_0(is_minf,
6764                     bool, const, Type)
6765PPL_DECLARE_FUN1_0_0(is_pinf,
6766                     bool, const, Type)
6767PPL_DECLARE_FUN1_0_0(is_int,
6768                     bool, const, Type)
6769PPL_DECLARE_FUN1_0_2(assign_special,
6770                     Result, nonconst, Type, Result_Class, Rounding_Dir)
6771PPL_DECLARE_FUN1_0_2(construct_special,
6772                     Result, nonconst, Type, Result_Class, Rounding_Dir)
6773PPL_DECLARE_FUN2_0_1(construct,
6774                     Result, nonconst, To, const, From, Rounding_Dir)
6775PPL_DECLARE_FUN2_0_1(assign,
6776                     Result, nonconst, To, const, From, Rounding_Dir)
6777PPL_DECLARE_FUN2_0_1(floor,
6778                     Result, nonconst, To, const, From, Rounding_Dir)
6779PPL_DECLARE_FUN2_0_1(ceil,
6780                     Result, nonconst, To, const, From, Rounding_Dir)
6781PPL_DECLARE_FUN2_0_1(trunc,
6782                     Result, nonconst, To, const, From, Rounding_Dir)
6783PPL_DECLARE_FUN2_0_1(neg,
6784                     Result, nonconst, To, const, From, Rounding_Dir)
6785PPL_DECLARE_FUN2_0_1(abs,
6786                     Result, nonconst, To, const, From, Rounding_Dir)
6787PPL_DECLARE_FUN2_0_1(sqrt,
6788                     Result, nonconst, To, const, From, Rounding_Dir)
6789PPL_DECLARE_FUN3_0_1(add,
6790                     Result, nonconst, To,
6791                     const, From1, const, From2, Rounding_Dir)
6792PPL_DECLARE_FUN3_0_1(sub,
6793                     Result, nonconst, To,
6794                     const, From1, const, From2, Rounding_Dir)
6795PPL_DECLARE_FUN3_0_1(mul,
6796                     Result, nonconst, To,
6797                     const, From1, const, From2, Rounding_Dir)
6798PPL_DECLARE_FUN3_0_1(div,
6799                     Result, nonconst, To,
6800                     const, From1, const, From2, Rounding_Dir)
6801PPL_DECLARE_FUN3_0_1(rem,
6802                     Result, nonconst, To,
6803                     const, From1, const, From2, Rounding_Dir)
6804PPL_DECLARE_FUN3_0_1(idiv,
6805                     Result, nonconst, To,
6806                     const, From1, const, From2, Rounding_Dir)
6807PPL_DECLARE_FUN2_0_2(add_2exp,
6808                     Result, nonconst, To,
6809                     const, From, unsigned int, Rounding_Dir)
6810PPL_DECLARE_FUN2_0_2(sub_2exp,
6811                     Result, nonconst, To,
6812                     const, From, unsigned int, Rounding_Dir)
6813PPL_DECLARE_FUN2_0_2(mul_2exp,
6814                     Result, nonconst, To,
6815                     const, From, unsigned int, Rounding_Dir)
6816PPL_DECLARE_FUN2_0_2(div_2exp,
6817                     Result, nonconst, To,
6818                     const, From, unsigned int, Rounding_Dir)
6819PPL_DECLARE_FUN2_0_2(smod_2exp,
6820                     Result, nonconst, To,
6821                     const, From, unsigned int, Rounding_Dir)
6822PPL_DECLARE_FUN2_0_2(umod_2exp,
6823                     Result, nonconst, To,
6824                     const, From, unsigned int, Rounding_Dir)
6825PPL_DECLARE_FUN3_0_1(add_mul,
6826                     Result, nonconst, To,
6827                     const, From1, const, From2, Rounding_Dir)
6828PPL_DECLARE_FUN3_0_1(sub_mul,
6829                     Result, nonconst, To,
6830                     const, From1, const, From2, Rounding_Dir)
6831PPL_DECLARE_FUN3_0_1(gcd,
6832                     Result, nonconst, To,
6833                     const, From1, const, From2, Rounding_Dir)
6834PPL_DECLARE_FUN5_0_1(gcdext,
6835                     Result, nonconst, To1, nonconst, To2, nonconst, To3,
6836                     const, From1, const, From2, Rounding_Dir)
6837PPL_DECLARE_FUN3_0_1(lcm,
6838                     Result, nonconst, To,
6839                     const, From1, const, From2, Rounding_Dir)
6840PPL_DECLARE_FUN1_0_2(input,
6841                     Result, nonconst, Type, std::istream&, Rounding_Dir)
6842PPL_DECLARE_FUN1_1_2(output,
6843                     Result, std::ostream&, const, Type,
6844                     const Numeric_Format&, Rounding_Dir)
6845
6846#undef PPL_DECLARE_FUN1_0_0
6847#undef PPL_DECLARE_FUN1_0_1
6848#undef PPL_DECLARE_FUN1_0_2
6849#undef PPL_DECLARE_FUN1_0_3
6850#undef PPL_DECLARE_FUN1_1_1
6851#undef PPL_DECLARE_FUN1_1_2
6852#undef PPL_DECLARE_FUN1_2_2
6853#undef PPL_DECLARE_FUN2_0_0
6854#undef PPL_DECLARE_FUN2_0_1
6855#undef PPL_DECLARE_FUN2_0_2
6856#undef PPL_DECLARE_FUN3_0_1
6857#undef PPL_DECLARE_FUN5_0_1
6858
6859template <typename Policy, typename To>
6860Result round(To& to, Result r, Rounding_Dir dir);
6861
6862Result input_mpq(mpq_class& to, std::istream& is);
6863
6864std::string float_mpq_to_string(mpq_class& q);
6865
6866} // namespace Checked
6867
6868struct Minus_Infinity {
6869  static const Result_Class vclass = VC_MINUS_INFINITY;
6870};
6871struct Plus_Infinity {
6872  static const Result_Class vclass = VC_PLUS_INFINITY;
6873};
6874struct Not_A_Number {
6875  static const Result_Class vclass = VC_NAN;
6876};
6877
6878template <typename T>
6879struct Is_Special : public False { };
6880
6881template <>
6882struct Is_Special<Minus_Infinity> : public True {};
6883
6884template <>
6885struct Is_Special<Plus_Infinity> : public True {};
6886
6887template <>
6888struct Is_Special<Not_A_Number> : public True {};
6889
6890extern Minus_Infinity MINUS_INFINITY;
6891extern Plus_Infinity PLUS_INFINITY;
6892extern Not_A_Number NOT_A_NUMBER;
6893
6894#ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
6895/*! \ingroup PPL_CXX_interface */
6896#endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
6897template <typename T>
6898struct Checked_Number_Transparent_Policy {
6899  //! Do not check for overflowed result.
6900  const_bool_nodef(check_overflow, false);
6901
6902  //! Do not check for attempts to add infinities with different sign.
6903  const_bool_nodef(check_inf_add_inf, false);
6904
6905  //! Do not check for attempts to subtract infinities with same sign.
6906  const_bool_nodef(check_inf_sub_inf, false);
6907
6908  //! Do not check for attempts to multiply infinities by zero.
6909  const_bool_nodef(check_inf_mul_zero, false);
6910
6911  //! Do not check for attempts to divide by zero.
6912  const_bool_nodef(check_div_zero, false);
6913
6914  //! Do not check for attempts to divide infinities.
6915  const_bool_nodef(check_inf_div_inf, false);
6916
6917  //! Do not check for attempts to compute remainder of infinities.
6918  const_bool_nodef(check_inf_mod, false);
6919
6920  //! Do not check for attempts to take the square root of a negative number.
6921  const_bool_nodef(check_sqrt_neg, false);
6922
6923  //! Handle not-a-number special value if \p T has it.
6924  const_bool_nodef(has_nan, std::numeric_limits<T>::has_quiet_NaN);
6925
6926  //! Handle infinity special values if \p T have them.
6927  const_bool_nodef(has_infinity, std::numeric_limits<T>::has_infinity);
6928
6929  /*! \brief
6930    The checked number can always be safely converted to the
6931    underlying type \p T and vice-versa.
6932  */
6933  const_bool_nodef(convertible, true);
6934
6935  //! Do not honor requests to check for FPU inexact results.
6936  const_bool_nodef(fpu_check_inexact, false);
6937
6938  //! Do not make extra checks to detect FPU NaN results.
6939  const_bool_nodef(fpu_check_nan_result, false);
6940
6941  /*! \brief
6942    For constructors, by default use the same rounding used by
6943    underlying type.
6944  */
6945  static const Rounding_Dir ROUND_DEFAULT_CONSTRUCTOR = ROUND_NATIVE;
6946
6947  /*! \brief
6948    For overloaded operators (operator+(), operator-(), ...), by
6949    default use the same rounding used by the underlying type.
6950  */
6951  static const Rounding_Dir ROUND_DEFAULT_OPERATOR = ROUND_NATIVE;
6952
6953  /*! \brief
6954    For input functions, by default use the same rounding used by
6955    the underlying type.
6956  */
6957  static const Rounding_Dir ROUND_DEFAULT_INPUT = ROUND_NATIVE;
6958
6959  /*! \brief
6960    For output functions, by default use the same rounding used by
6961    the underlying type.
6962  */
6963  static const Rounding_Dir ROUND_DEFAULT_OUTPUT = ROUND_NATIVE;
6964
6965  /*! \brief
6966    For all other functions, by default use the same rounding used by
6967    the underlying type.
6968  */
6969  static const Rounding_Dir ROUND_DEFAULT_FUNCTION = ROUND_NATIVE;
6970
6971  /*! \brief
6972    Handles \p r: called by all constructors, operators and functions that
6973    do not return a Result value.
6974  */
6975  static void handle_result(Result r);
6976};
6977
6978} // namespace Parma_Polyhedra_Library
6979
6980#define CHECK_P(cond, check) ((cond) ? (check) : (assert(!(check)), false))
6981
6982/* Automatically generated from PPL source file ../src/checked_inlines.hh line 1. */
6983/* Abstract checked arithmetic functions: fall-backs.
6984*/
6985
6986
6987/* Automatically generated from PPL source file ../src/checked_inlines.hh line 31. */
6988
6989/*! \brief
6990  Performs the test <CODE>a < b</CODE> avoiding the warning about the
6991  comparison being always false due to limited range of data type.
6992  FIXME: we have not found a working solution. The GCC option
6993  -Wno-type-limits suppresses the warning
6994*/
6995#define PPL_LT_SILENT(a, b) ((a) < (b))
6996#define PPL_GT_SILENT(a, b) ((a) > (b))
6997
6998namespace Parma_Polyhedra_Library {
6999
7000namespace Checked {
7001
7002template <typename T1, typename T2>
7003struct Safe_Conversion : public False {
7004};
7005template <typename T>
7006struct Safe_Conversion<T, T> : public True {
7007};
7008
7009#define PPL_SAFE_CONVERSION(To, From)                        \
7010  template <> struct Safe_Conversion<PPL_U(To), PPL_U(From)> \
7011    : public True { }
7012
7013#if PPL_CXX_PLAIN_CHAR_IS_SIGNED
7014PPL_SAFE_CONVERSION(signed short, char);
7015#endif
7016PPL_SAFE_CONVERSION(signed short, signed char);
7017#if PPL_SIZEOF_CHAR < PPL_SIZEOF_SHORT
7018#if !PPL_CXX_PLAIN_CHAR_IS_SIGNED
7019PPL_SAFE_CONVERSION(signed short, char);
7020#endif
7021PPL_SAFE_CONVERSION(signed short, unsigned char);
7022#endif
7023
7024#if PPL_CXX_PLAIN_CHAR_IS_SIGNED
7025PPL_SAFE_CONVERSION(signed int, char);
7026#endif
7027PPL_SAFE_CONVERSION(signed int, signed char);
7028PPL_SAFE_CONVERSION(signed int, signed short);
7029#if PPL_SIZEOF_CHAR < PPL_SIZEOF_INT
7030#if !PPL_CXX_PLAIN_CHAR_IS_SIGNED
7031PPL_SAFE_CONVERSION(signed int, char);
7032#endif
7033PPL_SAFE_CONVERSION(signed int, unsigned char);
7034#endif
7035#if PPL_SIZEOF_SHORT < PPL_SIZEOF_INT
7036PPL_SAFE_CONVERSION(signed int, unsigned short);
7037#endif
7038
7039#if PPL_CXX_PLAIN_CHAR_IS_SIGNED
7040PPL_SAFE_CONVERSION(signed long, char);
7041#endif
7042PPL_SAFE_CONVERSION(signed long, signed char);
7043PPL_SAFE_CONVERSION(signed long, signed short);
7044PPL_SAFE_CONVERSION(signed long, signed int);
7045#if PPL_SIZEOF_CHAR < PPL_SIZEOF_LONG
7046#if !PPL_CXX_PLAIN_CHAR_IS_SIGNED
7047PPL_SAFE_CONVERSION(signed long, char);
7048#endif
7049PPL_SAFE_CONVERSION(signed long, unsigned char);
7050#endif
7051#if PPL_SIZEOF_SHORT < PPL_SIZEOF_LONG
7052PPL_SAFE_CONVERSION(signed long, unsigned short);
7053#endif
7054#if PPL_SIZEOF_INT < PPL_SIZEOF_LONG
7055PPL_SAFE_CONVERSION(signed long, unsigned int);
7056#endif
7057
7058#if PPL_CXX_PLAIN_CHAR_IS_SIGNED
7059PPL_SAFE_CONVERSION(signed long long, char);
7060#endif
7061PPL_SAFE_CONVERSION(signed long long, signed char);
7062PPL_SAFE_CONVERSION(signed long long, signed short);
7063PPL_SAFE_CONVERSION(signed long long, signed int);
7064PPL_SAFE_CONVERSION(signed long long, signed long);
7065#if PPL_SIZEOF_CHAR < PPL_SIZEOF_LONG_LONG
7066#if !PPL_CXX_PLAIN_CHAR_IS_SIGNED
7067PPL_SAFE_CONVERSION(signed long long, char);
7068#endif
7069PPL_SAFE_CONVERSION(signed long long, unsigned char);
7070#endif
7071#if PPL_SIZEOF_SHORT < PPL_SIZEOF_LONG_LONG
7072PPL_SAFE_CONVERSION(signed long long, unsigned short);
7073#endif
7074#if PPL_SIZEOF_INT < PPL_SIZEOF_LONG_LONG
7075PPL_SAFE_CONVERSION(signed long long, unsigned int);
7076#endif
7077#if PPL_SIZEOF_LONG < PPL_SIZEOF_LONG_LONG
7078PPL_SAFE_CONVERSION(signed long long, unsigned long);
7079#endif
7080
7081#if !PPL_CXX_PLAIN_CHAR_IS_SIGNED
7082PPL_SAFE_CONVERSION(unsigned short, char);
7083#endif
7084PPL_SAFE_CONVERSION(unsigned short, unsigned char);
7085
7086#if !PPL_CXX_PLAIN_CHAR_IS_SIGNED
7087PPL_SAFE_CONVERSION(unsigned int, char);
7088#endif
7089PPL_SAFE_CONVERSION(unsigned int, unsigned char);
7090PPL_SAFE_CONVERSION(unsigned int, unsigned short);
7091
7092#if !PPL_CXX_PLAIN_CHAR_IS_SIGNED
7093PPL_SAFE_CONVERSION(unsigned long, char);
7094#endif
7095PPL_SAFE_CONVERSION(unsigned long, unsigned char);
7096PPL_SAFE_CONVERSION(unsigned long, unsigned short);
7097PPL_SAFE_CONVERSION(unsigned long, unsigned int);
7098
7099#if !PPL_CXX_PLAIN_CHAR_IS_SIGNED
7100PPL_SAFE_CONVERSION(unsigned long long, char);
7101#endif
7102PPL_SAFE_CONVERSION(unsigned long long, unsigned char);
7103PPL_SAFE_CONVERSION(unsigned long long, unsigned short);
7104PPL_SAFE_CONVERSION(unsigned long long, unsigned int);
7105PPL_SAFE_CONVERSION(unsigned long long, unsigned long);
7106
7107
7108#if PPL_SIZEOF_CHAR <= PPL_SIZEOF_FLOAT - 2
7109PPL_SAFE_CONVERSION(float, char);
7110PPL_SAFE_CONVERSION(float, signed char);
7111PPL_SAFE_CONVERSION(float, unsigned char);
7112#endif
7113#if PPL_SIZEOF_SHORT <= PPL_SIZEOF_FLOAT - 2
7114PPL_SAFE_CONVERSION(float, signed short);
7115PPL_SAFE_CONVERSION(float, unsigned short);
7116#endif
7117#if PPL_SIZEOF_INT <= PPL_SIZEOF_FLOAT - 2
7118PPL_SAFE_CONVERSION(float, signed int);
7119PPL_SAFE_CONVERSION(float, unsigned int);
7120#endif
7121#if PPL_SIZEOF_LONG <= PPL_SIZEOF_FLOAT - 2
7122PPL_SAFE_CONVERSION(float, signed long);
7123PPL_SAFE_CONVERSION(float, unsigned long);
7124#endif
7125#if PPL_SIZEOF_LONG_LONG <= PPL_SIZEOF_FLOAT - 2
7126PPL_SAFE_CONVERSION(float, signed long long);
7127PPL_SAFE_CONVERSION(float, unsigned long long);
7128#endif
7129
7130#if PPL_SIZEOF_CHAR <= PPL_SIZEOF_DOUBLE - 4
7131PPL_SAFE_CONVERSION(double, char);
7132PPL_SAFE_CONVERSION(double, signed char);
7133PPL_SAFE_CONVERSION(double, unsigned char);
7134#endif
7135#if PPL_SIZEOF_SHORT <= PPL_SIZEOF_DOUBLE - 4
7136PPL_SAFE_CONVERSION(double, signed short);
7137PPL_SAFE_CONVERSION(double, unsigned short);
7138#endif
7139#if PPL_SIZEOF_INT <= PPL_SIZEOF_DOUBLE - 4
7140PPL_SAFE_CONVERSION(double, signed int);
7141PPL_SAFE_CONVERSION(double, unsigned int);
7142#endif
7143#if PPL_SIZEOF_LONG <= PPL_SIZEOF_DOUBLE - 4
7144PPL_SAFE_CONVERSION(double, signed long);
7145PPL_SAFE_CONVERSION(double, unsigned long);
7146#endif
7147#if PPL_SIZEOF_LONG_LONG <= PPL_SIZEOF_DOUBLE - 4
7148PPL_SAFE_CONVERSION(double, signed long long);
7149PPL_SAFE_CONVERSION(double, unsigned long long);
7150#endif
7151PPL_SAFE_CONVERSION(double, float);
7152
7153#if PPL_SIZEOF_CHAR <= PPL_SIZEOF_LONG_DOUBLE - 4
7154PPL_SAFE_CONVERSION(long double, char);
7155PPL_SAFE_CONVERSION(long double, signed char);
7156PPL_SAFE_CONVERSION(long double, unsigned char);
7157#endif
7158#if PPL_SIZEOF_SHORT <= PPL_SIZEOF_LONG_DOUBLE - 4
7159PPL_SAFE_CONVERSION(long double, signed short);
7160PPL_SAFE_CONVERSION(long double, unsigned short);
7161#endif
7162#if PPL_SIZEOF_INT <= PPL_SIZEOF_LONG_DOUBLE - 4
7163PPL_SAFE_CONVERSION(long double, signed int);
7164PPL_SAFE_CONVERSION(long double, unsigned int);
7165#endif
7166#if PPL_SIZEOF_LONG <= PPL_SIZEOF_LONG_DOUBLE - 4
7167PPL_SAFE_CONVERSION(long double, signed long);
7168PPL_SAFE_CONVERSION(long double, unsigned long);
7169#endif
7170#if PPL_SIZEOF_LONG_LONG <= PPL_SIZEOF_LONG_DOUBLE - 4
7171PPL_SAFE_CONVERSION(long double, signed long long);
7172PPL_SAFE_CONVERSION(long double, unsigned long long);
7173#endif
7174PPL_SAFE_CONVERSION(long double, float);
7175PPL_SAFE_CONVERSION(long double, double);
7176
7177PPL_SAFE_CONVERSION(mpz_class, char);
7178PPL_SAFE_CONVERSION(mpz_class, signed char);
7179PPL_SAFE_CONVERSION(mpz_class, signed short);
7180PPL_SAFE_CONVERSION(mpz_class, signed int);
7181PPL_SAFE_CONVERSION(mpz_class, signed long);
7182// GMP's API does not support signed long long.
7183PPL_SAFE_CONVERSION(mpz_class, unsigned char);
7184PPL_SAFE_CONVERSION(mpz_class, unsigned short);
7185PPL_SAFE_CONVERSION(mpz_class, unsigned int);
7186PPL_SAFE_CONVERSION(mpz_class, unsigned long);
7187// GMP's API does not support unsigned long long.
7188
7189PPL_SAFE_CONVERSION(mpq_class, char);
7190PPL_SAFE_CONVERSION(mpq_class, signed char);
7191PPL_SAFE_CONVERSION(mpq_class, signed short);
7192PPL_SAFE_CONVERSION(mpq_class, signed int);
7193PPL_SAFE_CONVERSION(mpq_class, signed long);
7194// GMP's API does not support signed long long.
7195PPL_SAFE_CONVERSION(mpq_class, unsigned char);
7196PPL_SAFE_CONVERSION(mpq_class, unsigned short);
7197PPL_SAFE_CONVERSION(mpq_class, unsigned int);
7198PPL_SAFE_CONVERSION(mpq_class, unsigned long);
7199// GMP's API does not support unsigned long long.
7200PPL_SAFE_CONVERSION(mpq_class, float);
7201PPL_SAFE_CONVERSION(mpq_class, double);
7202// GMP's API does not support long double.
7203
7204#undef PPL_SAFE_CONVERSION
7205
7206template <typename Policy, typename Type>
7207struct PPL_FUNCTION_CLASS(construct)<Policy, Policy, Type, Type> {
7208  static inline Result function(Type& to, const Type& from, Rounding_Dir) {
7209    new(&to) Type(from);
7210    return V_EQ;
7211  }
7212};
7213
7214template <typename To_Policy, typename From_Policy, typename To, typename From>
7215struct PPL_FUNCTION_CLASS(construct) {
7216  static inline Result function(To& to, const From& from, Rounding_Dir dir) {
7217    new(&to) To();
7218    return assign<To_Policy, From_Policy>(to, from, dir);
7219  }
7220};
7221
7222template <typename To_Policy, typename To>
7223struct PPL_FUNCTION_CLASS(construct_special) {
7224  static inline Result function(To& to, Result_Class r, Rounding_Dir dir) {
7225    new(&to) To();
7226    return assign_special<To_Policy>(to, r, dir);
7227  }
7228};
7229
7230template <typename To_Policy, typename From_Policy, typename To, typename From>
7231inline Result
7232assign_exact(To& to, const From& from, Rounding_Dir) {
7233  to = from;
7234  return V_EQ;
7235}
7236
7237template <typename To_Policy, typename From_Policy, typename Type>
7238inline typename Enable_If<Is_Same<To_Policy, From_Policy>::value, void>::type
7239copy_generic(Type& to, const Type& from) {
7240  to = from;
7241}
7242
7243template <typename To_Policy, typename From_Policy, typename To, typename From>
7244inline Result
7245abs_generic(To& to, const From& from, Rounding_Dir dir) {
7246  if (from < 0) {
7247    return neg<To_Policy, From_Policy>(to, from, dir);
7248  }
7249  else {
7250    return assign<To_Policy, From_Policy>(to, from, dir);
7251  }
7252}
7253
7254template <typename To_Policy, typename From1_Policy, typename From2_Policy,
7255          typename To, typename From>
7256inline void
7257gcd_exact_no_abs(To& to, const From& x, const From& y) {
7258  To w_x = x;
7259  To w_y = y;
7260  To remainder;
7261  while (w_y != 0) {
7262    // The following is derived from the assumption that w_x % w_y
7263    // is always representable. This is true for both native integers
7264    // and IEC 559 floating point numbers.
7265    rem<To_Policy, From1_Policy, From2_Policy>(remainder, w_x, w_y,
7266                                               ROUND_NOT_NEEDED);
7267    w_x = w_y;
7268    w_y = remainder;
7269  }
7270  to = w_x;
7271}
7272
7273template <typename To_Policy, typename From1_Policy, typename From2_Policy,
7274          typename To, typename From1, typename From2>
7275inline Result
7276gcd_exact(To& to, const From1& x, const From2& y, Rounding_Dir dir) {
7277  gcd_exact_no_abs<To_Policy, From1_Policy, From2_Policy>(to, x, y);
7278  return abs<To_Policy, To_Policy>(to, to, dir);
7279}
7280
7281template <typename To1_Policy, typename To2_Policy, typename To3_Policy,
7282          typename From1_Policy, typename From2_Policy,
7283          typename To1, typename To2, typename To3,
7284          typename From1, typename From2>
7285inline Result
7286gcdext_exact(To1& to, To2& s, To3& t, const From1& x, const From2& y,
7287             Rounding_Dir dir) {
7288  // In case this becomes a bottleneck, we may consider using the
7289  // Stehle'-Zimmermann algorithm (see R. Crandall and C. Pomerance,
7290  // Prime Numbers - A Computational Perspective, Second Edition,
7291  // Springer, 2005).
7292  if (y == 0) {
7293    if (x == 0) {
7294      s = 0;
7295      t = 1;
7296      return V_EQ;
7297    }
7298    else {
7299      if (x < 0) {
7300        s = -1;
7301      }
7302      else {
7303        s = 1;
7304      }
7305      t = 0;
7306      return abs<To1_Policy, From1_Policy>(to, x, dir);
7307    }
7308  }
7309
7310  s = 1;
7311  t = 0;
7312  bool negative_x = x < 0;
7313  bool negative_y = y < 0;
7314
7315  Result r;
7316  r = abs<To1_Policy, From1_Policy>(to, x, dir);
7317  if (r != V_EQ) {
7318    return r;
7319  }
7320
7321  From2 a_y;
7322  r = abs<To1_Policy, From2_Policy>(a_y, y, dir);
7323  if (r != V_EQ) {
7324    return r;
7325  }
7326
7327  // If PPL_MATCH_GMP_GCDEXT is defined then s is favored when the absolute
7328  // values of the given numbers are equal.  For instance if x and y
7329  // are both 5 then s will be 1 and t will be 0, instead of the other
7330  // way round.  This is to match the behavior of GMP.
7331#define PPL_MATCH_GMP_GCDEXT 1
7332#ifdef PPL_MATCH_GMP_GCDEXT
7333  if (to == a_y) {
7334    goto sign_check;
7335  }
7336#endif
7337
7338  {
7339    To2 v1 = 0;
7340    To3 v2 = 1;
7341    To1 v3 = static_cast<To1>(a_y);
7342    while (true) {
7343      To1 q = to / v3;
7344      // Remainder, next candidate GCD.
7345      To1 t3 = to - q*v3;
7346      To2 t1 = s - static_cast<To2>(q)*v1;
7347      To3 t2 = t - static_cast<To3>(q)*v2;
7348      s = v1;
7349      t = v2;
7350      to = v3;
7351      if (t3 == 0) {
7352        break;
7353      }
7354      v1 = t1;
7355      v2 = t2;
7356      v3 = t3;
7357    }
7358  }
7359
7360#ifdef PPL_MATCH_GMP_GCDEXT
7361 sign_check:
7362#endif
7363  if (negative_x) {
7364    r = neg<To2_Policy, To2_Policy>(s, s, dir);
7365    if (r != V_EQ) {
7366      return r;
7367    }
7368  }
7369  if (negative_y) {
7370    return neg<To3_Policy, To3_Policy>(t, t, dir);
7371  }
7372  return V_EQ;
7373#undef PPL_MATCH_GMP_GCDEXT
7374}
7375
7376template <typename To_Policy, typename From1_Policy, typename From2_Policy,
7377          typename To, typename From1, typename From2>
7378inline Result
7379lcm_gcd_exact(To& to, const From1& x, const From2& y, Rounding_Dir dir) {
7380  if (x == 0 || y == 0) {
7381    to = 0;
7382    return V_EQ;
7383  }
7384  To a_x;
7385  To a_y;
7386  Result r;
7387  r = abs<From1_Policy, From1_Policy>(a_x, x, dir);
7388  if (r != V_EQ) {
7389    return r;
7390  }
7391  r = abs<From2_Policy, From2_Policy>(a_y, y, dir);
7392  if (r != V_EQ) {
7393    return r;
7394  }
7395  To gcd;
7396  gcd_exact_no_abs<To_Policy, From1_Policy, From2_Policy>(gcd, a_x, a_y);
7397  // The following is derived from the assumption that a_x / gcd(a_x, a_y)
7398  // is always representable. This is true for both native integers
7399  // and IEC 559 floating point numbers.
7400  div<To_Policy, From1_Policy, To_Policy>(to, a_x, gcd, ROUND_NOT_NEEDED);
7401  return mul<To_Policy, To_Policy, From2_Policy>(to, to, a_y, dir);
7402}
7403
7404template <typename Policy, typename Type>
7405inline Result_Relation
7406sgn_generic(const Type& x) {
7407  if (x > 0) {
7408    return VR_GT;
7409  }
7410  if (x == 0) {
7411    return VR_EQ;
7412  }
7413  return VR_LT;
7414}
7415
7416template <typename T1, typename T2, typename Enable = void>
7417struct Safe_Int_Comparison : public False {
7418};
7419
7420template <typename T1, typename T2>
7421struct Safe_Int_Comparison<T1, T2, typename Enable_If<(C_Integer<T1>::value && C_Integer<T2>::value)>::type>
7422  : public Bool<(C_Integer<T1>::is_signed
7423                 ? (C_Integer<T2>::is_signed
7424                    || sizeof(T2) < sizeof(T1)
7425                    || sizeof(T2) < sizeof(int))
7426                 : (!C_Integer<T2>::is_signed
7427                    || sizeof(T1) < sizeof(T2)
7428                    || sizeof(T1) < sizeof(int)))> {
7429};
7430
7431
7432template <typename T1, typename T2>
7433inline typename Enable_If<(Safe_Int_Comparison<T1, T2>::value
7434                           || Safe_Conversion<T1, T2>::value
7435                           || Safe_Conversion<T2, T1>::value), bool>::type
7436lt(const T1& x, const T2& y) {
7437  return x < y;
7438}
7439template <typename T1, typename T2>
7440inline typename Enable_If<(Safe_Int_Comparison<T1, T2>::value
7441                           || Safe_Conversion<T1, T2>::value
7442                           || Safe_Conversion<T2, T1>::value), bool>::type
7443le(const T1& x, const T2& y) {
7444  return x <= y;
7445}
7446template <typename T1, typename T2>
7447inline typename Enable_If<(Safe_Int_Comparison<T1, T2>::value
7448                           || Safe_Conversion<T1, T2>::value
7449                           || Safe_Conversion<T2, T1>::value), bool>::type
7450eq(const T1& x, const T2& y) {
7451  return x == y;
7452}
7453
7454template <typename S, typename U>
7455inline typename Enable_If<(!Safe_Int_Comparison<S, U>::value
7456                           && C_Integer<U>::value
7457                           && C_Integer<S>::is_signed), bool>::type
7458lt(const S& x, const U& y) {
7459  return x < 0 || static_cast<typename C_Integer<S>::other_type>(x) < y;
7460}
7461
7462template <typename U, typename S>
7463inline typename Enable_If<(!Safe_Int_Comparison<S, U>::value
7464                           && C_Integer<U>::value
7465                           && C_Integer<S>::is_signed), bool>::type
7466lt(const U& x, const S& y) {
7467  return y >= 0 && x < static_cast<typename C_Integer<S>::other_type>(y);
7468}
7469
7470template <typename S, typename U>
7471inline typename Enable_If<(!Safe_Int_Comparison<S, U>::value
7472                           && C_Integer<U>::value
7473                           && C_Integer<S>::is_signed), bool>::type
7474le(const S& x, const U& y) {
7475  return x < 0 || static_cast<typename C_Integer<S>::other_type>(x) <= y;
7476}
7477
7478template <typename U, typename S>
7479inline typename Enable_If<(!Safe_Int_Comparison<S, U>::value
7480                           && C_Integer<U>::value
7481                           && C_Integer<S>::is_signed), bool>::type
7482le(const U& x, const S& y) {
7483  return y >= 0 && x <= static_cast<typename C_Integer<S>::other_type>(y);
7484}
7485
7486template <typename S, typename U>
7487inline typename Enable_If<(!Safe_Int_Comparison<S, U>::value
7488                           && C_Integer<U>::value
7489                           && C_Integer<S>::is_signed), bool>::type
7490eq(const S& x, const U& y) {
7491  return x >= 0 && static_cast<typename C_Integer<S>::other_type>(x) == y;
7492}
7493
7494template <typename U, typename S>
7495inline typename Enable_If<(!Safe_Int_Comparison<S, U>::value
7496                           && C_Integer<U>::value
7497                           && C_Integer<S>::is_signed), bool>::type
7498eq(const U& x, const S& y) {
7499  return y >= 0 && x == static_cast<typename C_Integer<S>::other_type>(y);
7500}
7501
7502template <typename T1, typename T2>
7503inline typename Enable_If<(!Safe_Conversion<T1, T2>::value
7504                           && !Safe_Conversion<T2, T1>::value
7505                           && (!C_Integer<T1>::value || !C_Integer<T2>::value)), bool>::type
7506eq(const T1& x, const T2& y) {
7507  PPL_DIRTY_TEMP(T1, tmp);
7508  Result r = assign_r(tmp, y, ROUND_CHECK);
7509  // FIXME: We can do this also without fpu inexact check using a
7510  // conversion back and forth and then testing equality.  We should
7511  // code this in checked_float_inlines.hh, probably it's faster also
7512  // if fpu supports inexact check.
7513  PPL_ASSERT(r != V_LE && r != V_GE && r != V_LGE);
7514  return r == V_EQ && x == tmp;
7515}
7516
7517template <typename T1, typename T2>
7518inline typename Enable_If<(!Safe_Conversion<T1, T2>::value
7519                           && !Safe_Conversion<T2, T1>::value
7520                           && (!C_Integer<T1>::value || !C_Integer<T2>::value)), bool>::type
7521lt(const T1& x, const T2& y) {
7522  PPL_DIRTY_TEMP(T1, tmp);
7523  Result r = assign_r(tmp, y, ROUND_UP);
7524  if (!result_representable(r)) {
7525    return true;
7526  }
7527  switch (result_relation(r)) {
7528  case VR_EQ:
7529  case VR_LT:
7530  case VR_LE:
7531    return x < tmp;
7532  default:
7533    return false;
7534  }
7535}
7536
7537template <typename T1, typename T2>
7538inline typename
7539Enable_If<(!Safe_Conversion<T1, T2>::value
7540           && !Safe_Conversion<T2, T1>::value
7541           && (!C_Integer<T1>::value || !C_Integer<T2>::value)), bool>::type
7542le(const T1& x, const T2& y) {
7543  PPL_DIRTY_TEMP(T1, tmp);
7544  Result r = assign_r(tmp, y, (ROUND_UP | ROUND_STRICT_RELATION));
7545  // FIXME: We can do this also without fpu inexact check using a
7546  // conversion back and forth and then testing equality.  We should
7547  // code this in checked_float_inlines.hh, probably it's faster also
7548  // if fpu supports inexact check.
7549  PPL_ASSERT(r != V_LE && r != V_GE && r != V_LGE);
7550  if (!result_representable(r)) {
7551    return true;
7552  }
7553  switch (result_relation(r)) {
7554  case VR_EQ:
7555    return x <= tmp;
7556  case VR_LT:
7557    return x < tmp;
7558  case VR_LE:
7559  case VR_GE:
7560  case VR_LGE:
7561    // See comment above.
7562    PPL_UNREACHABLE;
7563    return false;
7564  default:
7565    return false;
7566  }
7567}
7568
7569template <typename Policy1, typename Policy2,
7570          typename Type1, typename Type2>
7571inline bool
7572lt_p(const Type1& x, const Type2& y) {
7573  return lt(x, y);
7574}
7575
7576template <typename Policy1, typename Policy2,
7577          typename Type1, typename Type2>
7578inline bool
7579le_p(const Type1& x, const Type2& y) {
7580  return le(x, y);
7581}
7582
7583template <typename Policy1, typename Policy2,
7584          typename Type1, typename Type2>
7585inline bool
7586eq_p(const Type1& x, const Type2& y) {
7587  return eq(x, y);
7588}
7589
7590template <typename Policy1, typename Policy2,
7591          typename Type1, typename Type2>
7592inline Result_Relation
7593cmp_generic(const Type1& x, const Type2& y) {
7594  if (lt(y, x)) {
7595    return VR_GT;
7596  }
7597  if (lt(x, y)) {
7598    return VR_LT;
7599  }
7600  return VR_EQ;
7601}
7602
7603template <typename Policy, typename Type>
7604inline Result
7605assign_nan(Type& to, Result r) {
7606  assign_special<Policy>(to, VC_NAN, ROUND_IGNORE);
7607  return r;
7608}
7609
7610template <typename Policy, typename Type>
7611inline Result
7612input_generic(Type& to, std::istream& is, Rounding_Dir dir) {
7613  PPL_DIRTY_TEMP(mpq_class, q);
7614  Result r = input_mpq(q, is);
7615  Result_Class c = result_class(r);
7616  switch (c) {
7617  case VC_MINUS_INFINITY:
7618  case VC_PLUS_INFINITY:
7619    return assign_special<Policy>(to, c, dir);
7620  case VC_NAN:
7621    return assign_nan<Policy>(to, r);
7622  default:
7623    break;
7624  }
7625  PPL_ASSERT(r == V_EQ);
7626  return assign<Policy, void>(to, q, dir);
7627}
7628
7629} // namespace Checked
7630
7631} // namespace Parma_Polyhedra_Library
7632
7633/* Automatically generated from PPL source file ../src/checked_int_inlines.hh line 1. */
7634/* Specialized "checked" functions for native integer numbers.
7635*/
7636
7637
7638/* Automatically generated from PPL source file ../src/checked_int_inlines.hh line 28. */
7639#include <cerrno>
7640#include <cstdlib>
7641#include <climits>
7642#include <string>
7643
7644#if !PPL_HAVE_DECL_STRTOLL
7645signed long long
7646strtoll(const char* nptr, char** endptr, int base);
7647#endif
7648
7649#if !PPL_HAVE_DECL_STRTOULL
7650unsigned long long
7651strtoull(const char* nptr, char** endptr, int base);
7652#endif
7653
7654namespace Parma_Polyhedra_Library {
7655
7656namespace Checked {
7657
7658#ifndef PPL_HAVE_INT_FAST16_T
7659typedef int16_t int_fast16_t;
7660#endif
7661
7662#ifndef PPL_HAVE_INT_FAST32_T
7663typedef int32_t int_fast32_t;
7664#endif
7665
7666#ifndef PPL_HAVE_INT_FAST64_T
7667typedef int64_t int_fast64_t;
7668#endif
7669
7670#ifndef PPL_HAVE_UINT_FAST16_T
7671typedef uint16_t uint_fast16_t;
7672#endif
7673
7674#ifndef PPL_HAVE_UINT_FAST32_T
7675typedef uint32_t uint_fast32_t;
7676#endif
7677
7678#ifndef PPL_HAVE_UINT_FAST64_T
7679typedef uint64_t uint_fast64_t;
7680#endif
7681
7682template <typename Policy, typename Type>
7683struct Extended_Int {
7684  static const Type plus_infinity = C_Integer<Type>::max;
7685  static const Type minus_infinity = ((C_Integer<Type>::min >= 0)
7686                                      ? (C_Integer<Type>::max - 1)
7687                                      : C_Integer<Type>::min);
7688  static const Type not_a_number
7689  = ((C_Integer<Type>::min >= 0)
7690     ? (C_Integer<Type>::max - 2 * (Policy::has_infinity ? 1 : 0))
7691     : (C_Integer<Type>::min + (Policy::has_infinity ? 1 : 0)));
7692  static const Type min
7693  = (C_Integer<Type>::min
7694     + ((C_Integer<Type>::min >= 0)
7695        ? 0
7696        : ((Policy::has_infinity ? 1 : 0) + (Policy::has_nan ? 1 : 0))));
7697  static const Type max
7698  = (C_Integer<Type>::max
7699     - ((C_Integer<Type>::min >= 0)
7700        ? (2 * (Policy::has_infinity ? 1 : 0) + (Policy::has_nan ? 1 : 0))
7701        : (Policy::has_infinity ? 1 : 0)));
7702};
7703
7704template <typename Policy, typename To>
7705inline Result
7706set_neg_overflow_int(To& to, Rounding_Dir dir) {
7707  if (round_up(dir)) {
7708    to = Extended_Int<Policy, To>::min;
7709    return V_LT_INF;
7710  }
7711  else {
7712    if (Policy::has_infinity) {
7713      to = Extended_Int<Policy, To>::minus_infinity;
7714      return V_GT_MINUS_INFINITY;
7715    }
7716    return V_GT_MINUS_INFINITY | V_UNREPRESENTABLE;
7717  }
7718}
7719
7720template <typename Policy, typename To>
7721inline Result
7722set_pos_overflow_int(To& to, Rounding_Dir dir) {
7723  if (round_down(dir)) {
7724    to = Extended_Int<Policy, To>::max;
7725    return V_GT_SUP;
7726  }
7727  else {
7728    if (Policy::has_infinity) {
7729      to = Extended_Int<Policy, To>::plus_infinity;
7730      return V_LT_PLUS_INFINITY;
7731    }
7732    return V_LT_PLUS_INFINITY | V_UNREPRESENTABLE;
7733  }
7734}
7735
7736template <typename Policy, typename To>
7737inline Result
7738round_lt_int_no_overflow(To& to, Rounding_Dir dir) {
7739  if (round_down(dir)) {
7740    --to;
7741    return V_GT;
7742  }
7743  return V_LT;
7744}
7745
7746template <typename Policy, typename To>
7747inline Result
7748round_gt_int_no_overflow(To& to, Rounding_Dir dir) {
7749  if (round_up(dir)) {
7750    ++to;
7751    return V_LT;
7752  }
7753  return V_GT;
7754}
7755
7756template <typename Policy, typename To>
7757inline Result
7758round_lt_int(To& to, Rounding_Dir dir) {
7759  if (round_down(dir)) {
7760    if (to == Extended_Int<Policy, To>::min) {
7761      if (Policy::has_infinity) {
7762        to = Extended_Int<Policy, To>::minus_infinity;
7763        return V_GT_MINUS_INFINITY;
7764      }
7765      return V_GT_MINUS_INFINITY | V_UNREPRESENTABLE;
7766    }
7767    else {
7768      --to;
7769      return V_GT;
7770    }
7771  }
7772  return V_LT;
7773}
7774
7775template <typename Policy, typename To>
7776inline Result
7777round_gt_int(To& to, Rounding_Dir dir) {
7778  if (round_up(dir)) {
7779    if (to == Extended_Int<Policy, To>::max) {
7780      if (Policy::has_infinity) {
7781        to = Extended_Int<Policy, To>::plus_infinity;
7782        return V_LT_PLUS_INFINITY;
7783      }
7784      return V_LT_PLUS_INFINITY | V_UNREPRESENTABLE;
7785    }
7786    else {
7787      ++to;
7788      return V_LT;
7789    }
7790  }
7791  return V_GT;
7792}
7793
7794PPL_SPECIALIZE_COPY(copy_generic, char)
7795PPL_SPECIALIZE_COPY(copy_generic, signed char)
7796PPL_SPECIALIZE_COPY(copy_generic, signed short)
7797PPL_SPECIALIZE_COPY(copy_generic, signed int)
7798PPL_SPECIALIZE_COPY(copy_generic, signed long)
7799PPL_SPECIALIZE_COPY(copy_generic, signed long long)
7800PPL_SPECIALIZE_COPY(copy_generic, unsigned char)
7801PPL_SPECIALIZE_COPY(copy_generic, unsigned short)
7802PPL_SPECIALIZE_COPY(copy_generic, unsigned int)
7803PPL_SPECIALIZE_COPY(copy_generic, unsigned long)
7804PPL_SPECIALIZE_COPY(copy_generic, unsigned long long)
7805
7806template <typename Policy, typename Type>
7807inline Result
7808classify_int(const Type v, bool nan, bool inf, bool sign) {
7809  if (Policy::has_nan
7810      && (nan || sign)
7811      && v == Extended_Int<Policy, Type>::not_a_number) {
7812    return V_NAN;
7813  }
7814  if (!inf && !sign) {
7815    return V_LGE;
7816  }
7817  if (Policy::has_infinity) {
7818    if (v == Extended_Int<Policy, Type>::minus_infinity) {
7819      return inf ? V_EQ_MINUS_INFINITY : V_LT;
7820    }
7821    if (v == Extended_Int<Policy, Type>::plus_infinity) {
7822      return inf ? V_EQ_PLUS_INFINITY : V_GT;
7823    }
7824  }
7825  if (sign) {
7826    if (v < 0) {
7827      return V_LT;
7828    }
7829    if (v > 0) {
7830      return V_GT;
7831    }
7832    return V_EQ;
7833  }
7834  return V_LGE;
7835}
7836
7837PPL_SPECIALIZE_CLASSIFY(classify_int, char)
7838PPL_SPECIALIZE_CLASSIFY(classify_int, signed char)
7839PPL_SPECIALIZE_CLASSIFY(classify_int, signed short)
7840PPL_SPECIALIZE_CLASSIFY(classify_int, signed int)
7841PPL_SPECIALIZE_CLASSIFY(classify_int, signed long)
7842PPL_SPECIALIZE_CLASSIFY(classify_int, signed long long)
7843PPL_SPECIALIZE_CLASSIFY(classify_int, unsigned char)
7844PPL_SPECIALIZE_CLASSIFY(classify_int, unsigned short)
7845PPL_SPECIALIZE_CLASSIFY(classify_int, unsigned int)
7846PPL_SPECIALIZE_CLASSIFY(classify_int, unsigned long)
7847PPL_SPECIALIZE_CLASSIFY(classify_int, unsigned long long)
7848
7849template <typename Policy, typename Type>
7850inline bool
7851is_nan_int(const Type v) {
7852  return Policy::has_nan && v == Extended_Int<Policy, Type>::not_a_number;
7853}
7854
7855PPL_SPECIALIZE_IS_NAN(is_nan_int, char)
7856PPL_SPECIALIZE_IS_NAN(is_nan_int, signed char)
7857PPL_SPECIALIZE_IS_NAN(is_nan_int, signed short)
7858PPL_SPECIALIZE_IS_NAN(is_nan_int, signed int)
7859PPL_SPECIALIZE_IS_NAN(is_nan_int, signed long)
7860PPL_SPECIALIZE_IS_NAN(is_nan_int, signed long long)
7861PPL_SPECIALIZE_IS_NAN(is_nan_int, unsigned char)
7862PPL_SPECIALIZE_IS_NAN(is_nan_int, unsigned short)
7863PPL_SPECIALIZE_IS_NAN(is_nan_int, unsigned int)
7864PPL_SPECIALIZE_IS_NAN(is_nan_int, unsigned long)
7865PPL_SPECIALIZE_IS_NAN(is_nan_int, unsigned long long)
7866
7867template <typename Policy, typename Type>
7868inline bool
7869is_minf_int(const Type v) {
7870  return Policy::has_infinity
7871    && v == Extended_Int<Policy, Type>::minus_infinity;
7872}
7873
7874PPL_SPECIALIZE_IS_MINF(is_minf_int, char)
7875PPL_SPECIALIZE_IS_MINF(is_minf_int, signed char)
7876PPL_SPECIALIZE_IS_MINF(is_minf_int, signed short)
7877PPL_SPECIALIZE_IS_MINF(is_minf_int, signed int)
7878PPL_SPECIALIZE_IS_MINF(is_minf_int, signed long)
7879PPL_SPECIALIZE_IS_MINF(is_minf_int, signed long long)
7880PPL_SPECIALIZE_IS_MINF(is_minf_int, unsigned char)
7881PPL_SPECIALIZE_IS_MINF(is_minf_int, unsigned short)
7882PPL_SPECIALIZE_IS_MINF(is_minf_int, unsigned int)
7883PPL_SPECIALIZE_IS_MINF(is_minf_int, unsigned long)
7884PPL_SPECIALIZE_IS_MINF(is_minf_int, unsigned long long)
7885
7886template <typename Policy, typename Type>
7887inline bool
7888is_pinf_int(const Type v) {
7889  return Policy::has_infinity
7890    && v == Extended_Int<Policy, Type>::plus_infinity;
7891}
7892
7893PPL_SPECIALIZE_IS_PINF(is_pinf_int, char)
7894PPL_SPECIALIZE_IS_PINF(is_pinf_int, signed char)
7895PPL_SPECIALIZE_IS_PINF(is_pinf_int, signed short)
7896PPL_SPECIALIZE_IS_PINF(is_pinf_int, signed int)
7897PPL_SPECIALIZE_IS_PINF(is_pinf_int, signed long)
7898PPL_SPECIALIZE_IS_PINF(is_pinf_int, signed long long)
7899PPL_SPECIALIZE_IS_PINF(is_pinf_int, unsigned char)
7900PPL_SPECIALIZE_IS_PINF(is_pinf_int, unsigned short)
7901PPL_SPECIALIZE_IS_PINF(is_pinf_int, unsigned int)
7902PPL_SPECIALIZE_IS_PINF(is_pinf_int, unsigned long)
7903PPL_SPECIALIZE_IS_PINF(is_pinf_int, unsigned long long)
7904
7905template <typename Policy, typename Type>
7906inline bool
7907is_int_int(const Type v) {
7908  return !is_nan<Policy>(v);
7909}
7910
7911PPL_SPECIALIZE_IS_INT(is_int_int, char)
7912PPL_SPECIALIZE_IS_INT(is_int_int, signed char)
7913PPL_SPECIALIZE_IS_INT(is_int_int, signed short)
7914PPL_SPECIALIZE_IS_INT(is_int_int, signed int)
7915PPL_SPECIALIZE_IS_INT(is_int_int, signed long)
7916PPL_SPECIALIZE_IS_INT(is_int_int, signed long long)
7917PPL_SPECIALIZE_IS_INT(is_int_int, unsigned char)
7918PPL_SPECIALIZE_IS_INT(is_int_int, unsigned short)
7919PPL_SPECIALIZE_IS_INT(is_int_int, unsigned int)
7920PPL_SPECIALIZE_IS_INT(is_int_int, unsigned long)
7921PPL_SPECIALIZE_IS_INT(is_int_int, unsigned long long)
7922
7923template <typename Policy, typename Type>
7924inline Result
7925assign_special_int(Type& v, Result_Class c, Rounding_Dir dir) {
7926  PPL_ASSERT(c == VC_MINUS_INFINITY || c == VC_PLUS_INFINITY || c == VC_NAN);
7927  switch (c) {
7928  case VC_NAN:
7929    if (Policy::has_nan) {
7930      v = Extended_Int<Policy, Type>::not_a_number;
7931      return V_NAN;
7932    }
7933    return V_NAN | V_UNREPRESENTABLE;
7934  case VC_MINUS_INFINITY:
7935    if (Policy::has_infinity) {
7936      v = Extended_Int<Policy, Type>::minus_infinity;
7937      return V_EQ_MINUS_INFINITY;
7938    }
7939    if (round_up(dir)) {
7940      v = Extended_Int<Policy, Type>::min;
7941      return V_LT_INF;
7942    }
7943    return V_EQ_MINUS_INFINITY | V_UNREPRESENTABLE;
7944  case VC_PLUS_INFINITY:
7945    if (Policy::has_infinity) {
7946      v = Extended_Int<Policy, Type>::plus_infinity;
7947      return V_EQ_PLUS_INFINITY;
7948    }
7949    if (round_down(dir)) {
7950      v = Extended_Int<Policy, Type>::max;
7951      return V_GT_SUP;
7952    }
7953    return V_EQ_PLUS_INFINITY | V_UNREPRESENTABLE;
7954  default:
7955    PPL_UNREACHABLE;
7956    return V_NAN | V_UNREPRESENTABLE;
7957  }
7958}
7959
7960PPL_SPECIALIZE_ASSIGN_SPECIAL(assign_special_int, char)
7961PPL_SPECIALIZE_ASSIGN_SPECIAL(assign_special_int, signed char)
7962PPL_SPECIALIZE_ASSIGN_SPECIAL(assign_special_int, signed short)
7963PPL_SPECIALIZE_ASSIGN_SPECIAL(assign_special_int, signed int)
7964PPL_SPECIALIZE_ASSIGN_SPECIAL(assign_special_int, signed long)
7965PPL_SPECIALIZE_ASSIGN_SPECIAL(assign_special_int, signed long long)
7966PPL_SPECIALIZE_ASSIGN_SPECIAL(assign_special_int, unsigned char)
7967PPL_SPECIALIZE_ASSIGN_SPECIAL(assign_special_int, unsigned short)
7968PPL_SPECIALIZE_ASSIGN_SPECIAL(assign_special_int, unsigned int)
7969PPL_SPECIALIZE_ASSIGN_SPECIAL(assign_special_int, unsigned long)
7970PPL_SPECIALIZE_ASSIGN_SPECIAL(assign_special_int, unsigned long long)
7971
7972template <typename To_Policy, typename From_Policy, typename To, typename From>
7973inline Result
7974assign_signed_int_signed_int(To& to, const From from, Rounding_Dir dir) {
7975  if (sizeof(To) < sizeof(From)
7976      || (sizeof(To) == sizeof(From)
7977      && (Extended_Int<To_Policy, To>::min > Extended_Int<From_Policy, From>::min
7978      || Extended_Int<To_Policy, To>::max < Extended_Int<From_Policy, From>::max))) {
7979    if (CHECK_P(To_Policy::check_overflow,
7980                PPL_LT_SILENT(from,
7981                              static_cast<From>(Extended_Int<To_Policy, To>::min)))) {
7982      return set_neg_overflow_int<To_Policy>(to, dir);
7983    }
7984    if (CHECK_P(To_Policy::check_overflow,
7985                PPL_GT_SILENT(from,
7986                              static_cast<From>(Extended_Int<To_Policy, To>::max)))) {
7987      return set_pos_overflow_int<To_Policy>(to, dir);
7988    }
7989  }
7990  to = static_cast<To>(from);
7991  return V_EQ;
7992}
7993
7994template <typename To_Policy, typename From_Policy, typename To, typename From>
7995inline Result
7996assign_signed_int_unsigned_int(To& to, const From from, Rounding_Dir dir) {
7997  if (sizeof(To) <= sizeof(From)) {
7998    if (CHECK_P(To_Policy::check_overflow,
7999                from > static_cast<From>(Extended_Int<To_Policy, To>::max))) {
8000      return set_pos_overflow_int<To_Policy>(to, dir);
8001    }
8002  }
8003  to = static_cast<To>(from);
8004  return V_EQ;
8005}
8006
8007template <typename To_Policy, typename From_Policy, typename To, typename From>
8008inline Result
8009assign_unsigned_int_signed_int(To& to, const From from, Rounding_Dir dir) {
8010  if (CHECK_P(To_Policy::check_overflow, from < 0)) {
8011    return set_neg_overflow_int<To_Policy>(to, dir);
8012  }
8013  if (sizeof(To) < sizeof(From)) {
8014    if (CHECK_P(To_Policy::check_overflow,
8015                from > static_cast<From>(Extended_Int<To_Policy, To>::max))) {
8016      return set_pos_overflow_int<To_Policy>(to, dir);
8017    }
8018  }
8019  to = static_cast<To>(from);
8020  return V_EQ;
8021}
8022
8023template <typename To_Policy, typename From_Policy, typename To, typename From>
8024inline Result
8025assign_unsigned_int_unsigned_int(To& to, const From from, Rounding_Dir dir) {
8026  if (sizeof(To) < sizeof(From)
8027      || (sizeof(To) == sizeof(From)
8028      && Extended_Int<To_Policy, To>::max < Extended_Int<From_Policy, From>::max)) {
8029    if (CHECK_P(To_Policy::check_overflow,
8030                PPL_GT_SILENT(from,
8031                              static_cast<From>(Extended_Int<To_Policy, To>::max)))) {
8032      return set_pos_overflow_int<To_Policy>(to, dir);
8033    }
8034  }
8035  to = static_cast<To>(from);
8036  return V_EQ;
8037}
8038
8039
8040#define PPL_ASSIGN2_SIGNED_SIGNED(Smaller, Larger) \
8041PPL_SPECIALIZE_ASSIGN(assign_signed_int_signed_int, Smaller, Larger) \
8042PPL_SPECIALIZE_ASSIGN(assign_signed_int_signed_int, Larger, Smaller)
8043
8044#define PPL_ASSIGN2_UNSIGNED_UNSIGNED(Smaller, Larger) \
8045PPL_SPECIALIZE_ASSIGN(assign_unsigned_int_unsigned_int, Smaller, Larger) \
8046PPL_SPECIALIZE_ASSIGN(assign_unsigned_int_unsigned_int, Larger, Smaller)
8047
8048#define PPL_ASSIGN2_UNSIGNED_SIGNED(Smaller, Larger) \
8049PPL_SPECIALIZE_ASSIGN(assign_unsigned_int_signed_int, Smaller, Larger) \
8050PPL_SPECIALIZE_ASSIGN(assign_signed_int_unsigned_int, Larger, Smaller)
8051
8052#define PPL_ASSIGN2_SIGNED_UNSIGNED(Smaller, Larger) \
8053PPL_SPECIALIZE_ASSIGN(assign_signed_int_unsigned_int, Smaller, Larger) \
8054PPL_SPECIALIZE_ASSIGN(assign_unsigned_int_signed_int, Larger, Smaller)
8055
8056#define PPL_ASSIGN_SIGNED(Type) \
8057PPL_SPECIALIZE_ASSIGN(assign_signed_int_signed_int, Type, Type)
8058#define PPL_ASSIGN_UNSIGNED(Type) \
8059PPL_SPECIALIZE_ASSIGN(assign_unsigned_int_unsigned_int, Type, Type)
8060
8061#if PPL_CXX_PLAIN_CHAR_IS_SIGNED
8062PPL_ASSIGN_SIGNED(char)
8063#endif
8064PPL_ASSIGN_SIGNED(signed char)
8065PPL_ASSIGN_SIGNED(signed short)
8066PPL_ASSIGN_SIGNED(signed int)
8067PPL_ASSIGN_SIGNED(signed long)
8068PPL_ASSIGN_SIGNED(signed long long)
8069#if !PPL_CXX_PLAIN_CHAR_IS_SIGNED
8070PPL_ASSIGN_UNSIGNED(char)
8071#endif
8072PPL_ASSIGN_UNSIGNED(unsigned char)
8073PPL_ASSIGN_UNSIGNED(unsigned short)
8074PPL_ASSIGN_UNSIGNED(unsigned int)
8075PPL_ASSIGN_UNSIGNED(unsigned long)
8076PPL_ASSIGN_UNSIGNED(unsigned long long)
8077
8078#if PPL_CXX_PLAIN_CHAR_IS_SIGNED
8079PPL_ASSIGN2_SIGNED_SIGNED(char, signed short)
8080PPL_ASSIGN2_SIGNED_SIGNED(char, signed int)
8081PPL_ASSIGN2_SIGNED_SIGNED(char, signed long)
8082PPL_ASSIGN2_SIGNED_SIGNED(char, signed long long)
8083#endif
8084PPL_ASSIGN2_SIGNED_SIGNED(signed char, signed short)
8085PPL_ASSIGN2_SIGNED_SIGNED(signed char, signed int)
8086PPL_ASSIGN2_SIGNED_SIGNED(signed char, signed long)
8087PPL_ASSIGN2_SIGNED_SIGNED(signed char, signed long long)
8088PPL_ASSIGN2_SIGNED_SIGNED(signed short, signed int)
8089PPL_ASSIGN2_SIGNED_SIGNED(signed short, signed long)
8090PPL_ASSIGN2_SIGNED_SIGNED(signed short, signed long long)
8091PPL_ASSIGN2_SIGNED_SIGNED(signed int, signed long)
8092PPL_ASSIGN2_SIGNED_SIGNED(signed int, signed long long)
8093PPL_ASSIGN2_SIGNED_SIGNED(signed long, signed long long)
8094#if !PPL_CXX_PLAIN_CHAR_IS_SIGNED
8095PPL_ASSIGN2_UNSIGNED_UNSIGNED(char, unsigned short)
8096PPL_ASSIGN2_UNSIGNED_UNSIGNED(char, unsigned int)
8097PPL_ASSIGN2_UNSIGNED_UNSIGNED(char, unsigned long)
8098PPL_ASSIGN2_UNSIGNED_UNSIGNED(char, unsigned long long)
8099#endif
8100PPL_ASSIGN2_UNSIGNED_UNSIGNED(unsigned char, unsigned short)
8101PPL_ASSIGN2_UNSIGNED_UNSIGNED(unsigned char, unsigned int)
8102PPL_ASSIGN2_UNSIGNED_UNSIGNED(unsigned char, unsigned long)
8103PPL_ASSIGN2_UNSIGNED_UNSIGNED(unsigned char, unsigned long long)
8104PPL_ASSIGN2_UNSIGNED_UNSIGNED(unsigned short, unsigned int)
8105PPL_ASSIGN2_UNSIGNED_UNSIGNED(unsigned short, unsigned long)
8106PPL_ASSIGN2_UNSIGNED_UNSIGNED(unsigned short, unsigned long long)
8107PPL_ASSIGN2_UNSIGNED_UNSIGNED(unsigned int, unsigned long)
8108PPL_ASSIGN2_UNSIGNED_UNSIGNED(unsigned int, unsigned long long)
8109PPL_ASSIGN2_UNSIGNED_UNSIGNED(unsigned long, unsigned long long)
8110#if !PPL_CXX_PLAIN_CHAR_IS_SIGNED
8111PPL_ASSIGN2_UNSIGNED_SIGNED(char, signed short)
8112PPL_ASSIGN2_UNSIGNED_SIGNED(char, signed int)
8113PPL_ASSIGN2_UNSIGNED_SIGNED(char, signed long)
8114PPL_ASSIGN2_UNSIGNED_SIGNED(char, signed long long)
8115#endif
8116PPL_ASSIGN2_UNSIGNED_SIGNED(unsigned char, signed short)
8117PPL_ASSIGN2_UNSIGNED_SIGNED(unsigned char, signed int)
8118PPL_ASSIGN2_UNSIGNED_SIGNED(unsigned char, signed long)
8119PPL_ASSIGN2_UNSIGNED_SIGNED(unsigned char, signed long long)
8120PPL_ASSIGN2_UNSIGNED_SIGNED(unsigned short, signed int)
8121PPL_ASSIGN2_UNSIGNED_SIGNED(unsigned short, signed long)
8122PPL_ASSIGN2_UNSIGNED_SIGNED(unsigned short, signed long long)
8123PPL_ASSIGN2_UNSIGNED_SIGNED(unsigned int, signed long)
8124PPL_ASSIGN2_UNSIGNED_SIGNED(unsigned int, signed long long)
8125PPL_ASSIGN2_UNSIGNED_SIGNED(unsigned long, signed long long)
8126#if PPL_CXX_PLAIN_CHAR_IS_SIGNED
8127PPL_ASSIGN2_SIGNED_UNSIGNED(char, unsigned char)
8128PPL_ASSIGN2_SIGNED_UNSIGNED(char, unsigned short)
8129PPL_ASSIGN2_SIGNED_UNSIGNED(char, unsigned int)
8130PPL_ASSIGN2_SIGNED_UNSIGNED(char, unsigned long)
8131PPL_ASSIGN2_SIGNED_UNSIGNED(char, unsigned long long)
8132#else
8133PPL_ASSIGN2_SIGNED_UNSIGNED(signed char, char)
8134#endif
8135PPL_ASSIGN2_SIGNED_UNSIGNED(signed char, unsigned char)
8136PPL_ASSIGN2_SIGNED_UNSIGNED(signed char, unsigned short)
8137PPL_ASSIGN2_SIGNED_UNSIGNED(signed char, unsigned int)
8138PPL_ASSIGN2_SIGNED_UNSIGNED(signed char, unsigned long)
8139PPL_ASSIGN2_SIGNED_UNSIGNED(signed char, unsigned long long)
8140PPL_ASSIGN2_SIGNED_UNSIGNED(signed short, unsigned short)
8141PPL_ASSIGN2_SIGNED_UNSIGNED(signed short, unsigned int)
8142PPL_ASSIGN2_SIGNED_UNSIGNED(signed short, unsigned long)
8143PPL_ASSIGN2_SIGNED_UNSIGNED(signed short, unsigned long long)
8144PPL_ASSIGN2_SIGNED_UNSIGNED(signed int, unsigned int)
8145PPL_ASSIGN2_SIGNED_UNSIGNED(signed int, unsigned long)
8146PPL_ASSIGN2_SIGNED_UNSIGNED(signed int, unsigned long long)
8147PPL_ASSIGN2_SIGNED_UNSIGNED(signed long, unsigned long)
8148PPL_ASSIGN2_SIGNED_UNSIGNED(signed long, unsigned long long)
8149PPL_ASSIGN2_SIGNED_UNSIGNED(signed long long, unsigned long long)
8150
8151template <typename To_Policy, typename From_Policy, typename To, typename From>
8152inline Result
8153assign_int_float(To& to, const From from, Rounding_Dir dir) {
8154  if (is_nan<From_Policy>(from)) {
8155    return assign_special<To_Policy>(to, VC_NAN, ROUND_IGNORE);
8156  }
8157  else if (is_minf<From_Policy>(from)) {
8158    return assign_special<To_Policy>(to, VC_MINUS_INFINITY, dir);
8159  }
8160  else if (is_pinf<From_Policy>(from)) {
8161    return assign_special<To_Policy>(to, VC_PLUS_INFINITY, dir);
8162  }
8163#if 0
8164  // FIXME: this is correct but it is inefficient and breaks the build
8165  // for the missing definition of static const members (a problem present
8166  // also in other areas of the PPL).
8167  if (CHECK_P(To_Policy::check_overflow,
8168              lt(from, Extended_Int<To_Policy, To>::min))) {
8169    return set_neg_overflow_int<To_Policy>(to, dir);
8170  }
8171  if (CHECK_P(To_Policy::check_overflow,
8172              !le(from, Extended_Int<To_Policy, To>::max))) {
8173    return set_pos_overflow_int<To_Policy>(to, dir);
8174  }
8175#else
8176  if (CHECK_P(To_Policy::check_overflow,
8177             (from < Extended_Int<To_Policy, To>::min))) {
8178    return set_neg_overflow_int<To_Policy>(to, dir);
8179  }
8180  if (CHECK_P(To_Policy::check_overflow,
8181             (from > Extended_Int<To_Policy, To>::max))) {
8182    return set_pos_overflow_int<To_Policy>(to, dir);
8183  }
8184#endif
8185  if (round_not_requested(dir)) {
8186    to = from;
8187    return V_LGE;
8188  }
8189  From i_from = rint(from);
8190  to = i_from;
8191  if (from == i_from) {
8192    return V_EQ;
8193  }
8194  if (round_direct(ROUND_UP)) {
8195    return round_lt_int<To_Policy>(to, dir);
8196  }
8197  if (round_direct(ROUND_DOWN)) {
8198    return round_gt_int<To_Policy>(to, dir);
8199  }
8200  if (from < i_from) {
8201    return round_lt_int<To_Policy>(to, dir);
8202  }
8203  PPL_ASSERT(from > i_from);
8204  return round_gt_int<To_Policy>(to, dir);
8205}
8206
8207PPL_SPECIALIZE_ASSIGN(assign_int_float, char, float)
8208PPL_SPECIALIZE_ASSIGN(assign_int_float, signed char, float)
8209PPL_SPECIALIZE_ASSIGN(assign_int_float, signed short, float)
8210PPL_SPECIALIZE_ASSIGN(assign_int_float, signed int, float)
8211PPL_SPECIALIZE_ASSIGN(assign_int_float, signed long, float)
8212PPL_SPECIALIZE_ASSIGN(assign_int_float, signed long long, float)
8213PPL_SPECIALIZE_ASSIGN(assign_int_float, unsigned char, float)
8214PPL_SPECIALIZE_ASSIGN(assign_int_float, unsigned short, float)
8215PPL_SPECIALIZE_ASSIGN(assign_int_float, unsigned int, float)
8216PPL_SPECIALIZE_ASSIGN(assign_int_float, unsigned long, float)
8217PPL_SPECIALIZE_ASSIGN(assign_int_float, unsigned long long, float)
8218
8219PPL_SPECIALIZE_ASSIGN(assign_int_float, char, double)
8220PPL_SPECIALIZE_ASSIGN(assign_int_float, signed char, double)
8221PPL_SPECIALIZE_ASSIGN(assign_int_float, signed short, double)
8222PPL_SPECIALIZE_ASSIGN(assign_int_float, signed int, double)
8223PPL_SPECIALIZE_ASSIGN(assign_int_float, signed long, double)
8224PPL_SPECIALIZE_ASSIGN(assign_int_float, signed long long, double)
8225PPL_SPECIALIZE_ASSIGN(assign_int_float, unsigned char, double)
8226PPL_SPECIALIZE_ASSIGN(assign_int_float, unsigned short, double)
8227PPL_SPECIALIZE_ASSIGN(assign_int_float, unsigned int, double)
8228PPL_SPECIALIZE_ASSIGN(assign_int_float, unsigned long, double)
8229PPL_SPECIALIZE_ASSIGN(assign_int_float, unsigned long long, double)
8230
8231PPL_SPECIALIZE_ASSIGN(assign_int_float, char, long double)
8232PPL_SPECIALIZE_ASSIGN(assign_int_float, signed char, long double)
8233PPL_SPECIALIZE_ASSIGN(assign_int_float, signed short, long double)
8234PPL_SPECIALIZE_ASSIGN(assign_int_float, signed int, long double)
8235PPL_SPECIALIZE_ASSIGN(assign_int_float, signed long, long double)
8236PPL_SPECIALIZE_ASSIGN(assign_int_float, signed long long, long double)
8237PPL_SPECIALIZE_ASSIGN(assign_int_float, unsigned char, long double)
8238PPL_SPECIALIZE_ASSIGN(assign_int_float, unsigned short, long double)
8239PPL_SPECIALIZE_ASSIGN(assign_int_float, unsigned int, long double)
8240PPL_SPECIALIZE_ASSIGN(assign_int_float, unsigned long, long double)
8241PPL_SPECIALIZE_ASSIGN(assign_int_float, unsigned long long, long double)
8242
8243#undef PPL_ASSIGN_SIGNED
8244#undef PPL_ASSIGN_UNSIGNED
8245#undef PPL_ASSIGN2_SIGNED_SIGNED
8246#undef PPL_ASSIGN2_UNSIGNED_UNSIGNED
8247#undef PPL_ASSIGN2_UNSIGNED_SIGNED
8248#undef PPL_ASSIGN2_SIGNED_UNSIGNED
8249
8250template <typename To_Policy, typename From_Policy, typename To>
8251inline Result
8252assign_signed_int_mpz(To& to, const mpz_class& from, Rounding_Dir dir) {
8253  if (sizeof(To) <= sizeof(signed long)) {
8254    if (!To_Policy::check_overflow) {
8255      to = from.get_si();
8256      return V_EQ;
8257    }
8258    if (from.fits_slong_p()) {
8259      signed long v = from.get_si();
8260      if (PPL_LT_SILENT(v, (Extended_Int<To_Policy, To>::min))) {
8261        return set_neg_overflow_int<To_Policy>(to, dir);
8262      }
8263      if (PPL_GT_SILENT(v, (Extended_Int<To_Policy, To>::max))) {
8264        return set_pos_overflow_int<To_Policy>(to, dir);
8265      }
8266      to = v;
8267      return V_EQ;
8268    }
8269  }
8270  else {
8271    mpz_srcptr m = from.get_mpz_t();
8272    size_t sz = mpz_size(m);
8273    if (sz <= sizeof(To) / sizeof(mp_limb_t)) {
8274      if (sz == 0) {
8275        to = 0;
8276        return V_EQ;
8277      }
8278      To v;
8279      mpz_export(&v, 0, -1, sizeof(To), 0, 0, m);
8280      if (v >= 0) {
8281        if (::sgn(from) < 0) {
8282          return neg<To_Policy, To_Policy>(to, v, dir);
8283        }
8284        to = v;
8285        return V_EQ;
8286      }
8287    }
8288  }
8289  return (::sgn(from) < 0)
8290    ? set_neg_overflow_int<To_Policy>(to, dir)
8291    : set_pos_overflow_int<To_Policy>(to, dir);
8292}
8293
8294#if PPL_CXX_PLAIN_CHAR_IS_SIGNED
8295PPL_SPECIALIZE_ASSIGN(assign_signed_int_mpz, char, mpz_class)
8296#endif
8297PPL_SPECIALIZE_ASSIGN(assign_signed_int_mpz, signed char, mpz_class)
8298PPL_SPECIALIZE_ASSIGN(assign_signed_int_mpz, signed short, mpz_class)
8299PPL_SPECIALIZE_ASSIGN(assign_signed_int_mpz, signed int, mpz_class)
8300PPL_SPECIALIZE_ASSIGN(assign_signed_int_mpz, signed long, mpz_class)
8301PPL_SPECIALIZE_ASSIGN(assign_signed_int_mpz, signed long long, mpz_class)
8302
8303template <typename To_Policy, typename From_Policy, typename To>
8304inline Result
8305assign_unsigned_int_mpz(To& to, const mpz_class& from, Rounding_Dir dir) {
8306  if (CHECK_P(To_Policy::check_overflow, ::sgn(from) < 0)) {
8307    return set_neg_overflow_int<To_Policy>(to, dir);
8308  }
8309  if (sizeof(To) <= sizeof(unsigned long)) {
8310    if (!To_Policy::check_overflow) {
8311      to = static_cast<To>(from.get_ui());
8312      return V_EQ;
8313    }
8314    if (from.fits_ulong_p()) {
8315      const unsigned long v = from.get_ui();
8316      if (PPL_GT_SILENT(v, (Extended_Int<To_Policy, To>::max))) {
8317        return set_pos_overflow_int<To_Policy>(to, dir);
8318      }
8319      to = static_cast<To>(v);
8320      return V_EQ;
8321    }
8322  }
8323  else {
8324    const mpz_srcptr m = from.get_mpz_t();
8325    const size_t sz = mpz_size(m);
8326    if (sz <= sizeof(To) / sizeof(mp_limb_t)) {
8327      if (sz == 0) {
8328        to = 0;
8329      }
8330      else {
8331        mpz_export(&to, 0, -1, sizeof(To), 0, 0, m);
8332      }
8333      return V_EQ;
8334    }
8335  }
8336  return set_pos_overflow_int<To_Policy>(to, dir);
8337}
8338
8339#if !PPL_CXX_PLAIN_CHAR_IS_SIGNED
8340PPL_SPECIALIZE_ASSIGN(assign_unsigned_int_mpz, char, mpz_class)
8341#endif
8342PPL_SPECIALIZE_ASSIGN(assign_unsigned_int_mpz, unsigned char, mpz_class)
8343PPL_SPECIALIZE_ASSIGN(assign_unsigned_int_mpz, unsigned short, mpz_class)
8344PPL_SPECIALIZE_ASSIGN(assign_unsigned_int_mpz, unsigned int, mpz_class)
8345PPL_SPECIALIZE_ASSIGN(assign_unsigned_int_mpz, unsigned long, mpz_class)
8346PPL_SPECIALIZE_ASSIGN(assign_unsigned_int_mpz, unsigned long long, mpz_class)
8347
8348template <typename To_Policy, typename From_Policy, typename To>
8349inline Result
8350assign_int_mpq(To& to, const mpq_class& from, Rounding_Dir dir) {
8351  mpz_srcptr n = from.get_num().get_mpz_t();
8352  mpz_srcptr d = from.get_den().get_mpz_t();
8353  PPL_DIRTY_TEMP(mpz_class, q);
8354  mpz_ptr q_z = q.get_mpz_t();
8355  if (round_not_requested(dir)) {
8356    mpz_tdiv_q(q_z, n, d);
8357    Result r = assign<To_Policy, void>(to, q, dir);
8358    if (r != V_EQ) {
8359      return r;
8360    }
8361    return V_LGE;
8362  }
8363  mpz_t rem;
8364  int sign;
8365  mpz_init(rem);
8366  mpz_tdiv_qr(q_z, rem, n, d);
8367  sign = mpz_sgn(rem);
8368  mpz_clear(rem);
8369  Result r = assign<To_Policy, void>(to, q, dir);
8370  if (r != V_EQ) {
8371    return r;
8372  }
8373  switch (sign) {
8374  case -1:
8375    return round_lt_int<To_Policy>(to, dir);
8376  case 1:
8377    return round_gt_int<To_Policy>(to, dir);
8378  default:
8379    return V_EQ;
8380  }
8381}
8382
8383PPL_SPECIALIZE_ASSIGN(assign_int_mpq, char, mpq_class)
8384PPL_SPECIALIZE_ASSIGN(assign_int_mpq, signed char, mpq_class)
8385PPL_SPECIALIZE_ASSIGN(assign_int_mpq, signed short, mpq_class)
8386PPL_SPECIALIZE_ASSIGN(assign_int_mpq, signed int, mpq_class)
8387PPL_SPECIALIZE_ASSIGN(assign_int_mpq, signed long, mpq_class)
8388PPL_SPECIALIZE_ASSIGN(assign_int_mpq, signed long long, mpq_class)
8389PPL_SPECIALIZE_ASSIGN(assign_int_mpq, unsigned char, mpq_class)
8390PPL_SPECIALIZE_ASSIGN(assign_int_mpq, unsigned short, mpq_class)
8391PPL_SPECIALIZE_ASSIGN(assign_int_mpq, unsigned int, mpq_class)
8392PPL_SPECIALIZE_ASSIGN(assign_int_mpq, unsigned long, mpq_class)
8393PPL_SPECIALIZE_ASSIGN(assign_int_mpq, unsigned long long, mpq_class)
8394
8395#if ~0 != -1
8396#error "Only two's complement is supported"
8397#endif
8398
8399#if UCHAR_MAX == 0xff
8400#define CHAR_BITS 8
8401#else
8402#error "Unexpected max for unsigned char"
8403#endif
8404
8405#if USHRT_MAX == 0xffff
8406#define SHRT_BITS 16
8407#else
8408#error "Unexpected max for unsigned short"
8409#endif
8410
8411#if UINT_MAX == 0xffffffff
8412#define INT_BITS 32
8413#else
8414#error "Unexpected max for unsigned int"
8415#endif
8416
8417#if ULONG_MAX == 0xffffffffUL
8418#define LONG_BITS 32
8419#elif ULONG_MAX == 0xffffffffffffffffULL
8420#define LONG_BITS 64
8421#else
8422#error "Unexpected max for unsigned long"
8423#endif
8424
8425#if ULLONG_MAX == 0xffffffffffffffffULL
8426#define LONG_LONG_BITS 64
8427#else
8428#error "Unexpected max for unsigned long long"
8429#endif
8430
8431
8432template <typename T>
8433struct Larger;
8434
8435// The following may be tuned for performance on specific architectures.
8436//
8437// Current guidelines:
8438//   - avoid division where possible (larger type variant for mul)
8439//   - use larger type variant for types smaller than architecture bit size
8440
8441template <>
8442struct Larger<char> {
8443  const_bool_nodef(use_for_neg, true);
8444  const_bool_nodef(use_for_add, true);
8445  const_bool_nodef(use_for_sub, true);
8446  const_bool_nodef(use_for_mul, true);
8447  typedef int_fast16_t type_for_neg;
8448  typedef int_fast16_t type_for_add;
8449  typedef int_fast16_t type_for_sub;
8450  typedef int_fast16_t type_for_mul;
8451};
8452
8453template <>
8454struct Larger<signed char> {
8455  const_bool_nodef(use_for_neg, true);
8456  const_bool_nodef(use_for_add, true);
8457  const_bool_nodef(use_for_sub, true);
8458  const_bool_nodef(use_for_mul, true);
8459  typedef int_fast16_t type_for_neg;
8460  typedef int_fast16_t type_for_add;
8461  typedef int_fast16_t type_for_sub;
8462  typedef int_fast16_t type_for_mul;
8463};
8464
8465template <>
8466struct Larger<unsigned char> {
8467  const_bool_nodef(use_for_neg, true);
8468  const_bool_nodef(use_for_add, true);
8469  const_bool_nodef(use_for_sub, true);
8470  const_bool_nodef(use_for_mul, true);
8471  typedef int_fast16_t type_for_neg;
8472  typedef uint_fast16_t type_for_add;
8473  typedef int_fast16_t type_for_sub;
8474  typedef uint_fast16_t type_for_mul;
8475};
8476
8477template <>
8478struct Larger<signed short> {
8479  const_bool_nodef(use_for_neg, true);
8480  const_bool_nodef(use_for_add, true);
8481  const_bool_nodef(use_for_sub, true);
8482  const_bool_nodef(use_for_mul, true);
8483  typedef int_fast32_t type_for_neg;
8484  typedef int_fast32_t type_for_add;
8485  typedef int_fast32_t type_for_sub;
8486  typedef int_fast32_t type_for_mul;
8487};
8488
8489template <>
8490struct Larger<unsigned short> {
8491  const_bool_nodef(use_for_neg, true);
8492  const_bool_nodef(use_for_add, true);
8493  const_bool_nodef(use_for_sub, true);
8494  const_bool_nodef(use_for_mul, true);
8495  typedef int_fast32_t type_for_neg;
8496  typedef uint_fast32_t type_for_add;
8497  typedef int_fast32_t type_for_sub;
8498  typedef uint_fast32_t type_for_mul;
8499};
8500
8501template <>
8502struct Larger<signed int> {
8503  const_bool_nodef(use_for_neg, (LONG_BITS == 64));
8504  const_bool_nodef(use_for_add, (LONG_BITS == 64));
8505  const_bool_nodef(use_for_sub, (LONG_BITS == 64));
8506  const_bool_nodef(use_for_mul, true);
8507  typedef int_fast64_t type_for_neg;
8508  typedef int_fast64_t type_for_add;
8509  typedef int_fast64_t type_for_sub;
8510  typedef int_fast64_t type_for_mul;
8511};
8512
8513template <>
8514struct Larger<unsigned int> {
8515  const_bool_nodef(use_for_neg, (LONG_BITS == 64));
8516  const_bool_nodef(use_for_add, (LONG_BITS == 64));
8517  const_bool_nodef(use_for_sub, (LONG_BITS == 64));
8518  const_bool_nodef(use_for_mul, true);
8519  typedef int_fast64_t type_for_neg;
8520  typedef uint_fast64_t type_for_add;
8521  typedef int_fast64_t type_for_sub;
8522  typedef uint_fast64_t type_for_mul;
8523};
8524
8525template <>
8526struct Larger<signed long> {
8527  const_bool_nodef(use_for_neg, false);
8528  const_bool_nodef(use_for_add, false);
8529  const_bool_nodef(use_for_sub, false);
8530  const_bool_nodef(use_for_mul, (LONG_BITS == 32));
8531  typedef int_fast64_t type_for_neg;
8532  typedef int_fast64_t type_for_add;
8533  typedef int_fast64_t type_for_sub;
8534  typedef int_fast64_t type_for_mul;
8535};
8536
8537template <>
8538struct Larger<unsigned long> {
8539  const_bool_nodef(use_for_neg, false);
8540  const_bool_nodef(use_for_add, false);
8541  const_bool_nodef(use_for_sub, false);
8542  const_bool_nodef(use_for_mul, (LONG_BITS == 32));
8543  typedef int_fast64_t type_for_neg;
8544  typedef uint_fast64_t type_for_add;
8545  typedef int_fast64_t type_for_sub;
8546  typedef uint_fast64_t type_for_mul;
8547};
8548
8549template <>
8550struct Larger<signed long long> {
8551  const_bool_nodef(use_for_neg, false);
8552  const_bool_nodef(use_for_add, false);
8553  const_bool_nodef(use_for_sub, false);
8554  const_bool_nodef(use_for_mul, false);
8555  typedef int_fast64_t type_for_neg;
8556  typedef int_fast64_t type_for_add;
8557  typedef int_fast64_t type_for_sub;
8558  typedef int_fast64_t type_for_mul;
8559};
8560
8561template <>
8562struct Larger<unsigned long long> {
8563  const_bool_nodef(use_for_neg, false);
8564  const_bool_nodef(use_for_add, false);
8565  const_bool_nodef(use_for_sub, false);
8566  const_bool_nodef(use_for_mul, false);
8567  typedef int_fast64_t type_for_neg;
8568  typedef uint_fast64_t type_for_add;
8569  typedef int_fast64_t type_for_sub;
8570  typedef uint_fast64_t type_for_mul;
8571};
8572
8573template <typename To_Policy, typename From_Policy, typename Type>
8574inline Result
8575neg_int_larger(Type& to, const Type x, Rounding_Dir dir) {
8576  typename Larger<Type>::type_for_neg l = x;
8577  l = -l;
8578  return assign<To_Policy, To_Policy>(to, l, dir);
8579}
8580
8581template <typename To_Policy, typename From1_Policy, typename From2_Policy,
8582          typename Type>
8583inline Result
8584add_int_larger(Type& to, const Type x, const Type y, Rounding_Dir dir) {
8585  typename Larger<Type>::type_for_add l = x;
8586  l += y;
8587  return assign<To_Policy, To_Policy>(to, l, dir);
8588}
8589
8590template <typename To_Policy, typename From1_Policy, typename From2_Policy,
8591          typename Type>
8592inline Result
8593sub_int_larger(Type& to, const Type x, const Type y, Rounding_Dir dir) {
8594  typename Larger<Type>::type_for_sub l = x;
8595  l -= y;
8596  return assign<To_Policy, To_Policy>(to, l, dir);
8597}
8598
8599template <typename To_Policy, typename From1_Policy, typename From2_Policy,
8600          typename Type>
8601inline Result
8602mul_int_larger(Type& to, const Type x, const Type y, Rounding_Dir dir) {
8603  typename Larger<Type>::type_for_mul l = x;
8604  l *= y;
8605  return assign<To_Policy, To_Policy>(to, l, dir);
8606}
8607
8608template <typename To_Policy, typename From_Policy, typename Type>
8609inline Result
8610neg_signed_int(Type& to, const Type from, Rounding_Dir dir) {
8611  if (To_Policy::check_overflow && Larger<Type>::use_for_neg) {
8612    return neg_int_larger<To_Policy, From_Policy>(to, from, dir);
8613  }
8614  if (CHECK_P(To_Policy::check_overflow,
8615              (from < -Extended_Int<To_Policy, Type>::max))) {
8616    return set_pos_overflow_int<To_Policy>(to, dir);
8617  }
8618  to = -from;
8619  return V_EQ;
8620}
8621
8622template <typename To_Policy, typename From_Policy, typename Type>
8623inline Result
8624neg_unsigned_int(Type& to, const Type from, Rounding_Dir dir) {
8625  if (To_Policy::check_overflow && Larger<Type>::use_for_neg) {
8626    return neg_int_larger<To_Policy, From_Policy>(to, from, dir);
8627  }
8628  if (CHECK_P(To_Policy::check_overflow, from != 0)) {
8629    return set_neg_overflow_int<To_Policy>(to, dir);
8630  }
8631  to = from;
8632  return V_EQ;
8633}
8634
8635template <typename To_Policy, typename From1_Policy, typename From2_Policy,
8636          typename Type>
8637inline Result
8638add_signed_int(Type& to, const Type x, const Type y, Rounding_Dir dir) {
8639  if (To_Policy::check_overflow && Larger<Type>::use_for_add) {
8640    return add_int_larger<To_Policy, From1_Policy, From2_Policy>(to, x, y, dir);
8641  }
8642  if (To_Policy::check_overflow) {
8643    if (y >= 0) {
8644      if (x > Extended_Int<To_Policy, Type>::max - y) {
8645        return set_pos_overflow_int<To_Policy>(to, dir);
8646      }
8647    }
8648    else if (x < Extended_Int<To_Policy, Type>::min - y) {
8649      return set_neg_overflow_int<To_Policy>(to, dir);
8650    }
8651  }
8652  to = x + y;
8653  return V_EQ;
8654}
8655
8656template <typename To_Policy, typename From1_Policy, typename From2_Policy,
8657          typename Type>
8658inline Result
8659add_unsigned_int(Type& to, const Type x, const Type y, Rounding_Dir dir) {
8660  if (To_Policy::check_overflow && Larger<Type>::use_for_add) {
8661    return add_int_larger<To_Policy, From1_Policy, From2_Policy>(to, x, y, dir);
8662  }
8663  if (CHECK_P(To_Policy::check_overflow,
8664              (x > Extended_Int<To_Policy, Type>::max - y))) {
8665    return set_pos_overflow_int<To_Policy>(to, dir);
8666  }
8667  to = x + y;
8668  return V_EQ;
8669}
8670
8671template <typename To_Policy, typename From1_Policy, typename From2_Policy,
8672          typename Type>
8673inline Result
8674sub_signed_int(Type& to, const Type x, const Type y, Rounding_Dir dir) {
8675  if (To_Policy::check_overflow && Larger<Type>::use_for_sub) {
8676    return sub_int_larger<To_Policy, From1_Policy, From2_Policy>(to, x, y, dir);
8677  }
8678  if (To_Policy::check_overflow) {
8679    if (y >= 0) {
8680      if (x < Extended_Int<To_Policy, Type>::min + y) {
8681        return set_neg_overflow_int<To_Policy>(to, dir);
8682      }
8683    }
8684    else if (x > Extended_Int<To_Policy, Type>::max + y) {
8685      return set_pos_overflow_int<To_Policy>(to, dir);
8686    }
8687  }
8688  to = x - y;
8689  return V_EQ;
8690}
8691
8692template <typename To_Policy, typename From1_Policy, typename From2_Policy,
8693          typename Type>
8694inline Result
8695sub_unsigned_int(Type& to, const Type x, const Type y, Rounding_Dir dir) {
8696  if (To_Policy::check_overflow && Larger<Type>::use_for_sub) {
8697    return sub_int_larger<To_Policy, From1_Policy, From2_Policy>(to, x, y, dir);
8698  }
8699  if (CHECK_P(To_Policy::check_overflow,
8700              (x < Extended_Int<To_Policy, Type>::min + y))) {
8701    return set_neg_overflow_int<To_Policy>(to, dir);
8702  }
8703  to = x - y;
8704  return V_EQ;
8705}
8706
8707template <typename To_Policy, typename From1_Policy, typename From2_Policy,
8708          typename Type>
8709inline Result
8710mul_signed_int(Type& to, const Type x, const Type y, Rounding_Dir dir) {
8711  if (To_Policy::check_overflow && Larger<Type>::use_for_mul) {
8712    return mul_int_larger<To_Policy, From1_Policy, From2_Policy>(to, x, y, dir);
8713  }
8714  if (!To_Policy::check_overflow) {
8715    to = x * y;
8716    return V_EQ;
8717  }
8718  if (y == 0) {
8719    to = 0;
8720    return V_EQ;
8721  }
8722  if (y == -1) {
8723    return neg_signed_int<To_Policy, From1_Policy>(to, x, dir);
8724  }
8725  if (x >= 0) {
8726    if (y > 0) {
8727      if (x > Extended_Int<To_Policy, Type>::max / y) {
8728        return set_pos_overflow_int<To_Policy>(to, dir);
8729      }
8730    }
8731    else {
8732      if (x > Extended_Int<To_Policy, Type>::min / y) {
8733        return set_neg_overflow_int<To_Policy>(to, dir);
8734      }
8735    }
8736  }
8737  else {
8738    if (y < 0) {
8739      if (x < Extended_Int<To_Policy, Type>::max / y) {
8740        return set_pos_overflow_int<To_Policy>(to, dir);
8741      }
8742    }
8743    else {
8744      if (x < Extended_Int<To_Policy, Type>::min / y) {
8745        return set_neg_overflow_int<To_Policy>(to, dir);
8746      }
8747    }
8748  }
8749  to = x * y;
8750  return V_EQ;
8751}
8752
8753template <typename To_Policy, typename From1_Policy, typename From2_Policy,
8754          typename Type>
8755inline Result
8756mul_unsigned_int(Type& to, const Type x, const Type y, Rounding_Dir dir) {
8757  if (To_Policy::check_overflow && Larger<Type>::use_for_mul) {
8758    return mul_int_larger<To_Policy, From1_Policy, From2_Policy>(to, x, y, dir);
8759  }
8760  if (!To_Policy::check_overflow) {
8761    to = x * y;
8762    return V_EQ;
8763  }
8764  if (y == 0) {
8765    to = 0;
8766    return V_EQ;
8767  }
8768  if (x > Extended_Int<To_Policy, Type>::max / y) {
8769    return set_pos_overflow_int<To_Policy>(to, dir);
8770  }
8771  to = x * y;
8772  return V_EQ;
8773}
8774
8775template <typename To_Policy, typename From1_Policy, typename From2_Policy,
8776          typename Type>
8777inline Result
8778div_signed_int(Type& to, const Type x, const Type y, Rounding_Dir dir) {
8779  if (CHECK_P(To_Policy::check_div_zero, y == 0)) {
8780    return assign_nan<To_Policy>(to, V_DIV_ZERO);
8781  }
8782  if (To_Policy::check_overflow && y == -1) {
8783    return neg_signed_int<To_Policy, From1_Policy>(to, x, dir);
8784  }
8785  to = x / y;
8786  if (round_not_requested(dir)) {
8787    return V_LGE;
8788  }
8789  if (y == -1) {
8790    return V_EQ;
8791  }
8792  Type m = x % y;
8793  if (m < 0) {
8794    return round_lt_int_no_overflow<To_Policy>(to, dir);
8795  }
8796  else if (m > 0) {
8797    return round_gt_int_no_overflow<To_Policy>(to, dir);
8798  }
8799  else {
8800    return V_EQ;
8801  }
8802}
8803
8804template <typename To_Policy, typename From1_Policy, typename From2_Policy,
8805          typename Type>
8806inline Result
8807div_unsigned_int(Type& to, const Type x, const Type y, Rounding_Dir dir) {
8808  if (CHECK_P(To_Policy::check_div_zero, y == 0)) {
8809    return assign_nan<To_Policy>(to, V_DIV_ZERO);
8810  }
8811  to = x / y;
8812  if (round_not_requested(dir)) {
8813    return V_GE;
8814  }
8815  Type m = x % y;
8816  if (m == 0) {
8817    return V_EQ;
8818  }
8819  return round_gt_int<To_Policy>(to, dir);
8820}
8821
8822template <typename To_Policy, typename From1_Policy, typename From2_Policy,
8823          typename Type>
8824inline Result
8825idiv_signed_int(Type& to, const Type x, const Type y, Rounding_Dir dir) {
8826  if (CHECK_P(To_Policy::check_div_zero, y == 0)) {
8827    return assign_nan<To_Policy>(to, V_DIV_ZERO);
8828  }
8829  if (To_Policy::check_overflow && y == -1) {
8830    return neg_signed_int<To_Policy, From1_Policy>(to, x, dir);
8831  }
8832  to = x / y;
8833  return V_EQ;
8834}
8835
8836template <typename To_Policy, typename From1_Policy, typename From2_Policy,
8837          typename Type>
8838inline Result
8839idiv_unsigned_int(Type& to, const Type x, const Type y, Rounding_Dir) {
8840  if (CHECK_P(To_Policy::check_div_zero, y == 0)) {
8841    return assign_nan<To_Policy>(to, V_DIV_ZERO);
8842  }
8843  to = x / y;
8844  return V_EQ;
8845}
8846
8847template <typename To_Policy, typename From1_Policy, typename From2_Policy,
8848          typename Type>
8849inline Result
8850rem_signed_int(Type& to, const Type x, const Type y, Rounding_Dir) {
8851  if (CHECK_P(To_Policy::check_div_zero, y == 0)) {
8852    return assign_nan<To_Policy>(to, V_MOD_ZERO);
8853  }
8854  to = (y == -1) ? 0 : (x % y);
8855  return V_EQ;
8856}
8857
8858template <typename To_Policy, typename From1_Policy, typename From2_Policy,
8859          typename Type>
8860inline Result
8861rem_unsigned_int(Type& to, const Type x, const Type y, Rounding_Dir) {
8862  if (CHECK_P(To_Policy::check_div_zero, y == 0)) {
8863    return assign_nan<To_Policy>(to, V_MOD_ZERO);
8864  }
8865  to = x % y;
8866  return V_EQ;
8867}
8868
8869template <typename To_Policy, typename From_Policy, typename Type>
8870inline Result
8871div_2exp_unsigned_int(Type& to, const Type x, unsigned int exp,
8872                      Rounding_Dir dir) {
8873  if (exp >= sizeof_to_bits(sizeof(Type))) {
8874    to = 0;
8875    if (round_not_requested(dir)) {
8876      return V_GE;
8877    }
8878    if (x == 0) {
8879      return V_EQ;
8880    }
8881    return round_gt_int_no_overflow<To_Policy>(to, dir);
8882  }
8883  to = x >> exp;
8884  if (round_not_requested(dir)) {
8885    return V_GE;
8886  }
8887  if (x & ((Type(1) << exp) - 1)) {
8888    return round_gt_int_no_overflow<To_Policy>(to, dir);
8889  }
8890  else {
8891    return V_EQ;
8892  }
8893}
8894
8895template <typename To_Policy, typename From_Policy, typename Type>
8896inline Result
8897div_2exp_signed_int(Type& to, const Type x, unsigned int exp,
8898                    Rounding_Dir dir) {
8899  if (x < 0) {
8900    if (exp >= sizeof_to_bits(sizeof(Type))) {
8901      to = 0;
8902      if (round_not_requested(dir)) {
8903        return V_LE;
8904      }
8905      return round_lt_int_no_overflow<To_Policy>(to, dir);
8906    }
8907    typedef typename C_Integer<Type>::other_type UType;
8908    UType ux = x;
8909    ux = -ux;
8910    to = ~Type(~-(ux >> exp));
8911    if (round_not_requested(dir)) {
8912      return V_LE;
8913    }
8914    if (ux & ((UType(1) << exp) -1)) {
8915      return round_lt_int_no_overflow<To_Policy>(to, dir);
8916    }
8917    return V_EQ;
8918  }
8919  else {
8920    if (exp >= sizeof_to_bits(sizeof(Type)) - 1) {
8921      to = 0;
8922      if (round_not_requested(dir)) {
8923        return V_GE;
8924      }
8925      if (x == 0) {
8926        return V_EQ;
8927      }
8928      return round_gt_int_no_overflow<To_Policy>(to, dir);
8929    }
8930    to = x >> exp;
8931    if (round_not_requested(dir)) {
8932      return V_GE;
8933    }
8934    if (x & ((Type(1) << exp) - 1)) {
8935      return round_gt_int_no_overflow<To_Policy>(to, dir);
8936    }
8937    else {
8938      return V_EQ;
8939    }
8940  }
8941}
8942
8943template <typename To_Policy, typename From_Policy, typename Type>
8944inline Result
8945add_2exp_unsigned_int(Type& to, const Type x, unsigned int exp,
8946                      Rounding_Dir dir) {
8947  if (!To_Policy::check_overflow) {
8948    to = x + (Type(1) << exp);
8949    return V_EQ;
8950  }
8951  if (exp >= sizeof_to_bits(sizeof(Type))) {
8952    return set_pos_overflow_int<To_Policy>(to, dir);
8953  }
8954  Type n = Type(1) << exp;
8955  return add_unsigned_int<To_Policy, From_Policy, void>(to, x, n, dir);
8956}
8957
8958template <typename To_Policy, typename From_Policy, typename Type>
8959inline Result
8960add_2exp_signed_int(Type& to, const Type x, unsigned int exp,
8961                    Rounding_Dir dir) {
8962  if (!To_Policy::check_overflow) {
8963    to = x + (Type(1) << exp);
8964    return V_EQ;
8965  }
8966  if (exp >= sizeof_to_bits(sizeof(Type))) {
8967    return set_pos_overflow_int<To_Policy>(to, dir);
8968  }
8969  if (exp == sizeof_to_bits(sizeof(Type)) - 1) {
8970    Type n = -2 * (Type(1) << (exp - 1));
8971    return sub_signed_int<To_Policy, From_Policy, void>(to, x, n, dir);
8972  }
8973  else {
8974    Type n = Type(1) << exp;
8975    return add_signed_int<To_Policy, From_Policy, void>(to, x, n, dir);
8976  }
8977}
8978
8979template <typename To_Policy, typename From_Policy, typename Type>
8980inline Result
8981sub_2exp_unsigned_int(Type& to, const Type x, unsigned int exp,
8982                      Rounding_Dir dir) {
8983  if (!To_Policy::check_overflow) {
8984    to = x - (Type(1) << exp);
8985    return V_EQ;
8986  }
8987  if (exp >= sizeof_to_bits(sizeof(Type))) {
8988    return set_neg_overflow_int<To_Policy>(to, dir);
8989  }
8990  Type n = Type(1) << exp;
8991  return sub_unsigned_int<To_Policy, From_Policy, void>(to, x, n, dir);
8992}
8993
8994template <typename To_Policy, typename From_Policy, typename Type>
8995inline Result
8996sub_2exp_signed_int(Type& to, const Type x, unsigned int exp,
8997                    Rounding_Dir dir) {
8998  if (!To_Policy::check_overflow) {
8999    to = x - (Type(1) << exp);
9000    return V_EQ;
9001  }
9002  if (exp >= sizeof_to_bits(sizeof(Type))) {
9003    return set_neg_overflow_int<To_Policy>(to, dir);
9004  }
9005  if (exp == sizeof_to_bits(sizeof(Type)) - 1) {
9006    Type n = -2 * (Type(1) << (exp - 1));
9007    return add_signed_int<To_Policy, From_Policy, void>(to, x, n, dir);
9008  }
9009  else {
9010    Type n = Type(1) << exp;
9011    return sub_signed_int<To_Policy, From_Policy, void>(to, x, n, dir);
9012  }
9013}
9014
9015template <typename To_Policy, typename From_Policy, typename Type>
9016inline Result
9017mul_2exp_unsigned_int(Type& to, const Type x, unsigned int exp,
9018                      Rounding_Dir dir) {
9019  if (!To_Policy::check_overflow) {
9020    to = x << exp;
9021    return V_EQ;
9022  }
9023  if (exp >= sizeof_to_bits(sizeof(Type))) {
9024    if (x == 0) {
9025      to = 0;
9026      return V_EQ;
9027    }
9028    return set_pos_overflow_int<To_Policy>(to, dir);
9029  }
9030  if (x > Extended_Int<To_Policy, Type>::max >> exp) {
9031    return set_pos_overflow_int<To_Policy>(to, dir);
9032  }
9033  to = x << exp;
9034  return V_EQ;
9035}
9036
9037template <typename To_Policy, typename From_Policy, typename Type>
9038inline Result
9039mul_2exp_signed_int(Type& to, const Type x, unsigned int exp,
9040                    Rounding_Dir dir) {
9041  if (x < 0) {
9042    if (!To_Policy::check_overflow) {
9043      to = x * (Type(1) << exp);
9044      return V_EQ;
9045    }
9046    if (exp >= sizeof_to_bits(sizeof(Type))) {
9047      return set_neg_overflow_int<To_Policy>(to, dir);
9048    }
9049    typedef typename C_Integer<Type>::other_type UType;
9050    UType mask = UType(-1) << (sizeof_to_bits(sizeof(Type)) - exp - 1);
9051    UType ux = x;
9052    if ((ux & mask) != mask) {
9053      return set_neg_overflow_int<To_Policy>(to, dir);
9054    }
9055    ux <<= exp;
9056    Type n = ~(Type(~ux));
9057    if (PPL_LT_SILENT(n, (Extended_Int<To_Policy, Type>::min))) {
9058      return set_neg_overflow_int<To_Policy>(to, dir);
9059    }
9060    to = n;
9061  }
9062  else {
9063    if (!To_Policy::check_overflow) {
9064      to = x << exp;
9065      return V_EQ;
9066    }
9067    if (exp >= sizeof_to_bits(sizeof(Type)) - 1) {
9068      if (x == 0) {
9069        to = 0;
9070        return V_EQ;
9071      }
9072      return set_pos_overflow_int<To_Policy>(to, dir);
9073    }
9074    if (x > Extended_Int<To_Policy, Type>::max >> exp) {
9075      return set_pos_overflow_int<To_Policy>(to, dir);
9076    }
9077    to = x << exp;
9078  }
9079  return V_EQ;
9080}
9081
9082template <typename To_Policy, typename From_Policy, typename Type>
9083inline Result
9084smod_2exp_unsigned_int(Type& to, const Type x, unsigned int exp,
9085                       Rounding_Dir dir) {
9086  if (exp > sizeof_to_bits(sizeof(Type))) {
9087    to = x;
9088  }
9089  else {
9090    Type v = (exp == sizeof_to_bits(sizeof(Type)) ? x : (x & ((Type(1) << exp) - 1)));
9091    if (v >= (Type(1) << (exp - 1))) {
9092      return set_neg_overflow_int<To_Policy>(to, dir);
9093    }
9094    else {
9095      to = v;
9096    }
9097  }
9098  return V_EQ;
9099}
9100
9101template <typename To_Policy, typename From_Policy, typename Type>
9102inline Result
9103smod_2exp_signed_int(Type& to, const Type x, unsigned int exp,
9104                     Rounding_Dir) {
9105  if (exp >= sizeof_to_bits(sizeof(Type))) {
9106    to = x;
9107  }
9108  else {
9109    Type m = Type(1) << (exp - 1);
9110    to = (x & (m - 1)) - (x & m);
9111  }
9112  return V_EQ;
9113}
9114
9115template <typename To_Policy, typename From_Policy, typename Type>
9116inline Result
9117umod_2exp_unsigned_int(Type& to, const Type x, unsigned int exp,
9118                       Rounding_Dir) {
9119  if (exp >= sizeof_to_bits(sizeof(Type))) {
9120    to = x;
9121  }
9122  else {
9123    to = x & ((Type(1) << exp) - 1);
9124  }
9125  return V_EQ;
9126}
9127
9128template <typename To_Policy, typename From_Policy, typename Type>
9129inline Result
9130umod_2exp_signed_int(Type& to, const Type x, unsigned int exp,
9131                     Rounding_Dir dir) {
9132  if (exp >= sizeof_to_bits(sizeof(Type))) {
9133    if (x < 0) {
9134      return set_pos_overflow_int<To_Policy>(to, dir);
9135    }
9136    to = x;
9137  }
9138  else {
9139    to = x & ((Type(1) << exp) - 1);
9140  }
9141  return V_EQ;
9142}
9143
9144template <typename Type>
9145inline void
9146isqrt_rem(Type& q, Type& r, const Type from) {
9147  q = 0;
9148  r = from;
9149  Type t(1);
9150  for (t <<= sizeof_to_bits(sizeof(Type)) - 2; t != 0; t >>= 2) {
9151    Type s = q + t;
9152    if (s <= r) {
9153      r -= s;
9154      q = s + t;
9155    }
9156    q >>= 1;
9157  }
9158}
9159
9160template <typename To_Policy, typename From_Policy, typename Type>
9161inline Result
9162sqrt_unsigned_int(Type& to, const Type from, Rounding_Dir dir) {
9163  Type rem;
9164  isqrt_rem(to, rem, from);
9165  if (round_not_requested(dir)) {
9166    return V_GE;
9167  }
9168  if (rem == 0) {
9169    return V_EQ;
9170  }
9171  return round_gt_int<To_Policy>(to, dir);
9172}
9173
9174template <typename To_Policy, typename From_Policy, typename Type>
9175inline Result
9176sqrt_signed_int(Type& to, const Type from, Rounding_Dir dir) {
9177  if (CHECK_P(To_Policy::check_sqrt_neg, from < 0)) {
9178    return assign_nan<To_Policy>(to, V_SQRT_NEG);
9179  }
9180  return sqrt_unsigned_int<To_Policy, From_Policy>(to, from, dir);
9181}
9182
9183template <typename To_Policy, typename From1_Policy, typename From2_Policy,
9184          typename Type>
9185inline Result
9186add_mul_int(Type& to, const Type x, const Type y, Rounding_Dir dir) {
9187  Type z;
9188  Result r = mul<To_Policy, From1_Policy, From2_Policy>(z, x, y, dir);
9189  switch (result_overflow(r)) {
9190  case 0:
9191    return add<To_Policy, To_Policy, To_Policy>(to, to, z, dir);
9192  case -1:
9193    if (to <= 0) {
9194      return set_neg_overflow_int<To_Policy>(to, dir);
9195    }
9196    return assign_nan<To_Policy>(to, V_UNKNOWN_NEG_OVERFLOW);
9197  case 1:
9198    if (to >= 0) {
9199      return set_pos_overflow_int<To_Policy>(to, dir);
9200    }
9201    return assign_nan<To_Policy>(to, V_UNKNOWN_POS_OVERFLOW);
9202  default:
9203    PPL_UNREACHABLE;
9204    return V_NAN;
9205  }
9206}
9207
9208template <typename To_Policy, typename From1_Policy, typename From2_Policy,
9209          typename Type>
9210inline Result
9211sub_mul_int(Type& to, const Type x, const Type y, Rounding_Dir dir) {
9212  Type z;
9213  Result r = mul<To_Policy, From1_Policy, From2_Policy>(z, x, y, dir);
9214  switch (result_overflow(r)) {
9215  case 0:
9216    return sub<To_Policy, To_Policy, To_Policy>(to, to, z, dir);
9217  case -1:
9218    if (to >= 0) {
9219      return set_pos_overflow_int<To_Policy>(to, dir);
9220    }
9221    return assign_nan<To_Policy>(to, V_UNKNOWN_NEG_OVERFLOW);
9222  case 1:
9223    if (to <= 0) {
9224      return set_neg_overflow_int<To_Policy>(to, dir);
9225    }
9226    return assign_nan<To_Policy>(to, V_UNKNOWN_POS_OVERFLOW);
9227  default:
9228    PPL_UNREACHABLE;
9229    return V_NAN;
9230  }
9231}
9232
9233template <typename Policy, typename Type>
9234inline Result
9235output_char(std::ostream& os, Type& from,
9236            const Numeric_Format&, Rounding_Dir) {
9237  os << int(from);
9238  return V_EQ;
9239}
9240
9241template <typename Policy, typename Type>
9242inline Result
9243output_int(std::ostream& os, Type& from, const Numeric_Format&, Rounding_Dir) {
9244  os << from;
9245  return V_EQ;
9246}
9247
9248#if PPL_CXX_PLAIN_CHAR_IS_SIGNED
9249PPL_SPECIALIZE_FLOOR(assign_signed_int_signed_int, char, char)
9250#endif
9251PPL_SPECIALIZE_FLOOR(assign_signed_int_signed_int, signed char, signed char)
9252PPL_SPECIALIZE_FLOOR(assign_signed_int_signed_int, signed short, signed short)
9253PPL_SPECIALIZE_FLOOR(assign_signed_int_signed_int, signed int, signed int)
9254PPL_SPECIALIZE_FLOOR(assign_signed_int_signed_int, signed long, signed long)
9255PPL_SPECIALIZE_FLOOR(assign_signed_int_signed_int, signed long long, signed long long)
9256#if !PPL_CXX_PLAIN_CHAR_IS_SIGNED
9257PPL_SPECIALIZE_FLOOR(assign_unsigned_int_unsigned_int, char, char)
9258#endif
9259PPL_SPECIALIZE_FLOOR(assign_unsigned_int_unsigned_int, unsigned char, unsigned char)
9260PPL_SPECIALIZE_FLOOR(assign_unsigned_int_unsigned_int, unsigned short, unsigned short)
9261PPL_SPECIALIZE_FLOOR(assign_unsigned_int_unsigned_int, unsigned int, unsigned int)
9262PPL_SPECIALIZE_FLOOR(assign_unsigned_int_unsigned_int, unsigned long, unsigned long)
9263PPL_SPECIALIZE_FLOOR(assign_unsigned_int_unsigned_int, unsigned long long, unsigned long long)
9264
9265#if PPL_CXX_PLAIN_CHAR_IS_SIGNED
9266PPL_SPECIALIZE_CEIL(assign_signed_int_signed_int, char, char)
9267#endif
9268PPL_SPECIALIZE_CEIL(assign_signed_int_signed_int, signed char, signed char)
9269PPL_SPECIALIZE_CEIL(assign_signed_int_signed_int, signed short, signed short)
9270PPL_SPECIALIZE_CEIL(assign_signed_int_signed_int, signed int, signed int)
9271PPL_SPECIALIZE_CEIL(assign_signed_int_signed_int, signed long, signed long)
9272PPL_SPECIALIZE_CEIL(assign_signed_int_signed_int, signed long long, signed long long)
9273#if !PPL_CXX_PLAIN_CHAR_IS_SIGNED
9274PPL_SPECIALIZE_CEIL(assign_unsigned_int_unsigned_int, char, char)
9275#endif
9276PPL_SPECIALIZE_CEIL(assign_unsigned_int_unsigned_int, unsigned char, unsigned char)
9277PPL_SPECIALIZE_CEIL(assign_unsigned_int_unsigned_int, unsigned short, unsigned short)
9278PPL_SPECIALIZE_CEIL(assign_unsigned_int_unsigned_int, unsigned int, unsigned int)
9279PPL_SPECIALIZE_CEIL(assign_unsigned_int_unsigned_int, unsigned long, unsigned long)
9280PPL_SPECIALIZE_CEIL(assign_unsigned_int_unsigned_int, unsigned long long, unsigned long long)
9281
9282#if PPL_CXX_PLAIN_CHAR_IS_SIGNED
9283PPL_SPECIALIZE_TRUNC(assign_signed_int_signed_int, char, char)
9284#endif
9285PPL_SPECIALIZE_TRUNC(assign_signed_int_signed_int, signed char, signed char)
9286PPL_SPECIALIZE_TRUNC(assign_signed_int_signed_int, signed short, signed short)
9287PPL_SPECIALIZE_TRUNC(assign_signed_int_signed_int, signed int, signed int)
9288PPL_SPECIALIZE_TRUNC(assign_signed_int_signed_int, signed long, signed long)
9289PPL_SPECIALIZE_TRUNC(assign_signed_int_signed_int, signed long long, signed long long)
9290#if !PPL_CXX_PLAIN_CHAR_IS_SIGNED
9291PPL_SPECIALIZE_TRUNC(assign_unsigned_int_unsigned_int, char, char)
9292#endif
9293PPL_SPECIALIZE_TRUNC(assign_unsigned_int_unsigned_int, unsigned char, unsigned char)
9294PPL_SPECIALIZE_TRUNC(assign_unsigned_int_unsigned_int, unsigned short, unsigned short)
9295PPL_SPECIALIZE_TRUNC(assign_unsigned_int_unsigned_int, unsigned int, unsigned int)
9296PPL_SPECIALIZE_TRUNC(assign_unsigned_int_unsigned_int, unsigned long, unsigned long)
9297PPL_SPECIALIZE_TRUNC(assign_unsigned_int_unsigned_int, unsigned long long, unsigned long long)
9298
9299#if PPL_CXX_PLAIN_CHAR_IS_SIGNED
9300PPL_SPECIALIZE_NEG(neg_signed_int, char, char)
9301#endif
9302PPL_SPECIALIZE_NEG(neg_signed_int, signed char, signed char)
9303PPL_SPECIALIZE_NEG(neg_signed_int, signed short, signed short)
9304PPL_SPECIALIZE_NEG(neg_signed_int, signed int, signed int)
9305PPL_SPECIALIZE_NEG(neg_signed_int, signed long, signed long)
9306PPL_SPECIALIZE_NEG(neg_signed_int, signed long long, signed long long)
9307#if !PPL_CXX_PLAIN_CHAR_IS_SIGNED
9308PPL_SPECIALIZE_NEG(neg_unsigned_int, char, char)
9309#endif
9310PPL_SPECIALIZE_NEG(neg_unsigned_int, unsigned char, unsigned char)
9311PPL_SPECIALIZE_NEG(neg_unsigned_int, unsigned short, unsigned short)
9312PPL_SPECIALIZE_NEG(neg_unsigned_int, unsigned int, unsigned int)
9313PPL_SPECIALIZE_NEG(neg_unsigned_int, unsigned long, unsigned long)
9314PPL_SPECIALIZE_NEG(neg_unsigned_int, unsigned long long, unsigned long long)
9315
9316#if PPL_CXX_PLAIN_CHAR_IS_SIGNED
9317PPL_SPECIALIZE_ADD(add_signed_int, char, char, char)
9318#endif
9319PPL_SPECIALIZE_ADD(add_signed_int, signed char, signed char, signed char)
9320PPL_SPECIALIZE_ADD(add_signed_int, signed short, signed short, signed short)
9321PPL_SPECIALIZE_ADD(add_signed_int, signed int, signed int, signed int)
9322PPL_SPECIALIZE_ADD(add_signed_int, signed long, signed long, signed long)
9323PPL_SPECIALIZE_ADD(add_signed_int, signed long long, signed long long, signed long long)
9324#if !PPL_CXX_PLAIN_CHAR_IS_SIGNED
9325PPL_SPECIALIZE_ADD(add_unsigned_int, char, char, char)
9326#endif
9327PPL_SPECIALIZE_ADD(add_unsigned_int, unsigned char, unsigned char, unsigned char)
9328PPL_SPECIALIZE_ADD(add_unsigned_int, unsigned short, unsigned short, unsigned short)
9329PPL_SPECIALIZE_ADD(add_unsigned_int, unsigned int, unsigned int, unsigned int)
9330PPL_SPECIALIZE_ADD(add_unsigned_int, unsigned long, unsigned long, unsigned long)
9331PPL_SPECIALIZE_ADD(add_unsigned_int, unsigned long long, unsigned long long, unsigned long long)
9332
9333#if PPL_CXX_PLAIN_CHAR_IS_SIGNED
9334PPL_SPECIALIZE_SUB(sub_signed_int, char, char, char)
9335#endif
9336PPL_SPECIALIZE_SUB(sub_signed_int, signed char, signed char, signed char)
9337PPL_SPECIALIZE_SUB(sub_signed_int, signed short, signed short, signed short)
9338PPL_SPECIALIZE_SUB(sub_signed_int, signed int, signed int, signed int)
9339PPL_SPECIALIZE_SUB(sub_signed_int, signed long, signed long, signed long)
9340PPL_SPECIALIZE_SUB(sub_signed_int, signed long long, signed long long, signed long long)
9341#if !PPL_CXX_PLAIN_CHAR_IS_SIGNED
9342PPL_SPECIALIZE_SUB(sub_unsigned_int, char, char, char)
9343#endif
9344PPL_SPECIALIZE_SUB(sub_unsigned_int, unsigned char, unsigned char, unsigned char)
9345PPL_SPECIALIZE_SUB(sub_unsigned_int, unsigned short, unsigned short, unsigned short)
9346PPL_SPECIALIZE_SUB(sub_unsigned_int, unsigned int, unsigned int, unsigned int)
9347PPL_SPECIALIZE_SUB(sub_unsigned_int, unsigned long, unsigned long, unsigned long)
9348PPL_SPECIALIZE_SUB(sub_unsigned_int, unsigned long long, unsigned long long, unsigned long long)
9349
9350#if PPL_CXX_PLAIN_CHAR_IS_SIGNED
9351PPL_SPECIALIZE_MUL(mul_signed_int, char, char, char)
9352#endif
9353PPL_SPECIALIZE_MUL(mul_signed_int, signed char, signed char, signed char)
9354PPL_SPECIALIZE_MUL(mul_signed_int, signed short, signed short, signed short)
9355PPL_SPECIALIZE_MUL(mul_signed_int, signed int, signed int, signed int)
9356PPL_SPECIALIZE_MUL(mul_signed_int, signed long, signed long, signed long)
9357PPL_SPECIALIZE_MUL(mul_signed_int, signed long long, signed long long, signed long long)
9358#if !PPL_CXX_PLAIN_CHAR_IS_SIGNED
9359PPL_SPECIALIZE_MUL(mul_unsigned_int, char, char, char)
9360#endif
9361PPL_SPECIALIZE_MUL(mul_unsigned_int, unsigned char, unsigned char, unsigned char)
9362PPL_SPECIALIZE_MUL(mul_unsigned_int, unsigned short, unsigned short, unsigned short)
9363PPL_SPECIALIZE_MUL(mul_unsigned_int, unsigned int, unsigned int, unsigned int)
9364PPL_SPECIALIZE_MUL(mul_unsigned_int, unsigned long, unsigned long, unsigned long)
9365PPL_SPECIALIZE_MUL(mul_unsigned_int, unsigned long long, unsigned long long, unsigned long long)
9366
9367#if PPL_CXX_PLAIN_CHAR_IS_SIGNED
9368PPL_SPECIALIZE_DIV(div_signed_int, char, char, char)
9369#endif
9370PPL_SPECIALIZE_DIV(div_signed_int, signed char, signed char, signed char)
9371PPL_SPECIALIZE_DIV(div_signed_int, signed short, signed short, signed short)
9372PPL_SPECIALIZE_DIV(div_signed_int, signed int, signed int, signed int)
9373PPL_SPECIALIZE_DIV(div_signed_int, signed long, signed long, signed long)
9374PPL_SPECIALIZE_DIV(div_signed_int, signed long long, signed long long, signed long long)
9375#if !PPL_CXX_PLAIN_CHAR_IS_SIGNED
9376PPL_SPECIALIZE_DIV(div_unsigned_int, char, char, char)
9377#endif
9378PPL_SPECIALIZE_DIV(div_unsigned_int, unsigned char, unsigned char, unsigned char)
9379PPL_SPECIALIZE_DIV(div_unsigned_int, unsigned short, unsigned short, unsigned short)
9380PPL_SPECIALIZE_DIV(div_unsigned_int, unsigned int, unsigned int, unsigned int)
9381PPL_SPECIALIZE_DIV(div_unsigned_int, unsigned long, unsigned long, unsigned long)
9382PPL_SPECIALIZE_DIV(div_unsigned_int, unsigned long long, unsigned long long, unsigned long long)
9383
9384#if PPL_CXX_PLAIN_CHAR_IS_SIGNED
9385PPL_SPECIALIZE_IDIV(idiv_signed_int, char, char, char)
9386#endif
9387PPL_SPECIALIZE_IDIV(idiv_signed_int, signed char, signed char, signed char)
9388PPL_SPECIALIZE_IDIV(idiv_signed_int, signed short, signed short, signed short)
9389PPL_SPECIALIZE_IDIV(idiv_signed_int, signed int, signed int, signed int)
9390PPL_SPECIALIZE_IDIV(idiv_signed_int, signed long, signed long, signed long)
9391PPL_SPECIALIZE_IDIV(idiv_signed_int, signed long long, signed long long, signed long long)
9392#if !PPL_CXX_PLAIN_CHAR_IS_SIGNED
9393PPL_SPECIALIZE_IDIV(idiv_unsigned_int, char, char, char)
9394#endif
9395PPL_SPECIALIZE_IDIV(idiv_unsigned_int, unsigned char, unsigned char, unsigned char)
9396PPL_SPECIALIZE_IDIV(idiv_unsigned_int, unsigned short, unsigned short, unsigned short)
9397PPL_SPECIALIZE_IDIV(idiv_unsigned_int, unsigned int, unsigned int, unsigned int)
9398PPL_SPECIALIZE_IDIV(idiv_unsigned_int, unsigned long, unsigned long, unsigned long)
9399PPL_SPECIALIZE_IDIV(idiv_unsigned_int, unsigned long long, unsigned long long, unsigned long long)
9400
9401#if PPL_CXX_PLAIN_CHAR_IS_SIGNED
9402PPL_SPECIALIZE_REM(rem_signed_int, char, char, char)
9403#endif
9404PPL_SPECIALIZE_REM(rem_signed_int, signed char, signed char, signed char)
9405PPL_SPECIALIZE_REM(rem_signed_int, signed short, signed short, signed short)
9406PPL_SPECIALIZE_REM(rem_signed_int, signed int, signed int, signed int)
9407PPL_SPECIALIZE_REM(rem_signed_int, signed long, signed long, signed long)
9408PPL_SPECIALIZE_REM(rem_signed_int, signed long long, signed long long, signed long long)
9409#if !PPL_CXX_PLAIN_CHAR_IS_SIGNED
9410PPL_SPECIALIZE_REM(rem_unsigned_int, char, char, char)
9411#endif
9412PPL_SPECIALIZE_REM(rem_unsigned_int, unsigned char, unsigned char, unsigned char)
9413PPL_SPECIALIZE_REM(rem_unsigned_int, unsigned short, unsigned short, unsigned short)
9414PPL_SPECIALIZE_REM(rem_unsigned_int, unsigned int, unsigned int, unsigned int)
9415PPL_SPECIALIZE_REM(rem_unsigned_int, unsigned long, unsigned long, unsigned long)
9416PPL_SPECIALIZE_REM(rem_unsigned_int, unsigned long long, unsigned long long, unsigned long long)
9417
9418#if PPL_CXX_PLAIN_CHAR_IS_SIGNED
9419PPL_SPECIALIZE_ADD_2EXP(add_2exp_signed_int, char, char)
9420#endif
9421PPL_SPECIALIZE_ADD_2EXP(add_2exp_signed_int, signed char, signed char)
9422PPL_SPECIALIZE_ADD_2EXP(add_2exp_signed_int, signed short, signed short)
9423PPL_SPECIALIZE_ADD_2EXP(add_2exp_signed_int, signed int, signed int)
9424PPL_SPECIALIZE_ADD_2EXP(add_2exp_signed_int, signed long, signed long)
9425PPL_SPECIALIZE_ADD_2EXP(add_2exp_signed_int, signed long long, signed long long)
9426#if !PPL_CXX_PLAIN_CHAR_IS_SIGNED
9427PPL_SPECIALIZE_ADD_2EXP(add_2exp_unsigned_int, char, char)
9428#endif
9429PPL_SPECIALIZE_ADD_2EXP(add_2exp_unsigned_int, unsigned char, unsigned char)
9430PPL_SPECIALIZE_ADD_2EXP(add_2exp_unsigned_int, unsigned short, unsigned short)
9431PPL_SPECIALIZE_ADD_2EXP(add_2exp_unsigned_int, unsigned int, unsigned int)
9432PPL_SPECIALIZE_ADD_2EXP(add_2exp_unsigned_int, unsigned long, unsigned long)
9433PPL_SPECIALIZE_ADD_2EXP(add_2exp_unsigned_int, unsigned long long, unsigned long long)
9434
9435#if PPL_CXX_PLAIN_CHAR_IS_SIGNED
9436PPL_SPECIALIZE_SUB_2EXP(sub_2exp_signed_int, char, char)
9437#endif
9438PPL_SPECIALIZE_SUB_2EXP(sub_2exp_signed_int, signed char, signed char)
9439PPL_SPECIALIZE_SUB_2EXP(sub_2exp_signed_int, signed short, signed short)
9440PPL_SPECIALIZE_SUB_2EXP(sub_2exp_signed_int, signed int, signed int)
9441PPL_SPECIALIZE_SUB_2EXP(sub_2exp_signed_int, signed long, signed long)
9442PPL_SPECIALIZE_SUB_2EXP(sub_2exp_signed_int, signed long long, signed long long)
9443#if !PPL_CXX_PLAIN_CHAR_IS_SIGNED
9444PPL_SPECIALIZE_SUB_2EXP(sub_2exp_unsigned_int, char, char)
9445#endif
9446PPL_SPECIALIZE_SUB_2EXP(sub_2exp_unsigned_int, unsigned char, unsigned char)
9447PPL_SPECIALIZE_SUB_2EXP(sub_2exp_unsigned_int, unsigned short, unsigned short)
9448PPL_SPECIALIZE_SUB_2EXP(sub_2exp_unsigned_int, unsigned int, unsigned int)
9449PPL_SPECIALIZE_SUB_2EXP(sub_2exp_unsigned_int, unsigned long, unsigned long)
9450PPL_SPECIALIZE_SUB_2EXP(sub_2exp_unsigned_int, unsigned long long, unsigned long long)
9451
9452#if PPL_CXX_PLAIN_CHAR_IS_SIGNED
9453PPL_SPECIALIZE_MUL_2EXP(mul_2exp_signed_int, char, char)
9454#endif
9455PPL_SPECIALIZE_MUL_2EXP(mul_2exp_signed_int, signed char, signed char)
9456PPL_SPECIALIZE_MUL_2EXP(mul_2exp_signed_int, signed short, signed short)
9457PPL_SPECIALIZE_MUL_2EXP(mul_2exp_signed_int, signed int, signed int)
9458PPL_SPECIALIZE_MUL_2EXP(mul_2exp_signed_int, signed long, signed long)
9459PPL_SPECIALIZE_MUL_2EXP(mul_2exp_signed_int, signed long long, signed long long)
9460#if !PPL_CXX_PLAIN_CHAR_IS_SIGNED
9461PPL_SPECIALIZE_MUL_2EXP(mul_2exp_unsigned_int, char, char)
9462#endif
9463PPL_SPECIALIZE_MUL_2EXP(mul_2exp_unsigned_int, unsigned char, unsigned char)
9464PPL_SPECIALIZE_MUL_2EXP(mul_2exp_unsigned_int, unsigned short, unsigned short)
9465PPL_SPECIALIZE_MUL_2EXP(mul_2exp_unsigned_int, unsigned int, unsigned int)
9466PPL_SPECIALIZE_MUL_2EXP(mul_2exp_unsigned_int, unsigned long, unsigned long)
9467PPL_SPECIALIZE_MUL_2EXP(mul_2exp_unsigned_int, unsigned long long, unsigned long long)
9468
9469#if PPL_CXX_PLAIN_CHAR_IS_SIGNED
9470PPL_SPECIALIZE_DIV_2EXP(div_2exp_signed_int, char, char)
9471#endif
9472PPL_SPECIALIZE_DIV_2EXP(div_2exp_signed_int, signed char, signed char)
9473PPL_SPECIALIZE_DIV_2EXP(div_2exp_signed_int, signed short, signed short)
9474PPL_SPECIALIZE_DIV_2EXP(div_2exp_signed_int, signed int, signed int)
9475PPL_SPECIALIZE_DIV_2EXP(div_2exp_signed_int, signed long, signed long)
9476PPL_SPECIALIZE_DIV_2EXP(div_2exp_signed_int, signed long long, signed long long)
9477#if !PPL_CXX_PLAIN_CHAR_IS_SIGNED
9478PPL_SPECIALIZE_DIV_2EXP(div_2exp_unsigned_int, char, char)
9479#endif
9480PPL_SPECIALIZE_DIV_2EXP(div_2exp_unsigned_int, unsigned char, unsigned char)
9481PPL_SPECIALIZE_DIV_2EXP(div_2exp_unsigned_int, unsigned short, unsigned short)
9482PPL_SPECIALIZE_DIV_2EXP(div_2exp_unsigned_int, unsigned int, unsigned int)
9483PPL_SPECIALIZE_DIV_2EXP(div_2exp_unsigned_int, unsigned long, unsigned long)
9484PPL_SPECIALIZE_DIV_2EXP(div_2exp_unsigned_int, unsigned long long, unsigned long long)
9485
9486#if PPL_CXX_PLAIN_CHAR_IS_SIGNED
9487PPL_SPECIALIZE_SMOD_2EXP(smod_2exp_signed_int, char, char)
9488#endif
9489PPL_SPECIALIZE_SMOD_2EXP(smod_2exp_signed_int, signed char, signed char)
9490PPL_SPECIALIZE_SMOD_2EXP(smod_2exp_signed_int, signed short, signed short)
9491PPL_SPECIALIZE_SMOD_2EXP(smod_2exp_signed_int, signed int, signed int)
9492PPL_SPECIALIZE_SMOD_2EXP(smod_2exp_signed_int, signed long, signed long)
9493PPL_SPECIALIZE_SMOD_2EXP(smod_2exp_signed_int, signed long long, signed long long)
9494#if !PPL_CXX_PLAIN_CHAR_IS_SIGNED
9495PPL_SPECIALIZE_SMOD_2EXP(smod_2exp_unsigned_int, char, char)
9496#endif
9497PPL_SPECIALIZE_SMOD_2EXP(smod_2exp_unsigned_int, unsigned char, unsigned char)
9498PPL_SPECIALIZE_SMOD_2EXP(smod_2exp_unsigned_int, unsigned short, unsigned short)
9499PPL_SPECIALIZE_SMOD_2EXP(smod_2exp_unsigned_int, unsigned int, unsigned int)
9500PPL_SPECIALIZE_SMOD_2EXP(smod_2exp_unsigned_int, unsigned long, unsigned long)
9501PPL_SPECIALIZE_SMOD_2EXP(smod_2exp_unsigned_int, unsigned long long, unsigned long long)
9502
9503#if PPL_CXX_PLAIN_CHAR_IS_SIGNED
9504PPL_SPECIALIZE_UMOD_2EXP(umod_2exp_signed_int, char, char)
9505#endif
9506PPL_SPECIALIZE_UMOD_2EXP(umod_2exp_signed_int, signed char, signed char)
9507PPL_SPECIALIZE_UMOD_2EXP(umod_2exp_signed_int, signed short, signed short)
9508PPL_SPECIALIZE_UMOD_2EXP(umod_2exp_signed_int, signed int, signed int)
9509PPL_SPECIALIZE_UMOD_2EXP(umod_2exp_signed_int, signed long, signed long)
9510PPL_SPECIALIZE_UMOD_2EXP(umod_2exp_signed_int, signed long long, signed long long)
9511#if !PPL_CXX_PLAIN_CHAR_IS_SIGNED
9512PPL_SPECIALIZE_UMOD_2EXP(umod_2exp_unsigned_int, char, char)
9513#endif
9514PPL_SPECIALIZE_UMOD_2EXP(umod_2exp_unsigned_int, unsigned char, unsigned char)
9515PPL_SPECIALIZE_UMOD_2EXP(umod_2exp_unsigned_int, unsigned short, unsigned short)
9516PPL_SPECIALIZE_UMOD_2EXP(umod_2exp_unsigned_int, unsigned int, unsigned int)
9517PPL_SPECIALIZE_UMOD_2EXP(umod_2exp_unsigned_int, unsigned long, unsigned long)
9518PPL_SPECIALIZE_UMOD_2EXP(umod_2exp_unsigned_int, unsigned long long, unsigned long long)
9519
9520#if PPL_CXX_PLAIN_CHAR_IS_SIGNED
9521PPL_SPECIALIZE_SQRT(sqrt_signed_int, char, char)
9522#endif
9523PPL_SPECIALIZE_SQRT(sqrt_signed_int, signed char, signed char)
9524PPL_SPECIALIZE_SQRT(sqrt_signed_int, signed short, signed short)
9525PPL_SPECIALIZE_SQRT(sqrt_signed_int, signed int, signed int)
9526PPL_SPECIALIZE_SQRT(sqrt_signed_int, signed long, signed long)
9527PPL_SPECIALIZE_SQRT(sqrt_signed_int, signed long long, signed long long)
9528#if !PPL_CXX_PLAIN_CHAR_IS_SIGNED
9529PPL_SPECIALIZE_SQRT(sqrt_unsigned_int, char, char)
9530#endif
9531PPL_SPECIALIZE_SQRT(sqrt_unsigned_int, unsigned char, unsigned char)
9532PPL_SPECIALIZE_SQRT(sqrt_unsigned_int, unsigned short, unsigned short)
9533PPL_SPECIALIZE_SQRT(sqrt_unsigned_int, unsigned int, unsigned int)
9534PPL_SPECIALIZE_SQRT(sqrt_unsigned_int, unsigned long, unsigned long)
9535PPL_SPECIALIZE_SQRT(sqrt_unsigned_int, unsigned long long, unsigned long long)
9536
9537#if PPL_CXX_PLAIN_CHAR_IS_SIGNED
9538PPL_SPECIALIZE_ABS(abs_generic, char, char)
9539#endif
9540PPL_SPECIALIZE_ABS(abs_generic, signed char, signed char)
9541PPL_SPECIALIZE_ABS(abs_generic, signed short, signed short)
9542PPL_SPECIALIZE_ABS(abs_generic, signed int, signed int)
9543PPL_SPECIALIZE_ABS(abs_generic, signed long, signed long)
9544PPL_SPECIALIZE_ABS(abs_generic, signed long long, signed long long)
9545#if !PPL_CXX_PLAIN_CHAR_IS_SIGNED
9546PPL_SPECIALIZE_ABS(assign_unsigned_int_unsigned_int, char, char)
9547#endif
9548PPL_SPECIALIZE_ABS(assign_unsigned_int_unsigned_int, unsigned char, unsigned char)
9549PPL_SPECIALIZE_ABS(assign_unsigned_int_unsigned_int, unsigned short, unsigned short)
9550PPL_SPECIALIZE_ABS(assign_unsigned_int_unsigned_int, unsigned int, unsigned int)
9551PPL_SPECIALIZE_ABS(assign_unsigned_int_unsigned_int, unsigned long, unsigned long)
9552PPL_SPECIALIZE_ABS(assign_unsigned_int_unsigned_int, unsigned long long, unsigned long long)
9553
9554PPL_SPECIALIZE_GCD(gcd_exact, char, char, char)
9555PPL_SPECIALIZE_GCD(gcd_exact, signed char, signed char, signed char)
9556PPL_SPECIALIZE_GCD(gcd_exact, signed short, signed short, signed short)
9557PPL_SPECIALIZE_GCD(gcd_exact, signed int, signed int, signed int)
9558PPL_SPECIALIZE_GCD(gcd_exact, signed long, signed long, signed long)
9559PPL_SPECIALIZE_GCD(gcd_exact, signed long long, signed long long, signed long long)
9560PPL_SPECIALIZE_GCD(gcd_exact, unsigned char, unsigned char, unsigned char)
9561PPL_SPECIALIZE_GCD(gcd_exact, unsigned short, unsigned short, unsigned short)
9562PPL_SPECIALIZE_GCD(gcd_exact, unsigned int, unsigned int, unsigned int)
9563PPL_SPECIALIZE_GCD(gcd_exact, unsigned long, unsigned long, unsigned long)
9564PPL_SPECIALIZE_GCD(gcd_exact, unsigned long long, unsigned long long, unsigned long long)
9565
9566PPL_SPECIALIZE_GCDEXT(gcdext_exact,
9567                      char, char, char, char, char)
9568PPL_SPECIALIZE_GCDEXT(gcdext_exact,
9569                      signed char, signed char, signed char,
9570                      signed char, signed char)
9571PPL_SPECIALIZE_GCDEXT(gcdext_exact,
9572                      signed short, signed short, signed short,
9573                      signed short, signed short)
9574PPL_SPECIALIZE_GCDEXT(gcdext_exact,
9575                      signed int, signed int, signed int,
9576                      signed int, signed int)
9577PPL_SPECIALIZE_GCDEXT(gcdext_exact,
9578                      signed long, signed long, signed long,
9579                      signed long, signed long)
9580PPL_SPECIALIZE_GCDEXT(gcdext_exact,
9581                      signed long long, signed long long, signed long long,
9582                      signed long long, signed long long)
9583PPL_SPECIALIZE_GCDEXT(gcdext_exact,
9584                      unsigned char, unsigned char, unsigned char,
9585                      unsigned char, unsigned char)
9586PPL_SPECIALIZE_GCDEXT(gcdext_exact,
9587                      unsigned short, unsigned short, unsigned short,
9588                      unsigned short, unsigned short)
9589PPL_SPECIALIZE_GCDEXT(gcdext_exact,
9590                      unsigned int, unsigned int, unsigned int,
9591                      unsigned int, unsigned int)
9592PPL_SPECIALIZE_GCDEXT(gcdext_exact,
9593                      unsigned long, unsigned long, unsigned long,
9594                      unsigned long, unsigned long)
9595PPL_SPECIALIZE_GCDEXT(gcdext_exact,
9596                      unsigned long long, unsigned long long,
9597                      unsigned long long, unsigned long long,
9598                      unsigned long long)
9599
9600PPL_SPECIALIZE_LCM(lcm_gcd_exact, char, char, char)
9601PPL_SPECIALIZE_LCM(lcm_gcd_exact, signed char, signed char, signed char)
9602PPL_SPECIALIZE_LCM(lcm_gcd_exact, signed short, signed short, signed short)
9603PPL_SPECIALIZE_LCM(lcm_gcd_exact, signed int, signed int, signed int)
9604PPL_SPECIALIZE_LCM(lcm_gcd_exact, signed long, signed long, signed long)
9605PPL_SPECIALIZE_LCM(lcm_gcd_exact, signed long long, signed long long, signed long long)
9606PPL_SPECIALIZE_LCM(lcm_gcd_exact, unsigned char, unsigned char, unsigned char)
9607PPL_SPECIALIZE_LCM(lcm_gcd_exact, unsigned short, unsigned short, unsigned short)
9608PPL_SPECIALIZE_LCM(lcm_gcd_exact, unsigned int, unsigned int, unsigned int)
9609PPL_SPECIALIZE_LCM(lcm_gcd_exact, unsigned long, unsigned long, unsigned long)
9610PPL_SPECIALIZE_LCM(lcm_gcd_exact, unsigned long long, unsigned long long, unsigned long long)
9611
9612PPL_SPECIALIZE_SGN(sgn_generic, char)
9613PPL_SPECIALIZE_SGN(sgn_generic, signed char)
9614PPL_SPECIALIZE_SGN(sgn_generic, signed short)
9615PPL_SPECIALIZE_SGN(sgn_generic, signed int)
9616PPL_SPECIALIZE_SGN(sgn_generic, signed long)
9617PPL_SPECIALIZE_SGN(sgn_generic, signed long long)
9618PPL_SPECIALIZE_SGN(sgn_generic, unsigned char)
9619PPL_SPECIALIZE_SGN(sgn_generic, unsigned short)
9620PPL_SPECIALIZE_SGN(sgn_generic, unsigned int)
9621PPL_SPECIALIZE_SGN(sgn_generic, unsigned long)
9622PPL_SPECIALIZE_SGN(sgn_generic, unsigned long long)
9623
9624PPL_SPECIALIZE_CMP(cmp_generic, char, char)
9625PPL_SPECIALIZE_CMP(cmp_generic, signed char, signed char)
9626PPL_SPECIALIZE_CMP(cmp_generic, signed short, signed short)
9627PPL_SPECIALIZE_CMP(cmp_generic, signed int, signed int)
9628PPL_SPECIALIZE_CMP(cmp_generic, signed long, signed long)
9629PPL_SPECIALIZE_CMP(cmp_generic, signed long long, signed long long)
9630PPL_SPECIALIZE_CMP(cmp_generic, unsigned char, unsigned char)
9631PPL_SPECIALIZE_CMP(cmp_generic, unsigned short, unsigned short)
9632PPL_SPECIALIZE_CMP(cmp_generic, unsigned int, unsigned int)
9633PPL_SPECIALIZE_CMP(cmp_generic, unsigned long, unsigned long)
9634PPL_SPECIALIZE_CMP(cmp_generic, unsigned long long, unsigned long long)
9635
9636PPL_SPECIALIZE_ADD_MUL(add_mul_int, char, char, char)
9637PPL_SPECIALIZE_ADD_MUL(add_mul_int, signed char, signed char, signed char)
9638PPL_SPECIALIZE_ADD_MUL(add_mul_int, signed short, signed short, signed short)
9639PPL_SPECIALIZE_ADD_MUL(add_mul_int, signed int, signed int, signed int)
9640PPL_SPECIALIZE_ADD_MUL(add_mul_int, signed long, signed long, signed long)
9641PPL_SPECIALIZE_ADD_MUL(add_mul_int, signed long long, signed long long, signed long long)
9642PPL_SPECIALIZE_ADD_MUL(add_mul_int, unsigned char, unsigned char, unsigned char)
9643PPL_SPECIALIZE_ADD_MUL(add_mul_int, unsigned short, unsigned short, unsigned short)
9644PPL_SPECIALIZE_ADD_MUL(add_mul_int, unsigned int, unsigned int, unsigned int)
9645PPL_SPECIALIZE_ADD_MUL(add_mul_int, unsigned long, unsigned long, unsigned long)
9646PPL_SPECIALIZE_ADD_MUL(add_mul_int, unsigned long long, unsigned long long, unsigned long long)
9647
9648PPL_SPECIALIZE_SUB_MUL(sub_mul_int, char, char, char)
9649PPL_SPECIALIZE_SUB_MUL(sub_mul_int, signed char, signed char, signed char)
9650PPL_SPECIALIZE_SUB_MUL(sub_mul_int, signed short, signed short, signed short)
9651PPL_SPECIALIZE_SUB_MUL(sub_mul_int, signed int, signed int, signed int)
9652PPL_SPECIALIZE_SUB_MUL(sub_mul_int, signed long, signed long, signed long)
9653PPL_SPECIALIZE_SUB_MUL(sub_mul_int, signed long long, signed long long, signed long long)
9654PPL_SPECIALIZE_SUB_MUL(sub_mul_int, unsigned char, unsigned char, unsigned char)
9655PPL_SPECIALIZE_SUB_MUL(sub_mul_int, unsigned short, unsigned short, unsigned short)
9656PPL_SPECIALIZE_SUB_MUL(sub_mul_int, unsigned int, unsigned int, unsigned int)
9657PPL_SPECIALIZE_SUB_MUL(sub_mul_int, unsigned long, unsigned long, unsigned long)
9658PPL_SPECIALIZE_SUB_MUL(sub_mul_int, unsigned long long, unsigned long long, unsigned long long)
9659
9660PPL_SPECIALIZE_INPUT(input_generic, char)
9661PPL_SPECIALIZE_INPUT(input_generic, signed char)
9662PPL_SPECIALIZE_INPUT(input_generic, signed short)
9663PPL_SPECIALIZE_INPUT(input_generic, signed int)
9664PPL_SPECIALIZE_INPUT(input_generic, signed long)
9665PPL_SPECIALIZE_INPUT(input_generic, signed long long)
9666PPL_SPECIALIZE_INPUT(input_generic, unsigned char)
9667PPL_SPECIALIZE_INPUT(input_generic, unsigned short)
9668PPL_SPECIALIZE_INPUT(input_generic, unsigned int)
9669PPL_SPECIALIZE_INPUT(input_generic, unsigned long)
9670PPL_SPECIALIZE_INPUT(input_generic, unsigned long long)
9671
9672PPL_SPECIALIZE_OUTPUT(output_char, char)
9673PPL_SPECIALIZE_OUTPUT(output_char, signed char)
9674PPL_SPECIALIZE_OUTPUT(output_int, signed short)
9675PPL_SPECIALIZE_OUTPUT(output_int, signed int)
9676PPL_SPECIALIZE_OUTPUT(output_int, signed long)
9677PPL_SPECIALIZE_OUTPUT(output_int, signed long long)
9678PPL_SPECIALIZE_OUTPUT(output_char, unsigned char)
9679PPL_SPECIALIZE_OUTPUT(output_int, unsigned short)
9680PPL_SPECIALIZE_OUTPUT(output_int, unsigned int)
9681PPL_SPECIALIZE_OUTPUT(output_int, unsigned long)
9682PPL_SPECIALIZE_OUTPUT(output_int, unsigned long long)
9683
9684} // namespace Checked
9685
9686} // namespace Parma_Polyhedra_Library
9687
9688/* Automatically generated from PPL source file ../src/checked_float_inlines.hh line 1. */
9689/* Specialized "checked" functions for native floating-point numbers.
9690*/
9691
9692
9693/* Automatically generated from PPL source file ../src/checked_float_inlines.hh line 28. */
9694#include <cmath>
9695
9696namespace Parma_Polyhedra_Library {
9697
9698namespace Checked {
9699
9700inline float
9701multiply_add(float x, float y, float z) {
9702#if PPL_HAVE_DECL_FMAF && defined(FP_FAST_FMAF) \
9703  && !defined(__alpha) && !defined(__FreeBSD__)
9704  return fmaf(x, y, z);
9705#else
9706  return x*y + z;
9707#endif
9708}
9709
9710inline double
9711multiply_add(double x, double y, double z) {
9712#if PPL_HAVE_DECL_FMA && defined(FP_FAST_FMA) \
9713  && !defined(__alpha) && !defined(__FreeBSD__)
9714  return fma(x, y, z);
9715#else
9716  return x*y + z;
9717#endif
9718}
9719
9720inline long double
9721multiply_add(long double x, long double y, long double z) {
9722#if PPL_HAVE_DECL_FMAL && defined(FP_FAST_FMAL) \
9723  && !defined(__alpha) && !defined(__FreeBSD__)
9724  return fmal(x, y, z);
9725#else
9726  return x*y + z;
9727#endif
9728}
9729
9730#if PPL_HAVE_DECL_RINTF
9731inline float
9732round_to_integer(float x) {
9733  return rintf(x);
9734}
9735#endif
9736
9737inline double
9738round_to_integer(double x) {
9739  return rint(x);
9740}
9741
9742#if PPL_HAVE_DECL_RINTL
9743inline long double
9744round_to_integer(long double x) {
9745  return rintl(x);
9746}
9747#elif !PPL_CXX_PROVIDES_PROPER_LONG_DOUBLE
9748// If proper long doubles are not provided, this is most likely
9749// because long double and double are the same type: use rint().
9750inline long double
9751round_to_integer(long double x) {
9752  return rint(x);
9753}
9754#elif defined(__i386__) && (defined(__GNUC__) || defined(__INTEL_COMPILER))
9755// On Cygwin, we have proper long doubles but rintl() is not defined:
9756// luckily, one machine instruction is enough to save the day.
9757inline long double
9758round_to_integer(long double x) {
9759  long double i;
9760  __asm__ ("frndint" : "=t" (i) : "0" (x));
9761  return i;
9762}
9763#endif
9764
9765inline bool
9766fpu_direct_rounding(Rounding_Dir dir) {
9767  return round_direct(dir) || round_not_requested(dir);
9768}
9769
9770inline bool
9771fpu_inverse_rounding(Rounding_Dir dir) {
9772  return round_inverse(dir);
9773}
9774
9775// The FPU mode is "round down".
9776//
9777// The result of the rounded down multiplication is thus computed directly.
9778//
9779//   a = 0.3
9780//   b = 0.1
9781//   c_i = a * b = 0.03
9782//   c = c_i = 0.0
9783//
9784// To obtain the result of the rounded up multiplication
9785// we do -(-a * b).
9786//
9787//   a = 0.3
9788//   b = 0.1
9789//   c_i = -a * b = -0.03
9790//
9791// Here c_i should be forced to lose excess precision, otherwise the
9792// FPU will truncate using the rounding mode in force, which is "round down".
9793//
9794//   c_i = -c_i = 0.03
9795//   c = c_i = 0.0
9796//
9797// Wrong result: we should have obtained c = 0.1.
9798
9799inline void
9800limit_precision(const float& v) {
9801  PPL_CC_FLUSH(v);
9802}
9803
9804inline void
9805limit_precision(const double& v) {
9806  PPL_CC_FLUSH(v);
9807}
9808
9809inline void
9810limit_precision(const long double&) {
9811}
9812
9813template <typename Policy, typename T>
9814inline Result
9815classify_float(const T v, bool nan, bool inf, bool sign) {
9816  Float<T> f(v);
9817  if ((nan || sign) && CHECK_P(Policy::has_nan, f.u.binary.is_nan())) {
9818    return V_NAN;
9819  }
9820  if (inf) {
9821    if (Policy::has_infinity) {
9822      int sign_inf = f.u.binary.inf_sign();
9823      if (sign_inf < 0) {
9824        return V_EQ_MINUS_INFINITY;
9825      }
9826      if (sign_inf > 0) {
9827        return V_EQ_PLUS_INFINITY;
9828      }
9829    }
9830    else {
9831      PPL_ASSERT(f.u.binary.inf_sign() == 0);
9832    }
9833  }
9834  if (sign) {
9835    if (v < 0) {
9836      return V_LT;
9837    }
9838    if (v > 0) {
9839      return V_GT;
9840    }
9841    return V_EQ;
9842  }
9843  return V_LGE;
9844}
9845
9846template <typename Policy, typename T>
9847inline bool
9848is_nan_float(const T v) {
9849  Float<T> f(v);
9850  return CHECK_P(Policy::has_nan, f.u.binary.is_nan());
9851}
9852
9853template <typename Policy, typename T>
9854inline bool
9855is_inf_float(const T v) {
9856  Float<T> f(v);
9857  return CHECK_P(Policy::has_infinity, (f.u.binary.inf_sign() != 0));
9858}
9859template <typename Policy, typename T>
9860inline bool
9861is_minf_float(const T v) {
9862  Float<T> f(v);
9863  return CHECK_P(Policy::has_infinity, (f.u.binary.inf_sign() < 0));
9864}
9865
9866template <typename Policy, typename T>
9867inline bool
9868is_pinf_float(const T v) {
9869  Float<T> f(v);
9870  return CHECK_P(Policy::has_infinity, (f.u.binary.inf_sign() > 0));
9871}
9872
9873
9874template <typename Policy, typename T>
9875inline bool
9876is_int_float(const T v) {
9877  return round_to_integer(v) == v;
9878}
9879
9880template <typename Policy, typename T>
9881inline Result
9882assign_special_float(T& v, Result_Class c, Rounding_Dir) {
9883  PPL_ASSERT(c == VC_MINUS_INFINITY || c == VC_PLUS_INFINITY || c == VC_NAN);
9884  switch (c) {
9885  case VC_MINUS_INFINITY:
9886    v = -HUGE_VAL;
9887    return V_EQ_MINUS_INFINITY;
9888  case VC_PLUS_INFINITY:
9889    v = HUGE_VAL;
9890    return V_EQ_PLUS_INFINITY;
9891  case VC_NAN:
9892    v = PPL_NAN;
9893    return V_NAN;
9894  default:
9895    PPL_UNREACHABLE;
9896    return V_NAN | V_UNREPRESENTABLE;
9897  }
9898}
9899
9900template <typename T>
9901inline void
9902pred_float(T& v) {
9903  Float<T> f(v);
9904  PPL_ASSERT(!f.u.binary.is_nan());
9905  PPL_ASSERT(f.u.binary.inf_sign() >= 0);
9906  if (f.u.binary.zero_sign() > 0) {
9907    f.u.binary.negate();
9908    f.u.binary.inc();
9909  }
9910  else if (f.u.binary.sign_bit()) {
9911    f.u.binary.inc();
9912  }
9913  else {
9914    f.u.binary.dec();
9915  }
9916  v = f.value();
9917}
9918
9919template <typename T>
9920inline void
9921succ_float(T& v) {
9922  Float<T> f(v);
9923  PPL_ASSERT(!f.u.binary.is_nan());
9924  PPL_ASSERT(f.u.binary.inf_sign() <= 0);
9925  if (f.u.binary.zero_sign() < 0) {
9926    f.u.binary.negate();
9927    f.u.binary.inc();
9928  }
9929  else if (!f.u.binary.sign_bit()) {
9930    f.u.binary.inc();
9931  }
9932  else {
9933    f.u.binary.dec();
9934  }
9935  v = f.value();
9936}
9937
9938template <typename Policy, typename To>
9939inline Result
9940round_lt_float(To& to, Rounding_Dir dir) {
9941  if (round_down(dir)) {
9942    pred_float(to);
9943    return V_GT;
9944  }
9945  return V_LT;
9946}
9947
9948template <typename Policy, typename To>
9949inline Result
9950round_gt_float(To& to, Rounding_Dir dir) {
9951  if (round_up(dir)) {
9952    succ_float(to);
9953    return V_LT;
9954  }
9955  return V_GT;
9956}
9957
9958
9959template <typename Policy>
9960inline void
9961prepare_inexact(Rounding_Dir dir) {
9962  if (Policy::fpu_check_inexact
9963      && !round_not_needed(dir) && round_strict_relation(dir)) {
9964    fpu_reset_inexact();
9965  }
9966}
9967
9968template <typename Policy>
9969inline Result
9970result_relation(Rounding_Dir dir) {
9971  if (Policy::fpu_check_inexact
9972      && !round_not_needed(dir) && round_strict_relation(dir)) {
9973    switch (fpu_check_inexact()) {
9974    case 0:
9975      return V_EQ;
9976    case -1:
9977      goto unknown;
9978    case 1:
9979      break;
9980    }
9981    switch (round_dir(dir)) {
9982    case ROUND_DOWN:
9983      return V_GT;
9984    case ROUND_UP:
9985      return V_LT;
9986    default:
9987      return V_NE;
9988    }
9989  }
9990  else {
9991  unknown:
9992    switch (round_dir(dir)) {
9993    case ROUND_DOWN:
9994      return V_GE;
9995    case ROUND_UP:
9996      return V_LE;
9997    default:
9998      return V_LGE;
9999    }
10000  }
10001}
10002
10003template <typename To_Policy, typename From_Policy, typename To, typename From>
10004inline Result
10005assign_float_float_exact(To& to, const From from, Rounding_Dir) {
10006  if (To_Policy::fpu_check_nan_result && is_nan<From_Policy>(from)) {
10007    return assign_special<To_Policy>(to, VC_NAN, ROUND_IGNORE);
10008  }
10009  to = from;
10010  return V_EQ;
10011}
10012
10013template <typename To_Policy, typename From_Policy, typename To, typename From>
10014inline Result
10015assign_float_float_inexact(To& to, const From from, Rounding_Dir dir) {
10016  if (To_Policy::fpu_check_nan_result && is_nan<From_Policy>(from)) {
10017    return assign_special<To_Policy>(to, VC_NAN, ROUND_IGNORE);
10018  }
10019  prepare_inexact<To_Policy>(dir);
10020  if (fpu_direct_rounding(dir)) {
10021    to = from;
10022  }
10023  else if (fpu_inverse_rounding(dir)) {
10024    From tmp = -from;
10025    to = tmp;
10026    limit_precision(to);
10027    to = -to;
10028  }
10029  else {
10030    fpu_rounding_control_word_type old
10031      = fpu_save_rounding_direction(round_fpu_dir(dir));
10032    limit_precision(from);
10033    to = from;
10034    limit_precision(to);
10035    fpu_restore_rounding_direction(old);
10036  }
10037  return result_relation<To_Policy>(dir);
10038}
10039
10040template <typename To_Policy, typename From_Policy, typename To, typename From>
10041inline Result
10042assign_float_float(To& to, const From from, Rounding_Dir dir) {
10043  if (sizeof(From) > sizeof(To)) {
10044    return assign_float_float_inexact<To_Policy, From_Policy>(to, from, dir);
10045  }
10046  else {
10047    return assign_float_float_exact<To_Policy, From_Policy>(to, from, dir);
10048  }
10049}
10050
10051template <typename To_Policy, typename From_Policy, typename Type>
10052inline Result
10053floor_float(Type& to, const Type from, Rounding_Dir) {
10054  if (To_Policy::fpu_check_nan_result && is_nan<From_Policy>(from)) {
10055    return assign_special<To_Policy>(to, VC_NAN, ROUND_IGNORE);
10056  }
10057  if (fpu_direct_rounding(ROUND_DOWN)) {
10058    to = round_to_integer(from);
10059  }
10060  else if (fpu_inverse_rounding(ROUND_DOWN)) {
10061    to = round_to_integer(-from);
10062    limit_precision(to);
10063    to = -to;
10064  }
10065  else {
10066    fpu_rounding_control_word_type old
10067      = fpu_save_rounding_direction(round_fpu_dir(ROUND_DOWN));
10068    limit_precision(from);
10069    to = round_to_integer(from);
10070    limit_precision(to);
10071    fpu_restore_rounding_direction(old);
10072  }
10073  return V_EQ;
10074}
10075
10076template <typename To_Policy, typename From_Policy, typename Type>
10077inline Result
10078ceil_float(Type& to, const Type from, Rounding_Dir) {
10079  if (To_Policy::fpu_check_nan_result && is_nan<From_Policy>(from)) {
10080    return assign_special<To_Policy>(to, VC_NAN, ROUND_IGNORE);
10081  }
10082  if (fpu_direct_rounding(ROUND_UP)) {
10083    to = round_to_integer(from);
10084  }
10085  else if (fpu_inverse_rounding(ROUND_UP)) {
10086    to = round_to_integer(-from);
10087    limit_precision(to);
10088    to = -to;
10089  }
10090  else {
10091    fpu_rounding_control_word_type old
10092      = fpu_save_rounding_direction(round_fpu_dir(ROUND_UP));
10093    limit_precision(from);
10094    to = round_to_integer(from);
10095    limit_precision(to);
10096    fpu_restore_rounding_direction(old);
10097  }
10098  return V_EQ;
10099}
10100
10101template <typename To_Policy, typename From_Policy, typename Type>
10102inline Result
10103trunc_float(Type& to, const Type from, Rounding_Dir dir) {
10104  if (To_Policy::fpu_check_nan_result && is_nan<From_Policy>(from)) {
10105    return assign_special<To_Policy>(to, VC_NAN, ROUND_IGNORE);
10106  }
10107  if (from >= 0) {
10108    return floor<To_Policy, From_Policy>(to, from, dir);
10109  }
10110  else {
10111    return ceil<To_Policy, From_Policy>(to, from, dir);
10112  }
10113}
10114
10115template <typename To_Policy, typename From_Policy, typename Type>
10116inline Result
10117neg_float(Type& to, const Type from, Rounding_Dir) {
10118  if (To_Policy::fpu_check_nan_result && is_nan<From_Policy>(from)) {
10119    return assign_special<To_Policy>(to, VC_NAN, ROUND_IGNORE);
10120  }
10121  to = -from;
10122  return V_EQ;
10123}
10124
10125template <typename To_Policy, typename From1_Policy, typename From2_Policy,
10126          typename Type>
10127inline Result
10128add_float(Type& to, const Type x, const Type y, Rounding_Dir dir) {
10129  if (To_Policy::check_inf_add_inf
10130      && is_inf_float<From1_Policy>(x) && x == -y) {
10131    return assign_nan<To_Policy>(to, V_INF_ADD_INF);
10132  }
10133  prepare_inexact<To_Policy>(dir);
10134  if (fpu_direct_rounding(dir)) {
10135    to = x + y;
10136  }
10137  else if (fpu_inverse_rounding(dir)) {
10138    to = -x - y;
10139    limit_precision(to);
10140    to = -to;
10141  }
10142  else {
10143    fpu_rounding_control_word_type old
10144      = fpu_save_rounding_direction(round_fpu_dir(dir));
10145    limit_precision(x);
10146    limit_precision(y);
10147    to = x + y;
10148    limit_precision(to);
10149    fpu_restore_rounding_direction(old);
10150  }
10151  if (To_Policy::fpu_check_nan_result && is_nan<To_Policy>(to)) {
10152    return V_NAN;
10153  }
10154  return result_relation<To_Policy>(dir);
10155}
10156
10157template <typename To_Policy, typename From1_Policy, typename From2_Policy,
10158          typename Type>
10159inline Result
10160sub_float(Type& to, const Type x, const Type y, Rounding_Dir dir) {
10161  if (To_Policy::check_inf_sub_inf
10162      && is_inf_float<From1_Policy>(x) && x == y) {
10163    return assign_nan<To_Policy>(to, V_INF_SUB_INF);
10164  }
10165  prepare_inexact<To_Policy>(dir);
10166  if (fpu_direct_rounding(dir)) {
10167    to = x - y;
10168  }
10169  else if (fpu_inverse_rounding(dir)) {
10170    to = y - x;
10171    limit_precision(to);
10172    to = -to;
10173  }
10174  else {
10175    fpu_rounding_control_word_type old
10176      = fpu_save_rounding_direction(round_fpu_dir(dir));
10177    limit_precision(x);
10178    limit_precision(y);
10179    to = x - y;
10180    limit_precision(to);
10181    fpu_restore_rounding_direction(old);
10182  }
10183  if (To_Policy::fpu_check_nan_result && is_nan<To_Policy>(to)) {
10184    return V_NAN;
10185  }
10186  return result_relation<To_Policy>(dir);
10187}
10188
10189template <typename To_Policy, typename From1_Policy, typename From2_Policy,
10190          typename Type>
10191inline Result
10192mul_float(Type& to, const Type x, const Type y, Rounding_Dir dir) {
10193  if (To_Policy::check_inf_mul_zero
10194      && ((x == 0 && is_inf_float<From2_Policy>(y))
10195          ||
10196          (y == 0 && is_inf_float<From1_Policy>(x)))) {
10197    return assign_nan<To_Policy>(to, V_INF_MUL_ZERO);
10198  }
10199  prepare_inexact<To_Policy>(dir);
10200  if (fpu_direct_rounding(dir)) {
10201    to = x * y;
10202  }
10203  else if (fpu_inverse_rounding(dir)) {
10204    to = x * -y;
10205    limit_precision(to);
10206    to = -to;
10207  }
10208  else {
10209    fpu_rounding_control_word_type old
10210      = fpu_save_rounding_direction(round_fpu_dir(dir));
10211    limit_precision(x);
10212    limit_precision(y);
10213    to = x * y;
10214    limit_precision(to);
10215    fpu_restore_rounding_direction(old);
10216  }
10217  if (To_Policy::fpu_check_nan_result && is_nan<To_Policy>(to)) {
10218    return V_NAN;
10219  }
10220  return result_relation<To_Policy>(dir);
10221}
10222
10223template <typename To_Policy, typename From1_Policy, typename From2_Policy,
10224          typename Type>
10225inline Result
10226div_float(Type& to, const Type x, const Type y, Rounding_Dir dir) {
10227  if (To_Policy::check_inf_div_inf
10228      && is_inf_float<From1_Policy>(x) && is_inf_float<From2_Policy>(y)) {
10229    return assign_nan<To_Policy>(to, V_INF_DIV_INF);
10230  }
10231  if (To_Policy::check_div_zero && y == 0) {
10232    return assign_nan<To_Policy>(to, V_DIV_ZERO);
10233  }
10234  prepare_inexact<To_Policy>(dir);
10235  if (fpu_direct_rounding(dir)) {
10236    to = x / y;
10237  }
10238  else if (fpu_inverse_rounding(dir)) {
10239    to = x / -y;
10240    limit_precision(to);
10241    to = -to;
10242  }
10243  else {
10244    fpu_rounding_control_word_type old
10245      = fpu_save_rounding_direction(round_fpu_dir(dir));
10246    limit_precision(x);
10247    limit_precision(y);
10248    to = x / y;
10249    limit_precision(to);
10250    fpu_restore_rounding_direction(old);
10251  }
10252  if (To_Policy::fpu_check_nan_result && is_nan<To_Policy>(to)) {
10253    return V_NAN;
10254  }
10255  return result_relation<To_Policy>(dir);
10256}
10257
10258template <typename To_Policy, typename From1_Policy, typename From2_Policy,
10259          typename Type>
10260inline Result
10261idiv_float(Type& to, const Type x, const Type y, Rounding_Dir dir) {
10262  Type temp;
10263  // The inexact check is useless
10264  dir = round_dir(dir);
10265  Result r = div<To_Policy, From1_Policy, From2_Policy>(temp, x, y, dir);
10266  if (result_class(r) != VC_NORMAL) {
10267    to = temp;
10268    return r;
10269  }
10270  Result r1 = trunc<To_Policy, To_Policy>(to, temp, ROUND_NOT_NEEDED);
10271  PPL_ASSERT(r1 == V_EQ);
10272  if (r == V_EQ || to != temp) {
10273    return r1;
10274  }
10275  // FIXME: Prove that it is impossible to return a strict relation
10276  return (dir == ROUND_UP) ? V_LE : V_GE;
10277}
10278
10279template <typename To_Policy, typename From1_Policy, typename From2_Policy,
10280          typename Type>
10281inline Result
10282rem_float(Type& to, const Type x, const Type y, Rounding_Dir) {
10283  if (To_Policy::check_inf_mod && is_inf_float<From1_Policy>(x)) {
10284    return assign_nan<To_Policy>(to, V_INF_MOD);
10285  }
10286  if (To_Policy::check_div_zero && y == 0) {
10287    return assign_nan<To_Policy>(to, V_MOD_ZERO);
10288  }
10289  to = std::fmod(x, y);
10290  if (To_Policy::fpu_check_nan_result && is_nan<To_Policy>(to)) {
10291    return V_NAN;
10292  }
10293  return V_EQ;
10294}
10295
10296struct Float_2exp {
10297  const_bool_nodef(has_nan, false);
10298  const_bool_nodef(has_infinity, false);
10299};
10300
10301template <typename To_Policy, typename From_Policy, typename Type>
10302inline Result
10303add_2exp_float(Type& to, const Type x, unsigned int exp, Rounding_Dir dir) {
10304  if (To_Policy::fpu_check_nan_result && is_nan<From_Policy>(x)) {
10305    return assign_special<To_Policy>(to, VC_NAN, ROUND_IGNORE);
10306  }
10307  PPL_ASSERT(exp < sizeof_to_bits(sizeof(unsigned long long)));
10308  return
10309    add<To_Policy, From_Policy, Float_2exp>(to,
10310                                            x,
10311                                            Type(1ULL << exp),
10312                                            dir);
10313}
10314
10315template <typename To_Policy, typename From_Policy, typename Type>
10316inline Result
10317sub_2exp_float(Type& to, const Type x, unsigned int exp, Rounding_Dir dir) {
10318  if (To_Policy::fpu_check_nan_result && is_nan<From_Policy>(x)) {
10319    return assign_special<To_Policy>(to, VC_NAN, ROUND_IGNORE);
10320  }
10321  PPL_ASSERT(exp < sizeof_to_bits(sizeof(unsigned long long)));
10322  return
10323    sub<To_Policy, From_Policy, Float_2exp>(to,
10324                                            x,
10325                                            Type(1ULL << exp),
10326                                            dir);
10327}
10328
10329template <typename To_Policy, typename From_Policy, typename Type>
10330inline Result
10331mul_2exp_float(Type& to, const Type x, unsigned int exp, Rounding_Dir dir) {
10332  if (To_Policy::fpu_check_nan_result && is_nan<From_Policy>(x)) {
10333    return assign_special<To_Policy>(to, VC_NAN, ROUND_IGNORE);
10334  }
10335  PPL_ASSERT(exp < sizeof_to_bits(sizeof(unsigned long long)));
10336  return
10337    mul<To_Policy, From_Policy, Float_2exp>(to,
10338                                            x,
10339                                            Type(1ULL << exp),
10340                                            dir);
10341}
10342
10343template <typename To_Policy, typename From_Policy, typename Type>
10344inline Result
10345div_2exp_float(Type& to, const Type x, unsigned int exp, Rounding_Dir dir) {
10346  if (To_Policy::fpu_check_nan_result && is_nan<From_Policy>(x)) {
10347    return assign_special<To_Policy>(to, VC_NAN, ROUND_IGNORE);
10348  }
10349  PPL_ASSERT(exp < sizeof_to_bits(sizeof(unsigned long long)));
10350  return
10351    div<To_Policy, From_Policy, Float_2exp>(to,
10352                                            x,
10353                                            Type(1ULL << exp),
10354                                            dir);
10355}
10356
10357template <typename To_Policy, typename From_Policy, typename Type>
10358inline Result
10359smod_2exp_float(Type& to, const Type x, unsigned int exp, Rounding_Dir dir) {
10360  if (To_Policy::fpu_check_nan_result && is_nan<From_Policy>(x)) {
10361    return assign_special<To_Policy>(to, VC_NAN, ROUND_IGNORE);
10362  }
10363  if (To_Policy::check_inf_mod && is_inf_float<From_Policy>(x)) {
10364    return assign_nan<To_Policy>(to, V_INF_MOD);
10365  }
10366  PPL_ASSERT(exp < sizeof_to_bits(sizeof(unsigned long long)));
10367  Type m = 1ULL << exp;
10368  rem_float<To_Policy, From_Policy, Float_2exp>(to, x, m, ROUND_IGNORE);
10369  Type m2 = m / 2;
10370  if (to < -m2) {
10371    return add_float<To_Policy, From_Policy, Float_2exp>(to, to, m, dir);
10372  }
10373  else if (to >= m2) {
10374    return sub_float<To_Policy, From_Policy, Float_2exp>(to, to, m, dir);
10375  }
10376  return V_EQ;
10377}
10378
10379template <typename To_Policy, typename From_Policy, typename Type>
10380inline Result
10381umod_2exp_float(Type& to, const Type x, unsigned int exp, Rounding_Dir dir) {
10382  if (To_Policy::fpu_check_nan_result && is_nan<From_Policy>(x)) {
10383    return assign_special<To_Policy>(to, VC_NAN, ROUND_IGNORE);
10384  }
10385  if (To_Policy::check_inf_mod && is_inf_float<From_Policy>(x)) {
10386    return assign_nan<To_Policy>(to, V_INF_MOD);
10387  }
10388  PPL_ASSERT(exp < sizeof_to_bits(sizeof(unsigned long long)));
10389  Type m = 1ULL << exp;
10390  rem_float<To_Policy, From_Policy, Float_2exp>(to, x, m, ROUND_IGNORE);
10391  if (to < 0) {
10392    return add_float<To_Policy, From_Policy, Float_2exp>(to, to, m, dir);
10393  }
10394  return V_EQ;
10395}
10396
10397template <typename To_Policy, typename From_Policy, typename Type>
10398inline Result
10399abs_float(Type& to, const Type from, Rounding_Dir) {
10400  if (To_Policy::fpu_check_nan_result && is_nan<From_Policy>(from)) {
10401    return assign_special<To_Policy>(to, VC_NAN, ROUND_IGNORE);
10402  }
10403  to = std::abs(from);
10404  return V_EQ;
10405}
10406
10407template <typename To_Policy, typename From_Policy, typename Type>
10408inline Result
10409sqrt_float(Type& to, const Type from, Rounding_Dir dir) {
10410  if (To_Policy::fpu_check_nan_result && is_nan<From_Policy>(from)) {
10411    return assign_special<To_Policy>(to, VC_NAN, ROUND_IGNORE);
10412  }
10413  if (To_Policy::check_sqrt_neg && from < 0) {
10414    return assign_nan<To_Policy>(to, V_SQRT_NEG);
10415  }
10416  prepare_inexact<To_Policy>(dir);
10417  if (fpu_direct_rounding(dir)) {
10418    to = std::sqrt(from);
10419  }
10420  else {
10421    fpu_rounding_control_word_type old
10422      = fpu_save_rounding_direction(round_fpu_dir(dir));
10423    limit_precision(from);
10424    to = std::sqrt(from);
10425    limit_precision(to);
10426    fpu_restore_rounding_direction(old);
10427  }
10428  return result_relation<To_Policy>(dir);
10429}
10430
10431template <typename Policy, typename Type>
10432inline Result_Relation
10433sgn_float(const Type x) {
10434  if (x > 0) {
10435    return VR_GT;
10436  }
10437  if (x < 0) {
10438    return VR_LT;
10439  }
10440  if (x == 0) {
10441    return VR_EQ;
10442  }
10443  return VR_EMPTY;
10444}
10445
10446template <typename Policy1, typename Policy2, typename Type>
10447inline Result_Relation
10448cmp_float(const Type x, const Type y) {
10449  if (x > y) {
10450    return VR_GT;
10451  }
10452  if (x < y) {
10453    return VR_LT;
10454  }
10455  if (x == y) {
10456    return VR_EQ;
10457  }
10458  return VR_EMPTY;
10459}
10460
10461template <typename To_Policy, typename From_Policy, typename To, typename From>
10462inline Result
10463assign_float_int_inexact(To& to, const From from, Rounding_Dir dir) {
10464  prepare_inexact<To_Policy>(dir);
10465  if (fpu_direct_rounding(dir)) {
10466    to = from;
10467  }
10468  else {
10469    fpu_rounding_control_word_type old
10470      = fpu_save_rounding_direction(round_fpu_dir(dir));
10471    to = from;
10472    limit_precision(to);
10473    fpu_restore_rounding_direction(old);
10474  }
10475  return result_relation<To_Policy>(dir);
10476}
10477
10478template <typename To_Policy, typename From_Policy, typename To, typename From>
10479inline Result
10480assign_float_int(To& to, const From from, Rounding_Dir dir) {
10481  if (sizeof_to_bits(sizeof(From)) > Float<To>::Binary::MANTISSA_BITS) {
10482    return assign_float_int_inexact<To_Policy, From_Policy>(to, from, dir);
10483  }
10484  else {
10485    return assign_exact<To_Policy, From_Policy>(to, from, dir);
10486  }
10487}
10488
10489template <typename Policy, typename T>
10490inline Result
10491set_neg_overflow_float(T& to, Rounding_Dir dir) {
10492  switch (round_dir(dir)) {
10493  case ROUND_UP:
10494    {
10495      Float<T> f;
10496      f.u.binary.set_max(true);
10497      to = f.value();
10498      return V_LT_INF;
10499    }
10500  case ROUND_DOWN: // Fall through.
10501  case ROUND_IGNORE:
10502    to = -HUGE_VAL;
10503    return V_GT_MINUS_INFINITY;
10504  default:
10505    PPL_UNREACHABLE;
10506    return V_GT_MINUS_INFINITY;
10507  }
10508}
10509
10510template <typename Policy, typename T>
10511inline Result
10512set_pos_overflow_float(T& to, Rounding_Dir dir) {
10513  switch (round_dir(dir)) {
10514  case ROUND_DOWN:
10515    {
10516      Float<T> f;
10517      f.u.binary.set_max(false);
10518      to = f.value();
10519      return V_GT_SUP;
10520    }
10521  case ROUND_UP: // Fall through.
10522  case ROUND_IGNORE:
10523    to = HUGE_VAL;
10524    return V_LT_PLUS_INFINITY;
10525  default:
10526    PPL_UNREACHABLE;
10527    return V_LT_PLUS_INFINITY;
10528  }
10529}
10530
10531template <typename To_Policy, typename From_Policy, typename T>
10532inline Result
10533assign_float_mpz(T& to, const mpz_class& from, Rounding_Dir dir) {
10534  int sign = sgn(from);
10535  if (sign == 0) {
10536    to = 0;
10537    return V_EQ;
10538  }
10539  mpz_srcptr from_z = from.get_mpz_t();
10540  size_t exponent = mpz_sizeinbase(from_z, 2) - 1;
10541  if (exponent > size_t(Float<T>::Binary::EXPONENT_MAX)) {
10542    if (sign < 0) {
10543      return set_neg_overflow_float<To_Policy>(to, dir);
10544    }
10545    else {
10546      return set_pos_overflow_float<To_Policy>(to, dir);
10547    }
10548  }
10549  unsigned long zeroes = mpn_scan1(from_z->_mp_d, 0);
10550  size_t meaningful_bits = exponent - zeroes;
10551  mpz_t mantissa;
10552  mpz_init(mantissa);
10553  if (exponent > Float<T>::Binary::MANTISSA_BITS) {
10554    mpz_tdiv_q_2exp(mantissa,
10555                    from_z,
10556                    exponent - Float<T>::Binary::MANTISSA_BITS);
10557  }
10558  else {
10559    mpz_mul_2exp(mantissa, from_z, Float<T>::Binary::MANTISSA_BITS - exponent);
10560  }
10561  Float<T> f;
10562  f.u.binary.build(sign < 0, mantissa, static_cast<long>(exponent));
10563  mpz_clear(mantissa);
10564  to = f.value();
10565  if (meaningful_bits > Float<T>::Binary::MANTISSA_BITS) {
10566    if (sign < 0) {
10567      return round_lt_float<To_Policy>(to, dir);
10568    }
10569    else {
10570      return round_gt_float<To_Policy>(to, dir);
10571    }
10572  }
10573  return V_EQ;
10574}
10575
10576template <typename To_Policy, typename From_Policy, typename T>
10577inline Result
10578assign_float_mpq(T& to, const mpq_class& from, Rounding_Dir dir) {
10579  const mpz_class& numer = from.get_num();
10580  const mpz_class& denom = from.get_den();
10581  if (denom == 1) {
10582    return assign_float_mpz<To_Policy, From_Policy>(to, numer, dir);
10583  }
10584  mpz_srcptr numer_z = numer.get_mpz_t();
10585  mpz_srcptr denom_z = denom.get_mpz_t();
10586  int sign = sgn(numer);
10587  long exponent = static_cast<long>(mpz_sizeinbase(numer_z, 2))
10588    - static_cast<long>(mpz_sizeinbase(denom_z, 2));
10589  if (exponent < Float<T>::Binary::EXPONENT_MIN_DENORM) {
10590    to = 0;
10591  inexact:
10592    if (sign < 0) {
10593      return round_lt_float<To_Policy>(to, dir);
10594    }
10595    else {
10596      return round_gt_float<To_Policy>(to, dir);
10597    }
10598  }
10599  if (exponent > Float<T>::Binary::EXPONENT_MAX + 1) {
10600  overflow:
10601    if (sign < 0) {
10602      return set_neg_overflow_float<To_Policy>(to, dir);
10603    }
10604    else {
10605      return set_pos_overflow_float<To_Policy>(to, dir);
10606    }
10607  }
10608  unsigned int needed_bits = Float<T>::Binary::MANTISSA_BITS + 1;
10609  if (exponent < Float<T>::Binary::EXPONENT_MIN) {
10610    long diff = Float<T>::Binary::EXPONENT_MIN - exponent;
10611    needed_bits -= static_cast<unsigned int>(diff);
10612  }
10613  mpz_t mantissa;
10614  mpz_init(mantissa);
10615  {
10616    long shift = static_cast<long>(needed_bits) - exponent;
10617    if (shift > 0) {
10618      mpz_mul_2exp(mantissa, numer_z, static_cast<unsigned long>(shift));
10619      numer_z = mantissa;
10620    }
10621    else if (shift < 0) {
10622      shift = -shift;
10623      mpz_mul_2exp(mantissa, denom_z, static_cast<unsigned long>(shift));
10624      denom_z = mantissa;
10625    }
10626  }
10627  mpz_t r;
10628  mpz_init(r);
10629  mpz_tdiv_qr(mantissa, r, numer_z, denom_z);
10630  size_t bits = mpz_sizeinbase(mantissa, 2);
10631  bool inexact = (mpz_sgn(r) != 0);
10632  mpz_clear(r);
10633  if (bits == needed_bits + 1) {
10634    inexact = (inexact || mpz_odd_p(mantissa));
10635    mpz_tdiv_q_2exp(mantissa, mantissa, 1);
10636  }
10637  else {
10638    --exponent;
10639  }
10640  if (exponent > Float<T>::Binary::EXPONENT_MAX) {
10641    mpz_clear(mantissa);
10642    goto overflow;
10643  }
10644  else if (exponent < Float<T>::Binary::EXPONENT_MIN - 1) {
10645    // Denormalized.
10646    exponent = Float<T>::Binary::EXPONENT_MIN - 1;
10647  }
10648  Float<T> f;
10649  f.u.binary.build(sign < 0, mantissa, exponent);
10650  mpz_clear(mantissa);
10651  to = f.value();
10652  if (inexact) {
10653    goto inexact;
10654  }
10655  return V_EQ;
10656}
10657
10658template <typename To_Policy, typename From1_Policy, typename From2_Policy,
10659          typename Type>
10660inline Result
10661add_mul_float(Type& to, const Type x, const Type y, Rounding_Dir dir) {
10662  if (To_Policy::check_inf_mul_zero
10663      && ((x == 0 && is_inf_float<From2_Policy>(y))
10664          ||
10665          (y == 0 && is_inf_float<From1_Policy>(x)))) {
10666    return assign_nan<To_Policy>(to, V_INF_MUL_ZERO);
10667  }
10668  // FIXME: missing check_inf_add_inf
10669  prepare_inexact<To_Policy>(dir);
10670  if (fpu_direct_rounding(dir)) {
10671    to = multiply_add(x, y, to);
10672  }
10673  else if (fpu_inverse_rounding(dir)) {
10674    to = multiply_add(-x, y, -to);
10675    limit_precision(to);
10676    to = -to;
10677  }
10678  else {
10679    fpu_rounding_control_word_type old
10680      = fpu_save_rounding_direction(round_fpu_dir(dir));
10681    limit_precision(x);
10682    limit_precision(y);
10683    limit_precision(to);
10684    to = multiply_add(x, y, to);
10685    limit_precision(to);
10686    fpu_restore_rounding_direction(old);
10687  }
10688  if (To_Policy::fpu_check_nan_result && is_nan<To_Policy>(to)) {
10689    return V_NAN;
10690  }
10691  return result_relation<To_Policy>(dir);
10692}
10693
10694template <typename To_Policy, typename From1_Policy, typename From2_Policy, typename Type>
10695inline Result
10696sub_mul_float(Type& to, const Type x, const Type y, Rounding_Dir dir) {
10697  if (To_Policy::check_inf_mul_zero
10698      && ((x == 0 && is_inf_float<From2_Policy>(y))
10699          ||
10700          (y == 0 && is_inf_float<From1_Policy>(x)))) {
10701    return assign_nan<To_Policy>(to, V_INF_MUL_ZERO);
10702  }
10703  // FIXME: missing check_inf_add_inf
10704  prepare_inexact<To_Policy>(dir);
10705  if (fpu_direct_rounding(dir)) {
10706    to = multiply_add(x, -y, to);
10707  }
10708  else if (fpu_inverse_rounding(dir)) {
10709    to = multiply_add(x, y, -to);
10710    limit_precision(to);
10711    to = -to;
10712  }
10713  else {
10714    fpu_rounding_control_word_type old
10715      = fpu_save_rounding_direction(round_fpu_dir(dir));
10716    limit_precision(x);
10717    limit_precision(y);
10718    limit_precision(to);
10719    to = multiply_add(x, -y, to);
10720    limit_precision(to);
10721    fpu_restore_rounding_direction(old);
10722  }
10723  if (To_Policy::fpu_check_nan_result && is_nan<To_Policy>(to)) {
10724    return V_NAN;
10725  }
10726  return result_relation<To_Policy>(dir);
10727}
10728
10729template <typename From>
10730inline void
10731assign_mpq_numeric_float(mpq_class& to, const From from) {
10732  to = from;
10733}
10734
10735template <>
10736inline void
10737assign_mpq_numeric_float(mpq_class& to, const long double from) {
10738  to = 0;
10739  if (from == 0.0L) {
10740    return;
10741  }
10742  mpz_class& num = to.get_num();
10743  mpz_class& den = to.get_den();
10744  int exp;
10745  long double n = std::frexp(from, &exp);
10746  bool neg = false;
10747  if (n < 0.0L) {
10748    neg = true;
10749    n = -n;
10750  }
10751  const long double mult = static_cast<long double>(ULONG_MAX) + 1.0L;
10752  const unsigned int bits = sizeof(unsigned long) * CHAR_BIT;
10753  while (true) {
10754    n *= mult;
10755    exp -= bits;
10756    const long double intpart = std::floor(n);
10757    num += static_cast<unsigned long>(intpart);
10758    n -= intpart;
10759    if (n == 0.0L) {
10760      break;
10761    }
10762    num <<= bits;
10763  }
10764  if (exp < 0) {
10765    den <<= -exp;
10766  }
10767  else {
10768    num <<= exp;
10769  }
10770  if (neg) {
10771    to = -to;
10772  }
10773  to.canonicalize();
10774}
10775
10776template <typename Policy, typename Type>
10777inline Result
10778output_float(std::ostream& os, const Type from, const Numeric_Format&,
10779             Rounding_Dir) {
10780  if (from == 0) {
10781    os << "0";
10782  }
10783  else if (is_minf<Policy>(from)) {
10784    os << "-inf";
10785  }
10786  else if (is_pinf<Policy>(from)) {
10787    os << "+inf";
10788  }
10789  else if (is_nan<Policy>(from)) {
10790    os << "nan";
10791  }
10792  else {
10793    mpq_class q;
10794    assign_mpq_numeric_float(q, from);
10795    std::string s = float_mpq_to_string(q);
10796    os << s;
10797  }
10798  return V_EQ;
10799}
10800
10801#if PPL_SUPPORTED_FLOAT
10802PPL_SPECIALIZE_ASSIGN(assign_float_float_exact, float, float)
10803#if PPL_SUPPORTED_DOUBLE
10804PPL_SPECIALIZE_ASSIGN(assign_float_float, float, double)
10805PPL_SPECIALIZE_ASSIGN(assign_float_float_exact, double, float)
10806#endif
10807#if PPL_SUPPORTED_LONG_DOUBLE
10808PPL_SPECIALIZE_ASSIGN(assign_float_float, float, long double)
10809PPL_SPECIALIZE_ASSIGN(assign_float_float_exact, long double, float)
10810#endif
10811#endif
10812
10813#if PPL_SUPPORTED_DOUBLE
10814PPL_SPECIALIZE_ASSIGN(assign_float_float_exact, double, double)
10815#if PPL_SUPPORTED_LONG_DOUBLE
10816PPL_SPECIALIZE_ASSIGN(assign_float_float, double, long double)
10817PPL_SPECIALIZE_ASSIGN(assign_float_float_exact, long double, double)
10818#endif
10819#endif
10820
10821#if PPL_SUPPORTED_LONG_DOUBLE
10822PPL_SPECIALIZE_ASSIGN(assign_float_float_exact, long double, long double)
10823#endif
10824
10825#if PPL_SUPPORTED_FLOAT
10826PPL_SPECIALIZE_CLASSIFY(classify_float, float)
10827PPL_SPECIALIZE_IS_NAN(is_nan_float, float)
10828PPL_SPECIALIZE_IS_MINF(is_minf_float, float)
10829PPL_SPECIALIZE_IS_PINF(is_pinf_float, float)
10830PPL_SPECIALIZE_ASSIGN_SPECIAL(assign_special_float, float)
10831PPL_SPECIALIZE_ASSIGN(assign_float_int, float, char)
10832PPL_SPECIALIZE_ASSIGN(assign_float_int, float, signed char)
10833PPL_SPECIALIZE_ASSIGN(assign_float_int, float, signed short)
10834PPL_SPECIALIZE_ASSIGN(assign_float_int, float, signed int)
10835PPL_SPECIALIZE_ASSIGN(assign_float_int, float, signed long)
10836PPL_SPECIALIZE_ASSIGN(assign_float_int, float, signed long long)
10837PPL_SPECIALIZE_ASSIGN(assign_float_int, float, unsigned char)
10838PPL_SPECIALIZE_ASSIGN(assign_float_int, float, unsigned short)
10839PPL_SPECIALIZE_ASSIGN(assign_float_int, float, unsigned int)
10840PPL_SPECIALIZE_ASSIGN(assign_float_int, float, unsigned long)
10841PPL_SPECIALIZE_ASSIGN(assign_float_int, float, unsigned long long)
10842PPL_SPECIALIZE_ASSIGN(assign_float_mpz, float, mpz_class)
10843PPL_SPECIALIZE_ASSIGN(assign_float_mpq, float, mpq_class)
10844PPL_SPECIALIZE_COPY(copy_generic, float)
10845PPL_SPECIALIZE_IS_INT(is_int_float, float)
10846PPL_SPECIALIZE_FLOOR(floor_float, float, float)
10847PPL_SPECIALIZE_CEIL(ceil_float, float, float)
10848PPL_SPECIALIZE_TRUNC(trunc_float, float, float)
10849PPL_SPECIALIZE_NEG(neg_float, float, float)
10850PPL_SPECIALIZE_ABS(abs_float, float, float)
10851PPL_SPECIALIZE_ADD(add_float, float, float, float)
10852PPL_SPECIALIZE_SUB(sub_float, float, float, float)
10853PPL_SPECIALIZE_MUL(mul_float, float, float, float)
10854PPL_SPECIALIZE_DIV(div_float, float, float, float)
10855PPL_SPECIALIZE_REM(rem_float, float, float, float)
10856PPL_SPECIALIZE_ADD_2EXP(add_2exp_float, float, float)
10857PPL_SPECIALIZE_SUB_2EXP(sub_2exp_float, float, float)
10858PPL_SPECIALIZE_MUL_2EXP(mul_2exp_float, float, float)
10859PPL_SPECIALIZE_DIV_2EXP(div_2exp_float, float, float)
10860PPL_SPECIALIZE_SMOD_2EXP(smod_2exp_float, float, float)
10861PPL_SPECIALIZE_UMOD_2EXP(umod_2exp_float, float, float)
10862PPL_SPECIALIZE_SQRT(sqrt_float, float, float)
10863PPL_SPECIALIZE_GCD(gcd_exact, float, float, float)
10864PPL_SPECIALIZE_GCDEXT(gcdext_exact, float, float, float, float, float)
10865PPL_SPECIALIZE_LCM(lcm_gcd_exact, float, float, float)
10866PPL_SPECIALIZE_SGN(sgn_float, float)
10867PPL_SPECIALIZE_CMP(cmp_float, float, float)
10868PPL_SPECIALIZE_ADD_MUL(add_mul_float, float, float, float)
10869PPL_SPECIALIZE_SUB_MUL(sub_mul_float, float, float, float)
10870PPL_SPECIALIZE_INPUT(input_generic, float)
10871PPL_SPECIALIZE_OUTPUT(output_float, float)
10872#endif
10873
10874#if PPL_SUPPORTED_DOUBLE
10875PPL_SPECIALIZE_CLASSIFY(classify_float, double)
10876PPL_SPECIALIZE_IS_NAN(is_nan_float, double)
10877PPL_SPECIALIZE_IS_MINF(is_minf_float, double)
10878PPL_SPECIALIZE_IS_PINF(is_pinf_float, double)
10879PPL_SPECIALIZE_ASSIGN_SPECIAL(assign_special_float, double)
10880PPL_SPECIALIZE_ASSIGN(assign_float_int, double, char)
10881PPL_SPECIALIZE_ASSIGN(assign_float_int, double, signed char)
10882PPL_SPECIALIZE_ASSIGN(assign_float_int, double, signed short)
10883PPL_SPECIALIZE_ASSIGN(assign_float_int, double, signed int)
10884PPL_SPECIALIZE_ASSIGN(assign_float_int, double, signed long)
10885PPL_SPECIALIZE_ASSIGN(assign_float_int, double, signed long long)
10886PPL_SPECIALIZE_ASSIGN(assign_float_int, double, unsigned char)
10887PPL_SPECIALIZE_ASSIGN(assign_float_int, double, unsigned short)
10888PPL_SPECIALIZE_ASSIGN(assign_float_int, double, unsigned int)
10889PPL_SPECIALIZE_ASSIGN(assign_float_int, double, unsigned long)
10890PPL_SPECIALIZE_ASSIGN(assign_float_int, double, unsigned long long)
10891PPL_SPECIALIZE_ASSIGN(assign_float_mpz, double, mpz_class)
10892PPL_SPECIALIZE_ASSIGN(assign_float_mpq, double, mpq_class)
10893PPL_SPECIALIZE_COPY(copy_generic, double)
10894PPL_SPECIALIZE_IS_INT(is_int_float, double)
10895PPL_SPECIALIZE_FLOOR(floor_float, double, double)
10896PPL_SPECIALIZE_CEIL(ceil_float, double, double)
10897PPL_SPECIALIZE_TRUNC(trunc_float, double, double)
10898PPL_SPECIALIZE_NEG(neg_float, double, double)
10899PPL_SPECIALIZE_ABS(abs_float, double, double)
10900PPL_SPECIALIZE_ADD(add_float, double, double, double)
10901PPL_SPECIALIZE_SUB(sub_float, double, double, double)
10902PPL_SPECIALIZE_MUL(mul_float, double, double, double)
10903PPL_SPECIALIZE_DIV(div_float, double, double, double)
10904PPL_SPECIALIZE_REM(rem_float, double, double, double)
10905PPL_SPECIALIZE_ADD_2EXP(add_2exp_float, double, double)
10906PPL_SPECIALIZE_SUB_2EXP(sub_2exp_float, double, double)
10907PPL_SPECIALIZE_MUL_2EXP(mul_2exp_float, double, double)
10908PPL_SPECIALIZE_DIV_2EXP(div_2exp_float, double, double)
10909PPL_SPECIALIZE_SMOD_2EXP(smod_2exp_float, double, double)
10910PPL_SPECIALIZE_UMOD_2EXP(umod_2exp_float, double, double)
10911PPL_SPECIALIZE_SQRT(sqrt_float, double, double)
10912PPL_SPECIALIZE_GCD(gcd_exact, double, double, double)
10913PPL_SPECIALIZE_GCDEXT(gcdext_exact, double, double, double, double, double)
10914PPL_SPECIALIZE_LCM(lcm_gcd_exact, double, double, double)
10915PPL_SPECIALIZE_SGN(sgn_float, double)
10916PPL_SPECIALIZE_CMP(cmp_float, double, double)
10917PPL_SPECIALIZE_ADD_MUL(add_mul_float, double, double, double)
10918PPL_SPECIALIZE_SUB_MUL(sub_mul_float, double, double, double)
10919PPL_SPECIALIZE_INPUT(input_generic, double)
10920PPL_SPECIALIZE_OUTPUT(output_float, double)
10921#endif
10922
10923#if PPL_SUPPORTED_LONG_DOUBLE
10924PPL_SPECIALIZE_CLASSIFY(classify_float, long double)
10925PPL_SPECIALIZE_IS_NAN(is_nan_float, long double)
10926PPL_SPECIALIZE_IS_MINF(is_minf_float, long double)
10927PPL_SPECIALIZE_IS_PINF(is_pinf_float, long double)
10928PPL_SPECIALIZE_ASSIGN_SPECIAL(assign_special_float, long double)
10929PPL_SPECIALIZE_ASSIGN(assign_float_int, long double, char)
10930PPL_SPECIALIZE_ASSIGN(assign_float_int, long double, signed char)
10931PPL_SPECIALIZE_ASSIGN(assign_float_int, long double, signed short)
10932PPL_SPECIALIZE_ASSIGN(assign_float_int, long double, signed int)
10933PPL_SPECIALIZE_ASSIGN(assign_float_int, long double, signed long)
10934PPL_SPECIALIZE_ASSIGN(assign_float_int, long double, signed long long)
10935PPL_SPECIALIZE_ASSIGN(assign_float_int, long double, unsigned char)
10936PPL_SPECIALIZE_ASSIGN(assign_float_int, long double, unsigned short)
10937PPL_SPECIALIZE_ASSIGN(assign_float_int, long double, unsigned int)
10938PPL_SPECIALIZE_ASSIGN(assign_float_int, long double, unsigned long)
10939PPL_SPECIALIZE_ASSIGN(assign_float_int, long double, unsigned long long)
10940PPL_SPECIALIZE_ASSIGN(assign_float_mpz, long double, mpz_class)
10941PPL_SPECIALIZE_ASSIGN(assign_float_mpq, long double, mpq_class)
10942PPL_SPECIALIZE_COPY(copy_generic, long double)
10943PPL_SPECIALIZE_IS_INT(is_int_float, long double)
10944PPL_SPECIALIZE_FLOOR(floor_float, long double, long double)
10945PPL_SPECIALIZE_CEIL(ceil_float, long double, long double)
10946PPL_SPECIALIZE_TRUNC(trunc_float, long double, long double)
10947PPL_SPECIALIZE_NEG(neg_float, long double, long double)
10948PPL_SPECIALIZE_ABS(abs_float, long double, long double)
10949PPL_SPECIALIZE_ADD(add_float, long double, long double, long double)
10950PPL_SPECIALIZE_SUB(sub_float, long double, long double, long double)
10951PPL_SPECIALIZE_MUL(mul_float, long double, long double, long double)
10952PPL_SPECIALIZE_DIV(div_float, long double, long double, long double)
10953PPL_SPECIALIZE_REM(rem_float, long double, long double, long double)
10954PPL_SPECIALIZE_ADD_2EXP(add_2exp_float, long double, long double)
10955PPL_SPECIALIZE_SUB_2EXP(sub_2exp_float, long double, long double)
10956PPL_SPECIALIZE_MUL_2EXP(mul_2exp_float, long double, long double)
10957PPL_SPECIALIZE_DIV_2EXP(div_2exp_float, long double, long double)
10958PPL_SPECIALIZE_SMOD_2EXP(smod_2exp_float, long double, long double)
10959PPL_SPECIALIZE_UMOD_2EXP(umod_2exp_float, long double, long double)
10960PPL_SPECIALIZE_SQRT(sqrt_float, long double, long double)
10961PPL_SPECIALIZE_GCD(gcd_exact, long double, long double, long double)
10962PPL_SPECIALIZE_GCDEXT(gcdext_exact, long double, long double, long double,
10963                  long double, long double)
10964PPL_SPECIALIZE_LCM(lcm_gcd_exact, long double, long double, long double)
10965PPL_SPECIALIZE_SGN(sgn_float, long double)
10966PPL_SPECIALIZE_CMP(cmp_float, long double, long double)
10967PPL_SPECIALIZE_ADD_MUL(add_mul_float, long double, long double, long double)
10968PPL_SPECIALIZE_SUB_MUL(sub_mul_float, long double, long double, long double)
10969PPL_SPECIALIZE_INPUT(input_generic, long double)
10970PPL_SPECIALIZE_OUTPUT(output_float, long double)
10971#endif
10972
10973} // namespace Checked
10974
10975} // namespace Parma_Polyhedra_Library
10976
10977/* Automatically generated from PPL source file ../src/checked_mpz_inlines.hh line 1. */
10978/* Specialized "checked" functions for GMP's mpz_class numbers.
10979*/
10980
10981
10982#include <sstream>
10983
10984namespace Parma_Polyhedra_Library {
10985
10986namespace Checked {
10987
10988template <typename Policy>
10989inline Result
10990round_lt_mpz(mpz_class& to, Rounding_Dir dir) {
10991  if (round_down(dir)) {
10992    --to;
10993    return V_GT;
10994  }
10995  return V_LT;
10996}
10997
10998template <typename Policy>
10999inline Result
11000round_gt_mpz(mpz_class& to, Rounding_Dir dir) {
11001  if (round_up(dir)) {
11002    ++to;
11003    return V_LT;
11004  }
11005  return V_GT;
11006}
11007
11008#if __cplusplus >= 201103L
11009//! Type of the _mp_size field of GMP's __mpz_struct.
11010typedef decltype(__mpz_struct()._mp_size) mp_size_field_t;
11011#elif PPL_HAVE_TYPEOF
11012//! Type of the _mp_size field of GMP's __mpz_struct.
11013typedef typeof(__mpz_struct()._mp_size) mp_size_field_t;
11014#else
11015//! This is assumed to be the type of the _mp_size field of GMP's __mpz_struct.
11016typedef int mp_size_field_t;
11017#endif
11018
11019inline mp_size_field_t
11020get_mp_size(const mpz_class &v) {
11021  return v.get_mpz_t()->_mp_size;
11022}
11023
11024inline void
11025set_mp_size(mpz_class &v, mp_size_field_t size) {
11026  v.get_mpz_t()->_mp_size = size;
11027}
11028
11029template <typename Policy>
11030inline Result
11031classify_mpz(const mpz_class& v, bool nan, bool inf, bool sign) {
11032  if (Policy::has_nan || Policy::has_infinity) {
11033    mp_size_field_t s = get_mp_size(v);
11034    if (Policy::has_nan
11035        && (nan || sign)
11036        && s == C_Integer<mp_size_field_t>::min + 1) {
11037      return V_NAN;
11038    }
11039    if (!inf && !sign) {
11040      return V_LGE;
11041    }
11042    if (Policy::has_infinity) {
11043      if (s == C_Integer<mp_size_field_t>::min) {
11044        return inf ? V_EQ_MINUS_INFINITY : V_LT;
11045      }
11046      if (s == C_Integer<mp_size_field_t>::max) {
11047        return inf ? V_EQ_PLUS_INFINITY : V_GT;
11048      }
11049    }
11050  }
11051  if (sign) {
11052    return static_cast<Result>(sgn<Policy>(v));
11053  }
11054  return V_LGE;
11055}
11056
11057PPL_SPECIALIZE_CLASSIFY(classify_mpz, mpz_class)
11058
11059template <typename Policy>
11060inline bool
11061is_nan_mpz(const mpz_class& v) {
11062  return Policy::has_nan
11063    && get_mp_size(v) == C_Integer<mp_size_field_t>::min + 1;
11064}
11065
11066PPL_SPECIALIZE_IS_NAN(is_nan_mpz, mpz_class)
11067
11068template <typename Policy>
11069inline bool
11070is_minf_mpz(const mpz_class& v) {
11071  return Policy::has_infinity
11072    && get_mp_size(v) == C_Integer<mp_size_field_t>::min;
11073}
11074
11075PPL_SPECIALIZE_IS_MINF(is_minf_mpz, mpz_class)
11076
11077template <typename Policy>
11078inline bool
11079is_pinf_mpz(const mpz_class& v) {
11080  return Policy::has_infinity
11081    && get_mp_size(v) == C_Integer<mp_size_field_t>::max;
11082}
11083
11084PPL_SPECIALIZE_IS_PINF(is_pinf_mpz, mpz_class)
11085
11086template <typename Policy>
11087inline bool
11088is_int_mpz(const mpz_class& v) {
11089  return !is_nan<Policy>(v);
11090}
11091
11092PPL_SPECIALIZE_IS_INT(is_int_mpz, mpz_class)
11093
11094template <typename Policy>
11095inline Result
11096assign_special_mpz(mpz_class& v, Result_Class c, Rounding_Dir) {
11097  switch (c) {
11098  case VC_NAN:
11099    if (Policy::has_nan) {
11100      set_mp_size(v, C_Integer<mp_size_field_t>::min + 1);
11101    }
11102    return V_NAN;
11103  case VC_MINUS_INFINITY:
11104    if (Policy::has_infinity) {
11105      set_mp_size(v, C_Integer<mp_size_field_t>::min);
11106      return V_EQ_MINUS_INFINITY;
11107    }
11108    return V_EQ_MINUS_INFINITY | V_UNREPRESENTABLE;
11109  case VC_PLUS_INFINITY:
11110    if (Policy::has_infinity) {
11111      set_mp_size(v, C_Integer<mp_size_field_t>::max);
11112      return V_EQ_PLUS_INFINITY;
11113    }
11114    return V_EQ_PLUS_INFINITY | V_UNREPRESENTABLE;
11115  default:
11116    PPL_UNREACHABLE;
11117    return V_NAN;
11118  }
11119}
11120
11121PPL_SPECIALIZE_ASSIGN_SPECIAL(assign_special_mpz, mpz_class)
11122
11123template <typename To_Policy, typename From_Policy>
11124inline void
11125copy_mpz(mpz_class& to, const mpz_class& from) {
11126  if (is_nan_mpz<From_Policy>(from)) {
11127    PPL_ASSERT(To_Policy::has_nan);
11128  }
11129  else if (is_minf_mpz<From_Policy>(from) || is_pinf_mpz<From_Policy>(from)) {
11130    PPL_ASSERT(To_Policy::has_infinity);
11131  }
11132  else {
11133    to = from;
11134    return;
11135  }
11136  set_mp_size(to, get_mp_size(from));
11137}
11138
11139PPL_SPECIALIZE_COPY(copy_mpz, mpz_class)
11140
11141template <typename To_Policy, typename From_Policy, typename From>
11142inline Result
11143construct_mpz_base(mpz_class& to, const From from, Rounding_Dir) {
11144    new(&to) mpz_class(from);
11145    return V_EQ;
11146}
11147
11148PPL_SPECIALIZE_CONSTRUCT(construct_mpz_base, mpz_class, char)
11149PPL_SPECIALIZE_CONSTRUCT(construct_mpz_base, mpz_class, signed char)
11150PPL_SPECIALIZE_CONSTRUCT(construct_mpz_base, mpz_class, signed short)
11151PPL_SPECIALIZE_CONSTRUCT(construct_mpz_base, mpz_class, signed int)
11152PPL_SPECIALIZE_CONSTRUCT(construct_mpz_base, mpz_class, signed long)
11153PPL_SPECIALIZE_CONSTRUCT(construct_mpz_base, mpz_class, unsigned char)
11154PPL_SPECIALIZE_CONSTRUCT(construct_mpz_base, mpz_class, unsigned short)
11155PPL_SPECIALIZE_CONSTRUCT(construct_mpz_base, mpz_class, unsigned int)
11156PPL_SPECIALIZE_CONSTRUCT(construct_mpz_base, mpz_class, unsigned long)
11157
11158template <typename To_Policy, typename From_Policy, typename From>
11159inline Result
11160construct_mpz_float(mpz_class& to, const From& from, Rounding_Dir dir) {
11161  if (is_nan<From_Policy>(from)) {
11162    return construct_special<To_Policy>(to, VC_NAN, ROUND_IGNORE);
11163  }
11164  else if (is_minf<From_Policy>(from)) {
11165    return construct_special<To_Policy>(to, VC_MINUS_INFINITY, dir);
11166  }
11167  else if (is_pinf<From_Policy>(from)) {
11168    return construct_special<To_Policy>(to, VC_PLUS_INFINITY, dir);
11169  }
11170  if (round_not_requested(dir)) {
11171    new(&to) mpz_class(from);
11172    return V_LGE;
11173  }
11174  From n = rint(from);
11175  new(&to) mpz_class(n);
11176  if (from == n) {
11177    return V_EQ;
11178  }
11179  if (from < 0) {
11180    return round_lt_mpz<To_Policy>(to, dir);
11181  }
11182  else {
11183    return round_gt_mpz<To_Policy>(to, dir);
11184  }
11185}
11186
11187PPL_SPECIALIZE_CONSTRUCT(construct_mpz_float, mpz_class, float)
11188PPL_SPECIALIZE_CONSTRUCT(construct_mpz_float, mpz_class, double)
11189
11190PPL_SPECIALIZE_ASSIGN(assign_exact, mpz_class, mpz_class)
11191PPL_SPECIALIZE_ASSIGN(assign_exact, mpz_class, char)
11192PPL_SPECIALIZE_ASSIGN(assign_exact, mpz_class, signed char)
11193PPL_SPECIALIZE_ASSIGN(assign_exact, mpz_class, signed short)
11194PPL_SPECIALIZE_ASSIGN(assign_exact, mpz_class, signed int)
11195PPL_SPECIALIZE_ASSIGN(assign_exact, mpz_class, signed long)
11196PPL_SPECIALIZE_ASSIGN(assign_exact, mpz_class, unsigned char)
11197PPL_SPECIALIZE_ASSIGN(assign_exact, mpz_class, unsigned short)
11198PPL_SPECIALIZE_ASSIGN(assign_exact, mpz_class, unsigned int)
11199PPL_SPECIALIZE_ASSIGN(assign_exact, mpz_class, unsigned long)
11200
11201template <typename To_Policy, typename From_Policy, typename From>
11202inline Result
11203assign_mpz_signed_int(mpz_class& to, const From from, Rounding_Dir) {
11204  if (sizeof(From) <= sizeof(signed long)) {
11205    to = static_cast<signed long>(from);
11206  }
11207  else {
11208    mpz_ptr m = to.get_mpz_t();
11209    if (from >= 0) {
11210      mpz_import(m, 1, 1, sizeof(From), 0, 0, &from);
11211    }
11212    else {
11213      From n = -from;
11214      mpz_import(m, 1, 1, sizeof(From), 0, 0, &n);
11215      mpz_neg(m, m);
11216    }
11217  }
11218  return V_EQ;
11219}
11220
11221PPL_SPECIALIZE_ASSIGN(assign_mpz_signed_int, mpz_class, signed long long)
11222
11223template <typename To_Policy, typename From_Policy, typename From>
11224inline Result
11225assign_mpz_unsigned_int(mpz_class& to, const From from, Rounding_Dir) {
11226  if (sizeof(From) <= sizeof(unsigned long)) {
11227    to = static_cast<unsigned long>(from);
11228  }
11229  else {
11230    mpz_import(to.get_mpz_t(), 1, 1, sizeof(From), 0, 0, &from);
11231  }
11232  return V_EQ;
11233}
11234
11235PPL_SPECIALIZE_ASSIGN(assign_mpz_unsigned_int, mpz_class, unsigned long long)
11236
11237template <typename To_Policy, typename From_Policy, typename From>
11238inline Result
11239assign_mpz_float(mpz_class& to, const From from, Rounding_Dir dir) {
11240  if (is_nan<From_Policy>(from)) {
11241    return assign_special<To_Policy>(to, VC_NAN, ROUND_IGNORE);
11242  }
11243  else if (is_minf<From_Policy>(from)) {
11244    return assign_special<To_Policy>(to, VC_MINUS_INFINITY, dir);
11245  }
11246  else if (is_pinf<From_Policy>(from)) {
11247    return assign_special<To_Policy>(to, VC_PLUS_INFINITY, dir);
11248  }
11249  if (round_not_requested(dir)) {
11250    to = from;
11251    return V_LGE;
11252  }
11253  From i_from = rint(from);
11254  to = i_from;
11255  if (from == i_from) {
11256    return V_EQ;
11257  }
11258  if (round_direct(ROUND_UP)) {
11259    return round_lt_mpz<To_Policy>(to, dir);
11260  }
11261  if (round_direct(ROUND_DOWN)) {
11262    return round_gt_mpz<To_Policy>(to, dir);
11263  }
11264  if (from < i_from) {
11265    return round_lt_mpz<To_Policy>(to, dir);
11266  }
11267  if (from > i_from) {
11268    return round_gt_mpz<To_Policy>(to, dir);
11269  }
11270  PPL_UNREACHABLE;
11271  return V_NAN;
11272}
11273
11274PPL_SPECIALIZE_ASSIGN(assign_mpz_float, mpz_class, float)
11275PPL_SPECIALIZE_ASSIGN(assign_mpz_float, mpz_class, double)
11276
11277template <typename To_Policy, typename From_Policy, typename From>
11278inline Result
11279assign_mpz_long_double(mpz_class& to, const From& from, Rounding_Dir dir) {
11280  if (is_nan<From_Policy>(from)) {
11281    return assign_special<To_Policy>(to, VC_NAN, ROUND_IGNORE);
11282  }
11283  else if (is_minf<From_Policy>(from)) {
11284    return assign_special<To_Policy>(to, VC_MINUS_INFINITY, dir);
11285  }
11286  else if (is_pinf<From_Policy>(from)) {
11287    return assign_special<To_Policy>(to, VC_PLUS_INFINITY, dir);
11288  }
11289  // FIXME: this is an incredibly inefficient implementation!
11290  std::stringstream ss;
11291  output<From_Policy>(ss, from, Numeric_Format(), dir);
11292  PPL_DIRTY_TEMP(mpq_class, tmp);
11293#ifndef NDEBUG
11294  Result r =
11295#endif
11296    input_mpq(tmp, ss);
11297  PPL_ASSERT(r == V_EQ);
11298  return assign<To_Policy, From_Policy>(to, tmp, dir);
11299}
11300
11301PPL_SPECIALIZE_ASSIGN(assign_mpz_long_double, mpz_class, long double)
11302
11303template <typename To_Policy, typename From_Policy>
11304inline Result
11305assign_mpz_mpq(mpz_class& to, const mpq_class& from, Rounding_Dir dir) {
11306  if (round_not_needed(dir)) {
11307    to = from.get_num();
11308    return V_LGE;
11309  }
11310  if (round_ignore(dir)) {
11311    to = from;
11312    return V_LGE;
11313  }
11314  const mpz_srcptr n = from.get_num().get_mpz_t();
11315  const mpz_srcptr d = from.get_den().get_mpz_t();
11316  if (round_down(dir)) {
11317    mpz_fdiv_q(to.get_mpz_t(), n, d);
11318    if (round_strict_relation(dir)) {
11319      return (mpz_divisible_p(n, d) != 0) ? V_EQ : V_GT;
11320    }
11321    return V_GE;
11322  }
11323  else {
11324    PPL_ASSERT(round_up(dir));
11325    mpz_cdiv_q(to.get_mpz_t(), n, d);
11326    if (round_strict_relation(dir)) {
11327      return (mpz_divisible_p(n, d) != 0) ? V_EQ : V_LT;
11328    }
11329    return V_LE;
11330  }
11331}
11332
11333PPL_SPECIALIZE_ASSIGN(assign_mpz_mpq, mpz_class, mpq_class)
11334
11335PPL_SPECIALIZE_FLOOR(assign_exact, mpz_class, mpz_class)
11336PPL_SPECIALIZE_CEIL(assign_exact, mpz_class, mpz_class)
11337PPL_SPECIALIZE_TRUNC(assign_exact, mpz_class, mpz_class)
11338
11339template <typename To_Policy, typename From_Policy>
11340inline Result
11341neg_mpz(mpz_class& to, const mpz_class& from, Rounding_Dir) {
11342  mpz_neg(to.get_mpz_t(), from.get_mpz_t());
11343  return V_EQ;
11344}
11345
11346PPL_SPECIALIZE_NEG(neg_mpz, mpz_class, mpz_class)
11347
11348template <typename To_Policy, typename From1_Policy, typename From2_Policy>
11349inline Result
11350add_mpz(mpz_class& to, const mpz_class& x, const mpz_class& y, Rounding_Dir) {
11351  to = x + y;
11352  return V_EQ;
11353}
11354
11355PPL_SPECIALIZE_ADD(add_mpz, mpz_class, mpz_class, mpz_class)
11356
11357template <typename To_Policy, typename From1_Policy, typename From2_Policy>
11358inline Result
11359sub_mpz(mpz_class& to, const mpz_class& x, const mpz_class& y, Rounding_Dir) {
11360  to = x - y;
11361  return V_EQ;
11362}
11363
11364PPL_SPECIALIZE_SUB(sub_mpz, mpz_class, mpz_class, mpz_class)
11365
11366template <typename To_Policy, typename From1_Policy, typename From2_Policy>
11367inline Result
11368mul_mpz(mpz_class& to, const mpz_class& x, const mpz_class& y, Rounding_Dir) {
11369  to = x * y;
11370  return V_EQ;
11371}
11372
11373PPL_SPECIALIZE_MUL(mul_mpz, mpz_class, mpz_class, mpz_class)
11374
11375template <typename To_Policy, typename From1_Policy, typename From2_Policy>
11376inline Result
11377div_mpz(mpz_class& to, const mpz_class& x, const mpz_class& y,
11378        Rounding_Dir dir) {
11379  if (CHECK_P(To_Policy::check_div_zero, ::sgn(y) == 0)) {
11380    return assign_nan<To_Policy>(to, V_DIV_ZERO);
11381  }
11382  const mpz_srcptr n = x.get_mpz_t();
11383  const mpz_srcptr d = y.get_mpz_t();
11384  if (round_not_needed(dir)) {
11385    mpz_divexact(to.get_mpz_t(), n, d);
11386    return V_LGE;
11387  }
11388  if (round_ignore(dir)) {
11389    mpz_cdiv_q(to.get_mpz_t(), n, d);
11390    return V_LE;
11391  }
11392  if (round_down(dir)) {
11393    mpz_fdiv_q(to.get_mpz_t(), n, d);
11394    if (round_strict_relation(dir)) {
11395      return (mpz_divisible_p(n, d) != 0) ? V_EQ : V_GT;
11396    }
11397    return V_GE;
11398  }
11399  else {
11400    PPL_ASSERT(round_up(dir));
11401    mpz_cdiv_q(to.get_mpz_t(), n, d);
11402    if (round_strict_relation(dir)) {
11403      return (mpz_divisible_p(n, d) != 0) ? V_EQ : V_LT;
11404    }
11405    return V_LE;
11406  }
11407}
11408
11409PPL_SPECIALIZE_DIV(div_mpz, mpz_class, mpz_class, mpz_class)
11410
11411template <typename To_Policy, typename From1_Policy, typename From2_Policy>
11412inline Result
11413idiv_mpz(mpz_class& to, const mpz_class& x, const mpz_class& y,
11414        Rounding_Dir) {
11415  if (CHECK_P(To_Policy::check_div_zero, ::sgn(y) == 0)) {
11416    return assign_nan<To_Policy>(to, V_DIV_ZERO);
11417  }
11418  mpz_srcptr n = x.get_mpz_t();
11419  mpz_srcptr d = y.get_mpz_t();
11420  mpz_tdiv_q(to.get_mpz_t(), n, d);
11421  return V_EQ;
11422}
11423
11424PPL_SPECIALIZE_IDIV(idiv_mpz, mpz_class, mpz_class, mpz_class)
11425
11426template <typename To_Policy, typename From1_Policy, typename From2_Policy>
11427inline Result
11428rem_mpz(mpz_class& to, const mpz_class& x, const mpz_class& y, Rounding_Dir) {
11429  if (CHECK_P(To_Policy::check_div_zero, ::sgn(y) == 0)) {
11430    return assign_nan<To_Policy>(to, V_MOD_ZERO);
11431  }
11432  to = x % y;
11433  return V_EQ;
11434}
11435
11436PPL_SPECIALIZE_REM(rem_mpz, mpz_class, mpz_class, mpz_class)
11437
11438template <typename To_Policy, typename From_Policy>
11439inline Result
11440add_2exp_mpz(mpz_class& to, const mpz_class& x, unsigned int exp,
11441             Rounding_Dir) {
11442  PPL_DIRTY_TEMP(mpz_class, v);
11443  v = 1;
11444  mpz_mul_2exp(v.get_mpz_t(), v.get_mpz_t(), exp);
11445  to = x + v;
11446  return V_EQ;
11447}
11448
11449PPL_SPECIALIZE_ADD_2EXP(add_2exp_mpz, mpz_class, mpz_class)
11450
11451template <typename To_Policy, typename From_Policy>
11452inline Result
11453sub_2exp_mpz(mpz_class& to, const mpz_class& x, unsigned int exp,
11454             Rounding_Dir) {
11455  PPL_DIRTY_TEMP(mpz_class, v);
11456  v = 1;
11457  mpz_mul_2exp(v.get_mpz_t(), v.get_mpz_t(), exp);
11458  to = x - v;
11459  return V_EQ;
11460}
11461
11462PPL_SPECIALIZE_SUB_2EXP(sub_2exp_mpz, mpz_class, mpz_class)
11463
11464template <typename To_Policy, typename From_Policy>
11465inline Result
11466mul_2exp_mpz(mpz_class& to, const mpz_class& x, unsigned int exp,
11467             Rounding_Dir) {
11468  mpz_mul_2exp(to.get_mpz_t(), x.get_mpz_t(), exp);
11469  return V_EQ;
11470}
11471
11472PPL_SPECIALIZE_MUL_2EXP(mul_2exp_mpz, mpz_class, mpz_class)
11473
11474template <typename To_Policy, typename From_Policy>
11475inline Result
11476div_2exp_mpz(mpz_class& to, const mpz_class& x, unsigned int exp,
11477             Rounding_Dir dir) {
11478  const mpz_srcptr n = x.get_mpz_t();
11479  if (round_not_requested(dir)) {
11480    mpz_tdiv_q_2exp(to.get_mpz_t(), x.get_mpz_t(), exp);
11481    return V_LGE;
11482  }
11483  if (round_down(dir)) {
11484    mpz_fdiv_q_2exp(to.get_mpz_t(), n, exp);
11485    if (round_strict_relation(dir)) {
11486      return (mpz_divisible_2exp_p(n, exp) != 0) ? V_EQ : V_GT;
11487    }
11488    return V_GE;
11489  }
11490  else {
11491    PPL_ASSERT(round_up(dir));
11492    mpz_cdiv_q_2exp(to.get_mpz_t(), n, exp);
11493    if (round_strict_relation(dir)) {
11494      return (mpz_divisible_2exp_p(n, exp) != 0) ? V_EQ : V_LT;
11495    }
11496    return V_LE;
11497  }
11498}
11499
11500PPL_SPECIALIZE_DIV_2EXP(div_2exp_mpz, mpz_class, mpz_class)
11501
11502template <typename To_Policy, typename From_Policy>
11503inline Result
11504smod_2exp_mpz(mpz_class& to, const mpz_class& x, unsigned int exp,
11505              Rounding_Dir) {
11506  if (mpz_tstbit(x.get_mpz_t(), exp - 1) != 0) {
11507    mpz_cdiv_r_2exp(to.get_mpz_t(), x.get_mpz_t(), exp);
11508  }
11509  else {
11510    mpz_fdiv_r_2exp(to.get_mpz_t(), x.get_mpz_t(), exp);
11511  }
11512  return V_EQ;
11513}
11514
11515PPL_SPECIALIZE_SMOD_2EXP(smod_2exp_mpz, mpz_class, mpz_class)
11516
11517template <typename To_Policy, typename From_Policy>
11518inline Result
11519umod_2exp_mpz(mpz_class& to, const mpz_class& x, unsigned int exp,
11520              Rounding_Dir) {
11521  mpz_fdiv_r_2exp(to.get_mpz_t(), x.get_mpz_t(), exp);
11522  return V_EQ;
11523}
11524
11525PPL_SPECIALIZE_UMOD_2EXP(umod_2exp_mpz, mpz_class, mpz_class)
11526
11527template <typename To_Policy, typename From_Policy>
11528inline Result
11529abs_mpz(mpz_class& to, const mpz_class& from, Rounding_Dir) {
11530  to = abs(from);
11531  return V_EQ;
11532}
11533
11534PPL_SPECIALIZE_ABS(abs_mpz, mpz_class, mpz_class)
11535
11536template <typename To_Policy, typename From1_Policy, typename From2_Policy>
11537inline Result
11538add_mul_mpz(mpz_class& to, const mpz_class& x, const mpz_class& y,
11539            Rounding_Dir) {
11540  mpz_addmul(to.get_mpz_t(), x.get_mpz_t(), y.get_mpz_t());
11541  return V_EQ;
11542}
11543
11544PPL_SPECIALIZE_ADD_MUL(add_mul_mpz, mpz_class, mpz_class, mpz_class)
11545
11546template <typename To_Policy, typename From1_Policy, typename From2_Policy>
11547inline Result
11548sub_mul_mpz(mpz_class& to, const mpz_class& x, const mpz_class& y,
11549            Rounding_Dir) {
11550  mpz_submul(to.get_mpz_t(), x.get_mpz_t(), y.get_mpz_t());
11551  return V_EQ;
11552}
11553
11554PPL_SPECIALIZE_SUB_MUL(sub_mul_mpz, mpz_class, mpz_class, mpz_class)
11555
11556template <typename To_Policy, typename From1_Policy, typename From2_Policy>
11557inline Result
11558gcd_mpz(mpz_class& to, const mpz_class& x, const mpz_class& y, Rounding_Dir) {
11559  mpz_gcd(to.get_mpz_t(), x.get_mpz_t(), y.get_mpz_t());
11560  return V_EQ;
11561}
11562
11563PPL_SPECIALIZE_GCD(gcd_mpz, mpz_class, mpz_class, mpz_class)
11564
11565template <typename To_Policy, typename From1_Policy, typename From2_Policy>
11566inline Result
11567gcdext_mpz(mpz_class& to, mpz_class& s, mpz_class& t,
11568           const mpz_class& x, const mpz_class& y,
11569           Rounding_Dir) {
11570  mpz_gcdext(to.get_mpz_t(), s.get_mpz_t(), t.get_mpz_t(),
11571             x.get_mpz_t(), y.get_mpz_t());
11572  return V_EQ;
11573}
11574
11575PPL_SPECIALIZE_GCDEXT(gcdext_mpz, mpz_class, mpz_class, mpz_class, mpz_class, mpz_class)
11576
11577template <typename To_Policy, typename From1_Policy, typename From2_Policy>
11578inline Result
11579lcm_mpz(mpz_class& to, const mpz_class& x, const mpz_class& y, Rounding_Dir) {
11580  mpz_lcm(to.get_mpz_t(), x.get_mpz_t(), y.get_mpz_t());
11581  return V_EQ;
11582}
11583
11584PPL_SPECIALIZE_LCM(lcm_mpz, mpz_class, mpz_class, mpz_class)
11585
11586template <typename To_Policy, typename From_Policy>
11587inline Result
11588sqrt_mpz(mpz_class& to, const mpz_class& from, Rounding_Dir dir) {
11589  if (CHECK_P(To_Policy::check_sqrt_neg, from < 0)) {
11590    return assign_nan<To_Policy>(to, V_SQRT_NEG);
11591  }
11592  if (round_not_requested(dir)) {
11593    to = sqrt(from);
11594    return V_GE;
11595  }
11596  PPL_DIRTY_TEMP(mpz_class, r);
11597  mpz_sqrtrem(to.get_mpz_t(), r.get_mpz_t(), from.get_mpz_t());
11598  if (r == 0) {
11599    return V_EQ;
11600  }
11601  return round_gt_mpz<To_Policy>(to, dir);
11602}
11603
11604PPL_SPECIALIZE_SQRT(sqrt_mpz, mpz_class, mpz_class)
11605
11606template <typename Policy, typename Type>
11607inline Result_Relation
11608sgn_mp(const Type& x) {
11609  const int sign = ::sgn(x);
11610  return (sign > 0) ? VR_GT : ((sign < 0) ? VR_LT : VR_EQ);
11611}
11612
11613PPL_SPECIALIZE_SGN(sgn_mp, mpz_class)
11614PPL_SPECIALIZE_SGN(sgn_mp, mpq_class)
11615
11616template <typename Policy1, typename Policy2, typename Type>
11617inline Result_Relation
11618cmp_mp(const Type& x, const Type& y) {
11619  int i = ::cmp(x, y);
11620  return (i > 0) ? VR_GT : ((i < 0) ? VR_LT : VR_EQ);
11621}
11622
11623PPL_SPECIALIZE_CMP(cmp_mp, mpz_class, mpz_class)
11624PPL_SPECIALIZE_CMP(cmp_mp, mpq_class, mpq_class)
11625
11626template <typename Policy>
11627inline Result
11628output_mpz(std::ostream& os, const mpz_class& from, const Numeric_Format&,
11629           Rounding_Dir) {
11630  os << from;
11631  return V_EQ;
11632}
11633
11634PPL_SPECIALIZE_INPUT(input_generic, mpz_class)
11635PPL_SPECIALIZE_OUTPUT(output_mpz, mpz_class)
11636
11637} // namespace Checked
11638
11639} // namespace Parma_Polyhedra_Library
11640
11641/* Automatically generated from PPL source file ../src/checked_mpq_inlines.hh line 1. */
11642/* Specialized "checked" functions for GMP's mpq_class numbers.
11643*/
11644
11645
11646#include <sstream>
11647#include <climits>
11648#include <stdexcept>
11649
11650namespace Parma_Polyhedra_Library {
11651
11652namespace Checked {
11653
11654template <typename Policy>
11655inline Result
11656classify_mpq(const mpq_class& v, bool nan, bool inf, bool sign) {
11657  if ((Policy::has_nan || Policy::has_infinity)
11658      && ::sgn(v.get_den()) == 0) {
11659    int s = ::sgn(v.get_num());
11660    if (Policy::has_nan && (nan || sign) && s == 0) {
11661      return V_NAN;
11662    }
11663    if (!inf && !sign) {
11664      return V_LGE;
11665    }
11666    if (Policy::has_infinity) {
11667      if (s < 0) {
11668        return inf ? V_EQ_MINUS_INFINITY : V_LT;
11669      }
11670      if (s > 0) {
11671        return inf ? V_EQ_PLUS_INFINITY : V_GT;
11672      }
11673    }
11674  }
11675  if (sign) {
11676    return static_cast<Result>(sgn<Policy>(v));
11677  }
11678  return V_LGE;
11679}
11680
11681PPL_SPECIALIZE_CLASSIFY(classify_mpq, mpq_class)
11682
11683template <typename Policy>
11684inline bool
11685is_nan_mpq(const mpq_class& v) {
11686  return Policy::has_nan
11687    && ::sgn(v.get_den()) == 0
11688    && ::sgn(v.get_num()) == 0;
11689}
11690
11691PPL_SPECIALIZE_IS_NAN(is_nan_mpq, mpq_class)
11692
11693template <typename Policy>
11694inline bool
11695is_minf_mpq(const mpq_class& v) {
11696  return Policy::has_infinity
11697    && ::sgn(v.get_den()) == 0
11698    && ::sgn(v.get_num()) < 0;
11699}
11700
11701PPL_SPECIALIZE_IS_MINF(is_minf_mpq, mpq_class)
11702
11703template <typename Policy>
11704inline bool
11705is_pinf_mpq(const mpq_class& v) {
11706  return Policy::has_infinity
11707    && ::sgn(v.get_den()) == 0
11708    && ::sgn(v.get_num()) > 0;
11709}
11710
11711PPL_SPECIALIZE_IS_PINF(is_pinf_mpq, mpq_class)
11712
11713template <typename Policy>
11714inline bool
11715is_int_mpq(const mpq_class& v) {
11716  if ((Policy::has_infinity || Policy::has_nan)
11717      && ::sgn(v.get_den()) == 0) {
11718    return !(Policy::has_nan && ::sgn(v.get_num()) == 0);
11719  }
11720  else {
11721    return v.get_den() == 1;
11722  }
11723}
11724
11725PPL_SPECIALIZE_IS_INT(is_int_mpq, mpq_class)
11726
11727template <typename Policy>
11728inline Result
11729assign_special_mpq(mpq_class& v, Result_Class c, Rounding_Dir) {
11730  switch (c) {
11731  case VC_NAN:
11732    if (Policy::has_nan) {
11733      v.get_num() = 0;
11734      v.get_den() = 0;
11735      return V_NAN | V_UNREPRESENTABLE;
11736    }
11737    return V_NAN;
11738  case VC_MINUS_INFINITY:
11739    if (Policy::has_infinity) {
11740      v.get_num() = -1;
11741      v.get_den() = 0;
11742      return V_EQ_MINUS_INFINITY;
11743    }
11744    return V_EQ_MINUS_INFINITY | V_UNREPRESENTABLE;
11745  case VC_PLUS_INFINITY:
11746    if (Policy::has_infinity) {
11747      v.get_num() = 1;
11748      v.get_den() = 0;
11749      return V_EQ_PLUS_INFINITY;
11750    }
11751    return V_EQ_PLUS_INFINITY | V_UNREPRESENTABLE;
11752  default:
11753    PPL_UNREACHABLE;
11754    return V_NAN | V_UNREPRESENTABLE;
11755  }
11756}
11757
11758PPL_SPECIALIZE_ASSIGN_SPECIAL(assign_special_mpq, mpq_class)
11759
11760PPL_SPECIALIZE_COPY(copy_generic, mpq_class)
11761
11762template <typename To_Policy, typename From_Policy, typename From>
11763inline Result
11764construct_mpq_base(mpq_class& to, const From& from, Rounding_Dir) {
11765  new(&to) mpq_class(from);
11766  return V_EQ;
11767}
11768
11769PPL_SPECIALIZE_CONSTRUCT(construct_mpq_base, mpq_class, mpz_class)
11770PPL_SPECIALIZE_CONSTRUCT(construct_mpq_base, mpq_class, char)
11771PPL_SPECIALIZE_CONSTRUCT(construct_mpq_base, mpq_class, signed char)
11772PPL_SPECIALIZE_CONSTRUCT(construct_mpq_base, mpq_class, signed short)
11773PPL_SPECIALIZE_CONSTRUCT(construct_mpq_base, mpq_class, signed int)
11774PPL_SPECIALIZE_CONSTRUCT(construct_mpq_base, mpq_class, signed long)
11775PPL_SPECIALIZE_CONSTRUCT(construct_mpq_base, mpq_class, unsigned char)
11776PPL_SPECIALIZE_CONSTRUCT(construct_mpq_base, mpq_class, unsigned short)
11777PPL_SPECIALIZE_CONSTRUCT(construct_mpq_base, mpq_class, unsigned int)
11778PPL_SPECIALIZE_CONSTRUCT(construct_mpq_base, mpq_class, unsigned long)
11779
11780template <typename To_Policy, typename From_Policy, typename From>
11781inline Result
11782construct_mpq_float(mpq_class& to, const From& from, Rounding_Dir dir) {
11783  if (is_nan<From_Policy>(from)) {
11784    return construct_special<To_Policy>(to, VC_NAN, ROUND_IGNORE);
11785  }
11786  else if (is_minf<From_Policy>(from)) {
11787    return construct_special<To_Policy>(to, VC_MINUS_INFINITY, dir);
11788  }
11789  else if (is_pinf<From_Policy>(from)) {
11790    return construct_special<To_Policy>(to, VC_PLUS_INFINITY, dir);
11791  }
11792  new(&to) mpq_class(from);
11793  return V_EQ;
11794}
11795
11796PPL_SPECIALIZE_CONSTRUCT(construct_mpq_float, mpq_class, float)
11797PPL_SPECIALIZE_CONSTRUCT(construct_mpq_float, mpq_class, double)
11798
11799PPL_SPECIALIZE_ASSIGN(assign_exact, mpq_class, mpq_class)
11800PPL_SPECIALIZE_ASSIGN(assign_exact, mpq_class, mpz_class)
11801PPL_SPECIALIZE_ASSIGN(assign_exact, mpq_class, char)
11802PPL_SPECIALIZE_ASSIGN(assign_exact, mpq_class, signed char)
11803PPL_SPECIALIZE_ASSIGN(assign_exact, mpq_class, signed short)
11804PPL_SPECIALIZE_ASSIGN(assign_exact, mpq_class, signed int)
11805PPL_SPECIALIZE_ASSIGN(assign_exact, mpq_class, signed long)
11806PPL_SPECIALIZE_ASSIGN(assign_exact, mpq_class, unsigned char)
11807PPL_SPECIALIZE_ASSIGN(assign_exact, mpq_class, unsigned short)
11808PPL_SPECIALIZE_ASSIGN(assign_exact, mpq_class, unsigned int)
11809PPL_SPECIALIZE_ASSIGN(assign_exact, mpq_class, unsigned long)
11810
11811template <typename To_Policy, typename From_Policy, typename From>
11812inline Result
11813assign_mpq_float(mpq_class& to, const From& from, Rounding_Dir dir) {
11814  if (is_nan<From_Policy>(from)) {
11815    return assign_special<To_Policy>(to, VC_NAN, ROUND_IGNORE);
11816  }
11817  else if (is_minf<From_Policy>(from)) {
11818    return assign_special<To_Policy>(to, VC_MINUS_INFINITY, dir);
11819  }
11820  else if (is_pinf<From_Policy>(from)) {
11821    return assign_special<To_Policy>(to, VC_PLUS_INFINITY, dir);
11822  }
11823  assign_mpq_numeric_float(to, from);
11824  return V_EQ;
11825}
11826
11827PPL_SPECIALIZE_ASSIGN(assign_mpq_float, mpq_class, float)
11828PPL_SPECIALIZE_ASSIGN(assign_mpq_float, mpq_class, double)
11829PPL_SPECIALIZE_ASSIGN(assign_mpq_float, mpq_class, long double)
11830
11831template <typename To_Policy, typename From_Policy, typename From>
11832inline Result
11833assign_mpq_signed_int(mpq_class& to, const From from, Rounding_Dir) {
11834  if (sizeof(From) <= sizeof(signed long)) {
11835    to = static_cast<signed long>(from);
11836  }
11837  else {
11838    mpz_ptr m = to.get_num().get_mpz_t();
11839    if (from >= 0) {
11840      mpz_import(m, 1, 1, sizeof(From), 0, 0, &from);
11841    }
11842    else {
11843      From n = -from;
11844      mpz_import(m, 1, 1, sizeof(From), 0, 0, &n);
11845      mpz_neg(m, m);
11846    }
11847    to.get_den() = 1;
11848  }
11849  return V_EQ;
11850}
11851
11852PPL_SPECIALIZE_ASSIGN(assign_mpq_signed_int, mpq_class, signed long long)
11853
11854template <typename To_Policy, typename From_Policy, typename From>
11855inline Result
11856assign_mpq_unsigned_int(mpq_class& to, const From from, Rounding_Dir) {
11857  if (sizeof(From) <= sizeof(unsigned long)) {
11858    to = static_cast<unsigned long>(from);
11859  }
11860  else {
11861    mpz_import(to.get_num().get_mpz_t(), 1, 1, sizeof(From), 0, 0, &from);
11862    to.get_den() = 1;
11863  }
11864  return V_EQ;
11865}
11866
11867PPL_SPECIALIZE_ASSIGN(assign_mpq_unsigned_int, mpq_class, unsigned long long)
11868
11869template <typename To_Policy, typename From_Policy>
11870inline Result
11871floor_mpq(mpq_class& to, const mpq_class& from, Rounding_Dir) {
11872  mpz_fdiv_q(to.get_num().get_mpz_t(),
11873             from.get_num().get_mpz_t(), from.get_den().get_mpz_t());
11874  to.get_den() = 1;
11875  return V_EQ;
11876}
11877
11878PPL_SPECIALIZE_FLOOR(floor_mpq, mpq_class, mpq_class)
11879
11880template <typename To_Policy, typename From_Policy>
11881inline Result
11882ceil_mpq(mpq_class& to, const mpq_class& from, Rounding_Dir) {
11883  mpz_cdiv_q(to.get_num().get_mpz_t(),
11884             from.get_num().get_mpz_t(), from.get_den().get_mpz_t());
11885  to.get_den() = 1;
11886  return V_EQ;
11887}
11888
11889PPL_SPECIALIZE_CEIL(ceil_mpq, mpq_class, mpq_class)
11890
11891template <typename To_Policy, typename From_Policy>
11892inline Result
11893trunc_mpq(mpq_class& to, const mpq_class& from, Rounding_Dir) {
11894  mpz_tdiv_q(to.get_num().get_mpz_t(),
11895             from.get_num().get_mpz_t(), from.get_den().get_mpz_t());
11896  to.get_den() = 1;
11897  return V_EQ;
11898}
11899
11900PPL_SPECIALIZE_TRUNC(trunc_mpq, mpq_class, mpq_class)
11901
11902template <typename To_Policy, typename From_Policy>
11903inline Result
11904neg_mpq(mpq_class& to, const mpq_class& from, Rounding_Dir) {
11905  mpq_neg(to.get_mpq_t(), from.get_mpq_t());
11906  return V_EQ;
11907}
11908
11909PPL_SPECIALIZE_NEG(neg_mpq, mpq_class, mpq_class)
11910
11911template <typename To_Policy, typename From1_Policy, typename From2_Policy>
11912inline Result
11913add_mpq(mpq_class& to, const mpq_class& x, const mpq_class& y, Rounding_Dir) {
11914  to = x + y;
11915  return V_EQ;
11916}
11917
11918PPL_SPECIALIZE_ADD(add_mpq, mpq_class, mpq_class, mpq_class)
11919
11920template <typename To_Policy, typename From1_Policy, typename From2_Policy>
11921inline Result
11922sub_mpq(mpq_class& to, const mpq_class& x, const mpq_class& y, Rounding_Dir) {
11923  to = x - y;
11924  return V_EQ;
11925}
11926
11927PPL_SPECIALIZE_SUB(sub_mpq, mpq_class, mpq_class, mpq_class)
11928
11929template <typename To_Policy, typename From1_Policy, typename From2_Policy>
11930inline Result
11931mul_mpq(mpq_class& to, const mpq_class& x, const mpq_class& y, Rounding_Dir) {
11932  to = x * y;
11933  return V_EQ;
11934}
11935
11936PPL_SPECIALIZE_MUL(mul_mpq, mpq_class, mpq_class, mpq_class)
11937
11938template <typename To_Policy, typename From1_Policy, typename From2_Policy>
11939inline Result
11940div_mpq(mpq_class& to, const mpq_class& x, const mpq_class& y, Rounding_Dir) {
11941  if (CHECK_P(To_Policy::check_div_zero, sgn(y) == 0)) {
11942    return assign_nan<To_Policy>(to, V_DIV_ZERO);
11943  }
11944  to = x / y;
11945  return V_EQ;
11946}
11947
11948PPL_SPECIALIZE_DIV(div_mpq, mpq_class, mpq_class, mpq_class)
11949
11950template <typename To_Policy, typename From1_Policy, typename From2_Policy>
11951inline Result
11952idiv_mpq(mpq_class& to, const mpq_class& x, const mpq_class& y, Rounding_Dir dir) {
11953  if (CHECK_P(To_Policy::check_div_zero, sgn(y) == 0)) {
11954    return assign_nan<To_Policy>(to, V_DIV_ZERO);
11955  }
11956  to = x / y;
11957  return trunc<To_Policy, To_Policy>(to, to, dir);
11958}
11959
11960PPL_SPECIALIZE_IDIV(idiv_mpq, mpq_class, mpq_class, mpq_class)
11961
11962template <typename To_Policy, typename From1_Policy, typename From2_Policy>
11963inline Result
11964rem_mpq(mpq_class& to, const mpq_class& x, const mpq_class& y, Rounding_Dir) {
11965  if (CHECK_P(To_Policy::check_div_zero, sgn(y) == 0)) {
11966    return assign_nan<To_Policy>(to, V_MOD_ZERO);
11967  }
11968  PPL_DIRTY_TEMP(mpq_class, tmp);
11969  tmp = x / y;
11970  tmp.get_num() %= tmp.get_den();
11971  to = tmp * y;
11972  return V_EQ;
11973}
11974
11975PPL_SPECIALIZE_REM(rem_mpq, mpq_class, mpq_class, mpq_class)
11976
11977template <typename To_Policy, typename From_Policy>
11978inline Result
11979add_2exp_mpq(mpq_class& to, const mpq_class& x, unsigned int exp,
11980             Rounding_Dir) {
11981  PPL_DIRTY_TEMP(mpz_class, v);
11982  v = 1;
11983  mpz_mul_2exp(v.get_mpz_t(), v.get_mpz_t(), exp);
11984  to = x + v;
11985  return V_EQ;
11986}
11987
11988PPL_SPECIALIZE_ADD_2EXP(add_2exp_mpq, mpq_class, mpq_class)
11989
11990template <typename To_Policy, typename From_Policy>
11991inline Result
11992sub_2exp_mpq(mpq_class& to, const mpq_class& x, unsigned int exp,
11993             Rounding_Dir) {
11994  PPL_DIRTY_TEMP(mpz_class, v);
11995  v = 1;
11996  mpz_mul_2exp(v.get_mpz_t(), v.get_mpz_t(), exp);
11997  to = x - v;
11998  return V_EQ;
11999}
12000
12001PPL_SPECIALIZE_SUB_2EXP(sub_2exp_mpq, mpq_class, mpq_class)
12002
12003template <typename To_Policy, typename From_Policy>
12004inline Result
12005mul_2exp_mpq(mpq_class& to, const mpq_class& x, unsigned int exp,
12006             Rounding_Dir) {
12007  mpz_mul_2exp(to.get_num().get_mpz_t(), x.get_num().get_mpz_t(), exp);
12008  to.get_den() = x.get_den();
12009  to.canonicalize();
12010  return V_EQ;
12011}
12012
12013PPL_SPECIALIZE_MUL_2EXP(mul_2exp_mpq, mpq_class, mpq_class)
12014
12015template <typename To_Policy, typename From_Policy>
12016inline Result
12017div_2exp_mpq(mpq_class& to, const mpq_class& x, unsigned int exp,
12018             Rounding_Dir) {
12019  to.get_num() = x.get_num();
12020  mpz_mul_2exp(to.get_den().get_mpz_t(), x.get_den().get_mpz_t(), exp);
12021  to.canonicalize();
12022  return V_EQ;
12023}
12024
12025PPL_SPECIALIZE_DIV_2EXP(div_2exp_mpq, mpq_class, mpq_class)
12026
12027template <typename To_Policy, typename From_Policy>
12028inline Result
12029smod_2exp_mpq(mpq_class& to, const mpq_class& x, unsigned int exp,
12030              Rounding_Dir) {
12031  mpz_mul_2exp(to.get_den().get_mpz_t(), x.get_den().get_mpz_t(), exp);
12032  mpz_fdiv_r(to.get_num().get_mpz_t(), x.get_num().get_mpz_t(), to.get_den().get_mpz_t());
12033  mpz_fdiv_q_2exp(to.get_den().get_mpz_t(), to.get_den().get_mpz_t(), 1);
12034  bool neg = to.get_num() >= to.get_den();
12035  mpz_mul_2exp(to.get_den().get_mpz_t(), to.get_den().get_mpz_t(), 1);
12036  if (neg) {
12037    to.get_num() -= to.get_den();
12038  }
12039  mpz_mul_2exp(to.get_num().get_mpz_t(), to.get_num().get_mpz_t(), exp);
12040  to.canonicalize();
12041  return V_EQ;
12042}
12043
12044PPL_SPECIALIZE_SMOD_2EXP(smod_2exp_mpq, mpq_class, mpq_class)
12045
12046template <typename To_Policy, typename From_Policy>
12047inline Result
12048umod_2exp_mpq(mpq_class& to, const mpq_class& x, unsigned int exp,
12049              Rounding_Dir) {
12050  mpz_mul_2exp(to.get_den().get_mpz_t(), x.get_den().get_mpz_t(), exp);
12051  mpz_fdiv_r(to.get_num().get_mpz_t(), x.get_num().get_mpz_t(), to.get_den().get_mpz_t());
12052  mpz_mul_2exp(to.get_num().get_mpz_t(), to.get_num().get_mpz_t(), exp);
12053  to.canonicalize();
12054  return V_EQ;
12055}
12056
12057PPL_SPECIALIZE_UMOD_2EXP(umod_2exp_mpq, mpq_class, mpq_class)
12058
12059template <typename To_Policy, typename From_Policy>
12060inline Result
12061abs_mpq(mpq_class& to, const mpq_class& from, Rounding_Dir) {
12062  to = abs(from);
12063  return V_EQ;
12064}
12065
12066PPL_SPECIALIZE_ABS(abs_mpq, mpq_class, mpq_class)
12067
12068template <typename To_Policy, typename From1_Policy, typename From2_Policy>
12069inline Result
12070add_mul_mpq(mpq_class& to, const mpq_class& x, const mpq_class& y,
12071            Rounding_Dir) {
12072  to += x * y;
12073  return V_EQ;
12074}
12075
12076PPL_SPECIALIZE_ADD_MUL(add_mul_mpq, mpq_class, mpq_class, mpq_class)
12077
12078template <typename To_Policy, typename From1_Policy, typename From2_Policy>
12079inline Result
12080sub_mul_mpq(mpq_class& to, const mpq_class& x, const mpq_class& y,
12081            Rounding_Dir) {
12082  to -= x * y;
12083  return V_EQ;
12084}
12085
12086PPL_SPECIALIZE_SUB_MUL(sub_mul_mpq, mpq_class, mpq_class, mpq_class)
12087
12088extern unsigned irrational_precision;
12089
12090template <typename To_Policy, typename From_Policy>
12091inline Result
12092sqrt_mpq(mpq_class& to, const mpq_class& from, Rounding_Dir dir) {
12093  if (CHECK_P(To_Policy::check_sqrt_neg, from < 0)) {
12094    return assign_nan<To_Policy>(to, V_SQRT_NEG);
12095  }
12096  if (from == 0) {
12097    to = 0;
12098    return V_EQ;
12099  }
12100  bool gt1 = from.get_num() > from.get_den();
12101  const mpz_class& from_a = gt1 ? from.get_num() : from.get_den();
12102  const mpz_class& from_b = gt1 ? from.get_den() : from.get_num();
12103  mpz_class& to_a = gt1 ? to.get_num() : to.get_den();
12104  mpz_class& to_b = gt1 ? to.get_den() : to.get_num();
12105  Rounding_Dir rdir = gt1 ? dir : inverse(dir);
12106  mul_2exp<To_Policy, From_Policy>(to_a, from_a,
12107                                   2*irrational_precision, ROUND_IGNORE);
12108  Result r_div
12109    = div<To_Policy, To_Policy, To_Policy>(to_a, to_a, from_b, rdir);
12110  Result r_sqrt = sqrt<To_Policy, To_Policy>(to_a, to_a, rdir);
12111  to_b = 1;
12112  mul_2exp<To_Policy, To_Policy>(to_b, to_b,
12113                                 irrational_precision, ROUND_IGNORE);
12114  to.canonicalize();
12115  return (r_div != V_EQ) ? r_div : r_sqrt;
12116}
12117
12118PPL_SPECIALIZE_SQRT(sqrt_mpq, mpq_class, mpq_class)
12119
12120template <typename Policy>
12121inline Result
12122input_mpq(mpq_class& to, std::istream& is, Rounding_Dir dir) {
12123  Result r = input_mpq(to, is);
12124  Result_Class c = result_class(r);
12125  switch (c) {
12126  case VC_MINUS_INFINITY:
12127  case VC_PLUS_INFINITY:
12128    return assign_special<Policy>(to, c, dir);
12129  case VC_NAN:
12130    return assign_nan<Policy>(to, r);
12131  default:
12132    return r;
12133  }
12134}
12135
12136PPL_SPECIALIZE_INPUT(input_mpq, mpq_class)
12137
12138template <typename Policy>
12139inline Result
12140output_mpq(std::ostream& os,
12141           const mpq_class& from,
12142           const Numeric_Format&,
12143           Rounding_Dir) {
12144  os << from;
12145  return V_EQ;
12146}
12147
12148PPL_SPECIALIZE_OUTPUT(output_mpq, mpq_class)
12149
12150} // namespace Checked
12151
12152//! Returns the precision parameter used for irrational calculations.
12153inline unsigned
12154irrational_precision() {
12155  return Checked::irrational_precision;
12156}
12157
12158//! Sets the precision parameter used for irrational calculations.
12159/*! The lesser between numerator and denominator is limited to 2**\p p.
12160
12161  If \p p is less than or equal to <CODE>INT_MAX</CODE>, sets the
12162  precision parameter used for irrational calculations to \p p.
12163
12164  \exception std::invalid_argument
12165  Thrown if \p p is greater than <CODE>INT_MAX</CODE>.
12166*/
12167inline void
12168set_irrational_precision(const unsigned p) {
12169  if (p <= INT_MAX) {
12170    Checked::irrational_precision = p;
12171  }
12172  else {
12173    throw std::invalid_argument("PPL::set_irrational_precision(p)"
12174                                " with p > INT_MAX");
12175  }
12176}
12177
12178} // namespace Parma_Polyhedra_Library
12179
12180/* Automatically generated from PPL source file ../src/checked_ext_inlines.hh line 1. */
12181/* Checked extended arithmetic functions.
12182*/
12183
12184
12185namespace Parma_Polyhedra_Library {
12186
12187template <typename T> struct FPU_Related : public False {};
12188template <> struct FPU_Related<float> : public True {};
12189template <> struct FPU_Related<double> : public True {};
12190template <> struct FPU_Related<long double> : public True {};
12191
12192namespace Checked {
12193
12194template <typename T>
12195inline bool
12196handle_ext_natively(const T&) {
12197  return FPU_Related<T>::value;
12198}
12199
12200template <typename Policy, typename Type>
12201inline bool
12202ext_to_handle(const Type& x) {
12203  return !handle_ext_natively(x)
12204    && (Policy::has_infinity || Policy::has_nan);
12205}
12206
12207template <typename Policy, typename Type>
12208inline Result_Relation
12209sgn_ext(const Type& x) {
12210  if (!ext_to_handle<Policy>(x)) {
12211    goto native;
12212  }
12213  if (is_nan<Policy>(x)) {
12214    return VR_EMPTY;
12215  }
12216  else if (is_minf<Policy>(x)) {
12217    return VR_LT;
12218  }
12219  else if (is_pinf<Policy>(x)) {
12220    return VR_GT;
12221  }
12222  else {
12223  native:
12224    return sgn<Policy>(x);
12225  }
12226}
12227
12228template <typename To_Policy, typename From_Policy,
12229          typename To, typename From>
12230inline Result
12231construct_ext(To& to, const From& x, Rounding_Dir dir) {
12232  if (!ext_to_handle<From_Policy>(x)) {
12233    goto native;
12234  }
12235  if (is_nan<From_Policy>(x)) {
12236    return construct_special<To_Policy>(to, VC_NAN, ROUND_IGNORE);
12237  }
12238  else if (is_minf<From_Policy>(x)) {
12239    return construct_special<To_Policy>(to, VC_MINUS_INFINITY, dir);
12240  }
12241  else if (is_pinf<From_Policy>(x)) {
12242    return construct_special<To_Policy>(to, VC_PLUS_INFINITY, dir);
12243  }
12244  else {
12245  native:
12246    return construct<To_Policy, From_Policy>(to, x, dir);
12247  }
12248}
12249
12250template <typename To_Policy, typename From_Policy,
12251          typename To, typename From>
12252inline Result
12253assign_ext(To& to, const From& x, Rounding_Dir dir) {
12254  if (!ext_to_handle<From_Policy>(x)) {
12255    goto native;
12256  }
12257  if (is_nan<From_Policy>(x)) {
12258    return assign_special<To_Policy>(to, VC_NAN, ROUND_IGNORE);
12259  }
12260  else if (is_minf<From_Policy>(x)) {
12261    return assign_special<To_Policy>(to, VC_MINUS_INFINITY, dir);
12262  }
12263  else if (is_pinf<From_Policy>(x)) {
12264    return assign_special<To_Policy>(to, VC_PLUS_INFINITY, dir);
12265  }
12266  else {
12267  native:
12268    return assign<To_Policy, From_Policy>(to, x, dir);
12269  }
12270}
12271
12272template <typename To_Policy, typename From_Policy,
12273          typename To, typename From>
12274inline Result
12275neg_ext(To& to, const From& x, Rounding_Dir dir) {
12276  if (!ext_to_handle<From_Policy>(x)) {
12277    goto native;
12278  }
12279  if (is_nan<From_Policy>(x)) {
12280    return assign_special<To_Policy>(to, VC_NAN, ROUND_IGNORE);
12281  }
12282  else if (is_minf<From_Policy>(x)) {
12283    return assign_special<To_Policy>(to, VC_PLUS_INFINITY, dir);
12284  }
12285  else if (is_pinf<From_Policy>(x)) {
12286    return assign_special<To_Policy>(to, VC_MINUS_INFINITY, dir);
12287  }
12288  else {
12289  native:
12290    return neg<To_Policy, From_Policy>(to, x, dir);
12291  }
12292}
12293
12294template <typename To_Policy, typename From_Policy,
12295          typename To, typename From>
12296inline Result
12297floor_ext(To& to, const From& x, Rounding_Dir dir) {
12298  if (!ext_to_handle<From_Policy>(x)) {
12299    goto native;
12300  }
12301  if (is_nan<From_Policy>(x)) {
12302    return assign_special<To_Policy>(to, VC_NAN, ROUND_IGNORE);
12303  }
12304  else if (is_minf<From_Policy>(x)) {
12305    return assign_special<To_Policy>(to, VC_MINUS_INFINITY, dir);
12306  }
12307  else if (is_pinf<From_Policy>(x)) {
12308    return assign_special<To_Policy>(to, VC_PLUS_INFINITY, dir);
12309  }
12310  else {
12311  native:
12312    return floor<To_Policy, From_Policy>(to, x, dir);
12313  }
12314}
12315
12316template <typename To_Policy, typename From_Policy,
12317          typename To, typename From>
12318inline Result
12319ceil_ext(To& to, const From& x, Rounding_Dir dir) {
12320  if (!ext_to_handle<From_Policy>(x)) {
12321    goto native;
12322  }
12323  if (is_nan<From_Policy>(x)) {
12324    return assign_special<To_Policy>(to, VC_NAN, ROUND_IGNORE);
12325  }
12326  else if (is_minf<From_Policy>(x)) {
12327    return assign_special<To_Policy>(to, VC_MINUS_INFINITY, dir);
12328  }
12329  else if (is_pinf<From_Policy>(x)) {
12330    return assign_special<To_Policy>(to, VC_PLUS_INFINITY, dir);
12331  }
12332  else {
12333  native:
12334    return ceil<To_Policy, From_Policy>(to, x, dir);
12335  }
12336}
12337
12338template <typename To_Policy, typename From_Policy,
12339          typename To, typename From>
12340inline Result
12341trunc_ext(To& to, const From& x, Rounding_Dir dir) {
12342  if (!ext_to_handle<From_Policy>(x)) {
12343    goto native;
12344  }
12345  if (is_nan<From_Policy>(x)) {
12346    return assign_special<To_Policy>(to, VC_NAN, ROUND_IGNORE);
12347  }
12348  else if (is_minf<From_Policy>(x)) {
12349    return assign_special<To_Policy>(to, VC_MINUS_INFINITY, dir);
12350  }
12351  else if (is_pinf<From_Policy>(x)) {
12352    return assign_special<To_Policy>(to, VC_PLUS_INFINITY, dir);
12353  }
12354  else {
12355  native:
12356    return trunc<To_Policy, From_Policy>(to, x, dir);
12357  }
12358}
12359
12360template <typename To_Policy, typename From_Policy,
12361          typename To, typename From>
12362inline Result
12363abs_ext(To& to, const From& x, Rounding_Dir dir) {
12364  if (!ext_to_handle<From_Policy>(x)) {
12365    goto native;
12366  }
12367  if (is_nan<From_Policy>(x)) {
12368    return assign_special<To_Policy>(to, VC_NAN, ROUND_IGNORE);
12369  }
12370  else if (is_minf<From_Policy>(x) || is_pinf<From_Policy>(x)) {
12371    return assign_special<To_Policy>(to, VC_PLUS_INFINITY, dir);
12372  }
12373  else {
12374  native:
12375    return abs<To_Policy, From_Policy>(to, x, dir);
12376  }
12377}
12378
12379template <typename To_Policy, typename From1_Policy, typename From2_Policy,
12380          typename To, typename From1, typename From2>
12381inline Result
12382add_ext(To& to, const From1& x, const From2& y, Rounding_Dir dir) {
12383  if (!ext_to_handle<From1_Policy>(x) && !ext_to_handle<From2_Policy>(y)) {
12384    goto native;
12385  }
12386  if (is_nan<From1_Policy>(x) || is_nan<From2_Policy>(y)) {
12387    return assign_special<To_Policy>(to, VC_NAN, ROUND_IGNORE);
12388  }
12389  else if (is_minf<From1_Policy>(x)) {
12390    if (CHECK_P(To_Policy::check_inf_add_inf, is_pinf<From2_Policy>(y))) {
12391      goto inf_add_inf;
12392    }
12393    else {
12394      goto minf;
12395    }
12396  }
12397  else if (is_pinf<From1_Policy>(x)) {
12398    if (CHECK_P(To_Policy::check_inf_add_inf, is_minf<From2_Policy>(y))) {
12399    inf_add_inf:
12400      return assign_nan<To_Policy>(to, V_INF_ADD_INF);
12401    }
12402    else {
12403      goto pinf;
12404    }
12405  }
12406  else {
12407    if (is_minf<From2_Policy>(y)) {
12408    minf:
12409      return assign_special<To_Policy>(to, VC_MINUS_INFINITY, dir);
12410    }
12411    else if (is_pinf<From2_Policy>(y)) {
12412    pinf:
12413      return assign_special<To_Policy>(to, VC_PLUS_INFINITY, dir);
12414    }
12415    else {
12416    native:
12417      return add<To_Policy, From1_Policy, From2_Policy>(to, x, y, dir);
12418    }
12419  }
12420}
12421
12422template <typename To_Policy, typename From1_Policy, typename From2_Policy,
12423          typename To, typename From1, typename From2>
12424inline Result
12425sub_ext(To& to, const From1& x, const From2& y, Rounding_Dir dir) {
12426  if (!ext_to_handle<From1_Policy>(x) && !ext_to_handle<From2_Policy>(y)) {
12427    goto native;
12428  }
12429  if (is_nan<From1_Policy>(x) || is_nan<From2_Policy>(y)) {
12430    return assign_special<To_Policy>(to, VC_NAN, ROUND_IGNORE);
12431  }
12432  else if (is_minf<From1_Policy>(x)) {
12433    if (CHECK_P(To_Policy::check_inf_sub_inf, is_minf<From2_Policy>(y))) {
12434      goto inf_sub_inf;
12435    }
12436    else {
12437      goto minf;
12438    }
12439  }
12440  else if (is_pinf<From1_Policy>(x)) {
12441    if (CHECK_P(To_Policy::check_inf_sub_inf, is_pinf<From2_Policy>(y))) {
12442    inf_sub_inf:
12443      return assign_nan<To_Policy>(to, V_INF_SUB_INF);
12444    }
12445    else {
12446      goto pinf;
12447    }
12448  }
12449  else {
12450    if (is_pinf<From2_Policy>(y)) {
12451    minf:
12452      return assign_special<To_Policy>(to, VC_MINUS_INFINITY, dir);
12453    }
12454    else if (is_minf<From2_Policy>(y)) {
12455    pinf:
12456      return assign_special<To_Policy>(to, VC_PLUS_INFINITY, dir);
12457    }
12458    else {
12459    native:
12460      return sub<To_Policy, From1_Policy, From2_Policy>(to, x, y, dir);
12461    }
12462  }
12463}
12464
12465template <typename To_Policy, typename From1_Policy, typename From2_Policy,
12466          typename To, typename From1, typename From2>
12467inline Result
12468mul_ext(To& to, const From1& x, const From2& y, Rounding_Dir dir) {
12469  if (!ext_to_handle<From1_Policy>(x) && !ext_to_handle<From2_Policy>(y)) {
12470    goto native;
12471  }
12472  if (is_nan<From1_Policy>(x) || is_nan<From2_Policy>(y)) {
12473    return assign_special<To_Policy>(to, VC_NAN, ROUND_IGNORE);
12474  }
12475  if (is_minf<From1_Policy>(x)) {
12476    switch (sgn_ext<From2_Policy>(y)) {
12477    case VR_LT:
12478      goto pinf;
12479    case VR_GT:
12480      goto minf;
12481    default:
12482      goto inf_mul_zero;
12483    }
12484  }
12485  else if (is_pinf<From1_Policy>(x)) {
12486    switch (sgn_ext<From2_Policy>(y)) {
12487    case VR_LT:
12488      goto minf;
12489    case VR_GT:
12490      goto pinf;
12491    default:
12492      goto inf_mul_zero;
12493    }
12494  }
12495  else {
12496    if (is_minf<From2_Policy>(y)) {
12497      switch (sgn<From1_Policy>(x)) {
12498      case VR_LT:
12499        goto pinf;
12500      case VR_GT:
12501        goto minf;
12502      default:
12503        goto inf_mul_zero;
12504      }
12505    }
12506    else if (is_pinf<From2_Policy>(y)) {
12507      switch (sgn<From1_Policy>(x)) {
12508      case VR_LT:
12509      minf:
12510        return assign_special<To_Policy>(to, VC_MINUS_INFINITY, dir);
12511      case VR_GT:
12512      pinf:
12513        return assign_special<To_Policy>(to, VC_PLUS_INFINITY, dir);
12514      default:
12515      inf_mul_zero:
12516        PPL_ASSERT(To_Policy::check_inf_mul_zero);
12517        return assign_nan<To_Policy>(to, V_INF_MUL_ZERO);
12518      }
12519    }
12520    else {
12521    native:
12522      return mul<To_Policy, From1_Policy, From2_Policy>(to, x, y, dir);
12523    }
12524  }
12525}
12526
12527
12528template <typename To_Policy, typename From1_Policy, typename From2_Policy,
12529          typename To, typename From1, typename From2>
12530inline Result
12531add_mul_ext(To& to, const From1& x, const From2& y, Rounding_Dir dir) {
12532  if (!ext_to_handle<To_Policy>(to)
12533      && !ext_to_handle<From1_Policy>(x) && !ext_to_handle<From2_Policy>(y)) {
12534    goto native;
12535  }
12536  if (is_nan<To_Policy>(to)
12537      || is_nan<From1_Policy>(x) || is_nan<From2_Policy>(y)) {
12538    return assign_special<To_Policy>(to, VC_NAN, ROUND_IGNORE);
12539  }
12540  if (is_minf<From1_Policy>(x)) {
12541    switch (sgn_ext<From2_Policy>(y)) {
12542    case VR_LT:
12543      goto a_pinf;
12544    case VR_GT:
12545      goto a_minf;
12546    default:
12547      goto inf_mul_zero;
12548    }
12549  }
12550  else if (is_pinf<From1_Policy>(x)) {
12551    switch (sgn_ext<From2_Policy>(y)) {
12552    case VR_LT:
12553      goto a_minf;
12554    case VR_GT:
12555      goto a_pinf;
12556    default:
12557      goto inf_mul_zero;
12558    }
12559  }
12560  else {
12561    if (is_minf<From2_Policy>(y)) {
12562      switch (sgn<From1_Policy>(x)) {
12563      case VR_LT:
12564        goto a_pinf;
12565      case VR_GT:
12566        goto a_minf;
12567      default:
12568        goto inf_mul_zero;
12569      }
12570    }
12571    else if (is_pinf<From2_Policy>(y)) {
12572      switch (sgn<From1_Policy>(x)) {
12573      case VR_LT:
12574      a_minf:
12575        if (CHECK_P(To_Policy::check_inf_add_inf, is_pinf<To_Policy>(to))) {
12576          goto inf_add_inf;
12577        }
12578        else {
12579          goto minf;
12580        }
12581      case VR_GT:
12582      a_pinf:
12583        if (CHECK_P(To_Policy::check_inf_add_inf, is_minf<To_Policy>(to))) {
12584        inf_add_inf:
12585          return assign_nan<To_Policy>(to, V_INF_ADD_INF);
12586        }
12587        else {
12588          goto pinf;
12589        }
12590      default:
12591      inf_mul_zero:
12592        PPL_ASSERT(To_Policy::check_inf_mul_zero);
12593        return assign_nan<To_Policy>(to, V_INF_MUL_ZERO);
12594      }
12595    }
12596    else {
12597      if (is_minf<To_Policy>(to)) {
12598      minf:
12599        return assign_special<To_Policy>(to, VC_MINUS_INFINITY, dir);
12600      }
12601      if (is_pinf<To_Policy>(to)) {
12602      pinf:
12603        return assign_special<To_Policy>(to, VC_PLUS_INFINITY, dir);
12604      }
12605    native:
12606      return add_mul<To_Policy, From1_Policy, From2_Policy>(to, x, y, dir);
12607    }
12608  }
12609}
12610
12611template <typename To_Policy, typename From1_Policy, typename From2_Policy,
12612          typename To, typename From1, typename From2>
12613inline Result
12614sub_mul_ext(To& to, const From1& x, const From2& y, Rounding_Dir dir) {
12615  if (!ext_to_handle<To_Policy>(to)
12616      && !ext_to_handle<From1_Policy>(x) && !ext_to_handle<From2_Policy>(y)) {
12617    goto native;
12618  }
12619  if (is_nan<To_Policy>(to)
12620      || is_nan<From1_Policy>(x) || is_nan<From2_Policy>(y)) {
12621    return assign_special<To_Policy>(to, VC_NAN, ROUND_IGNORE);
12622  }
12623  if (is_minf<From1_Policy>(x)) {
12624    switch (sgn_ext<From2_Policy>(y)) {
12625    case VR_LT:
12626      goto a_pinf;
12627    case VR_GT:
12628      goto a_minf;
12629    default:
12630      goto inf_mul_zero;
12631    }
12632  }
12633  else if (is_pinf<From1_Policy>(x)) {
12634    switch (sgn_ext<From2_Policy>(y)) {
12635    case VR_LT:
12636      goto a_minf;
12637    case VR_GT:
12638      goto a_pinf;
12639    default:
12640      goto inf_mul_zero;
12641    }
12642  }
12643  else {
12644    if (is_minf<From2_Policy>(y)) {
12645      switch (sgn<From1_Policy>(x)) {
12646      case VR_LT:
12647        goto a_pinf;
12648      case VR_GT:
12649        goto a_minf;
12650      default:
12651        goto inf_mul_zero;
12652      }
12653    }
12654    else if (is_pinf<From2_Policy>(y)) {
12655      switch (sgn<From1_Policy>(x)) {
12656      case VR_LT:
12657      a_minf:
12658        if (CHECK_P(To_Policy::check_inf_sub_inf, is_minf<To_Policy>(to))) {
12659          goto inf_sub_inf;
12660        }
12661        else {
12662          goto pinf;
12663        }
12664      case VR_GT:
12665      a_pinf:
12666        if (CHECK_P(To_Policy::check_inf_sub_inf, is_pinf<To_Policy>(to))) {
12667        inf_sub_inf:
12668          return assign_nan<To_Policy>(to, V_INF_SUB_INF);
12669        }
12670        else {
12671          goto minf;
12672        }
12673      default:
12674      inf_mul_zero:
12675        PPL_ASSERT(To_Policy::check_inf_mul_zero);
12676        return assign_nan<To_Policy>(to, V_INF_MUL_ZERO);
12677      }
12678    }
12679    else {
12680      if (is_minf<To_Policy>(to)) {
12681      minf:
12682        return assign_special<To_Policy>(to, VC_MINUS_INFINITY, dir);
12683      }
12684      if (is_pinf<To_Policy>(to)) {
12685      pinf:
12686        return assign_special<To_Policy>(to, VC_PLUS_INFINITY, dir);
12687      }
12688    native:
12689      return sub_mul<To_Policy, From1_Policy, From2_Policy>(to, x, y, dir);
12690    }
12691  }
12692}
12693
12694template <typename To_Policy, typename From1_Policy, typename From2_Policy,
12695          typename To, typename From1, typename From2>
12696inline Result
12697div_ext(To& to, const From1& x, const From2& y, Rounding_Dir dir) {
12698  if (!ext_to_handle<From1_Policy>(x) && !ext_to_handle<From2_Policy>(y)) {
12699    goto native;
12700  }
12701  if (is_nan<From1_Policy>(x) || is_nan<From2_Policy>(y)) {
12702    return assign_special<To_Policy>(to, VC_NAN, ROUND_IGNORE);
12703  }
12704  if (is_minf<From1_Policy>(x)) {
12705    if (CHECK_P(To_Policy::check_inf_div_inf, is_minf<From2_Policy>(y)
12706                || is_pinf<From2_Policy>(y))) {
12707      goto inf_div_inf;
12708    }
12709    else {
12710      switch (sgn<From2_Policy>(y)) {
12711      case VR_LT:
12712        goto pinf;
12713      case VR_GT:
12714        goto minf;
12715      default:
12716        goto div_zero;
12717      }
12718    }
12719  }
12720  else if (is_pinf<From1_Policy>(x)) {
12721    if (CHECK_P(To_Policy::check_inf_div_inf, is_minf<From2_Policy>(y)
12722                || is_pinf<From2_Policy>(y))) {
12723    inf_div_inf:
12724      return assign_nan<To_Policy>(to, V_INF_DIV_INF);
12725    }
12726    else {
12727      switch (sgn<From2_Policy>(y)) {
12728      case VR_LT:
12729      minf:
12730        return assign_special<To_Policy>(to, VC_MINUS_INFINITY, dir);
12731      case VR_GT:
12732      pinf:
12733        return assign_special<To_Policy>(to, VC_PLUS_INFINITY, dir);
12734      default:
12735      div_zero:
12736        PPL_ASSERT(To_Policy::check_div_zero);
12737        return assign_nan<To_Policy>(to, V_DIV_ZERO);
12738      }
12739    }
12740  }
12741  else {
12742    if (is_minf<From2_Policy>(y) || is_pinf<From2_Policy>(y)) {
12743      to = 0;
12744      return V_EQ;
12745    }
12746    else {
12747    native:
12748      return div<To_Policy, From1_Policy, From2_Policy>(to, x, y, dir);
12749    }
12750  }
12751}
12752
12753
12754template <typename To_Policy, typename From1_Policy, typename From2_Policy,
12755          typename To, typename From1, typename From2>
12756inline Result
12757idiv_ext(To& to, const From1& x, const From2& y, Rounding_Dir dir) {
12758  if (!ext_to_handle<From1_Policy>(x) && !ext_to_handle<From2_Policy>(y)) {
12759    goto native;
12760  }
12761  if (is_nan<From1_Policy>(x) || is_nan<From2_Policy>(y)) {
12762    return assign_special<To_Policy>(to, VC_NAN, ROUND_IGNORE);
12763  }
12764  if (is_minf<From1_Policy>(x)) {
12765    if (CHECK_P(To_Policy::check_inf_div_inf, is_minf<From2_Policy>(y)
12766                || is_pinf<From2_Policy>(y))) {
12767      goto inf_div_inf;
12768    }
12769    else {
12770      switch (sgn<From2_Policy>(y)) {
12771      case VR_LT:
12772        goto pinf;
12773      case VR_GT:
12774        goto minf;
12775      default:
12776        goto div_zero;
12777      }
12778    }
12779  }
12780  else if (is_pinf<From1_Policy>(x)) {
12781    if (CHECK_P(To_Policy::check_inf_div_inf, is_minf<From2_Policy>(y)
12782                || is_pinf<From2_Policy>(y))) {
12783    inf_div_inf:
12784      return assign_nan<To_Policy>(to, V_INF_DIV_INF);
12785    }
12786    else {
12787      switch (sgn<From2_Policy>(y)) {
12788      case VR_LT:
12789      minf:
12790        return assign_special<To_Policy>(to, VC_MINUS_INFINITY, dir);
12791      case VR_GT:
12792      pinf:
12793        return assign_special<To_Policy>(to, VC_PLUS_INFINITY, dir);
12794      default:
12795      div_zero:
12796        PPL_ASSERT(To_Policy::check_div_zero);
12797        return assign_nan<To_Policy>(to, V_DIV_ZERO);
12798      }
12799    }
12800  }
12801  else {
12802    if (is_minf<From2_Policy>(y) || is_pinf<From2_Policy>(y)) {
12803      to = 0;
12804      return V_EQ;
12805    }
12806    else {
12807    native:
12808      return idiv<To_Policy, From1_Policy, From2_Policy>(to, x, y, dir);
12809    }
12810  }
12811}
12812
12813
12814template <typename To_Policy, typename From1_Policy, typename From2_Policy,
12815          typename To, typename From1, typename From2>
12816inline Result
12817rem_ext(To& to, const From1& x, const From2& y, Rounding_Dir dir) {
12818  if (!ext_to_handle<From1_Policy>(x) && !ext_to_handle<From2_Policy>(y)) {
12819    goto native;
12820  }
12821  if (is_nan<From1_Policy>(x) || is_nan<From2_Policy>(y)) {
12822    return assign_special<To_Policy>(to, VC_NAN, ROUND_IGNORE);
12823  }
12824  else if (CHECK_P(To_Policy::check_inf_mod, is_minf<From1_Policy>(x)
12825                   || is_pinf<From1_Policy>(x))) {
12826    return assign_nan<To_Policy>(to, V_INF_MOD);
12827  }
12828  else {
12829    if (is_minf<From1_Policy>(y) || is_pinf<From2_Policy>(y)) {
12830      to = x;
12831      return V_EQ;
12832    }
12833    else {
12834    native:
12835      return rem<To_Policy, From1_Policy, From2_Policy>(to, x, y, dir);
12836    }
12837  }
12838}
12839
12840template <typename To_Policy, typename From_Policy,
12841          typename To, typename From>
12842inline Result
12843add_2exp_ext(To& to, const From& x, unsigned int exp, Rounding_Dir dir) {
12844  if (!ext_to_handle<From_Policy>(x)) {
12845    goto native;
12846  }
12847  if (is_nan<From_Policy>(x)) {
12848    return assign_special<To_Policy>(to, VC_NAN, ROUND_IGNORE);
12849  }
12850  else if (is_minf<From_Policy>(x)) {
12851    return assign_special<To_Policy>(to, VC_MINUS_INFINITY, dir);
12852  }
12853  else if (is_pinf<From_Policy>(x)) {
12854    return assign_special<To_Policy>(to, VC_PLUS_INFINITY, dir);
12855  }
12856  else {
12857  native:
12858    return add_2exp<To_Policy, From_Policy>(to, x, exp, dir);
12859  }
12860}
12861
12862template <typename To_Policy, typename From_Policy,
12863          typename To, typename From>
12864inline Result
12865sub_2exp_ext(To& to, const From& x, unsigned int exp, Rounding_Dir dir) {
12866  if (!ext_to_handle<From_Policy>(x)) {
12867    goto native;
12868  }
12869  if (is_nan<From_Policy>(x)) {
12870    return assign_special<To_Policy>(to, VC_NAN, ROUND_IGNORE);
12871  }
12872  else if (is_minf<From_Policy>(x)) {
12873    return assign_special<To_Policy>(to, VC_MINUS_INFINITY, dir);
12874  }
12875  else if (is_pinf<From_Policy>(x)) {
12876    return assign_special<To_Policy>(to, VC_PLUS_INFINITY, dir);
12877  }
12878  else {
12879  native:
12880    return sub_2exp<To_Policy, From_Policy>(to, x, exp, dir);
12881  }
12882}
12883
12884template <typename To_Policy, typename From_Policy,
12885          typename To, typename From>
12886inline Result
12887mul_2exp_ext(To& to, const From& x, unsigned int exp, Rounding_Dir dir) {
12888  if (!ext_to_handle<From_Policy>(x)) {
12889    goto native;
12890  }
12891  if (is_nan<From_Policy>(x)) {
12892    return assign_special<To_Policy>(to, VC_NAN, ROUND_IGNORE);
12893  }
12894  else if (is_minf<From_Policy>(x)) {
12895    return assign_special<To_Policy>(to, VC_MINUS_INFINITY, dir);
12896  }
12897  else if (is_pinf<From_Policy>(x)) {
12898    return assign_special<To_Policy>(to, VC_PLUS_INFINITY, dir);
12899  }
12900  else {
12901  native:
12902    return mul_2exp<To_Policy, From_Policy>(to, x, exp, dir);
12903  }
12904}
12905
12906template <typename To_Policy, typename From_Policy,
12907          typename To, typename From>
12908inline Result
12909div_2exp_ext(To& to, const From& x, unsigned int exp, Rounding_Dir dir) {
12910  if (!ext_to_handle<From_Policy>(x)) {
12911    goto native;
12912  }
12913  if (is_nan<From_Policy>(x)) {
12914    return assign_special<To_Policy>(to, VC_NAN, ROUND_IGNORE);
12915  }
12916  else if (is_minf<From_Policy>(x)) {
12917    return assign_special<To_Policy>(to, VC_MINUS_INFINITY, dir);
12918  }
12919  else if (is_pinf<From_Policy>(x)) {
12920    return assign_special<To_Policy>(to, VC_PLUS_INFINITY, dir);
12921  }
12922  else {
12923  native:
12924    return div_2exp<To_Policy, From_Policy>(to, x, exp, dir);
12925  }
12926}
12927
12928template <typename To_Policy, typename From_Policy,
12929          typename To, typename From>
12930inline Result
12931smod_2exp_ext(To& to, const From& x, unsigned int exp, Rounding_Dir dir) {
12932  if (!ext_to_handle<From_Policy>(x)) {
12933    goto native;
12934  }
12935  if (is_nan<From_Policy>(x)) {
12936    return assign_special<To_Policy>(to, VC_NAN, ROUND_IGNORE);
12937  }
12938  else if (CHECK_P(To_Policy::check_inf_mod, is_minf<From_Policy>(x)
12939                   || is_pinf<From_Policy>(x))) {
12940    return assign_nan<To_Policy>(to, V_INF_MOD);
12941  }
12942  else {
12943  native:
12944    return smod_2exp<To_Policy, From_Policy>(to, x, exp, dir);
12945  }
12946}
12947
12948template <typename To_Policy, typename From_Policy,
12949          typename To, typename From>
12950inline Result
12951umod_2exp_ext(To& to, const From& x, unsigned int exp, Rounding_Dir dir) {
12952  if (!ext_to_handle<From_Policy>(x)) {
12953    goto native;
12954  }
12955  if (is_nan<From_Policy>(x)) {
12956    return assign_special<To_Policy>(to, VC_NAN, ROUND_IGNORE);
12957  }
12958  else if (CHECK_P(To_Policy::check_inf_mod, is_minf<From_Policy>(x)
12959                   || is_pinf<From_Policy>(x))) {
12960    return assign_nan<To_Policy>(to, V_INF_MOD);
12961  }
12962  else {
12963  native:
12964    return umod_2exp<To_Policy, From_Policy>(to, x, exp, dir);
12965  }
12966}
12967
12968template <typename To_Policy, typename From_Policy,
12969          typename To, typename From>
12970inline Result
12971sqrt_ext(To& to, const From& x, Rounding_Dir dir) {
12972  if (!ext_to_handle<From_Policy>(x)) {
12973    goto native;
12974  }
12975  if (is_nan<From_Policy>(x)) {
12976    return assign_special<To_Policy>(to, VC_NAN, ROUND_IGNORE);
12977  }
12978  else if (is_minf<From_Policy>(x)) {
12979    return assign_nan<To_Policy>(to, V_SQRT_NEG);
12980  }
12981  else if (is_pinf<From_Policy>(x)) {
12982    return assign_special<To_Policy>(to, VC_PLUS_INFINITY, dir);
12983  }
12984  else {
12985  native:
12986    return sqrt<To_Policy, From_Policy>(to, x, dir);
12987  }
12988}
12989
12990template <typename To_Policy, typename From1_Policy, typename From2_Policy,
12991          typename To, typename From1, typename From2>
12992inline Result
12993gcd_ext(To& to, const From1& x, const From2& y, Rounding_Dir dir) {
12994  if (is_nan<From1_Policy>(x) || is_nan<From2_Policy>(y)) {
12995    return assign_special<To_Policy>(to, VC_NAN, ROUND_IGNORE);
12996  }
12997  else if (is_minf<From1_Policy>(x) || is_pinf<From1_Policy>(x)) {
12998    return abs_ext<To_Policy, From2_Policy>(to, y, dir);
12999  }
13000  else if (is_minf<From2_Policy>(y) || is_pinf<From2_Policy>(y)) {
13001    return abs_ext<To_Policy, From1_Policy>(to, x, dir);
13002  }
13003  else {
13004    return gcd<To_Policy, From1_Policy, From2_Policy>(to, x, y, dir);
13005  }
13006}
13007
13008template <typename To1_Policy, typename To2_Policy, typename To3_Policy,
13009          typename From1_Policy, typename From2_Policy,
13010          typename To1, typename To2, typename To3,
13011          typename From1, typename From2>
13012inline Result
13013gcdext_ext(To1& to, To2& s, To3& t, const From1& x, const From2& y,
13014           Rounding_Dir dir) {
13015  if (is_nan<From1_Policy>(x) || is_nan<From2_Policy>(y)) {
13016    return assign_special<To1_Policy>(to, VC_NAN, ROUND_IGNORE);
13017  }
13018  else if (is_minf<From1_Policy>(x) || is_pinf<From1_Policy>(x)) {
13019    s = 0;
13020    t = y > 0 ? -1 : 1;
13021    return abs_ext<To1_Policy, From2_Policy>(to, y, dir);
13022  }
13023  else if (is_minf<From2_Policy>(y) || is_pinf<From2_Policy>(y)) {
13024    s = x > 0 ? -1 : 1;
13025    t = 0;
13026    return abs_ext<To1_Policy, From1_Policy>(to, x, dir);
13027  }
13028  else {
13029    return gcdext<To1_Policy, To2_Policy, To3_Policy, From1_Policy, From2_Policy>(to, s, t, x, y, dir);
13030  }
13031}
13032
13033template <typename To_Policy, typename From1_Policy, typename From2_Policy,
13034          typename To, typename From1, typename From2>
13035inline Result
13036lcm_ext(To& to, const From1& x, const From2& y, Rounding_Dir dir) {
13037  if (is_nan<From1_Policy>(x) || is_nan<From2_Policy>(y)) {
13038    return assign_special<To_Policy>(to, VC_NAN, ROUND_IGNORE);
13039  }
13040  else if (is_minf<From1_Policy>(x) || is_pinf<From1_Policy>(x)
13041           || is_minf<From2_Policy>(y) || is_pinf<From2_Policy>(y)) {
13042    return assign_special<To_Policy>(to, VC_PLUS_INFINITY, dir);
13043  }
13044  else {
13045    return lcm<To_Policy, From1_Policy, From2_Policy>(to, x, y, dir);
13046  }
13047}
13048
13049template <typename Policy1, typename Policy2,
13050          typename Type1, typename Type2>
13051inline Result_Relation
13052cmp_ext(const Type1& x, const Type2& y) {
13053  if (!ext_to_handle<Policy1>(x) && !ext_to_handle<Policy2>(y)) {
13054    goto native;
13055  }
13056  if (is_nan<Policy1>(x) || is_nan<Policy2>(y)) {
13057    return VR_EMPTY;
13058  }
13059  else if (is_minf<Policy1>(x)) {
13060    return is_minf<Policy2>(y) ? VR_EQ : VR_LT;
13061  }
13062  else if (is_pinf<Policy1>(x)) {
13063    return is_pinf<Policy2>(y) ? VR_EQ : VR_GT;
13064  }
13065  else {
13066    if (is_minf<Policy2>(y)) {
13067      return VR_GT;
13068    }
13069    if (is_pinf<Policy2>(y)) {
13070      return VR_LT;
13071    }
13072  native:
13073    return cmp<Policy1, Policy2>(x, y);
13074  }
13075}
13076
13077template <typename Policy1, typename Policy2,
13078          typename Type1, typename Type2>
13079inline bool
13080lt_ext(const Type1& x, const Type2& y) {
13081  if (!ext_to_handle<Policy1>(x) && !ext_to_handle<Policy2>(y)) {
13082    goto native;
13083  }
13084  if (is_nan<Policy1>(x) || is_nan<Policy2>(y)) {
13085    return false;
13086  }
13087  if (is_pinf<Policy1>(x) || is_minf<Policy2>(y)) {
13088    return false;
13089  }
13090  if (is_minf<Policy1>(x) || is_pinf<Policy2>(y)) {
13091    return true;
13092  }
13093 native:
13094  return lt_p<Policy1, Policy2>(x, y);
13095}
13096
13097template <typename Policy1, typename Policy2,
13098          typename Type1, typename Type2>
13099inline bool
13100gt_ext(const Type1& x, const Type2& y) {
13101  return lt_ext<Policy1, Policy2>(y, x);
13102}
13103
13104template <typename Policy1, typename Policy2,
13105          typename Type1, typename Type2>
13106inline bool
13107le_ext(const Type1& x, const Type2& y) {
13108  if (!ext_to_handle<Policy1>(x) && !ext_to_handle<Policy2>(y)) {
13109    goto native;
13110  }
13111  if (is_nan<Policy1>(x) || is_nan<Policy2>(y)) {
13112    return false;
13113  }
13114  if (is_minf<Policy1>(x) || is_pinf<Policy2>(y)) {
13115    return true;
13116  }
13117  if (is_pinf<Policy1>(x) || is_minf<Policy2>(y)) {
13118    return false;
13119  }
13120 native:
13121  return le_p<Policy1, Policy2>(x, y);
13122}
13123
13124template <typename Policy1, typename Policy2,
13125          typename Type1, typename Type2>
13126inline bool
13127ge_ext(const Type1& x, const Type2& y) {
13128  return le_ext<Policy1, Policy2>(y, x);
13129}
13130
13131template <typename Policy1, typename Policy2,
13132          typename Type1, typename Type2>
13133inline bool
13134eq_ext(const Type1& x, const Type2& y) {
13135  if (!ext_to_handle<Policy1>(x) && !ext_to_handle<Policy2>(y)) {
13136    goto native;
13137  }
13138  if (is_nan<Policy1>(x) || is_nan<Policy2>(y)) {
13139    return false;
13140  }
13141  if (is_minf<Policy1>(x)) {
13142    return is_minf<Policy2>(y);
13143  }
13144  if (is_pinf<Policy1>(x)) {
13145    return is_pinf<Policy2>(y);
13146  }
13147  else if (is_minf<Policy2>(y) || is_pinf<Policy2>(y)) {
13148    return false;
13149  }
13150 native:
13151  return eq_p<Policy1, Policy2>(x, y);
13152}
13153
13154template <typename Policy1, typename Policy2,
13155          typename Type1, typename Type2>
13156inline bool
13157ne_ext(const Type1& x, const Type2& y) {
13158  return !eq_ext<Policy1, Policy2>(x, y);
13159}
13160
13161template <typename Policy, typename Type>
13162inline Result
13163output_ext(std::ostream& os, const Type& x,
13164           const Numeric_Format& format, Rounding_Dir dir) {
13165  if (!ext_to_handle<Policy>(x)) {
13166    goto native;
13167  }
13168  if (is_nan<Policy>(x)) {
13169    os << "nan";
13170    return V_NAN;
13171  }
13172  if (is_minf<Policy>(x)) {
13173    os << "-inf";
13174    return V_EQ;
13175  }
13176  if (is_pinf<Policy>(x)) {
13177    os << "+inf";
13178    return V_EQ;
13179  }
13180 native:
13181  return output<Policy>(os, x, format, dir);
13182}
13183
13184template <typename To_Policy, typename To>
13185inline Result
13186input_ext(To& to, std::istream& is, Rounding_Dir dir) {
13187  return input<To_Policy>(to, is, dir);
13188}
13189
13190} // namespace Checked
13191
13192} // namespace Parma_Polyhedra_Library
13193
13194/* Automatically generated from PPL source file ../src/checked_defs.hh line 706. */
13195
13196#undef nonconst
13197#ifdef PPL_SAVED_nonconst
13198#define nonconst PPL_SAVED_nonconst
13199#undef PPL_SAVED_nonconst
13200#endif
13201
13202#undef PPL_FUNCTION_CLASS
13203#undef PPL_NAN
13204
13205/* Automatically generated from PPL source file ../src/Checked_Number_defs.hh line 31. */
13206#include <iosfwd>
13207
13208namespace Parma_Polyhedra_Library {
13209
13210#ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
13211/*! \ingroup PPL_CXX_interface */
13212#endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
13213struct Extended_Number_Policy {
13214  const_bool_nodef(check_overflow, true);
13215  const_bool_nodef(check_inf_add_inf, false);
13216  const_bool_nodef(check_inf_sub_inf, false);
13217  const_bool_nodef(check_inf_mul_zero, false);
13218  const_bool_nodef(check_div_zero, false);
13219  const_bool_nodef(check_inf_div_inf, false);
13220  const_bool_nodef(check_inf_mod, false);
13221  const_bool_nodef(check_sqrt_neg, false);
13222  const_bool_nodef(has_nan, true);
13223  const_bool_nodef(has_infinity, true);
13224
13225  // `convertible' is intentionally not defined: the compile time
13226  // error on conversions is the expected behavior.
13227
13228  const_bool_nodef(fpu_check_inexact, true);
13229  const_bool_nodef(fpu_check_nan_result, true);
13230
13231  // ROUND_DEFAULT_CONSTRUCTOR is intentionally not defined.
13232  // ROUND_DEFAULT_OPERATOR is intentionally not defined.
13233  // ROUND_DEFAULT_FUNCTION is intentionally not defined.
13234  // ROUND_DEFAULT_INPUT is intentionally not defined.
13235  // ROUND_DEFAULT_OUTPUT is intentionally not defined.
13236
13237  static void handle_result(Result r);
13238};
13239
13240#ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
13241//! A policy checking for overflows.
13242/*! \ingroup PPL_CXX_interface */
13243#endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
13244template <typename T>
13245struct Check_Overflow_Policy {
13246  const_bool_nodef(check_overflow, true);
13247  const_bool_nodef(check_inf_add_inf, false);
13248  const_bool_nodef(check_inf_sub_inf, false);
13249  const_bool_nodef(check_inf_mul_zero, false);
13250  const_bool_nodef(check_div_zero, false);
13251  const_bool_nodef(check_inf_div_inf, false);
13252  const_bool_nodef(check_inf_mod, false);
13253  const_bool_nodef(check_sqrt_neg, false);
13254  const_bool_nodef(has_nan, std::numeric_limits<T>::has_quiet_NaN);
13255  const_bool_nodef(has_infinity, std::numeric_limits<T>::has_infinity);
13256  const_bool_nodef(convertible, true);
13257  const_bool_nodef(fpu_check_inexact, true);
13258  const_bool_nodef(fpu_check_nan_result, true);
13259};
13260
13261#ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
13262/*! \ingroup PPL_CXX_interface */
13263#endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
13264template <typename T, typename Enable = void>
13265struct Native_Checked_From_Wrapper;
13266
13267#ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
13268/*! \ingroup PPL_CXX_interface */
13269#endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
13270template <typename T>
13271struct Native_Checked_From_Wrapper<T, typename Enable_If<Is_Native<T>::value>::type> {
13272  typedef Checked_Number_Transparent_Policy<T> Policy;
13273  static const T& raw_value(const T& v) {
13274    return v;
13275  }
13276};
13277
13278#ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
13279/*! \ingroup PPL_CXX_interface */
13280#endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
13281template <typename T, typename P>
13282struct Native_Checked_From_Wrapper<Checked_Number<T, P> > {
13283  typedef P Policy;
13284  static const T& raw_value(const Checked_Number<T, P>& v) {
13285    return v.raw_value();
13286  }
13287};
13288
13289#ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
13290/*! \ingroup PPL_CXX_interface */
13291#endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
13292template <typename T, typename Enable = void>
13293struct Native_Checked_To_Wrapper;
13294
13295#ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
13296/*! \ingroup PPL_CXX_interface */
13297#endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
13298template <typename T>
13299struct Native_Checked_To_Wrapper<T, typename Enable_If<Is_Native<T>::value>::type> {
13300  typedef Check_Overflow_Policy<T> Policy;
13301  static T& raw_value(T& v) {
13302    return v;
13303  }
13304};
13305
13306#ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
13307/*! \ingroup PPL_CXX_interface */
13308#endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
13309template <typename T, typename P>
13310struct Native_Checked_To_Wrapper<Checked_Number<T, P> > {
13311  typedef P Policy;
13312  static T& raw_value(Checked_Number<T, P>& v) {
13313    return v.raw_value();
13314  }
13315};
13316
13317#ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
13318/*! \ingroup PPL_CXX_interface */
13319#endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
13320template <typename T>
13321struct Is_Checked : public False { };
13322
13323#ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
13324/*! \ingroup PPL_CXX_interface */
13325#endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
13326template <typename T, typename P>
13327struct Is_Checked<Checked_Number<T, P> > : public True { };
13328
13329#ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
13330/*! \ingroup PPL_CXX_interface */
13331#endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
13332template <typename T>
13333struct Is_Native_Or_Checked
13334  : public Bool<Is_Native<T>::value || Is_Checked<T>::value> { };
13335
13336//! A wrapper for numeric types implementing a given policy.
13337/*! \ingroup PPL_CXX_interface
13338  The wrapper and related functions implement an interface which is common
13339  to all kinds of coefficient types, therefore allowing for a uniform
13340  coding style. This class also implements the policy encoded by the
13341  second template parameter. The default policy is to perform the detection
13342  of overflow errors.
13343*/
13344template <typename T, typename Policy>
13345class Checked_Number {
13346public:
13347
13348  //! \name Constructors
13349  //@{
13350
13351  //! Default constructor.
13352  Checked_Number();
13353
13354  //! Copy constructor.
13355  Checked_Number(const Checked_Number& y);
13356
13357  //! Direct initialization from a Checked_Number and rounding mode.
13358  template <typename From, typename From_Policy>
13359  Checked_Number(const Checked_Number<From, From_Policy>& y, Rounding_Dir dir);
13360
13361  //! Direct initialization from a plain char and rounding mode.
13362  Checked_Number(char y, Rounding_Dir dir);
13363
13364  //! Direct initialization from a signed char and rounding mode.
13365  Checked_Number(signed char y, Rounding_Dir dir);
13366
13367  //! Direct initialization from a signed short and rounding mode.
13368  Checked_Number(signed short y, Rounding_Dir dir);
13369
13370  //! Direct initialization from a signed int and rounding mode.
13371  Checked_Number(signed int y, Rounding_Dir dir);
13372
13373  //! Direct initialization from a signed long and rounding mode.
13374  Checked_Number(signed long y, Rounding_Dir dir);
13375
13376  //! Direct initialization from a signed long long and rounding mode.
13377  Checked_Number(signed long long y, Rounding_Dir dir);
13378
13379  //! Direct initialization from an unsigned char and rounding mode.
13380  Checked_Number(unsigned char y, Rounding_Dir dir);
13381
13382  //! Direct initialization from an unsigned short and rounding mode.
13383  Checked_Number(unsigned short y, Rounding_Dir dir);
13384
13385  //! Direct initialization from an unsigned int and rounding mode.
13386  Checked_Number(unsigned int y, Rounding_Dir dir);
13387
13388  //! Direct initialization from an unsigned long and rounding mode.
13389  Checked_Number(unsigned long y, Rounding_Dir dir);
13390
13391  //! Direct initialization from an unsigned long long and rounding mode.
13392  Checked_Number(unsigned long long y, Rounding_Dir dir);
13393
13394#if PPL_SUPPORTED_FLOAT
13395  //! Direct initialization from a float and rounding mode.
13396  Checked_Number(float y, Rounding_Dir dir);
13397#endif
13398
13399#if PPL_SUPPORTED_DOUBLE
13400  //! Direct initialization from a double and rounding mode.
13401  Checked_Number(double y, Rounding_Dir dir);
13402#endif
13403
13404#if PPL_SUPPORTED_LONG_DOUBLE
13405  //! Direct initialization from a long double and rounding mode.
13406  Checked_Number(long double y, Rounding_Dir dir);
13407#endif
13408
13409  //! Direct initialization from a rational and rounding mode.
13410  Checked_Number(const mpq_class& y, Rounding_Dir dir);
13411
13412  //! Direct initialization from an unbounded integer and rounding mode.
13413  Checked_Number(const mpz_class& y, Rounding_Dir dir);
13414
13415  //! Direct initialization from a C string and rounding mode.
13416  Checked_Number(const char* y, Rounding_Dir dir);
13417
13418  //! Direct initialization from special and rounding mode.
13419  template <typename From>
13420  Checked_Number(const From&, Rounding_Dir dir,
13421                 typename Enable_If<Is_Special<From>::value, bool>::type
13422                 ignored = false);
13423
13424  //! Direct initialization from a Checked_Number, default rounding mode.
13425  template <typename From, typename From_Policy>
13426  explicit Checked_Number(const Checked_Number<From, From_Policy>& y);
13427
13428  //! Direct initialization from a plain char, default rounding mode.
13429  Checked_Number(char y);
13430
13431  //! Direct initialization from a signed char, default rounding mode.
13432  Checked_Number(signed char y);
13433
13434  //! Direct initialization from a signed short, default rounding mode.
13435  Checked_Number(signed short y);
13436
13437  //! Direct initialization from a signed int, default rounding mode.
13438  Checked_Number(signed int y);
13439
13440  //! Direct initialization from a signed long, default rounding mode.
13441  Checked_Number(signed long y);
13442
13443  //! Direct initialization from a signed long long, default rounding mode.
13444  Checked_Number(signed long long y);
13445
13446  //! Direct initialization from an unsigned char, default rounding mode.
13447  Checked_Number(unsigned char y);
13448
13449  //! Direct initialization from an unsigned short, default rounding mode.
13450  Checked_Number(unsigned short y);
13451
13452  //! Direct initialization from an unsigned int, default rounding mode.
13453  Checked_Number(unsigned int y);
13454
13455  //! Direct initialization from an unsigned long, default rounding mode.
13456  Checked_Number(unsigned long y);
13457
13458  //! Direct initialization from an unsigned long long, default rounding mode.
13459  Checked_Number(unsigned long long y);
13460
13461  //! Direct initialization from a float, default rounding mode.
13462  Checked_Number(float y);
13463
13464  //! Direct initialization from a double, default rounding mode.
13465  Checked_Number(double y);
13466
13467  //! Direct initialization from a long double, default rounding mode.
13468  Checked_Number(long double y);
13469
13470  //! Direct initialization from a rational, default rounding mode.
13471  Checked_Number(const mpq_class& y);
13472
13473  //! Direct initialization from an unbounded integer, default rounding mode.
13474  Checked_Number(const mpz_class& y);
13475
13476  //! Direct initialization from a C string, default rounding mode.
13477  Checked_Number(const char* y);
13478
13479  //! Direct initialization from special, default rounding mode
13480  template <typename From>
13481  Checked_Number(const From&, typename Enable_If<Is_Special<From>::value, bool>::type ignored = false);
13482
13483
13484  //@} // Constructors
13485
13486  //! \name Accessors and Conversions
13487  //@{
13488
13489  //! Conversion operator: returns a copy of the underlying numeric value.
13490  operator T() const;
13491
13492  //! Returns a reference to the underlying numeric value.
13493  T& raw_value();
13494
13495  //! Returns a const reference to the underlying numeric value.
13496  const T& raw_value() const;
13497
13498  //@} // Accessors and Conversions
13499
13500  //! Checks if all the invariants are satisfied.
13501  bool OK() const;
13502
13503  //! Classifies *this.
13504  /*!
13505    Returns the appropriate Result characterizing:
13506    - whether \p *this is NaN,
13507      if \p nan is <CODE>true</CODE>;
13508    - whether \p *this is a (positive or negative) infinity,
13509      if \p inf is <CODE>true</CODE>;
13510    - the sign of \p *this,
13511      if \p sign is <CODE>true</CODE>.
13512  */
13513  Result classify(bool nan = true, bool inf = true, bool sign = true) const;
13514
13515  //! \name Assignment Operators
13516  //@{
13517
13518  //! Assignment operator.
13519  Checked_Number& operator=(const Checked_Number& y);
13520
13521  //! Assignment operator.
13522  template <typename From>
13523  Checked_Number& operator=(const From& y);
13524
13525  //! Add and assign operator.
13526  template <typename From_Policy>
13527  Checked_Number& operator+=(const Checked_Number<T, From_Policy>& y);
13528
13529  //! Add and assign operator.
13530  Checked_Number& operator+=(const T& y);
13531
13532  //! Add and assign operator.
13533  template <typename From>
13534  typename Enable_If<Is_Native_Or_Checked<From>::value,
13535                     Checked_Number<T, Policy>&>::type
13536  operator+=(const From& y);
13537
13538  //! Subtract and assign operator.
13539  template <typename From_Policy>
13540  Checked_Number& operator-=(const Checked_Number<T, From_Policy>& y);
13541
13542  //! Subtract and assign operator.
13543  Checked_Number& operator-=(const T& y);
13544
13545  //! Subtract and assign operator.
13546  template <typename From>
13547  typename Enable_If<Is_Native_Or_Checked<From>::value,
13548                     Checked_Number<T, Policy>&>::type
13549  operator-=(const From& y);
13550
13551  //! Multiply and assign operator.
13552  template <typename From_Policy>
13553  Checked_Number& operator*=(const Checked_Number<T, From_Policy>& y);
13554
13555  //! Multiply and assign operator.
13556  Checked_Number& operator*=(const T& y);
13557
13558  //! Multiply and assign operator.
13559  template <typename From>
13560  typename Enable_If<Is_Native_Or_Checked<From>::value,
13561                     Checked_Number<T, Policy>&>::type
13562  operator*=(const From& y);
13563
13564  //! Divide and assign operator.
13565  template <typename From_Policy>
13566  Checked_Number& operator/=(const Checked_Number<T, From_Policy>& y);
13567
13568  //! Divide and assign operator.
13569  Checked_Number& operator/=(const T& y);
13570
13571  //! Divide and assign operator.
13572  template <typename From>
13573  typename Enable_If<Is_Native_Or_Checked<From>::value,
13574                     Checked_Number<T, Policy>&>::type
13575  operator/=(const From& y);
13576
13577  //! Compute remainder and assign operator.
13578  template <typename From_Policy>
13579  Checked_Number& operator%=(const Checked_Number<T, From_Policy>& y);
13580
13581  //! Compute remainder and assign operator.
13582  Checked_Number& operator%=(const T& y);
13583
13584  //! Compute remainder and assign operator.
13585  template <typename From>
13586  typename Enable_If<Is_Native_Or_Checked<From>::value,
13587                     Checked_Number<T, Policy>& >::type
13588  operator%=(const From& y);
13589
13590  //@} // Assignment Operators
13591
13592
13593  //! \name Increment and Decrement Operators
13594  //@{
13595
13596  //! Pre-increment operator.
13597  Checked_Number& operator++();
13598
13599  //! Post-increment operator.
13600  Checked_Number  operator++(int);
13601
13602  //! Pre-decrement operator.
13603  Checked_Number& operator--();
13604
13605  //! Post-decrement operator.
13606  Checked_Number  operator--(int);
13607
13608  //@} // Increment and Decrement Operators
13609
13610private:
13611  //! The underlying numeric value.
13612  T v;
13613};
13614
13615#ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
13616/*! \ingroup PPL_CXX_interface */
13617#endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
13618template <typename T, typename P>
13619struct Slow_Copy<Checked_Number<T, P> > : public Bool<Slow_Copy<T>::value> {};
13620
13621/*! \relates Checked_Number */
13622template <typename T>
13623typename Enable_If<Is_Native_Or_Checked<T>::value, bool>::type
13624is_not_a_number(const T& x);
13625
13626/*! \relates Checked_Number */
13627template <typename T>
13628typename Enable_If<Is_Native_Or_Checked<T>::value, bool>::type
13629is_minus_infinity(const T& x);
13630
13631/*! \relates Checked_Number */
13632template <typename T>
13633typename Enable_If<Is_Native_Or_Checked<T>::value, bool>::type
13634is_plus_infinity(const T& x);
13635
13636/*! \relates Checked_Number */
13637template <typename T>
13638typename Enable_If<Is_Native_Or_Checked<T>::value, int>::type
13639infinity_sign(const T& x);
13640
13641/*! \relates Checked_Number */
13642template <typename T>
13643typename Enable_If<Is_Native_Or_Checked<T>::value, bool>::type
13644is_integer(const T& x);
13645
13646/*! \relates Checked_Number */
13647template <typename To, typename From>
13648typename Enable_If<Is_Native_Or_Checked<To>::value && Is_Special<From>::value, Result>::type
13649construct(To& to, const From& x, Rounding_Dir dir);
13650
13651/*! \relates Checked_Number */
13652template <typename To, typename From>
13653typename Enable_If<Is_Native_Or_Checked<To>::value && Is_Special<From>::value, Result>::type
13654assign_r(To& to, const From& x, Rounding_Dir dir);
13655
13656/*! \relates Checked_Number */
13657template <typename To>
13658typename Enable_If<Is_Native_Or_Checked<To>::value, Result>::type
13659assign_r(To& to, const char* x, Rounding_Dir dir);
13660
13661/*! \relates Checked_Number */
13662template <typename To, typename To_Policy>
13663typename Enable_If<Is_Native_Or_Checked<To>::value, Result>::type
13664assign_r(To& to, char* x, Rounding_Dir dir);
13665
13666#define PPL_DECLARE_FUNC1_A(name) \
13667template <typename To, typename From> \
13668typename Enable_If<Is_Native_Or_Checked<To>::value \
13669                   && Is_Native_Or_Checked<From>::value, \
13670                   Result>::type \
13671 PPL_U(name)(To& to, const From& x, Rounding_Dir dir);
13672
13673PPL_DECLARE_FUNC1_A(assign_r)
13674PPL_DECLARE_FUNC1_A(floor_assign_r)
13675PPL_DECLARE_FUNC1_A(ceil_assign_r)
13676PPL_DECLARE_FUNC1_A(trunc_assign_r)
13677PPL_DECLARE_FUNC1_A(neg_assign_r)
13678PPL_DECLARE_FUNC1_A(abs_assign_r)
13679PPL_DECLARE_FUNC1_A(sqrt_assign_r)
13680
13681#undef PPL_DECLARE_FUNC1_A
13682
13683#define PPL_DECLARE_FUNC1_B(name) \
13684template <typename To, typename From> \
13685typename Enable_If<Is_Native_Or_Checked<To>::value \
13686                   && Is_Native_Or_Checked<From>::value, \
13687                   Result>::type \
13688 PPL_U(name)(To& to, const From& x, unsigned int exp, Rounding_Dir dir);
13689
13690PPL_DECLARE_FUNC1_B(add_2exp_assign_r)
13691PPL_DECLARE_FUNC1_B(sub_2exp_assign_r)
13692PPL_DECLARE_FUNC1_B(mul_2exp_assign_r)
13693PPL_DECLARE_FUNC1_B(div_2exp_assign_r)
13694PPL_DECLARE_FUNC1_B(smod_2exp_assign_r)
13695PPL_DECLARE_FUNC1_B(umod_2exp_assign_r)
13696
13697#undef PPL_DECLARE_FUNC1_B
13698
13699#define PPL_DECLARE_FUNC2(name) \
13700template <typename To, typename From1, typename From2> \
13701typename Enable_If<Is_Native_Or_Checked<To>::value \
13702                   && Is_Native_Or_Checked<From1>::value \
13703                   && Is_Native_Or_Checked<From2>::value, \
13704                   Result>::type \
13705 PPL_U(name)(To& to, const From1& x, const From2& y, Rounding_Dir dir);
13706
13707PPL_DECLARE_FUNC2(add_assign_r)
13708PPL_DECLARE_FUNC2(sub_assign_r)
13709PPL_DECLARE_FUNC2(mul_assign_r)
13710PPL_DECLARE_FUNC2(div_assign_r)
13711PPL_DECLARE_FUNC2(idiv_assign_r)
13712PPL_DECLARE_FUNC2(rem_assign_r)
13713PPL_DECLARE_FUNC2(gcd_assign_r)
13714PPL_DECLARE_FUNC2(lcm_assign_r)
13715PPL_DECLARE_FUNC2(add_mul_assign_r)
13716PPL_DECLARE_FUNC2(sub_mul_assign_r)
13717
13718#undef PPL_DECLARE_FUNC2
13719
13720#define PPL_DECLARE_FUNC4(name) \
13721template <typename To1, typename To2, typename To3, \
13722          typename From1, typename From2> \
13723typename Enable_If<Is_Native_Or_Checked<To1>::value \
13724                   && Is_Native_Or_Checked<To2>::value \
13725                   && Is_Native_Or_Checked<To3>::value \
13726                   && Is_Native_Or_Checked<From1>::value \
13727                   && Is_Native_Or_Checked<From2>::value, \
13728                   Result>::type \
13729 PPL_U(name)(To1& to, To2& s, To3& t,     \
13730     const From1& x, const From2& y, \
13731     Rounding_Dir dir);
13732
13733PPL_DECLARE_FUNC4(gcdext_assign_r)
13734
13735#undef PPL_DECLARE_FUNC4
13736
13737//! \name Accessor Functions
13738//@{
13739
13740//@} // Accessor Functions
13741
13742//! \name Memory Size Inspection Functions
13743//@{
13744
13745//! Returns the total size in bytes of the memory occupied by \p x.
13746/*! \relates Checked_Number */
13747template <typename T, typename Policy>
13748memory_size_type
13749total_memory_in_bytes(const Checked_Number<T, Policy>& x);
13750
13751//! Returns the size in bytes of the memory managed by \p x.
13752/*! \relates Checked_Number */
13753template <typename T, typename Policy>
13754memory_size_type
13755external_memory_in_bytes(const Checked_Number<T, Policy>& x);
13756
13757//@} // Memory Size Inspection Functions
13758
13759//! \name Arithmetic Operators
13760//@{
13761
13762//! Unary plus operator.
13763/*! \relates Checked_Number */
13764template <typename T, typename Policy>
13765Checked_Number<T, Policy>
13766operator+(const Checked_Number<T, Policy>& x);
13767
13768//! Unary minus operator.
13769/*! \relates Checked_Number */
13770template <typename T, typename Policy>
13771Checked_Number<T, Policy>
13772operator-(const Checked_Number<T, Policy>& x);
13773
13774//! Assigns to \p x largest integral value not greater than \p x.
13775/*! \relates Checked_Number */
13776template <typename T, typename Policy>
13777void
13778floor_assign(Checked_Number<T, Policy>& x);
13779
13780//! Assigns to \p x largest integral value not greater than \p y.
13781/*! \relates Checked_Number */
13782template <typename T, typename Policy>
13783void
13784floor_assign(Checked_Number<T, Policy>& x, const Checked_Number<T, Policy>& y);
13785
13786//! Assigns to \p x smallest integral value not less than \p x.
13787/*! \relates Checked_Number */
13788template <typename T, typename Policy>
13789void
13790ceil_assign(Checked_Number<T, Policy>& x);
13791
13792//! Assigns to \p x smallest integral value not less than \p y.
13793/*! \relates Checked_Number */
13794template <typename T, typename Policy>
13795void
13796ceil_assign(Checked_Number<T, Policy>& x, const Checked_Number<T, Policy>& y);
13797
13798//! Round \p x to the nearest integer not larger in absolute value.
13799/*! \relates Checked_Number */
13800template <typename T, typename Policy>
13801void
13802trunc_assign(Checked_Number<T, Policy>& x);
13803
13804//! Assigns to \p x the value of \p y rounded to the nearest integer not larger in absolute value.
13805/*! \relates Checked_Number */
13806template <typename T, typename Policy>
13807void
13808trunc_assign(Checked_Number<T, Policy>& x, const Checked_Number<T, Policy>& y);
13809
13810//! Assigns to \p x its negation.
13811/*! \relates Checked_Number */
13812template <typename T, typename Policy>
13813void
13814neg_assign(Checked_Number<T, Policy>& x);
13815
13816//! Assigns to \p x the negation of \p y.
13817/*! \relates Checked_Number */
13818template <typename T, typename Policy>
13819void
13820neg_assign(Checked_Number<T, Policy>& x, const Checked_Number<T, Policy>& y);
13821
13822//! Assigns to \p x its absolute value.
13823/*! \relates Checked_Number */
13824template <typename T, typename Policy>
13825void
13826abs_assign(Checked_Number<T, Policy>& x);
13827
13828//! Assigns to \p x the absolute value of \p y.
13829/*! \relates Checked_Number */
13830template <typename T, typename Policy>
13831void
13832abs_assign(Checked_Number<T, Policy>& x, const Checked_Number<T, Policy>& y);
13833
13834//! Assigns to \p x the value <CODE>x + y * z</CODE>.
13835/*! \relates Checked_Number */
13836template <typename T, typename Policy>
13837void
13838add_mul_assign(Checked_Number<T, Policy>& x,
13839               const Checked_Number<T, Policy>& y,
13840               const Checked_Number<T, Policy>& z);
13841
13842//! Assigns to \p x the value <CODE>x - y * z</CODE>.
13843/*! \relates Checked_Number */
13844template <typename T, typename Policy>
13845void
13846sub_mul_assign(Checked_Number<T, Policy>& x,
13847               const Checked_Number<T, Policy>& y,
13848               const Checked_Number<T, Policy>& z);
13849
13850//! Assigns to \p x the greatest common divisor of \p y and \p z.
13851/*! \relates Checked_Number */
13852template <typename T, typename Policy>
13853void
13854gcd_assign(Checked_Number<T, Policy>& x,
13855           const Checked_Number<T, Policy>& y,
13856           const Checked_Number<T, Policy>& z);
13857
13858/*! \brief
13859  Assigns to \p x the greatest common divisor of \p y and \p z,
13860  setting \p s and \p t such that s*y + t*z = x = gcd(y, z).
13861*/
13862/*! \relates Checked_Number */
13863template <typename T, typename Policy>
13864void
13865gcdext_assign(Checked_Number<T, Policy>& x,
13866              Checked_Number<T, Policy>& s,
13867              Checked_Number<T, Policy>& t,
13868              const Checked_Number<T, Policy>& y,
13869              const Checked_Number<T, Policy>& z);
13870
13871//! Assigns to \p x the least common multiple of \p y and \p z.
13872/*! \relates Checked_Number */
13873template <typename T, typename Policy>
13874void
13875lcm_assign(Checked_Number<T, Policy>& x,
13876           const Checked_Number<T, Policy>& y,
13877           const Checked_Number<T, Policy>& z);
13878
13879//! Assigns to \p x the value \f$ y \cdot 2^\mathtt{exp} \f$.
13880/*! \relates Checked_Number */
13881template <typename T, typename Policy>
13882void
13883mul_2exp_assign(Checked_Number<T, Policy>& x,
13884                const Checked_Number<T, Policy>& y,
13885                unsigned int exp);
13886
13887//! Assigns to \p x the value \f$ y / 2^\mathtt{exp} \f$.
13888/*! \relates Checked_Number */
13889template <typename T, typename Policy>
13890void
13891div_2exp_assign(Checked_Number<T, Policy>& x,
13892                const Checked_Number<T, Policy>& y,
13893                unsigned int exp);
13894
13895/*! \brief
13896  If \p z divides \p y, assigns to \p x the quotient of the integer
13897  division of \p y and \p z.
13898
13899  \relates Checked_Number
13900  The behavior is undefined if \p z does not divide \p y.
13901*/
13902template <typename T, typename Policy>
13903void
13904exact_div_assign(Checked_Number<T, Policy>& x,
13905                 const Checked_Number<T, Policy>& y,
13906                 const Checked_Number<T, Policy>& z);
13907
13908//! Assigns to \p x the integer square root of \p y.
13909/*! \relates Checked_Number */
13910template <typename T, typename Policy>
13911void sqrt_assign(Checked_Number<T, Policy>& x,
13912                 const Checked_Number<T, Policy>& y);
13913
13914//@} // Arithmetic Operators
13915
13916
13917//! \name Relational Operators and Comparison Functions
13918//@{
13919
13920//! Equality operator.
13921/*! \relates Checked_Number */
13922template <typename T1, typename T2>
13923inline
13924typename Enable_If<Is_Native_Or_Checked<T1>::value
13925                   && Is_Native_Or_Checked<T2>::value
13926                   && (Is_Checked<T1>::value || Is_Checked<T2>::value),
13927                   bool>::type
13928operator==(const T1& x, const T2& y);
13929
13930/*! \relates Checked_Number */
13931template <typename T1, typename T2>
13932inline typename Enable_If<Is_Native_Or_Checked<T1>::value
13933                          && Is_Native_Or_Checked<T2>::value,
13934                          bool>::type
13935equal(const T1& x, const T2& y);
13936
13937//! Disequality operator.
13938/*! \relates Checked_Number */
13939template <typename T1, typename T2>
13940inline
13941typename Enable_If<Is_Native_Or_Checked<T1>::value
13942                   && Is_Native_Or_Checked<T2>::value
13943                   && (Is_Checked<T1>::value || Is_Checked<T2>::value),
13944                   bool>::type
13945operator!=(const T1& x, const T2& y);
13946
13947/*! \relates Checked_Number */
13948template <typename T1, typename T2>
13949inline typename Enable_If<Is_Native_Or_Checked<T1>::value
13950                          && Is_Native_Or_Checked<T2>::value,
13951                          bool>::type
13952not_equal(const T1& x, const T2& y);
13953
13954//! Greater than or equal to operator.
13955/*! \relates Checked_Number */
13956template <typename T1, typename T2>
13957inline
13958typename Enable_If<Is_Native_Or_Checked<T1>::value
13959                   && Is_Native_Or_Checked<T2>::value
13960                   && (Is_Checked<T1>::value || Is_Checked<T2>::value),
13961                   bool>::type
13962operator>=(const T1& x, const T2& y);
13963
13964/*! \relates Checked_Number */
13965template <typename T1, typename T2>
13966inline typename Enable_If<Is_Native_Or_Checked<T1>::value
13967                          && Is_Native_Or_Checked<T2>::value,
13968                          bool>::type
13969greater_or_equal(const T1& x, const T2& y);
13970
13971//! Greater than operator.
13972/*! \relates Checked_Number */
13973template <typename T1, typename T2>
13974inline
13975typename Enable_If<Is_Native_Or_Checked<T1>::value
13976                   && Is_Native_Or_Checked<T2>::value
13977                   && (Is_Checked<T1>::value || Is_Checked<T2>::value),
13978                   bool>::type
13979operator>(const T1& x, const T2& y);
13980
13981/*! \relates Checked_Number */
13982template <typename T1, typename T2>
13983inline typename Enable_If<Is_Native_Or_Checked<T1>::value
13984                          && Is_Native_Or_Checked<T2>::value,
13985                          bool>::type
13986greater_than(const T1& x, const T2& y);
13987
13988//! Less than or equal to operator.
13989/*! \relates Checked_Number */
13990template <typename T1, typename T2>
13991inline
13992typename Enable_If<Is_Native_Or_Checked<T1>::value
13993                   && Is_Native_Or_Checked<T2>::value
13994                   && (Is_Checked<T1>::value || Is_Checked<T2>::value),
13995                   bool>::type
13996operator<=(const T1& x, const T2& y);
13997
13998/*! \relates Checked_Number */
13999template <typename T1, typename T2>
14000inline typename Enable_If<Is_Native_Or_Checked<T1>::value
14001                          && Is_Native_Or_Checked<T2>::value,
14002                          bool>::type
14003less_or_equal(const T1& x, const T2& y);
14004
14005//! Less than operator.
14006/*! \relates Checked_Number */
14007template <typename T1, typename T2>
14008inline
14009typename Enable_If<Is_Native_Or_Checked<T1>::value
14010                   && Is_Native_Or_Checked<T2>::value
14011                   && (Is_Checked<T1>::value || Is_Checked<T2>::value),
14012                   bool>::type
14013operator<(const T1& x, const T2& y);
14014
14015/*! \relates Checked_Number */
14016template <typename T1, typename T2>
14017inline typename Enable_If<Is_Native_Or_Checked<T1>::value
14018                          && Is_Native_Or_Checked<T2>::value,
14019                          bool>::type
14020less_than(const T1& x, const T2& y);
14021
14022/*! \brief
14023  Returns \f$-1\f$, \f$0\f$ or \f$1\f$ depending on whether the value
14024  of \p x is negative, zero or positive, respectively.
14025
14026  \relates Checked_Number
14027*/
14028template <typename From>
14029inline typename Enable_If<Is_Native_Or_Checked<From>::value, int>::type \
14030sgn(const From& x);
14031
14032/*! \brief
14033  Returns a negative, zero or positive value depending on whether
14034  \p x is lower than, equal to or greater than \p y, respectively.
14035
14036  \relates Checked_Number
14037*/
14038template <typename From1, typename From2>
14039inline typename Enable_If<Is_Native_Or_Checked<From1>::value
14040                          && Is_Native_Or_Checked<From2>::value,
14041                          int>::type
14042cmp(const From1& x, const From2& y);
14043
14044//@} // Relational Operators and Comparison Functions
14045
14046//! \name Input-Output Operators
14047//@{
14048
14049/*! \relates Checked_Number */
14050template <typename T>
14051typename Enable_If<Is_Native_Or_Checked<T>::value, Result>::type
14052output(std::ostream& os,
14053       const T& x,
14054       const Numeric_Format& format,
14055       Rounding_Dir dir);
14056
14057//! Output operator.
14058/*! \relates Checked_Number */
14059template <typename T, typename Policy>
14060std::ostream&
14061operator<<(std::ostream& os, const Checked_Number<T, Policy>& x);
14062
14063//! Ascii dump for native or checked.
14064/*! \relates Checked_Number */
14065template <typename T>
14066typename Enable_If<Is_Native_Or_Checked<T>::value, void>::type
14067ascii_dump(std::ostream& s, const T& t);
14068
14069//! Input function.
14070/*!
14071  \relates Checked_Number
14072
14073  \param is
14074  Input stream to read from;
14075
14076  \param x
14077  Number (possibly extended) to assign to in case of successful reading;
14078
14079  \param dir
14080  Rounding mode to be applied.
14081
14082  \return
14083  Result of the input operation.  Success, success with imprecision,
14084  overflow, parsing error: all possibilities are taken into account,
14085  checked for, and properly reported.
14086
14087  This function attempts reading a (possibly extended) number from the given
14088  stream \p is, possibly rounding as specified by \p dir, assigning the result
14089  to \p x upon success, and returning the appropriate Result.
14090
14091  The input syntax allows the specification of:
14092  - plain base-10 integer numbers as <CODE>34976098</CODE>,
14093    <CODE>-77</CODE> and <CODE>+13</CODE>;
14094  - base-10 integer numbers in scientific notation as <CODE>15e2</CODE>
14095    and <CODE>15*^2</CODE> (both meaning \f$15 \cdot 10^2 = 1500\f$),
14096    <CODE>9200e-2</CODE> and <CODE>-18*^+11111111111111111</CODE>;
14097  - base-10 rational numbers in fraction notation as
14098    <CODE>15/3</CODE> and <CODE>15/-3</CODE>;
14099  - base-10 rational numbers in fraction/scientific notation as
14100    <CODE>15/30e-1</CODE> (meaning \f$5\f$) and <CODE>15*^-3/29e2</CODE>
14101    (meaning \f$3/580000\f$);
14102  - base-10 rational numbers in floating point notation as
14103    <CODE>71.3</CODE> (meaning \f$713/10\f$) and
14104    <CODE>-0.123456</CODE> (meaning \f$-1929/15625\f$);
14105  - base-10 rational numbers in floating point scientific notation as
14106    <CODE>2.2e-1</CODE> (meaning \f$11/50\f$) and <CODE>-2.20001*^+3</CODE>
14107    (meaning \f$-220001/100\f$);
14108  - integers and rationals (in fractional, floating point and scientific
14109    notations) specified by using Mathematica-style bases, in the range
14110    from 2 to 36, as
14111    <CODE>2^^11</CODE> (meaning \f$3\f$),
14112    <CODE>36^^z</CODE> (meaning \f$35\f$),
14113    <CODE>36^^xyz</CODE> (meaning \f$44027\f$),
14114    <CODE>2^^11.1</CODE> (meaning \f$7/2\f$),
14115    <CODE>10^^2e3</CODE> (meaning \f$2000\f$),
14116    <CODE>8^^2e3</CODE> (meaning \f$1024\f$),
14117    <CODE>8^^2.1e3</CODE> (meaning \f$1088\f$),
14118    <CODE>8^^20402543.120347e7</CODE> (meaning \f$9073863231288\f$),
14119    <CODE>8^^2.1</CODE> (meaning \f$17/8\f$);
14120    note that the base and the exponent are always written as plain
14121    base-10 integer numbers; also, when an ambiguity may arise, the
14122    character <CODE>e</CODE> is interpreted as a digit, so that
14123    <CODE>16^^1e2</CODE> (meaning \f$482\f$) is different from
14124    <CODE>16^^1*^2</CODE> (meaning \f$256\f$);
14125  - the C-style hexadecimal prefix <CODE>0x</CODE> is interpreted as
14126    the Mathematica-style prefix <CODE>16^^</CODE>;
14127  - the C-style binary exponent indicator <CODE>p</CODE> can only be used
14128    when base 16 has been specified; if used, the exponent will be
14129    applied to base 2 (instead of base 16, as is the case when the
14130    indicator <CODE>e</CODE> is used);
14131  - special values like <CODE>inf</CODE> and <CODE>+inf</CODE>
14132    (meaning \f$+\infty\f$), <CODE>-inf</CODE> (meaning \f$-\infty\f$),
14133    and <CODE>nan</CODE> (meaning "not a number").
14134
14135  The rationale behind the accepted syntax can be summarized as follows:
14136  - if the syntax is accepted by Mathematica, then this function
14137    accepts it with the same semantics;
14138  - if the syntax is acceptable as standard C++ integer or floating point
14139    literal (except for octal notation and type suffixes, which are not
14140    supported), then this function accepts it with the same semantics;
14141  - natural extensions of the above are accepted with the natural
14142    extensions of the semantics;
14143  - special values are accepted.
14144
14145  Valid syntax is more formally and completely specified by the
14146  following grammar, with the additional provisos that everything is
14147  <EM>case insensitive</EM>, that the syntactic category
14148  <CODE>BDIGIT</CODE> is further restricted by the current base
14149  and that for all bases above 14, any <CODE>e</CODE> is always
14150  interpreted as a digit and never as a delimiter for the exponent part
14151  (if such a delimiter is desired, it has to be written as <CODE>*^</CODE>).
14152
14153\code
14154number  : NAN                                   INF     : 'inf'
14155        | SIGN INF                                      ;
14156        | INF
14157        | num                                   NAN     : 'nan'
14158        | num DIV num                                   ;
14159        ;
14160                                                SIGN    : '-'
14161num     : u_num                                         | '+'
14162        | SIGN u_num                                    ;
14163
14164u_num   : u_num1                                EXP     : 'e'
14165        | HEX u_num1                                    | 'p'
14166        | base BASE u_num1                              | '*^'
14167        ;                                               ;
14168                                                POINT   : '.'
14169u_num1  : mantissa                                      ;
14170        | mantissa EXP exponent
14171        ;                                       DIV     : '/'
14172                                                        ;
14173mantissa: bdigits
14174        | POINT bdigits                         MINUS   : '-'
14175        | bdigits POINT                                 ;
14176        | bdigits POINT bdigits
14177        ;                                       PLUS    : '+'
14178                                                ;
14179exponent: SIGN digits
14180        | digits                                HEX     : '0x'
14181        ;                                       ;
14182
14183bdigits : BDIGIT                                BASE    : '^^'
14184        | bdigits BDIGIT                                ;
14185        ;
14186                                                DIGIT   : '0' .. '9'
14187digits  : DIGIT                                         ;
14188        | digits DIGIT
14189        ;                                       BDIGIT  : '0' .. '9'
14190                                                        | 'a' .. 'z'
14191                                                        ;
14192\endcode
14193*/
14194template <typename T>
14195typename Enable_If<Is_Native_Or_Checked<T>::value, Result>::type
14196input(T& x, std::istream& is, Rounding_Dir dir);
14197
14198//! Input operator.
14199/*! \relates Checked_Number */
14200template <typename T, typename Policy>
14201std::istream&
14202operator>>(std::istream& is, Checked_Number<T, Policy>& x);
14203
14204//! Ascii load for native or checked.
14205/*! \relates Checked_Number */
14206template <typename T>
14207typename Enable_If<Is_Native_Or_Checked<T>::value, bool>::type
14208ascii_load(std::ostream& s, T& t);
14209
14210//@} // Input-Output Operators
14211
14212void throw_result_exception(Result r);
14213
14214template <typename T>
14215T
14216plus_infinity();
14217
14218template <typename T>
14219T
14220minus_infinity();
14221
14222template <typename T>
14223T
14224not_a_number();
14225
14226//! Swaps \p x with \p y.
14227/*! \relates Checked_Number */
14228template <typename T, typename Policy>
14229void swap(Checked_Number<T, Policy>& x, Checked_Number<T, Policy>& y);
14230
14231template <typename T, typename Policy>
14232struct FPU_Related<Checked_Number<T, Policy> > : public FPU_Related<T> {};
14233
14234template <typename T>
14235void maybe_reset_fpu_inexact();
14236
14237template <typename T>
14238int maybe_check_fpu_inexact();
14239
14240} // namespace Parma_Polyhedra_Library
14241
14242/* Automatically generated from PPL source file ../src/Checked_Number_inlines.hh line 1. */
14243/* Checked_Number class implementation: inline functions.
14244*/
14245
14246
14247/* Automatically generated from PPL source file ../src/Checked_Number_inlines.hh line 28. */
14248#include <stdexcept>
14249#include <sstream>
14250
14251namespace Parma_Polyhedra_Library {
14252
14253#ifndef NDEBUG
14254#define DEBUG_ROUND_NOT_NEEDED
14255#endif
14256
14257inline Rounding_Dir
14258rounding_dir(Rounding_Dir dir) {
14259  if (dir == ROUND_NOT_NEEDED) {
14260#ifdef DEBUG_ROUND_NOT_NEEDED
14261    return ROUND_CHECK;
14262#endif
14263  }
14264  return dir;
14265}
14266
14267inline Result
14268check_result(Result r, Rounding_Dir dir) {
14269  if (dir == ROUND_NOT_NEEDED) {
14270#ifdef DEBUG_ROUND_NOT_NEEDED
14271    PPL_ASSERT(result_relation(r) == VR_EQ);
14272#endif
14273    return r;
14274  }
14275  return r;
14276}
14277
14278
14279template <typename T>
14280inline void
14281Checked_Number_Transparent_Policy<T>::handle_result(Result) {
14282}
14283
14284inline void
14285Extended_Number_Policy::handle_result(Result r) {
14286  if (result_class(r) == VC_NAN) {
14287    throw_result_exception(r);
14288  }
14289}
14290
14291template <typename T, typename Policy>
14292inline
14293Checked_Number<T, Policy>::Checked_Number()
14294 : v(0) {
14295}
14296
14297template <typename T, typename Policy>
14298inline
14299Checked_Number<T, Policy>::Checked_Number(const Checked_Number& y) {
14300  // TODO: avoid default construction of value member.
14301  Checked::copy<Policy, Policy>(v, y.raw_value());
14302}
14303
14304template <typename T, typename Policy>
14305template <typename From, typename From_Policy>
14306inline
14307Checked_Number<T, Policy>
14308::Checked_Number(const Checked_Number<From, From_Policy>& y,
14309                 Rounding_Dir dir) {
14310  // TODO: avoid default construction of value member.
14311  Policy::handle_result(check_result(Checked::assign_ext<Policy, From_Policy>
14312                                     (v,
14313                                      y.raw_value(),
14314                                      rounding_dir(dir)),
14315                                     dir)
14316                        );
14317}
14318
14319template <typename T, typename Policy>
14320template <typename From, typename From_Policy>
14321inline
14322Checked_Number<T, Policy>
14323::Checked_Number(const Checked_Number<From, From_Policy>& y) {
14324  // TODO: avoid default construction of value member.
14325  Rounding_Dir dir = Policy::ROUND_DEFAULT_CONSTRUCTOR;
14326  Policy::handle_result(check_result(Checked::assign_ext<Policy, From_Policy>
14327                                     (v,
14328                                      y.raw_value(),
14329                                      rounding_dir(dir)),
14330                                     dir));
14331}
14332
14333// TODO: avoid default construction of value member.
14334#define PPL_DEFINE_CTOR(type) \
14335template <typename T, typename Policy> \
14336inline \
14337Checked_Number<T, Policy>::Checked_Number(const type y, Rounding_Dir dir) { \
14338  Policy::handle_result(check_result(Checked::assign_ext<Policy,        \
14339                                     Checked_Number_Transparent_Policy<PPL_U(type)> > \
14340                                     (v, y, rounding_dir(dir)),         \
14341                                     dir));                             \
14342}                                                                       \
14343template <typename T, typename Policy>                                  \
14344inline                                                                  \
14345Checked_Number<T, Policy>::Checked_Number(const type y) {               \
14346  Rounding_Dir dir = Policy::ROUND_DEFAULT_CONSTRUCTOR;                 \
14347  Policy::handle_result(check_result(Checked::assign_ext<Policy,        \
14348                                     Checked_Number_Transparent_Policy<PPL_U(type)> > \
14349                                     (v, y, rounding_dir(dir)),         \
14350                                     dir));                             \
14351}
14352
14353PPL_DEFINE_CTOR(char)
14354PPL_DEFINE_CTOR(signed char)
14355PPL_DEFINE_CTOR(signed short)
14356PPL_DEFINE_CTOR(signed int)
14357PPL_DEFINE_CTOR(signed long)
14358PPL_DEFINE_CTOR(signed long long)
14359PPL_DEFINE_CTOR(unsigned char)
14360PPL_DEFINE_CTOR(unsigned short)
14361PPL_DEFINE_CTOR(unsigned int)
14362PPL_DEFINE_CTOR(unsigned long)
14363PPL_DEFINE_CTOR(unsigned long long)
14364#if PPL_SUPPORTED_FLOAT
14365PPL_DEFINE_CTOR(float)
14366#endif
14367#if PPL_SUPPORTED_DOUBLE
14368PPL_DEFINE_CTOR(double)
14369#endif
14370#if PPL_SUPPORTED_LONG_DOUBLE
14371PPL_DEFINE_CTOR(long double)
14372#endif
14373PPL_DEFINE_CTOR(mpq_class&)
14374PPL_DEFINE_CTOR(mpz_class&)
14375
14376#undef PPL_DEFINE_CTOR
14377
14378
14379template <typename T, typename Policy>
14380inline
14381Checked_Number<T, Policy>::Checked_Number(const char* y, Rounding_Dir dir) {
14382  std::istringstream s(y);
14383  Policy::handle_result(check_result(Checked::input<Policy>(v,
14384                                                            s,
14385                                                            rounding_dir(dir)),
14386                                     dir));
14387}
14388
14389template <typename T, typename Policy>
14390inline
14391Checked_Number<T, Policy>::Checked_Number(const char* y) {
14392  std::istringstream s(y);
14393  Rounding_Dir dir = Policy::ROUND_DEFAULT_CONSTRUCTOR;
14394  Policy::handle_result(check_result(Checked::input<Policy>(v,
14395                                                            s,
14396                                                            rounding_dir(dir)),
14397                                     dir));
14398}
14399
14400template <typename T, typename Policy>
14401template <typename From>
14402inline
14403Checked_Number<T, Policy>
14404::Checked_Number(const From&,
14405                 Rounding_Dir dir,
14406                 typename Enable_If<Is_Special<From>::value, bool>::type) {
14407  Policy::handle_result(check_result(Checked::assign_special<Policy>(v,
14408                                                                     From::vclass,
14409                                                                     rounding_dir(dir)),
14410                                     dir));
14411}
14412
14413template <typename T, typename Policy>
14414template <typename From>
14415inline
14416Checked_Number<T, Policy>::Checked_Number(const From&, typename Enable_If<Is_Special<From>::value, bool>::type) {
14417  Rounding_Dir dir = Policy::ROUND_DEFAULT_CONSTRUCTOR;
14418  Policy::handle_result(check_result(Checked::assign_special<Policy>(v,
14419                                                            From::vclass,
14420                                                            rounding_dir(dir)),
14421                                     dir));
14422}
14423
14424template <typename To, typename From>
14425inline typename Enable_If<Is_Native_Or_Checked<To>::value
14426                          && Is_Special<From>::value, Result>::type
14427assign_r(To& to, const From&, Rounding_Dir dir) {
14428  return check_result(Checked::assign_special<typename Native_Checked_To_Wrapper<To>
14429                      ::Policy>(Native_Checked_To_Wrapper<To>::raw_value(to),
14430                                From::vclass,
14431                                rounding_dir(dir)),
14432                      dir);
14433}
14434
14435template <typename To, typename From>
14436inline typename Enable_If<Is_Native_Or_Checked<To>::value && Is_Special<From>::value, Result>::type
14437construct(To& to, const From&, Rounding_Dir dir) {
14438  return check_result(Checked::construct_special<typename Native_Checked_To_Wrapper<To>
14439                      ::Policy>(Native_Checked_To_Wrapper<To>::raw_value(to),
14440                                From::vclass,
14441                                rounding_dir(dir)),
14442                      dir);
14443}
14444
14445template <typename T>
14446inline typename Enable_If<Is_Native_Or_Checked<T>::value, bool>::type
14447is_minus_infinity(const T& x) {
14448  return Checked::is_minf<typename Native_Checked_From_Wrapper<T>
14449    ::Policy>(Native_Checked_From_Wrapper<T>::raw_value(x));
14450}
14451
14452template <typename T>
14453inline typename Enable_If<Is_Native_Or_Checked<T>::value, bool>::type
14454is_plus_infinity(const T& x) {
14455  return Checked::is_pinf<typename Native_Checked_From_Wrapper<T>
14456    ::Policy>(Native_Checked_From_Wrapper<T>::raw_value(x));
14457}
14458
14459template <typename T>
14460inline typename Enable_If<Is_Native_Or_Checked<T>::value, int>::type
14461infinity_sign(const T& x) {
14462  return is_minus_infinity(x) ? -1 : (is_plus_infinity(x) ? 1 : 0);
14463}
14464
14465template <typename T>
14466inline typename Enable_If<Is_Native_Or_Checked<T>::value, bool>::type
14467is_not_a_number(const T& x) {
14468  return Checked::is_nan<typename Native_Checked_From_Wrapper<T>
14469    ::Policy>(Native_Checked_From_Wrapper<T>::raw_value(x));
14470}
14471
14472template <typename T>
14473inline typename Enable_If<Is_Native_Or_Checked<T>::value, bool>::type
14474is_integer(const T& x) {
14475  return Checked::is_int<typename Native_Checked_From_Wrapper<T>
14476    ::Policy>(Native_Checked_From_Wrapper<T>::raw_value(x));
14477}
14478
14479template <typename T, typename Policy>
14480inline
14481Checked_Number<T, Policy>::operator T() const {
14482  if (Policy::convertible) {
14483    return v;
14484  }
14485}
14486
14487template <typename T, typename Policy>
14488inline T&
14489Checked_Number<T, Policy>::raw_value() {
14490  return v;
14491}
14492
14493template <typename T, typename Policy>
14494inline const T&
14495Checked_Number<T, Policy>::raw_value() const {
14496  return v;
14497}
14498
14499/*! \relates Checked_Number */
14500template <typename T, typename Policy>
14501inline const T&
14502raw_value(const Checked_Number<T, Policy>& x) {
14503  return x.raw_value();
14504}
14505
14506/*! \relates Checked_Number */
14507template <typename T, typename Policy>
14508inline T&
14509raw_value(Checked_Number<T, Policy>& x) {
14510  return x.raw_value();
14511}
14512
14513template <typename T, typename Policy>
14514inline bool
14515Checked_Number<T, Policy>::OK() const {
14516  return true;
14517}
14518
14519template <typename T, typename Policy>
14520inline Result
14521Checked_Number<T, Policy>::classify(bool nan, bool inf, bool sign) const {
14522  return Checked::classify<Policy>(v, nan, inf, sign);
14523}
14524
14525template <typename T, typename Policy>
14526inline bool
14527is_not_a_number(const Checked_Number<T, Policy>& x) {
14528  return Checked::is_nan<Policy>(x.raw_value());
14529}
14530
14531template <typename T, typename Policy>
14532inline bool
14533is_minus_infinity(const Checked_Number<T, Policy>& x) {
14534  return Checked::is_minf<Policy>(x.raw_value());
14535}
14536
14537template <typename T, typename Policy>
14538inline bool
14539is_plus_infinity(const Checked_Number<T, Policy>& x) {
14540  return Checked::is_pinf<Policy>(x.raw_value());
14541}
14542
14543/*! \relates Checked_Number */
14544template <typename T, typename Policy>
14545inline memory_size_type
14546total_memory_in_bytes(const Checked_Number<T, Policy>& x) {
14547  return total_memory_in_bytes(x.raw_value());
14548}
14549
14550/*! \relates Checked_Number */
14551template <typename T, typename Policy>
14552inline memory_size_type
14553external_memory_in_bytes(const Checked_Number<T, Policy>& x) {
14554  return external_memory_in_bytes(x.raw_value());
14555}
14556
14557
14558/*! \relates Checked_Number */
14559template <typename To>
14560inline typename Enable_If<Is_Native_Or_Checked<To>::value, Result>::type
14561assign_r(To& to, const char* x, Rounding_Dir dir) {
14562  std::istringstream s(x);
14563  return check_result(Checked::input<typename Native_Checked_To_Wrapper<To>
14564                      ::Policy>(Native_Checked_To_Wrapper<To>::raw_value(to),
14565                                s,
14566                                rounding_dir(dir)),
14567                      dir);
14568}
14569
14570#define PPL_DEFINE_FUNC1_A(name, func) \
14571template <typename To, typename From>                                   \
14572inline typename Enable_If<Is_Native_Or_Checked<To>::value               \
14573                          && Is_Native_Or_Checked<From>::value,         \
14574                          Result>::type                                 \
14575 PPL_U(name)(To& to, const From& x, Rounding_Dir dir) {                 \
14576  return                                                                \
14577    check_result(Checked::func<typename Native_Checked_To_Wrapper<To>   \
14578                 ::Policy,                                              \
14579                 typename Native_Checked_From_Wrapper<From>             \
14580                 ::Policy>(Native_Checked_To_Wrapper<To>::raw_value(to), \
14581                           Native_Checked_From_Wrapper<From>::raw_value(x), \
14582                           rounding_dir(dir)), dir);                    \
14583}
14584
14585PPL_DEFINE_FUNC1_A(construct, construct_ext)
14586PPL_DEFINE_FUNC1_A(assign_r, assign_ext)
14587PPL_DEFINE_FUNC1_A(floor_assign_r, floor_ext)
14588PPL_DEFINE_FUNC1_A(ceil_assign_r, ceil_ext)
14589PPL_DEFINE_FUNC1_A(trunc_assign_r, trunc_ext)
14590PPL_DEFINE_FUNC1_A(neg_assign_r, neg_ext)
14591PPL_DEFINE_FUNC1_A(abs_assign_r, abs_ext)
14592PPL_DEFINE_FUNC1_A(sqrt_assign_r, sqrt_ext)
14593
14594#undef PPL_DEFINE_FUNC1_A
14595
14596#define PPL_DEFINE_FUNC1_B(name, func) \
14597template <typename To, typename From>                                   \
14598inline typename Enable_If<Is_Native_Or_Checked<To>::value               \
14599                          && Is_Native_Or_Checked<From>::value,         \
14600                          Result>::type                                 \
14601 PPL_U(name)(To& to, const From& x, unsigned int exp, Rounding_Dir dir) { \
14602  return                                                                \
14603    check_result(Checked::func<typename Native_Checked_To_Wrapper<To>   \
14604                 ::Policy,                                              \
14605                 typename Native_Checked_From_Wrapper<From>             \
14606                 ::Policy>(Native_Checked_To_Wrapper<To>::raw_value(to), \
14607                           Native_Checked_From_Wrapper<From>::raw_value(x), \
14608                           exp,                                         \
14609                           rounding_dir(dir)),                          \
14610                 dir);                                                  \
14611}
14612
14613PPL_DEFINE_FUNC1_B(add_2exp_assign_r, add_2exp_ext)
14614PPL_DEFINE_FUNC1_B(sub_2exp_assign_r, sub_2exp_ext)
14615PPL_DEFINE_FUNC1_B(mul_2exp_assign_r, mul_2exp_ext)
14616PPL_DEFINE_FUNC1_B(div_2exp_assign_r, div_2exp_ext)
14617PPL_DEFINE_FUNC1_B(smod_2exp_assign_r, smod_2exp_ext)
14618PPL_DEFINE_FUNC1_B(umod_2exp_assign_r, umod_2exp_ext)
14619
14620#undef PPL_DEFINE_FUNC1_B
14621
14622#define PPL_DEFINE_FUNC2(name, func) \
14623template <typename To, typename From1, typename From2>                  \
14624inline typename Enable_If<Is_Native_Or_Checked<To>::value               \
14625                          && Is_Native_Or_Checked<From1>::value         \
14626                          && Is_Native_Or_Checked<From2>::value,        \
14627                          Result>::type                                 \
14628 PPL_U(name)(To& to, const From1& x, const From2& y, Rounding_Dir dir) { \
14629  return                                                                \
14630    check_result(Checked::func<typename Native_Checked_To_Wrapper<To>   \
14631                 ::Policy,                                              \
14632                 typename Native_Checked_From_Wrapper<From1>            \
14633                 ::Policy,                                              \
14634                 typename Native_Checked_From_Wrapper<From2>            \
14635                 ::Policy>(Native_Checked_To_Wrapper<To>::raw_value(to), \
14636                           Native_Checked_From_Wrapper<From1>::raw_value(x), \
14637                           Native_Checked_From_Wrapper<From2>::raw_value(y), \
14638                           rounding_dir(dir)),                          \
14639                 dir);                                                  \
14640}
14641
14642PPL_DEFINE_FUNC2(add_assign_r, add_ext)
14643PPL_DEFINE_FUNC2(sub_assign_r, sub_ext)
14644PPL_DEFINE_FUNC2(mul_assign_r, mul_ext)
14645PPL_DEFINE_FUNC2(div_assign_r, div_ext)
14646PPL_DEFINE_FUNC2(idiv_assign_r, idiv_ext)
14647PPL_DEFINE_FUNC2(rem_assign_r, rem_ext)
14648PPL_DEFINE_FUNC2(gcd_assign_r, gcd_ext)
14649PPL_DEFINE_FUNC2(lcm_assign_r, lcm_ext)
14650PPL_DEFINE_FUNC2(add_mul_assign_r, add_mul_ext)
14651PPL_DEFINE_FUNC2(sub_mul_assign_r, sub_mul_ext)
14652
14653#undef PPL_DEFINE_FUNC2
14654
14655#define PPL_DEFINE_FUNC4(name, func)                                    \
14656template <typename To1,                                                 \
14657          typename To2,                                                 \
14658          typename To3,                                                 \
14659          typename From1,                                               \
14660          typename From2>                                               \
14661inline typename Enable_If<Is_Native_Or_Checked<To1>::value              \
14662                          && Is_Native_Or_Checked<To2>::value           \
14663                          && Is_Native_Or_Checked<To3>::value           \
14664                          && Is_Native_Or_Checked<From1>::value         \
14665                          && Is_Native_Or_Checked<From2>::value,        \
14666                          Result>::type                                 \
14667 PPL_U(name)(To1& to, To2& s, To3& t, const From1& x, const From2& y,   \
14668     Rounding_Dir dir) {                                                \
14669  return                                                                \
14670    check_result(Checked::func<typename Native_Checked_To_Wrapper<To1>::Policy, \
14671                 typename Native_Checked_To_Wrapper<To2>::Policy,       \
14672                 typename Native_Checked_To_Wrapper<To3>::Policy,       \
14673                 typename Native_Checked_From_Wrapper<From1>::Policy,   \
14674                 typename Native_Checked_From_Wrapper<From2>::Policy>   \
14675                 (Native_Checked_To_Wrapper<To1>::raw_value(to),        \
14676                  Native_Checked_To_Wrapper<To2>::raw_value(s),         \
14677                  Native_Checked_To_Wrapper<To3>::raw_value(t),         \
14678                  Native_Checked_From_Wrapper<From1>::raw_value(x),     \
14679                  Native_Checked_From_Wrapper<From2>::raw_value(y),     \
14680                  rounding_dir(dir)),                                   \
14681                 dir);                                                  \
14682}
14683
14684PPL_DEFINE_FUNC4(gcdext_assign_r, gcdext_ext)
14685
14686#undef PPL_DEFINE_PPL_DEFINE_FUNC4
14687
14688#define PPL_DEFINE_INCREMENT(f, fun) \
14689template <typename T, typename Policy> \
14690inline Checked_Number<T, Policy>& \
14691Checked_Number<T, Policy>::f() { \
14692  Policy::handle_result((fun)(*this, *this, T(1),             \
14693                            Policy::ROUND_DEFAULT_OPERATOR)); \
14694  return *this; \
14695} \
14696template <typename T, typename Policy> \
14697inline Checked_Number<T, Policy> \
14698Checked_Number<T, Policy>::f(int) {\
14699  T r = v;\
14700  Policy::handle_result((fun)(*this, *this, T(1),             \
14701                            Policy::ROUND_DEFAULT_OPERATOR)); \
14702  return r;\
14703}
14704
14705PPL_DEFINE_INCREMENT(operator ++, add_assign_r)
14706PPL_DEFINE_INCREMENT(operator --, sub_assign_r)
14707
14708#undef PPL_DEFINE_INCREMENT
14709
14710template <typename T, typename Policy>
14711inline Checked_Number<T, Policy>&
14712Checked_Number<T, Policy>::operator=(const Checked_Number<T, Policy>& y) {
14713  Checked::copy<Policy, Policy>(v, y.raw_value());
14714  return *this;
14715}
14716template <typename T, typename Policy>
14717template <typename From>
14718inline Checked_Number<T, Policy>&
14719Checked_Number<T, Policy>::operator=(const From& y) {
14720  Policy::handle_result(assign_r(*this, y, Policy::ROUND_DEFAULT_OPERATOR));
14721  return *this;
14722}
14723
14724#define PPL_DEFINE_BINARY_OP_ASSIGN(f, fun) \
14725template <typename T, typename Policy> \
14726template <typename From_Policy> \
14727inline Checked_Number<T, Policy>& \
14728Checked_Number<T, Policy>::f(const Checked_Number<T, From_Policy>& y) { \
14729  Policy::handle_result((fun)(*this, *this, y,                          \
14730                            Policy::ROUND_DEFAULT_OPERATOR)); \
14731  return *this; \
14732} \
14733template <typename T, typename Policy> \
14734inline Checked_Number<T, Policy>& \
14735Checked_Number<T, Policy>::f(const T& y) { \
14736  Policy::handle_result((fun)(*this, *this, y,                \
14737                            Policy::ROUND_DEFAULT_OPERATOR)); \
14738  return *this; \
14739} \
14740template <typename T, typename Policy> \
14741template <typename From> \
14742inline typename Enable_If<Is_Native_Or_Checked<From>::value, \
14743                          Checked_Number<T, Policy>& >::type \
14744Checked_Number<T, Policy>::f(const From& y) { \
14745  Checked_Number<T, Policy> cy(y); \
14746  Policy::handle_result((fun)(*this, *this, cy,               \
14747                            Policy::ROUND_DEFAULT_OPERATOR)); \
14748  return *this; \
14749}
14750
14751PPL_DEFINE_BINARY_OP_ASSIGN(operator +=, add_assign_r)
14752PPL_DEFINE_BINARY_OP_ASSIGN(operator -=, sub_assign_r)
14753PPL_DEFINE_BINARY_OP_ASSIGN(operator *=, mul_assign_r)
14754PPL_DEFINE_BINARY_OP_ASSIGN(operator /=, div_assign_r)
14755PPL_DEFINE_BINARY_OP_ASSIGN(operator %=, rem_assign_r)
14756
14757#undef PPL_DEFINE_BINARY_OP_ASSIGN
14758
14759#define PPL_DEFINE_BINARY_OP(f, fun) \
14760template <typename T, typename Policy> \
14761inline Checked_Number<T, Policy> \
14762 PPL_U(f)(const Checked_Number<T, Policy>& x,   \
14763         const Checked_Number<T, Policy>& y) {  \
14764  Checked_Number<T, Policy> r; \
14765  Policy::handle_result((fun)(r, x, y, Policy::ROUND_DEFAULT_OPERATOR)); \
14766  return r; \
14767} \
14768template <typename Type, typename T, typename Policy>   \
14769inline \
14770typename Enable_If<Is_Native<Type>::value, Checked_Number<T, Policy> >::type \
14771 PPL_U(f)(const Type& x, const Checked_Number<T, Policy>& y) {          \
14772  Checked_Number<T, Policy> r(x); \
14773  Policy::handle_result((fun)(r, r, y, Policy::ROUND_DEFAULT_OPERATOR)); \
14774  return r; \
14775} \
14776template <typename T, typename Policy, typename Type>   \
14777inline \
14778typename Enable_If<Is_Native<Type>::value, Checked_Number<T, Policy> >::type \
14779 PPL_U(f)(const Checked_Number<T, Policy>& x, const Type& y) {          \
14780  Checked_Number<T, Policy> r(y); \
14781  Policy::handle_result((fun)(r, x, r, Policy::ROUND_DEFAULT_OPERATOR)); \
14782  return r; \
14783}
14784
14785PPL_DEFINE_BINARY_OP(operator +, add_assign_r)
14786PPL_DEFINE_BINARY_OP(operator -, sub_assign_r)
14787PPL_DEFINE_BINARY_OP(operator *, mul_assign_r)
14788PPL_DEFINE_BINARY_OP(operator /, div_assign_r)
14789PPL_DEFINE_BINARY_OP(operator %, rem_assign_r)
14790
14791#undef PPL_DEFINE_BINARY_OP
14792
14793#define PPL_DEFINE_COMPARE_OP(f, fun)                                   \
14794template <typename T1, typename T2>                                     \
14795inline                                                                  \
14796typename Enable_If<Is_Native_Or_Checked<T1>::value                      \
14797                   && Is_Native_Or_Checked<T2>::value                   \
14798                   && (Is_Checked<T1>::value || Is_Checked<T2>::value), \
14799                   bool>::type                                          \
14800 PPL_U(f)(const T1& x, const T2& y) {                                   \
14801  return Checked::fun<typename Native_Checked_From_Wrapper<T1>::Policy, \
14802                      typename Native_Checked_From_Wrapper<T2>::Policy> \
14803    (Native_Checked_From_Wrapper<T1>::raw_value(x),                     \
14804     Native_Checked_From_Wrapper<T2>::raw_value(y));                    \
14805}
14806
14807PPL_DEFINE_COMPARE_OP(operator ==, eq_ext)
14808PPL_DEFINE_COMPARE_OP(operator !=, ne_ext)
14809PPL_DEFINE_COMPARE_OP(operator >=, ge_ext)
14810PPL_DEFINE_COMPARE_OP(operator >, gt_ext)
14811PPL_DEFINE_COMPARE_OP(operator <=, le_ext)
14812PPL_DEFINE_COMPARE_OP(operator <, lt_ext)
14813
14814#undef PPL_DEFINE_COMPARE_OP
14815
14816#define PPL_DEFINE_COMPARE(f, fun)                                      \
14817template <typename T1, typename T2>                                     \
14818inline typename Enable_If<Is_Native_Or_Checked<T1>::value               \
14819                          && Is_Native_Or_Checked<T2>::value,           \
14820                          bool>::type                                   \
14821 PPL_U(f)(const T1& x, const T2& y) {                                   \
14822  return Checked::fun<typename Native_Checked_From_Wrapper<T1>::Policy, \
14823                      typename Native_Checked_From_Wrapper<T2>::Policy> \
14824    (Native_Checked_From_Wrapper<T1>::raw_value(x),                     \
14825     Native_Checked_From_Wrapper<T2>::raw_value(y));                    \
14826}
14827
14828PPL_DEFINE_COMPARE(equal, eq_ext)
14829PPL_DEFINE_COMPARE(not_equal, ne_ext)
14830PPL_DEFINE_COMPARE(greater_or_equal, ge_ext)
14831PPL_DEFINE_COMPARE(greater_than, gt_ext)
14832PPL_DEFINE_COMPARE(less_or_equal, le_ext)
14833PPL_DEFINE_COMPARE(less_than, lt_ext)
14834
14835#undef PPL_DEFINE_COMPARE
14836
14837/*! \relates Checked_Number */
14838template <typename T, typename Policy>
14839inline Checked_Number<T, Policy>
14840operator+(const Checked_Number<T, Policy>& x) {
14841  return x;
14842}
14843
14844/*! \relates Checked_Number */
14845template <typename T, typename Policy>
14846inline Checked_Number<T, Policy>
14847operator-(const Checked_Number<T, Policy>& x) {
14848  Checked_Number<T, Policy> r;
14849  Policy::handle_result(neg_assign_r(r, x, Policy::ROUND_DEFAULT_OPERATOR));
14850  return r;
14851}
14852
14853#define PPL_DEFINE_ASSIGN_FUN2_1(f, fun) \
14854template <typename T, typename Policy> \
14855inline void \
14856 PPL_U(f)(Checked_Number<T, Policy>& x) {                               \
14857  Policy::handle_result((fun)(x, x, Policy::ROUND_DEFAULT_FUNCTION));   \
14858}
14859
14860#define PPL_DEFINE_ASSIGN_FUN2_2(f, fun) \
14861template <typename T, typename Policy> \
14862inline void \
14863 PPL_U(f)(Checked_Number<T, Policy>& x, const Checked_Number<T, Policy>& y) { \
14864  Policy::handle_result((fun)(x, y, Policy::ROUND_DEFAULT_FUNCTION)); \
14865}
14866
14867#define PPL_DEFINE_ASSIGN_FUN3_3(f, fun) \
14868template <typename T, typename Policy> \
14869inline void \
14870 PPL_U(f)(Checked_Number<T, Policy>& x, const Checked_Number<T, Policy>& y, \
14871  const Checked_Number<T, Policy>& z) { \
14872  Policy::handle_result((fun)(x, y, z, Policy::ROUND_DEFAULT_FUNCTION)); \
14873}
14874
14875#define PPL_DEFINE_ASSIGN_FUN5_5(f, fun)                                        \
14876template <typename T, typename Policy>                                  \
14877inline void                                                             \
14878 PPL_U(f)(Checked_Number<T, Policy>& x,                                 \
14879  Checked_Number<T, Policy>& s, Checked_Number<T, Policy>& t,           \
14880  const Checked_Number<T, Policy>& y,                                   \
14881  const Checked_Number<T, Policy>& z) {                                 \
14882  Policy::handle_result((fun)(x, s, t, y, z, Policy::ROUND_DEFAULT_FUNCTION)); \
14883}
14884
14885PPL_DEFINE_ASSIGN_FUN2_2(sqrt_assign, sqrt_assign_r)
14886
14887PPL_DEFINE_ASSIGN_FUN2_1(floor_assign, floor_assign_r)
14888PPL_DEFINE_ASSIGN_FUN2_2(floor_assign, floor_assign_r)
14889
14890PPL_DEFINE_ASSIGN_FUN2_1(ceil_assign, ceil_assign_r)
14891PPL_DEFINE_ASSIGN_FUN2_2(ceil_assign, ceil_assign_r)
14892
14893PPL_DEFINE_ASSIGN_FUN2_1(trunc_assign, trunc_assign_r)
14894PPL_DEFINE_ASSIGN_FUN2_2(trunc_assign, trunc_assign_r)
14895
14896PPL_DEFINE_ASSIGN_FUN2_1(neg_assign, neg_assign_r)
14897PPL_DEFINE_ASSIGN_FUN2_2(neg_assign, neg_assign_r)
14898
14899PPL_DEFINE_ASSIGN_FUN2_1(abs_assign, abs_assign_r)
14900PPL_DEFINE_ASSIGN_FUN2_2(abs_assign, abs_assign_r)
14901
14902PPL_DEFINE_ASSIGN_FUN3_3(add_mul_assign, add_mul_assign_r)
14903
14904PPL_DEFINE_ASSIGN_FUN3_3(sub_mul_assign, sub_mul_assign_r)
14905
14906PPL_DEFINE_ASSIGN_FUN3_3(rem_assign, rem_assign_r)
14907
14908PPL_DEFINE_ASSIGN_FUN3_3(gcd_assign, gcd_assign_r)
14909
14910PPL_DEFINE_ASSIGN_FUN5_5(gcdext_assign, gcdext_assign_r)
14911
14912PPL_DEFINE_ASSIGN_FUN3_3(lcm_assign, lcm_assign_r)
14913
14914#undef PPL_DEFINE_ASSIGN_FUN2_1
14915#undef PPL_DEFINE_ASSIGN_FUN2_2
14916#undef PPL_DEFINE_ASSIGN_FUN3_2
14917#undef PPL_DEFINE_ASSIGN_FUN3_3
14918#undef PPL_DEFINE_ASSIGN_FUN5_5
14919
14920#define PPL_DEFINE_ASSIGN_2EXP(f, fun)                                  \
14921template <typename T, typename Policy>                                  \
14922inline void                                                             \
14923 PPL_U(f)(Checked_Number<T, Policy>& x,                                 \
14924          const Checked_Number<T, Policy>& y, unsigned int exp) {       \
14925  Policy::handle_result((fun)(x, y, exp, Policy::ROUND_DEFAULT_FUNCTION)); \
14926}
14927
14928PPL_DEFINE_ASSIGN_2EXP(mul_2exp_assign, mul_2exp_assign_r)
14929PPL_DEFINE_ASSIGN_2EXP(div_2exp_assign, div_2exp_assign_r)
14930
14931template <typename T, typename Policy>
14932inline void
14933exact_div_assign(Checked_Number<T, Policy>& x,
14934                 const Checked_Number<T, Policy>& y,
14935                 const Checked_Number<T, Policy>& z) {
14936  Policy::handle_result(div_assign_r(x, y, z, ROUND_NOT_NEEDED));
14937}
14938
14939/*! \relates Checked_Number */
14940template <typename From>
14941inline typename Enable_If<Is_Native_Or_Checked<From>::value, int>::type
14942sgn(const From& x) {
14943  Result_Relation r
14944    = Checked::sgn_ext<typename Native_Checked_From_Wrapper<From>::Policy>
14945        (Native_Checked_From_Wrapper<From>::raw_value(x));
14946  switch (r) {
14947  case VR_LT:
14948    return -1;
14949  case VR_EQ:
14950    return 0;
14951  case VR_GT:
14952    return 1;
14953  default:
14954    throw(0);
14955  }
14956}
14957
14958/*! \relates Checked_Number */
14959template <typename From1, typename From2>
14960inline typename Enable_If<Is_Native_Or_Checked<From1>::value
14961                          && Is_Native_Or_Checked<From2>::value,
14962                          int>::type
14963cmp(const From1& x, const From2& y) {
14964  Result_Relation r
14965    = Checked::cmp_ext<typename Native_Checked_From_Wrapper<From1>::Policy,
14966                       typename Native_Checked_From_Wrapper<From2>::Policy>
14967                 (Native_Checked_From_Wrapper<From1>::raw_value(x),
14968                  Native_Checked_From_Wrapper<From2>::raw_value(y));
14969  switch (r) {
14970  case VR_LT:
14971    return -1;
14972  case VR_EQ:
14973    return 0;
14974  case VR_GT:
14975    return 1;
14976  default:
14977    throw(0);
14978  }
14979}
14980
14981/*! \relates Checked_Number */
14982template <typename T>
14983typename Enable_If<Is_Native_Or_Checked<T>::value, Result>::type
14984output(std::ostream& os, const T& x,
14985       const Numeric_Format& format, Rounding_Dir dir) {
14986  return check_result(Checked::output_ext<typename Native_Checked_From_Wrapper<T>::Policy>
14987                      (os,
14988                       Native_Checked_From_Wrapper<T>::raw_value(x),
14989                       format,
14990                       rounding_dir(dir)),
14991                      dir);
14992}
14993
14994/*! \relates Checked_Number */
14995template <typename T, typename Policy>
14996inline std::ostream&
14997operator<<(std::ostream& os, const Checked_Number<T, Policy>& x) {
14998  Policy::handle_result(output(os, x, Numeric_Format(), ROUND_IGNORE));
14999  return os;
15000}
15001
15002/*! \relates Checked_Number */
15003template <typename T>
15004typename Enable_If<Is_Native_Or_Checked<T>::value, Result>::type
15005input(T& x, std::istream& is, Rounding_Dir dir) {
15006  return check_result(Checked::input_ext<typename Native_Checked_To_Wrapper<T>::Policy>
15007                      (Native_Checked_To_Wrapper<T>::raw_value(x),
15008                       is,
15009                       rounding_dir(dir)),
15010                      dir);
15011}
15012
15013/*! \relates Checked_Number */
15014template <typename T, typename Policy>
15015inline std::istream& operator>>(std::istream& is,
15016                                Checked_Number<T, Policy>& x) {
15017  Result r = input(x, is, Policy::ROUND_DEFAULT_INPUT);
15018  if (r == V_CVT_STR_UNK) {
15019    is.setstate(std::ios::failbit);
15020  }
15021  else {
15022    Policy::handle_result(r);
15023  }
15024  return is;
15025}
15026
15027template <typename T>
15028inline T
15029plus_infinity() {
15030  return PLUS_INFINITY;
15031}
15032
15033template <typename T>
15034inline T
15035minus_infinity() {
15036  return MINUS_INFINITY;
15037}
15038
15039template <typename T>
15040inline T
15041not_a_number() {
15042  return NOT_A_NUMBER;
15043}
15044
15045/*! \relates Checked_Number */
15046template <typename T, typename Policy>
15047inline void
15048swap(Checked_Number<T, Policy>& x, Checked_Number<T, Policy>& y) {
15049  using std::swap;
15050  swap(x.raw_value(), y.raw_value());
15051}
15052
15053template <typename T>
15054inline void
15055maybe_reset_fpu_inexact() {
15056  if (FPU_Related<T>::value) {
15057    return fpu_reset_inexact();
15058  }
15059}
15060
15061template <typename T>
15062inline int
15063maybe_check_fpu_inexact() {
15064  if (FPU_Related<T>::value) {
15065    return fpu_check_inexact();
15066  }
15067  else {
15068    return 0;
15069  }
15070}
15071
15072} // namespace Parma_Polyhedra_Library
15073
15074/* Automatically generated from PPL source file ../src/Checked_Number_templates.hh line 1. */
15075/* Checked_Number class implementation: non-inline template functions.
15076*/
15077
15078
15079/* Automatically generated from PPL source file ../src/Checked_Number_templates.hh line 28. */
15080#include <iomanip>
15081#include <limits>
15082
15083namespace Parma_Polyhedra_Library {
15084
15085template <typename T>
15086typename Enable_If<Is_Native_Or_Checked<T>::value, void>::type
15087ascii_dump(std::ostream& s, const T& t) {
15088  if (std::numeric_limits<T>::is_exact) {
15089    // An exact data type: pretty printer is accurate.
15090    s << t;
15091  }
15092  else {
15093    // An inexact data type (probably floating point):
15094    // first dump its hexadecimal representation ...
15095    const std::ios::fmtflags old_flags = s.setf(std::ios::hex,
15096                                                std::ios::basefield);
15097    const unsigned char* p = reinterpret_cast<const unsigned char*>(&t);
15098    for (unsigned i = 0; i < sizeof(T); ++i) {
15099      s << std::setw(2) << std::setfill('0') << static_cast<unsigned>(p[i]);
15100    }
15101    s.flags(old_flags);
15102    // ... and then pretty print it for readability.
15103    s << " (" << t << ")";
15104  }
15105}
15106
15107template <typename T>
15108typename Enable_If<Is_Native_Or_Checked<T>::value, bool>::type
15109ascii_load(std::istream& s, T& t) {
15110  if (std::numeric_limits<T>::is_exact) {
15111    // An exact data type: input from pretty printed version is accurate.
15112    s >> t;
15113    return !s.fail();
15114  }
15115  else {
15116    // An inexact data type (probably floating point):
15117    // first load its hexadecimal representation ...
15118    std::string str;
15119    if (!(s >> str) || str.size() != 2*sizeof(T)) {
15120      return false;
15121    }
15122    unsigned char* p = reinterpret_cast<unsigned char*>(&t);
15123    // CHECKME: any (portable) simpler way?
15124    for (unsigned i = 0; i < sizeof(T); ++i) {
15125      unsigned byte_value = 0;
15126      for (unsigned j = 0; j < 2; ++j) {
15127        byte_value <<= 4;
15128        unsigned half_byte_value;
15129        // Interpret single hex character.
15130        switch (str[2*i + j]) {
15131        case '0':
15132          half_byte_value = 0;
15133          break;
15134        case '1':
15135          half_byte_value = 1;
15136          break;
15137        case '2':
15138          half_byte_value = 2;
15139          break;
15140        case '3':
15141          half_byte_value = 3;
15142          break;
15143        case '4':
15144          half_byte_value = 4;
15145          break;
15146        case '5':
15147          half_byte_value = 5;
15148          break;
15149        case '6':
15150          half_byte_value = 6;
15151          break;
15152        case '7':
15153          half_byte_value = 7;
15154          break;
15155        case '8':
15156          half_byte_value = 8;
15157          break;
15158        case '9':
15159          half_byte_value = 9;
15160          break;
15161        case 'A':
15162        case 'a':
15163          half_byte_value = 10;
15164          break;
15165        case 'B':
15166        case 'b':
15167          half_byte_value = 11;
15168          break;
15169        case 'C':
15170        case 'c':
15171          half_byte_value = 12;
15172          break;
15173        case 'D':
15174        case 'd':
15175          half_byte_value = 13;
15176          break;
15177        case 'E':
15178        case 'e':
15179          half_byte_value = 14;
15180          break;
15181        case 'F':
15182        case 'f':
15183          half_byte_value = 15;
15184          break;
15185        default:
15186          return false;
15187        }
15188        byte_value += half_byte_value;
15189      }
15190      PPL_ASSERT(byte_value <= 255);
15191      p[i] = static_cast<unsigned char>(byte_value);
15192    }
15193    // ... then read and discard pretty printed value.
15194    if (!(s >> str)) {
15195      return false;
15196    }
15197    const std::string::size_type sz = str.size();
15198    return sz > 2 && str[0] == '(' && str[sz-1] == ')';
15199  }
15200}
15201
15202} // namespace Parma_Polyhedra_Library
15203
15204/* Automatically generated from PPL source file ../src/Checked_Number_defs.hh line 1069. */
15205
15206/* Automatically generated from PPL source file ../src/checked_numeric_limits.hh line 29. */
15207#include <limits>
15208
15209namespace std {
15210
15211using namespace Parma_Polyhedra_Library;
15212
15213#define PPL_SPECIALIZE_LIMITS_INT(T)                                    \
15214  /*! \brief Partial specialization of std::numeric_limits. */          \
15215  template <typename Policy>                                            \
15216  class numeric_limits<Checked_Number<PPL_U(T), Policy> >              \
15217    : public numeric_limits<PPL_U(T)> {                                 \
15218  private:                                                              \
15219    typedef Checked_Number<PPL_U(T), Policy> Type;                      \
15220                                                                        \
15221  public:                                                               \
15222    static const bool has_infinity = Policy::has_infinity;              \
15223    static const bool has_quiet_NaN =  Policy::has_nan;                 \
15224                                                                        \
15225    static Type min() {                                                 \
15226      Type v;                                                           \
15227      v.raw_value() = Checked::Extended_Int<Policy, PPL_U(T)>::min;     \
15228      return v;                                                         \
15229    }                                                                   \
15230                                                                        \
15231    static Type max() {                                                 \
15232      Type v;                                                           \
15233      v.raw_value() = Checked::Extended_Int<Policy, PPL_U(T)>::max;     \
15234      return v;                                                         \
15235    }                                                                   \
15236                                                                        \
15237    static Type infinity() {                                            \
15238      Type v;                                                           \
15239      Checked::assign_special<Policy>(v.raw_value(), VC_PLUS_INFINITY,  \
15240                                      ROUND_IGNORE);                    \
15241      return v;                                                         \
15242    }                                                                   \
15243                                                                        \
15244    static Type quiet_NaN() {                                           \
15245      Type v;                                                           \
15246      Checked::assign_special<Policy>(v.raw_value(), VC_NAN,            \
15247                                      ROUND_IGNORE);                    \
15248      return v;                                                         \
15249    }                                                                   \
15250  };
15251
15252PPL_SPECIALIZE_LIMITS_INT(char)
15253
15254PPL_SPECIALIZE_LIMITS_INT(signed char)
15255PPL_SPECIALIZE_LIMITS_INT(signed short)
15256PPL_SPECIALIZE_LIMITS_INT(signed int)
15257PPL_SPECIALIZE_LIMITS_INT(signed long)
15258PPL_SPECIALIZE_LIMITS_INT(signed long long)
15259
15260PPL_SPECIALIZE_LIMITS_INT(unsigned char)
15261PPL_SPECIALIZE_LIMITS_INT(unsigned short)
15262PPL_SPECIALIZE_LIMITS_INT(unsigned int)
15263PPL_SPECIALIZE_LIMITS_INT(unsigned long)
15264PPL_SPECIALIZE_LIMITS_INT(unsigned long long)
15265
15266#undef PPL_SPECIALIZE_LIMITS_INT
15267
15268#define PPL_SPECIALIZE_LIMITS_FLOAT(T)                                  \
15269  /*! \brief Partial specialization of std::numeric_limits. */          \
15270  template <typename Policy>                                            \
15271  struct numeric_limits<Checked_Number<PPL_U(T), Policy> >              \
15272    : public numeric_limits<PPL_U(T)> {                                 \
15273};
15274
15275#if PPL_SUPPORTED_FLOAT
15276PPL_SPECIALIZE_LIMITS_FLOAT(float)
15277#endif
15278#if PPL_SUPPORTED_DOUBLE
15279PPL_SPECIALIZE_LIMITS_FLOAT(double)
15280#endif
15281#if PPL_SUPPORTED_LONG_DOUBLE
15282PPL_SPECIALIZE_LIMITS_FLOAT(long double)
15283#endif
15284
15285#undef PPL_SPECIALIZE_LIMITS_FLOAT
15286
15287#ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
15288//! Partial specialization of std::numeric_limits.
15289#endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
15290template <typename Policy>
15291class
15292numeric_limits<Checked_Number<mpz_class, Policy> >
15293  : public numeric_limits<mpz_class> {
15294private:
15295  typedef Checked_Number<mpz_class, Policy> Type;
15296
15297public:
15298  static const bool has_infinity = Policy::has_infinity;
15299  static const bool has_quiet_NaN =  Policy::has_nan;
15300
15301  static Type infinity() {
15302    Type v;
15303    Checked::assign_special<Policy>(v.raw_value(), VC_PLUS_INFINITY,
15304                                    ROUND_IGNORE);
15305    return v;
15306  }
15307
15308  static Type quiet_NaN() {
15309    Type v;
15310    Checked::assign_special<Policy>(v.raw_value(), VC_NAN, ROUND_IGNORE);
15311    return v;
15312  }
15313};
15314
15315#ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
15316//! Partial specialization of std::numeric_limits.
15317#endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
15318template <typename Policy>
15319class
15320numeric_limits<Checked_Number<mpq_class, Policy> >
15321: public numeric_limits<mpq_class> {
15322private:
15323  typedef Checked_Number<mpq_class, Policy> Type;
15324
15325public:
15326  static const bool has_infinity = Policy::has_infinity;
15327  static const bool has_quiet_NaN =  Policy::has_nan;
15328
15329  static Type infinity() {
15330    Type v;
15331    Checked::assign_special<Policy>(v.raw_value(), VC_PLUS_INFINITY,
15332                                    ROUND_IGNORE);
15333    return v;
15334  }
15335
15336  static Type quiet_NaN() {
15337    Type v;
15338    Checked::assign_special<Policy>(v.raw_value(), VC_NAN, ROUND_IGNORE);
15339    return v;
15340  }
15341};
15342
15343} // namespace std
15344
15345/* Automatically generated from PPL source file ../src/stdiobuf_defs.hh line 1. */
15346/* stdiobuf class declaration.
15347*/
15348
15349
15350/* Automatically generated from PPL source file ../src/stdiobuf_types.hh line 1. */
15351
15352
15353namespace Parma_Polyhedra_Library {
15354
15355class stdiobuf;
15356
15357} // namespace Parma_Polyhedra_Library
15358
15359/* Automatically generated from PPL source file ../src/stdiobuf_defs.hh line 28. */
15360#include <cstdio>
15361#include <streambuf>
15362
15363class Parma_Polyhedra_Library::stdiobuf
15364  : public std::basic_streambuf<char, std::char_traits<char> > {
15365public:
15366  //! Constructor.
15367  stdiobuf(FILE* file);
15368
15369protected:
15370  /*! \brief
15371    Gets a character in case of underflow.
15372
15373    \remarks
15374    Specified by ISO/IEC 14882:1998: 27.5.2.4.3.
15375  */
15376  virtual int_type underflow();
15377
15378  /*! \brief
15379    In case of underflow, gets a character and advances the next pointer.
15380
15381    \remarks
15382    Specified by ISO/IEC 14882:1998: 27.5.2.4.3.
15383  */
15384  virtual int_type uflow();
15385
15386  /*! \brief
15387    Gets a sequence of characters.
15388
15389    \remarks
15390    Specified by ISO/IEC 14882:1998: 27.5.2.4.3.
15391  */
15392  virtual std::streamsize xsgetn(char_type* s, std::streamsize n);
15393
15394  /*! \brief
15395    Puts character back in case of backup underflow.
15396
15397    \remarks
15398    Specified by ISO/IEC 14882:1998: 27.5.2.4.4.
15399  */
15400  virtual int_type pbackfail(int_type c = traits_type::eof());
15401
15402  /*! \brief
15403    Writes a sequence of characters.
15404
15405    \remarks
15406    Specified by ISO/IEC 14882:1998: 27.5.2.4.5.
15407  */
15408  virtual std::streamsize xsputn(const char_type* s, std::streamsize n);
15409
15410  /*! \brief
15411    Writes a character in case of overflow.
15412
15413    Specified by ISO/IEC 14882:1998: 27.5.2.4.5.
15414  */
15415  virtual int_type overflow(int_type c);
15416
15417  /*! \brief
15418    Synchronizes the stream buffer.
15419
15420    Specified by ISO/IEC 14882:1998: 27.5.2.4.2.
15421  */
15422  virtual int sync();
15423
15424private:
15425  //! Character type of the streambuf.
15426  typedef char char_type;
15427
15428  //! Traits type of the streambuf.
15429  typedef std::char_traits<char_type> traits_type;
15430
15431  //! Integer type of the streambuf.
15432  typedef traits_type::int_type int_type;
15433
15434  //! The encapsulated stdio file.
15435  FILE* fp;
15436
15437  //! Buffer for the last character read.
15438  int_type unget_char_buf;
15439};
15440
15441/* Automatically generated from PPL source file ../src/stdiobuf_inlines.hh line 1. */
15442/* stdiobuf class implementation: inline functions.
15443*/
15444
15445
15446namespace Parma_Polyhedra_Library {
15447
15448inline
15449stdiobuf::stdiobuf(FILE* file)
15450  : fp(file), unget_char_buf(traits_type::eof()) {
15451}
15452
15453} // namespace Parma_Polyhedra_Library
15454
15455/* Automatically generated from PPL source file ../src/stdiobuf_defs.hh line 110. */
15456
15457/* Automatically generated from PPL source file ../src/c_streambuf_defs.hh line 1. */
15458/* c_streambuf class declaration.
15459*/
15460
15461
15462/* Automatically generated from PPL source file ../src/c_streambuf_types.hh line 1. */
15463
15464
15465namespace Parma_Polyhedra_Library {
15466
15467class c_streambuf;
15468
15469} // namespace Parma_Polyhedra_Library
15470
15471/* Automatically generated from PPL source file ../src/c_streambuf_defs.hh line 28. */
15472#include <streambuf>
15473#include <cstddef>
15474
15475class Parma_Polyhedra_Library::c_streambuf
15476  : public std::basic_streambuf<char, std::char_traits<char> > {
15477public:
15478  //! Constructor.
15479  c_streambuf();
15480
15481  //! Destructor.
15482  virtual ~c_streambuf();
15483
15484protected:
15485  /*! \brief
15486    Gets a character in case of underflow.
15487
15488    \remarks
15489    Specified by ISO/IEC 14882:1998: 27.5.2.4.3.
15490  */
15491  virtual int_type underflow();
15492
15493  /*! \brief
15494    In case of underflow, gets a character and advances the next pointer.
15495
15496    \remarks
15497    Specified by ISO/IEC 14882:1998: 27.5.2.4.3.
15498  */
15499  virtual int_type uflow();
15500
15501  /*! \brief
15502    Gets a sequence of characters.
15503
15504    \remarks
15505    Specified by ISO/IEC 14882:1998: 27.5.2.4.3.
15506  */
15507  virtual std::streamsize xsgetn(char_type* s, std::streamsize n);
15508
15509  /*! \brief
15510    Puts character back in case of backup underflow.
15511
15512    \remarks
15513    Specified by ISO/IEC 14882:1998: 27.5.2.4.4.
15514  */
15515  virtual int_type pbackfail(int_type c = traits_type::eof());
15516
15517  /*! \brief
15518    Writes a sequence of characters.
15519
15520    \remarks
15521    Specified by ISO/IEC 14882:1998: 27.5.2.4.5.
15522  */
15523  virtual std::streamsize xsputn(const char_type* s, std::streamsize n);
15524
15525  /*! \brief
15526    Writes a character in case of overflow.
15527
15528    Specified by ISO/IEC 14882:1998: 27.5.2.4.5.
15529  */
15530  virtual int_type overflow(int_type c);
15531
15532  /*! \brief
15533    Synchronizes the stream buffer.
15534
15535    Specified by ISO/IEC 14882:1998: 27.5.2.4.2.
15536  */
15537  virtual int sync();
15538
15539private:
15540  //! Character type of the streambuf.
15541  typedef char char_type;
15542
15543  //! Traits type of the streambuf.
15544  typedef std::char_traits<char_type> traits_type;
15545
15546  //! Integer type of the streambuf.
15547  typedef traits_type::int_type int_type;
15548
15549  //! Buffer for the last character read.
15550  int_type unget_char_buf;
15551
15552  //! Buffer for next character
15553  int_type next_char_buf;
15554
15555  virtual size_t cb_read(char *, size_t) {
15556    return 0;
15557  }
15558  virtual size_t cb_write(const char *, size_t) {
15559    return 0;
15560  }
15561  virtual int cb_sync() {
15562    return 0;
15563  }
15564  virtual int cb_flush() {
15565    return 0;
15566  }
15567};
15568
15569/* Automatically generated from PPL source file ../src/c_streambuf_inlines.hh line 1. */
15570/* c_streambuf class implementation: inline functions.
15571*/
15572
15573
15574namespace Parma_Polyhedra_Library {
15575
15576inline
15577c_streambuf::c_streambuf()
15578  : unget_char_buf(traits_type::eof()), next_char_buf(traits_type::eof()) {
15579}
15580
15581} // namespace Parma_Polyhedra_Library
15582
15583/* Automatically generated from PPL source file ../src/c_streambuf_defs.hh line 126. */
15584
15585/* Automatically generated from PPL source file ../src/Integer_Interval.hh line 1. */
15586/* Integer_Interval class declaration and implementation.
15587*/
15588
15589
15590/* Automatically generated from PPL source file ../src/Interval_defs.hh line 1. */
15591/* Declarations for the Interval class and its constituents.
15592*/
15593
15594
15595/* Automatically generated from PPL source file ../src/Interval_types.hh line 1. */
15596
15597
15598namespace Parma_Polyhedra_Library {
15599
15600template <typename Boundary, typename Info>
15601class Interval;
15602
15603} // namespace Parma_Polyhedra_Library
15604
15605/* Automatically generated from PPL source file ../src/assign_or_swap.hh line 1. */
15606/* The assign_or_swap() utility functions.
15607*/
15608
15609
15610/* Automatically generated from PPL source file ../src/Has_Assign_Or_Swap.hh line 1. */
15611/* Has_Assign_Or_Swap classes declarations.
15612*/
15613
15614
15615/* Automatically generated from PPL source file ../src/Has_Assign_Or_Swap.hh line 28. */
15616
15617namespace Parma_Polyhedra_Library {
15618
15619#ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
15620/*! \ingroup PPL_CXX_interface
15621  The assign_or_swap() method is not present by default.
15622*/
15623#endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
15624template <typename T, typename Enable = void>
15625struct Has_Assign_Or_Swap : public False {
15626};
15627
15628#ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
15629/*! \ingroup PPL_CXX_interface
15630  The assign_or_swap() method is present if it is present (!).
15631*/
15632#endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
15633template <typename T>
15634struct Has_Assign_Or_Swap<T,
15635                          typename Enable_If_Is<void (T::*)(T& x),
15636                                                &T::assign_or_swap>::type>
15637  : public True {
15638};
15639
15640} // namespace Parma_Polyhedra_Library
15641
15642/* Automatically generated from PPL source file ../src/assign_or_swap.hh line 30. */
15643
15644namespace Parma_Polyhedra_Library {
15645
15646#ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
15647/*! \ingroup PPL_CXX_interface
15648  If there is an assign_or_swap() method, use it.
15649*/
15650#endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
15651template <typename T>
15652inline typename Enable_If<Has_Assign_Or_Swap<T>::value, void>::type
15653assign_or_swap(T& to, T& from) {
15654  to.assign_or_swap(from);
15655}
15656
15657#ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
15658/*! \ingroup PPL_CXX_interface
15659  If there is no assign_or_swap() method but copies are not slow, copy.
15660*/
15661#endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
15662template <typename T>
15663inline typename Enable_If<!Has_Assign_Or_Swap<T>::value
15664                          && !Slow_Copy<T>::value, void>::type
15665assign_or_swap(T& to, T& from) {
15666  to = from;
15667}
15668
15669#ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
15670/*! \ingroup PPL_CXX_interface
15671  If there is no assign_or_swap() and copies are slow, delegate to swap().
15672*/
15673#endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
15674template <typename T>
15675inline typename Enable_If<!Has_Assign_Or_Swap<T>::value
15676                          && Slow_Copy<T>::value, void>::type
15677assign_or_swap(T& to, T& from) {
15678  using std::swap;
15679  swap(to, from);
15680}
15681
15682} // namespace Parma_Polyhedra_Library
15683
15684/* Automatically generated from PPL source file ../src/intervals_defs.hh line 1. */
15685/* Helper classes for intervals.
15686*/
15687
15688
15689/* Automatically generated from PPL source file ../src/intervals_defs.hh line 29. */
15690#include <cstdlib>
15691
15692namespace Parma_Polyhedra_Library {
15693
15694#ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
15695//! The result of an operation on intervals.
15696/*! \ingroup PPL_CXX_interface */
15697#endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
15698enum I_Result {
15699#ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
15700  //! \hideinitializer Result may be empty.
15701#endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
15702  I_EMPTY = 1U,
15703#ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
15704  //! \hideinitializer Result may have only one value.
15705#endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
15706  I_SINGLETON = 2U,
15707#ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
15708  /*! \brief \hideinitializer
15709    Result may have more than one value, but it is not the domain universe.
15710  */
15711#endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
15712  I_SOME = 4U,
15713#ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
15714  //! \hideinitializer Result may be the domain universe.
15715#endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
15716  I_UNIVERSE = 8U,
15717#ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
15718  //! \hideinitializer Result is not empty.
15719#endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
15720  I_NOT_EMPTY = I_SINGLETON | I_SOME | I_UNIVERSE,
15721#ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
15722  //! \hideinitializer Result may be empty or not empty.
15723#endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
15724  I_ANY = I_EMPTY | I_NOT_EMPTY,
15725#ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
15726  //! \hideinitializer Result may be empty or not empty.
15727#endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
15728  I_NOT_UNIVERSE = I_EMPTY | I_SINGLETON | I_SOME,
15729#ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
15730  //! \hideinitializer Result is neither empty nor the domain universe.
15731#endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
15732  I_NOT_DEGENERATE = I_SINGLETON | I_SOME,
15733#ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
15734  //! \hideinitializer Result is definitely exact.
15735#endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
15736  I_EXACT = 16,
15737#ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
15738  //! \hideinitializer Result is definitely inexact.
15739#endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
15740  I_INEXACT = 32,
15741#ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
15742  //! \hideinitializer Operation has definitely changed the set.
15743#endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
15744  I_CHANGED = 64,
15745#ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
15746  //! \hideinitializer Operation has left the set definitely unchanged.
15747#endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
15748  I_UNCHANGED = 128,
15749#ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
15750  //! \hideinitializer Operation is undefined for some combination of values.
15751#endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
15752  I_SINGULARITIES = 256
15753};
15754
15755inline I_Result
15756operator|(I_Result a, I_Result b) {
15757  return static_cast<I_Result>(static_cast<unsigned>(a)
15758                               | static_cast<unsigned>(b));
15759}
15760
15761inline I_Result
15762operator&(I_Result a, I_Result b) {
15763  return static_cast<I_Result>(static_cast<unsigned>(a)
15764                               & static_cast<unsigned>(b));
15765}
15766
15767inline I_Result
15768operator-(I_Result a, I_Result b) {
15769    return static_cast<I_Result>(static_cast<unsigned>(a)
15770                                 & ~static_cast<unsigned>(b));
15771}
15772
15773template <typename Criteria, typename T>
15774struct Use_By_Ref;
15775
15776struct Use_Slow_Copy;
15777template <typename T>
15778struct Use_By_Ref<Use_Slow_Copy, T>
15779  : public Bool<Slow_Copy<T>::value> {
15780};
15781
15782struct By_Value;
15783template <typename T>
15784struct Use_By_Ref<By_Value, T>
15785  : public False {
15786};
15787
15788struct By_Ref;
15789template <typename T>
15790struct Use_By_Ref<By_Ref, T>
15791  : public True {
15792};
15793
15794template <typename T, typename Criteria = Use_Slow_Copy, typename Enable = void>
15795class Val_Or_Ref;
15796
15797template <typename T, typename Criteria>
15798class Val_Or_Ref<T, Criteria,
15799                 typename Enable_If<!Use_By_Ref<Criteria, T>::value>::type> {
15800  T value;
15801public:
15802  typedef T Arg_Type;
15803  typedef T Return_Type;
15804  Val_Or_Ref()
15805    : value() {
15806  }
15807  explicit Val_Or_Ref(Arg_Type v, bool = false)
15808    : value(v) {
15809  }
15810  Val_Or_Ref& operator=(Arg_Type v) {
15811    value = v;
15812    return *this;
15813  }
15814  void set(Arg_Type v, bool = false) {
15815    value = v;
15816  }
15817  Return_Type get() const {
15818    return value;
15819  }
15820  operator Return_Type() const {
15821    return get();
15822  }
15823};
15824
15825template <typename T, typename Criteria>
15826class Val_Or_Ref<T, Criteria,
15827                 typename Enable_If<Use_By_Ref<Criteria, T>::value>::type> {
15828  const T* ptr;
15829public:
15830  typedef T& Arg_Type;
15831  typedef const T& Return_Type;
15832  Val_Or_Ref()
15833    : ptr(0) {
15834  }
15835  explicit Val_Or_Ref(Arg_Type v)
15836    : ptr(&v) {
15837  }
15838  Val_Or_Ref(const T& v, bool)
15839    : ptr(&v) {
15840  }
15841  Val_Or_Ref& operator=(Arg_Type v) {
15842    ptr = &v;
15843    return *this;
15844  }
15845  void set(Arg_Type v) {
15846    ptr = &v;
15847  }
15848  void set(const T& v, bool) {
15849    ptr = &v;
15850  }
15851  Return_Type get() const {
15852    return *ptr;
15853  }
15854  operator Return_Type() const {
15855    return get();
15856  }
15857};
15858
15859class I_Constraint_Base {
15860};
15861
15862template <typename Derived>
15863class I_Constraint_Common : public I_Constraint_Base {
15864public:
15865  template <typename T>
15866  Result convert_real(T& to) const {
15867    const Derived& c = static_cast<const Derived&>(*this);
15868    Result r = c.rel();
15869    switch (r) {
15870    case V_EMPTY:
15871    case V_LGE:
15872      return r;
15873    case V_LE:
15874      r = assign_r(to, c.value(), (ROUND_UP | ROUND_STRICT_RELATION));
15875      r = result_relation_class(r);
15876      if (r == V_EQ) {
15877        return V_LE;
15878      }
15879      goto lt;
15880    case V_LT:
15881      r = assign_r(to, c.value(), ROUND_UP);
15882      r = result_relation_class(r);
15883    lt:
15884      switch (r) {
15885      case V_EMPTY:
15886      case V_LT_PLUS_INFINITY:
15887      case V_EQ_MINUS_INFINITY:
15888        return r;
15889      case V_LT:
15890      case V_LE:
15891      case V_EQ:
15892        return V_LT;
15893      default:
15894        break;
15895      }
15896      break;
15897    case V_GE:
15898      r = assign_r(to, c.value(), (ROUND_DOWN | ROUND_STRICT_RELATION));
15899      r = result_relation_class(r);
15900      if (r == V_EQ) {
15901        return V_GE;
15902      }
15903      goto gt;
15904    case V_GT:
15905      r = assign_r(to, c.value(), ROUND_DOWN);
15906      r = result_relation_class(r);
15907    gt:
15908      switch (r) {
15909      case V_EMPTY:
15910      case V_GT_MINUS_INFINITY:
15911      case V_EQ_PLUS_INFINITY:
15912        return r;
15913      case V_LT:
15914      case V_LE:
15915      case V_EQ:
15916        return V_GT;
15917      default:
15918        break;
15919      }
15920      break;
15921    case V_EQ:
15922      r = assign_r(to, c.value(), ROUND_CHECK);
15923      r = result_relation_class(r);
15924      PPL_ASSERT(r != V_LT && r != V_GT);
15925      if (r == V_EQ) {
15926        return V_EQ;
15927      }
15928      else {
15929        return V_EMPTY;
15930      }
15931    case V_NE:
15932      r = assign_r(to, c.value(), ROUND_CHECK);
15933      r = result_relation_class(r);
15934      if (r == V_EQ) {
15935        return V_NE;
15936      }
15937      else {
15938        return V_LGE;
15939      }
15940    default:
15941      break;
15942    }
15943    PPL_UNREACHABLE;
15944    return V_EMPTY;
15945  }
15946  template <typename T>
15947  Result convert_real(T& to1, Result& rel2, T& to2) const {
15948    const Derived& c = static_cast<const Derived&>(*this);
15949    Result rel1;
15950    if (c.rel() != V_EQ) {
15951      rel2 = convert(to2);
15952      return V_LGE;
15953    }
15954    rel2 = assign_r(to2, c.value(), ROUND_UP);
15955    rel2 = result_relation_class(rel2);
15956    switch (rel2) {
15957    case V_EMPTY:
15958    case V_EQ_MINUS_INFINITY:
15959    case V_EQ:
15960      return V_LGE;
15961    default:
15962      break;
15963    }
15964    rel1 = assign_r(to1, c.value(), ROUND_DOWN);
15965    rel1 = result_relation_class(rel1);
15966    switch (rel1) {
15967    case V_EQ:
15968      PPL_ASSERT(rel2 == V_LE);
15969      goto eq;
15970    case V_EQ_PLUS_INFINITY:
15971    case V_EMPTY:
15972      rel2 = rel1;
15973      return V_LGE;
15974    case V_GE:
15975      if (rel2 == V_LE && to1 == to2) {
15976      eq:
15977        rel2 = V_EQ;
15978        return V_LGE;
15979      }
15980      /* Fall through*/
15981    case V_GT:
15982    case V_GT_MINUS_INFINITY:
15983      return rel1;
15984    default:
15985      PPL_UNREACHABLE;
15986      return V_EMPTY;
15987    }
15988    switch (rel2) {
15989    case V_LE:
15990    case V_LT:
15991    case V_LT_PLUS_INFINITY:
15992      return rel1;
15993    default:
15994      PPL_UNREACHABLE;
15995      return V_EMPTY;
15996    }
15997  }
15998  template <typename T>
15999  Result convert_integer(T& to) const {
16000    Result rel = convert_real(to);
16001    switch (rel) {
16002    case V_LT:
16003      if (is_integer(to)) {
16004        rel = sub_assign_r(to, to, T(1), (ROUND_UP | ROUND_STRICT_RELATION));
16005        rel = result_relation_class(rel);
16006        return (rel == V_EQ) ? V_LE : rel;
16007      }
16008      /* Fall through */
16009    case V_LE:
16010      rel = floor_assign_r(to, to, ROUND_UP);
16011      rel = result_relation_class(rel);
16012      PPL_ASSERT(rel == V_EQ);
16013      return V_LE;
16014    case V_GT:
16015      if (is_integer(to)) {
16016        rel = add_assign_r(to, to, T(1), (ROUND_DOWN | ROUND_STRICT_RELATION));
16017        rel = result_relation_class(rel);
16018        return (rel == V_EQ) ? V_GE : rel;
16019      }
16020      /* Fall through */
16021    case V_GE:
16022      rel = ceil_assign_r(to, to, ROUND_DOWN);
16023      rel = result_relation_class(rel);
16024      PPL_ASSERT(rel == V_EQ);
16025      return V_GE;
16026    case V_EQ:
16027      if (is_integer(to)) {
16028        return V_EQ;
16029      }
16030      return V_EMPTY;
16031    case V_NE:
16032      if (is_integer(to)) {
16033        return V_NE;
16034      }
16035      return V_LGE;
16036    default:
16037      return rel;
16038    }
16039  }
16040};
16041
16042struct I_Constraint_Rel {
16043  Result rel;
16044  I_Constraint_Rel(Result r)
16045    : rel(r) {
16046    PPL_ASSERT(result_relation_class(r) == r);
16047  }
16048  I_Constraint_Rel(Relation_Symbol r)
16049    : rel(static_cast<Result>(r)) {
16050  }
16051  operator Result() const {
16052    return rel;
16053  }
16054};
16055
16056template <typename T, typename Val_Or_Ref_Criteria = Use_Slow_Copy,
16057          bool extended = false>
16058class I_Constraint
16059  : public I_Constraint_Common<I_Constraint<T, Val_Or_Ref_Criteria,
16060                                            extended> > {
16061  typedef Val_Or_Ref<T, Val_Or_Ref_Criteria> Val_Ref;
16062  typedef typename Val_Ref::Arg_Type Arg_Type;
16063  typedef typename Val_Ref::Return_Type Return_Type;
16064  Result rel_;
16065  Val_Ref value_;
16066public:
16067  typedef T value_type;
16068  explicit I_Constraint()
16069    : rel_(V_LGE) {
16070  }
16071  I_Constraint(I_Constraint_Rel r, Arg_Type v)
16072    : rel_(r), value_(v) {
16073  }
16074  I_Constraint(I_Constraint_Rel r, const T& v, bool force)
16075    : rel_(r), value_(v, force) {
16076  }
16077  template <typename U>
16078  I_Constraint(I_Constraint_Rel r, const U& v)
16079    : rel_(r), value_(v) {
16080  }
16081  void set(I_Constraint_Rel r, Arg_Type v) {
16082    rel_ =  r;
16083    value_.set(v);
16084  }
16085  void set(I_Constraint_Rel r, const T& v, bool force) {
16086    rel_ =  r;
16087    value_.set(v, force);
16088  }
16089  template <typename U>
16090  void set(I_Constraint_Rel r, const U& v) {
16091    rel_ = r;
16092    value_.set(v);
16093  }
16094  Return_Type value() const {
16095    return value_;
16096  }
16097  Result rel() const {
16098    return rel_;
16099  }
16100};
16101
16102template <typename T>
16103inline I_Constraint<T>
16104i_constraint(I_Constraint_Rel rel, const T& v) {
16105  return I_Constraint<T>(rel, v);
16106}
16107
16108template <typename T>
16109inline I_Constraint<T>
16110i_constraint(I_Constraint_Rel rel, const T& v, bool force) {
16111  return I_Constraint<T>(rel, v, force);
16112}
16113
16114template <typename T>
16115inline I_Constraint<T>
16116i_constraint(I_Constraint_Rel rel, T& v) {
16117  return I_Constraint<T>(rel, v);
16118}
16119
16120template <typename T, typename Val_Or_Ref_Criteria>
16121inline I_Constraint<T, Val_Or_Ref_Criteria>
16122i_constraint(I_Constraint_Rel rel, const T& v, const Val_Or_Ref_Criteria&) {
16123  return I_Constraint<T, Val_Or_Ref_Criteria>(rel, v);
16124}
16125
16126template <typename T, typename Val_Or_Ref_Criteria>
16127inline I_Constraint<T, Val_Or_Ref_Criteria>
16128i_constraint(I_Constraint_Rel rel, const T& v, bool force,
16129             const Val_Or_Ref_Criteria&) {
16130  return I_Constraint<T, Val_Or_Ref_Criteria>(rel, v, force);
16131}
16132
16133template <typename T, typename Val_Or_Ref_Criteria>
16134inline I_Constraint<T, Val_Or_Ref_Criteria>
16135i_constraint(I_Constraint_Rel rel, T& v, const Val_Or_Ref_Criteria&) {
16136  return I_Constraint<T, Val_Or_Ref_Criteria>(rel, v);
16137}
16138
16139} // namespace Parma_Polyhedra_Library
16140
16141/* Automatically generated from PPL source file ../src/Interval_Info_defs.hh line 1. */
16142/* Interval_Info class declaration and implementation.
16143*/
16144
16145
16146/* Automatically generated from PPL source file ../src/Boundary_defs.hh line 1. */
16147/* Interval boundary functions.
16148*/
16149
16150
16151/* Automatically generated from PPL source file ../src/Boundary_defs.hh line 28. */
16152
16153namespace Parma_Polyhedra_Library {
16154
16155namespace Boundary_NS {
16156
16157struct Property {
16158  enum Type {
16159    SPECIAL_,
16160    OPEN_
16161  };
16162  typedef bool Value;
16163  static const Value default_value = true;
16164  static const Value unsupported_value = false;
16165  Property(Type t)
16166    : type(t) {
16167  }
16168  Type type;
16169};
16170
16171static const Property SPECIAL(Property::SPECIAL_);
16172static const Property OPEN(Property::OPEN_);
16173
16174enum Boundary_Type {
16175  LOWER = ROUND_DOWN,
16176  UPPER = ROUND_UP
16177};
16178
16179inline Rounding_Dir
16180round_dir_check(Boundary_Type t, bool check = false) {
16181  if (check) {
16182    return static_cast<Rounding_Dir>(t) | ROUND_STRICT_RELATION;
16183  }
16184  else {
16185    return static_cast<Rounding_Dir>(t);
16186  }
16187}
16188
16189template <typename T, typename Info>
16190inline Result
16191special_set_boundary_infinity(Boundary_Type type, T&, Info& info) {
16192  PPL_ASSERT(Info::store_special);
16193  info.set_boundary_property(type, SPECIAL);
16194  return V_EQ;
16195}
16196
16197template <typename T, typename Info>
16198inline bool
16199special_is_open(Boundary_Type, const T&, const Info&) {
16200  return !Info::may_contain_infinity;
16201}
16202
16203template <typename T, typename Info>
16204inline bool
16205normal_is_open(Boundary_Type type, const T& x, const Info& info) {
16206  if (Info::store_open) {
16207    return info.get_boundary_property(type, OPEN);
16208  }
16209  else {
16210    return !Info::store_special && !Info::may_contain_infinity
16211      && normal_is_boundary_infinity(type, x, info);
16212  }
16213}
16214
16215template <typename T, typename Info>
16216inline bool
16217is_open(Boundary_Type type, const T& x, const Info& info) {
16218  if (Info::store_open) {
16219    return info.get_boundary_property(type, OPEN);
16220  }
16221  else {
16222    return !Info::may_contain_infinity
16223      && is_boundary_infinity(type, x, info);
16224  }
16225}
16226
16227template <typename T, typename Info>
16228inline Result
16229set_unbounded(Boundary_Type type, T& x, Info& info) {
16230  PPL_COMPILE_TIME_CHECK(Info::store_special
16231                         || std::numeric_limits<T>::is_bounded
16232                         || std::numeric_limits<T>::has_infinity,
16233                         "unbounded is not representable");
16234  Result r;
16235  if (Info::store_special) {
16236    r = special_set_boundary_infinity(type, x, info);
16237  }
16238  else if (type == LOWER) {
16239    r = assign_r(x, MINUS_INFINITY, ROUND_UP);
16240  }
16241  else {
16242    r = assign_r(x, PLUS_INFINITY, ROUND_DOWN);
16243  }
16244  if (result_relation(r) == VR_EQ && !Info::may_contain_infinity) {
16245    info.set_boundary_property(type, OPEN);
16246  }
16247  return r;
16248}
16249
16250template <typename T, typename Info>
16251inline Result
16252set_minus_infinity(Boundary_Type type, T& x, Info& info, bool open = false) {
16253  if (open) {
16254    PPL_ASSERT(type == LOWER);
16255  }
16256  else {
16257    PPL_ASSERT(Info::may_contain_infinity);
16258  }
16259  Result r;
16260  if (Info::store_special) {
16261    PPL_ASSERT(type == LOWER);
16262    r = special_set_boundary_infinity(type, x, info);
16263  }
16264  else {
16265    r = assign_r(x, MINUS_INFINITY, round_dir_check(type));
16266    PPL_ASSERT(result_representable(r));
16267  }
16268  if (open || result_relation(r) != VR_EQ) {
16269    info.set_boundary_property(type, OPEN);
16270  }
16271  return r;
16272}
16273
16274template <typename T, typename Info>
16275inline Result
16276set_plus_infinity(Boundary_Type type, T& x, Info& info, bool open = false) {
16277  if (open) {
16278    PPL_ASSERT(type == UPPER);
16279  }
16280  else {
16281    PPL_ASSERT(Info::may_contain_infinity);
16282  }
16283  Result r;
16284  if (Info::store_special) {
16285    PPL_ASSERT(type == UPPER);
16286    r = special_set_boundary_infinity(type, x, info);
16287  }
16288  else {
16289    r = assign_r(x, PLUS_INFINITY, round_dir_check(type));
16290    PPL_ASSERT(result_representable(r));
16291  }
16292  if (open || result_relation(r) != VR_EQ) {
16293    info.set_boundary_property(type, OPEN);
16294  }
16295  return r;
16296}
16297
16298template <typename T, typename Info>
16299inline Result
16300set_boundary_infinity(Boundary_Type type, T& x, Info& info, bool open = false) {
16301  PPL_ASSERT(open || Info::may_contain_infinity);
16302  Result r;
16303  if (Info::store_special) {
16304    r = special_set_boundary_infinity(type, x, info);
16305  }
16306  else if (type == LOWER) {
16307    r = assign_r(x, MINUS_INFINITY, round_dir_check(type));
16308  }
16309  else {
16310    r = assign_r(x, PLUS_INFINITY, round_dir_check(type));
16311  }
16312  PPL_ASSERT(result_representable(r));
16313  if (open) {
16314    info.set_boundary_property(type, OPEN);
16315  }
16316  return r;
16317}
16318
16319template <typename T, typename Info>
16320inline bool
16321is_domain_inf(Boundary_Type type, const T& x, const Info& info) {
16322  if (Info::store_special && type == LOWER) {
16323    return info.get_boundary_property(type, SPECIAL);
16324  }
16325  else if (std::numeric_limits<T>::has_infinity) {
16326    return Parma_Polyhedra_Library::is_minus_infinity(x);
16327  }
16328  else if (std::numeric_limits<T>::is_bounded) {
16329    return x == std::numeric_limits<T>::min();
16330  }
16331  else {
16332    return false;
16333  }
16334}
16335
16336template <typename T, typename Info>
16337inline bool
16338is_domain_sup(Boundary_Type type, const T& x, const Info& info) {
16339  if (Info::store_special && type == UPPER) {
16340    return info.get_boundary_property(type, SPECIAL);
16341  }
16342  else if (std::numeric_limits<T>::has_infinity) {
16343    return Parma_Polyhedra_Library::is_plus_infinity(x);
16344  }
16345  else if (std::numeric_limits<T>::is_bounded) {
16346      return x == std::numeric_limits<T>::max();
16347  }
16348  else {
16349    return false;
16350  }
16351}
16352
16353template <typename T, typename Info>
16354inline bool
16355normal_is_boundary_infinity(Boundary_Type type, const T& x, const Info&) {
16356  if (!std::numeric_limits<T>::has_infinity) {
16357    return false;
16358  }
16359  if (type == LOWER) {
16360    return Parma_Polyhedra_Library::is_minus_infinity(x);
16361  }
16362  else {
16363    return Parma_Polyhedra_Library::is_plus_infinity(x);
16364  }
16365}
16366
16367template <typename T, typename Info>
16368inline bool
16369is_boundary_infinity(Boundary_Type type, const T& x, const Info& info) {
16370  if (Info::store_special) {
16371    return info.get_boundary_property(type, SPECIAL);
16372  }
16373  else {
16374    return normal_is_boundary_infinity(type, x, info);
16375  }
16376}
16377
16378template <typename T, typename Info>
16379inline bool
16380normal_is_reverse_infinity(Boundary_Type type, const T& x, const Info&) {
16381  if (!Info::may_contain_infinity) {
16382    return false;
16383  }
16384  else if (type == LOWER) {
16385    return Parma_Polyhedra_Library::is_plus_infinity(x);
16386  }
16387  else {
16388    return Parma_Polyhedra_Library::is_minus_infinity(x);
16389  }
16390}
16391
16392template <typename T, typename Info>
16393inline bool
16394is_minus_infinity(Boundary_Type type, const T& x, const Info& info) {
16395  if (type == LOWER) {
16396    if (Info::store_special) {
16397      return info.get_boundary_property(type, SPECIAL);
16398    }
16399    else {
16400      return normal_is_boundary_infinity(type, x, info);
16401    }
16402  }
16403  else {
16404    return !Info::store_special && normal_is_reverse_infinity(type, x, info);
16405  }
16406}
16407
16408template <typename T, typename Info>
16409inline bool
16410is_plus_infinity(Boundary_Type type, const T& x, const Info& info) {
16411  if (type == UPPER) {
16412    if (Info::store_special) {
16413      return info.get_boundary_property(type, SPECIAL);
16414    }
16415    else {
16416      return normal_is_boundary_infinity(type, x, info);
16417    }
16418  }
16419  else {
16420    return !Info::store_special && normal_is_reverse_infinity(type, x, info);
16421  }
16422}
16423
16424template <typename T, typename Info>
16425inline bool
16426is_reverse_infinity(Boundary_Type type, const T& x, const Info& info) {
16427  return normal_is_reverse_infinity(type, x, info);
16428}
16429
16430template <typename T, typename Info>
16431inline int
16432infinity_sign(Boundary_Type type, const T& x, const Info& info) {
16433  if (is_boundary_infinity(type, x, info)) {
16434    return (type == LOWER) ? -1 : 1;
16435  }
16436  else if (is_reverse_infinity(type, x, info)) {
16437    return (type == UPPER) ? -1 : 1;
16438  }
16439  else {
16440    return 0;
16441  }
16442}
16443
16444template <typename T, typename Info>
16445inline bool
16446is_boundary_infinity_closed(Boundary_Type type, const T& x, const Info& info) {
16447  return Info::may_contain_infinity
16448    && !info.get_boundary_property(type, OPEN)
16449    && is_boundary_infinity(type, x, info);
16450}
16451
16452template <typename Info>
16453inline bool
16454boundary_infinity_is_open(Boundary_Type type, const Info& info) {
16455  return !Info::may_contain_infinity
16456    || info.get_boundary_property(type, OPEN);
16457}
16458
16459template <typename T, typename Info>
16460inline int
16461sgn_b(Boundary_Type type, const T& x, const Info& info) {
16462  if (info.get_boundary_property(type, SPECIAL)) {
16463    return (type == LOWER) ? -1 : 1;
16464  }
16465  else {
16466    // The following Parma_Polyhedra_Library:: qualification is to work
16467    // around a bug of GCC 4.0.x.
16468    return Parma_Polyhedra_Library::sgn(x);
16469  }
16470}
16471
16472template <typename T, typename Info>
16473inline int
16474sgn(Boundary_Type type, const T& x, const Info& info) {
16475  int sign = sgn_b(type, x, info);
16476  if (x == 0 && info.get_boundary_property(type, OPEN)) {
16477    return (type == LOWER) ? -1 : 1;
16478  }
16479  else {
16480    return sign;
16481  }
16482}
16483
16484template <typename T1, typename Info1, typename T2, typename Info2>
16485inline bool
16486eq(Boundary_Type type1, const T1& x1, const Info1& info1,
16487   Boundary_Type type2, const T2& x2, const Info2& info2) {
16488  if (type1 == type2) {
16489    if (is_open(type1, x1, info1)
16490        != is_open(type2, x2, info2)) {
16491      return false;
16492    }
16493  }
16494  else if (is_open(type1, x1, info1)
16495           || is_open(type2, x2, info2)) {
16496    return false;
16497  }
16498  if (is_minus_infinity(type1, x1, info1)) {
16499    return is_minus_infinity(type2, x2, info2);
16500  }
16501  else if (is_plus_infinity(type1, x1, info1)) {
16502    return is_plus_infinity(type2, x2, info2);
16503  }
16504  else if (is_minus_infinity(type2, x2, info2)
16505           || is_plus_infinity(type2, x2, info2)) {
16506    return false;
16507  }
16508  else {
16509    return equal(x1, x2);
16510  }
16511}
16512
16513template <typename T1, typename Info1, typename T2, typename Info2>
16514inline bool
16515lt(Boundary_Type type1, const T1& x1, const Info1& info1,
16516   Boundary_Type type2, const T2& x2, const Info2& info2) {
16517  if (is_open(type1, x1, info1)) {
16518    if (type1 == UPPER
16519        && (type2 == LOWER
16520            || !is_open(type2, x2, info2))) {
16521      goto le;
16522    }
16523  }
16524  else if (type2 == LOWER
16525           && is_open(type2, x2, info2)) {
16526  le:
16527    if (is_minus_infinity(type1, x1, info1)
16528        || is_plus_infinity(type2, x2, info2)) {
16529      return true;
16530    }
16531    if (is_plus_infinity(type1, x1, info1)
16532        || is_minus_infinity(type2, x2, info2)) {
16533      return false;
16534    }
16535    else {
16536      return less_or_equal(x1, x2);
16537    }
16538  }
16539  if (is_plus_infinity(type1, x1, info1)
16540      || is_minus_infinity(type2, x2, info2)) {
16541    return false;
16542  }
16543  if (is_minus_infinity(type1, x1, info1)
16544      || is_plus_infinity(type2, x2, info2)) {
16545    return true;
16546  }
16547  else {
16548    return less_than(x1, x2);
16549  }
16550}
16551
16552template <typename T1, typename Info1, typename T2, typename Info2>
16553inline bool
16554gt(Boundary_Type type1, const T1& x1, const Info1& info1,
16555   Boundary_Type type2, const T2& x2, const Info2& info2) {
16556  return lt(type2, x2, info2, type1, x1, info1);
16557}
16558
16559template <typename T1, typename Info1, typename T2, typename Info2>
16560inline bool
16561le(Boundary_Type type1, const T1& x1, const Info1& info1,
16562   Boundary_Type type2, const T2& x2, const Info2& info2) {
16563  return !gt(type1, x1, info1, type2, x2, info2);
16564}
16565
16566template <typename T1, typename Info1, typename T2, typename Info2>
16567inline bool
16568ge(Boundary_Type type1, const T1& x1, const Info1& info1,
16569   Boundary_Type type2, const T2& x2, const Info2& info2) {
16570  return !lt(type1, x1, info1, type2, x2, info2);
16571}
16572
16573template <typename T, typename Info>
16574inline Result
16575adjust_boundary(Boundary_Type type, T& x, Info& info,
16576                bool open, Result r) {
16577  r = result_relation_class(r);
16578  if (type == LOWER) {
16579    switch (r) {
16580    case V_GT_MINUS_INFINITY:
16581      open = true;
16582      /* Fall through */
16583    case V_EQ_MINUS_INFINITY:
16584      if (!Info::store_special) {
16585        return r;
16586      }
16587      if (open) {
16588        info.set_boundary_property(type, OPEN);
16589      }
16590      return special_set_boundary_infinity(type, x, info);
16591    case V_GT:
16592      open = true;
16593      /* Fall through */
16594    case V_GE:
16595    case V_EQ:
16596      if (open) {
16597        info.set_boundary_property(type, OPEN);
16598      }
16599      return r;
16600    default:
16601      PPL_UNREACHABLE;
16602      return V_NAN;
16603    }
16604  }
16605  else {
16606    switch (r) {
16607    case V_LT_PLUS_INFINITY:
16608      open = true;
16609      /* Fall through */
16610    case V_EQ_PLUS_INFINITY:
16611      if (!Info::store_special) {
16612        return r;
16613      }
16614      if (open) {
16615        info.set_boundary_property(type, OPEN);
16616      }
16617      return special_set_boundary_infinity(type, x, info);
16618    case V_LT:
16619      open = true;
16620      /* Fall through */
16621    case V_LE:
16622    case V_EQ:
16623      if (open) {
16624        info.set_boundary_property(type, OPEN);
16625      }
16626      return r;
16627    default:
16628      PPL_UNREACHABLE;
16629      return V_NAN;
16630    }
16631  }
16632}
16633
16634template <typename To, typename To_Info, typename T, typename Info>
16635inline Result
16636complement(Boundary_Type to_type, To& to, To_Info& to_info,
16637           Boundary_Type type, const T& x, const Info& info) {
16638  PPL_ASSERT(to_type != type);
16639  bool should_shrink;
16640  if (info.get_boundary_property(type, SPECIAL)) {
16641    should_shrink = !special_is_open(type, x, info);
16642    if (type == LOWER) {
16643      return set_minus_infinity(to_type, to, to_info, should_shrink);
16644    }
16645    else {
16646      return set_plus_infinity(to_type, to, to_info, should_shrink);
16647    }
16648  }
16649  should_shrink = !normal_is_open(type, x, info);
16650  bool check = (To_Info::check_inexact || (!should_shrink && To_Info::store_open));
16651  Result r = assign_r(to, x, round_dir_check(to_type, check));
16652  return adjust_boundary(to_type, to, to_info, should_shrink, r);
16653}
16654
16655template <typename To, typename To_Info, typename T, typename Info>
16656inline Result
16657assign(Boundary_Type to_type, To& to, To_Info& to_info,
16658       Boundary_Type type, const T& x, const Info& info,
16659       bool should_shrink = false) {
16660  PPL_ASSERT(to_type == type);
16661  if (info.get_boundary_property(type, SPECIAL)) {
16662    should_shrink = (should_shrink || special_is_open(type, x, info));
16663    return set_boundary_infinity(to_type, to, to_info, should_shrink);
16664  }
16665  should_shrink = (should_shrink || normal_is_open(type, x, info));
16666  const bool check
16667    = (To_Info::check_inexact || (!should_shrink && To_Info::store_open));
16668  const Result r = assign_r(to, x, round_dir_check(to_type, check));
16669  return adjust_boundary(to_type, to, to_info, should_shrink, r);
16670}
16671
16672template <typename To, typename To_Info, typename T, typename Info>
16673inline Result
16674min_assign(Boundary_Type to_type, To& to, To_Info& to_info,
16675           Boundary_Type type, const T& x, const Info& info) {
16676  if (lt(type, x, info, to_type, to, to_info)) {
16677    to_info.clear_boundary_properties(to_type);
16678    return assign(to_type, to, to_info, type, x, info);
16679  }
16680  return V_EQ;
16681}
16682
16683template <typename To, typename To_Info, typename T1, typename Info1, typename T2, typename Info2>
16684inline Result
16685min_assign(Boundary_Type to_type, To& to, To_Info& to_info,
16686           Boundary_Type type1, const T1& x1, const Info1& info1,
16687           Boundary_Type type2, const T2& x2, const Info2& info2) {
16688  if (lt(type1, x1, info1, type2, x2, info2)) {
16689    return assign(to_type, to, to_info, type1, x1, info1);
16690  }
16691  else {
16692    return assign(to_type, to, to_info, type2, x2, info2);
16693  }
16694}
16695
16696template <typename To, typename To_Info, typename T, typename Info>
16697inline Result
16698max_assign(Boundary_Type to_type, To& to, To_Info& to_info,
16699           Boundary_Type type, const T& x, const Info& info) {
16700  if (gt(type, x, info, to_type, to, to_info)) {
16701    to_info.clear_boundary_properties(to_type);
16702    return assign(to_type, to, to_info, type, x, info);
16703  }
16704  return V_EQ;
16705}
16706
16707template <typename To, typename To_Info, typename T1, typename Info1, typename T2, typename Info2>
16708inline Result
16709max_assign(Boundary_Type to_type, To& to, To_Info& to_info,
16710           Boundary_Type type1, const T1& x1, const Info1& info1,
16711           Boundary_Type type2, const T2& x2, const Info2& info2) {
16712  if (gt(type1, x1, info1, type2, x2, info2)) {
16713    return assign(to_type, to, to_info, type1, x1, info1);
16714  }
16715  else {
16716    return assign(to_type, to, to_info, type2, x2, info2);
16717  }
16718}
16719
16720template <typename To, typename To_Info, typename T, typename Info>
16721inline Result
16722neg_assign(Boundary_Type to_type, To& to, To_Info& to_info,
16723           Boundary_Type type, const T& x, const Info& info) {
16724  PPL_ASSERT(to_type != type);
16725  bool should_shrink;
16726  if (info.get_boundary_property(type, SPECIAL)) {
16727    should_shrink = special_is_open(type, x, info);
16728    return set_boundary_infinity(to_type, to, to_info, should_shrink);
16729  }
16730  should_shrink = normal_is_open(type, x, info);
16731  bool check = (To_Info::check_inexact || (!should_shrink && To_Info::store_open));
16732  Result r = neg_assign_r(to, x, round_dir_check(to_type, check));
16733  return adjust_boundary(to_type, to, to_info, should_shrink, r);
16734}
16735
16736template <typename To, typename To_Info, typename T1, typename Info1, typename T2, typename Info2>
16737inline Result
16738add_assign(Boundary_Type to_type, To& to, To_Info& to_info,
16739           Boundary_Type type1, const T1& x1, const Info1& info1,
16740           Boundary_Type type2, const T2& x2, const Info2& info2) {
16741  PPL_ASSERT(type1 == type2);
16742  bool should_shrink;
16743  if (is_boundary_infinity(type1, x1, info1)) {
16744    should_shrink = (boundary_infinity_is_open(type1, info1)
16745                     && !is_boundary_infinity_closed(type2, x2, info2));
16746    return set_boundary_infinity(to_type, to, to_info, should_shrink);
16747  }
16748  else if (is_boundary_infinity(type2, x2, info2)) {
16749    should_shrink = (boundary_infinity_is_open(type2, info2)
16750                     && !is_boundary_infinity_closed(type1, x1, info1));
16751    return set_boundary_infinity(to_type, to, to_info, should_shrink);
16752  }
16753  should_shrink = (normal_is_open(type1, x1, info1)
16754                   || normal_is_open(type2, x2, info2));
16755  bool check = (To_Info::check_inexact || (!should_shrink && To_Info::store_open));
16756  // FIXME: extended handling is not needed
16757  Result r = add_assign_r(to, x1, x2, round_dir_check(to_type, check));
16758  return adjust_boundary(to_type, to, to_info, should_shrink, r);
16759}
16760
16761template <typename To, typename To_Info, typename T1, typename Info1, typename T2, typename Info2>
16762inline Result
16763sub_assign(Boundary_Type to_type, To& to, To_Info& to_info,
16764           Boundary_Type type1, const T1& x1, const Info1& info1,
16765           Boundary_Type type2, const T2& x2, const Info2& info2) {
16766  PPL_ASSERT(type1 != type2);
16767  bool should_shrink;
16768  if (is_boundary_infinity(type1, x1, info1)) {
16769    should_shrink = (boundary_infinity_is_open(type1, info1)
16770                     && !is_boundary_infinity_closed(type2, x2, info2));
16771    return set_boundary_infinity(to_type, to, to_info, should_shrink);
16772  }
16773  else if (is_boundary_infinity(type2, x2, info2)) {
16774    should_shrink = (boundary_infinity_is_open(type2, info2)
16775                     && !is_boundary_infinity_closed(type1, x1, info1));
16776    return set_boundary_infinity(to_type, to, to_info, should_shrink);
16777  }
16778  should_shrink = (normal_is_open(type1, x1, info1)
16779                   || normal_is_open(type2, x2, info2));
16780  bool check = (To_Info::check_inexact || (!should_shrink && To_Info::store_open));
16781  // FIXME: extended handling is not needed
16782  Result r = sub_assign_r(to, x1, x2, round_dir_check(to_type, check));
16783  return adjust_boundary(to_type, to, to_info, should_shrink, r);
16784}
16785
16786template <typename To, typename To_Info, typename T1, typename Info1, typename T2, typename Info2>
16787inline Result
16788mul_assign(Boundary_Type to_type, To& to, To_Info& to_info,
16789           Boundary_Type type1, const T1& x1, const Info1& info1,
16790           Boundary_Type type2, const T2& x2, const Info2& info2) {
16791  bool should_shrink;
16792  if (is_boundary_infinity(type1, x1, info1)) {
16793    should_shrink = (boundary_infinity_is_open(type1, info1)
16794                     && !is_boundary_infinity_closed(type2, x2, info2));
16795    return set_boundary_infinity(to_type, to, to_info, should_shrink);
16796  }
16797  else if (is_boundary_infinity(type2, x2, info2)) {
16798    should_shrink = (boundary_infinity_is_open(type2, info2)
16799                     && !is_boundary_infinity_closed(type1, x1, info1));
16800    return set_boundary_infinity(to_type, to, to_info, should_shrink);
16801  }
16802  should_shrink = (normal_is_open(type1, x1, info1)
16803                   || normal_is_open(type2, x2, info2));
16804  bool check = (To_Info::check_inexact || (!should_shrink && To_Info::store_open));
16805  PPL_ASSERT(x1 != Constant<0>::value && x2 != Constant<0>::value);
16806  // FIXME: extended handling is not needed
16807  Result r = mul_assign_r(to, x1, x2, round_dir_check(to_type, check));
16808  return adjust_boundary(to_type, to, to_info, should_shrink, r);
16809}
16810
16811template <typename To, typename To_Info>
16812inline Result
16813set_zero(Boundary_Type to_type, To& to, To_Info& to_info, bool should_shrink) {
16814  bool check = (To_Info::check_inexact || (!should_shrink && To_Info::store_open));
16815  Result r = assign_r(to, Constant<0>::value, round_dir_check(to_type, check));
16816  return adjust_boundary(to_type, to, to_info, should_shrink, r);
16817}
16818
16819template <typename To, typename To_Info, typename T1, typename Info1, typename T2, typename Info2>
16820inline Result
16821mul_assign_z(Boundary_Type to_type, To& to, To_Info& to_info,
16822             Boundary_Type type1, const T1& x1, const Info1& info1, int x1s,
16823             Boundary_Type type2, const T2& x2, const Info2& info2, int x2s) {
16824  bool should_shrink;
16825  if (x1s != 0) {
16826    if (x2s != 0) {
16827      return mul_assign(to_type, to, to_info,
16828                        type1, x1, info1,
16829                        type2, x2, info2);
16830    }
16831    else {
16832      should_shrink = info2.get_boundary_property(type2, OPEN);
16833    }
16834  }
16835  else {
16836    should_shrink = (info1.get_boundary_property(type1, OPEN)
16837                     && (x2s != 0 || info2.get_boundary_property(type2, OPEN)));
16838  }
16839  return set_zero(to_type, to, to_info, should_shrink);
16840}
16841
16842template <typename To, typename To_Info, typename T1, typename Info1, typename T2, typename Info2>
16843inline Result
16844div_assign(Boundary_Type to_type, To& to, To_Info& to_info,
16845           Boundary_Type type1, const T1& x1, const Info1& info1,
16846           Boundary_Type type2, const T2& x2, const Info2& info2) {
16847  bool should_shrink;
16848  if (is_boundary_infinity(type1, x1, info1)) {
16849    should_shrink = boundary_infinity_is_open(type1, info1);
16850    return set_boundary_infinity(to_type, to, to_info, should_shrink);
16851  }
16852  else if (is_boundary_infinity(type2, x2, info2)) {
16853    should_shrink = boundary_infinity_is_open(type2, info2);
16854    return set_zero(to_type, to, to_info, should_shrink);
16855  }
16856  should_shrink = (normal_is_open(type1, x1, info1)
16857                   || normal_is_open(type2, x2, info2));
16858  bool check = (To_Info::check_inexact || (!should_shrink && To_Info::store_open));
16859  PPL_ASSERT(x1 != Constant<0>::value && x2 != Constant<0>::value);
16860  // FIXME: extended handling is not needed
16861  Result r = div_assign_r(to, x1, x2, round_dir_check(to_type, check));
16862  return adjust_boundary(to_type, to, to_info, should_shrink, r);
16863}
16864
16865
16866template <typename To, typename To_Info, typename T1, typename Info1, typename T2, typename Info2>
16867inline Result
16868div_assign_z(Boundary_Type to_type, To& to, To_Info& to_info,
16869             Boundary_Type type1, const T1& x1, const Info1& info1, int x1s,
16870             Boundary_Type type2, const T2& x2, const Info2& info2, int x2s) {
16871  if (x1s != 0) {
16872    if (x2s != 0) {
16873      return div_assign(to_type, to, to_info,
16874                        type1, x1, info1,
16875                        type2, x2, info2);
16876    }
16877    else {
16878      return set_boundary_infinity(to_type, to, to_info, true);
16879    }
16880  }
16881  else {
16882    bool should_shrink = info1.get_boundary_property(type1, OPEN)
16883      && !is_boundary_infinity_closed(type2, x2, info2);
16884    return set_zero(to_type, to, to_info, should_shrink);
16885  }
16886}
16887
16888template <typename To, typename To_Info, typename T, typename Info>
16889inline Result
16890umod_2exp_assign(Boundary_Type to_type, To& to, To_Info& to_info,
16891                 Boundary_Type type, const T& x, const Info& info,
16892                 unsigned int exp) {
16893  PPL_ASSERT(to_type == type);
16894  bool should_shrink;
16895  if (is_boundary_infinity(type, x, info)) {
16896    should_shrink = boundary_infinity_is_open(type, info);
16897    return set_boundary_infinity(to_type, to, to_info, should_shrink);
16898  }
16899  should_shrink = normal_is_open(type, x, info);
16900  bool check = (To_Info::check_inexact || (!should_shrink && To_Info::store_open));
16901  Result r = umod_2exp_assign_r(to, x, exp, round_dir_check(to_type, check));
16902  return adjust_boundary(to_type, to, to_info, should_shrink, r);
16903}
16904
16905template <typename To, typename To_Info, typename T, typename Info>
16906inline Result
16907smod_2exp_assign(Boundary_Type to_type, To& to, To_Info& to_info,
16908                 Boundary_Type type, const T& x, const Info& info,
16909                 unsigned int exp) {
16910  PPL_ASSERT(to_type == type);
16911  bool should_shrink;
16912  if (is_boundary_infinity(type, x, info)) {
16913    should_shrink = boundary_infinity_is_open(type, info);
16914    return set_boundary_infinity(to_type, to, to_info, should_shrink);
16915  }
16916  should_shrink = normal_is_open(type, x, info);
16917  bool check = (To_Info::check_inexact || (!should_shrink && To_Info::store_open));
16918  Result r = smod_2exp_assign_r(to, x, exp, round_dir_check(to_type, check));
16919  return adjust_boundary(to_type, to, to_info, should_shrink, r);
16920}
16921
16922} // namespace Boundary_NS
16923
16924} // namespace Parma_Polyhedra_Library
16925
16926/* Automatically generated from PPL source file ../src/Interval_Info_defs.hh line 28. */
16927#include <iostream>
16928
16929namespace Parma_Polyhedra_Library {
16930
16931namespace Interval_NS {
16932
16933struct Property {
16934  enum Type {
16935    CARDINALITY_0_,
16936    CARDINALITY_1_,
16937    CARDINALITY_IS_
16938  };
16939  typedef bool Value;
16940  static const Value default_value = true;
16941  static const Value unsupported_value = false;
16942  Property(Type t)
16943    : type(t) {
16944  }
16945  Type type;
16946};
16947
16948const Property CARDINALITY_0(Property::CARDINALITY_0_);
16949const Property CARDINALITY_1(Property::CARDINALITY_1_);
16950const Property CARDINALITY_IS(Property::CARDINALITY_IS_);
16951
16952template <typename T>
16953inline void
16954reset_bits(T& bits) {
16955  bits = 0;
16956}
16957
16958template <typename T>
16959inline void
16960reset_bit(T& bits, unsigned int bit) {
16961  bits &= ~(static_cast<T>(1) << bit);
16962}
16963
16964template <typename T>
16965inline void
16966set_bit(T& bits, unsigned int bit, bool value) {
16967  if (value) {
16968    bits |= static_cast<T>(1) << bit;
16969  }
16970  else {
16971    reset_bit(bits, bit);
16972  }
16973}
16974
16975template <typename T>
16976inline bool
16977get_bit(const T& bits, unsigned int bit) {
16978  return (bits & (static_cast<T>(1) << bit)) != 0;
16979}
16980
16981template <typename T>
16982inline void
16983set_bits(T& bits, unsigned int start, unsigned int len, T value) {
16984  bits &= ~(((static_cast<T>(1) << len) - 1) << start);
16985  bits |= value << start;
16986}
16987
16988template <typename T>
16989inline T
16990get_bits(T& bits, unsigned int start, unsigned int len) {
16991  return (bits >> start) & ((static_cast<T>(1) << len) - 1);
16992}
16993
16994} // namespace Interval_NS
16995
16996using namespace Interval_NS;
16997using namespace Boundary_NS;
16998
16999
17000template <typename Policy>
17001class Interval_Info_Null {
17002public:
17003  const_bool_nodef(may_be_empty, Policy::may_be_empty);
17004  const_bool_nodef(may_contain_infinity, Policy::may_contain_infinity);
17005  const_bool_nodef(check_inexact, Policy::check_inexact);
17006  const_bool_nodef(store_special, false);
17007  const_bool_nodef(store_open, false);
17008  const_bool_nodef(cache_empty, false);
17009  const_bool_nodef(cache_singleton, false);
17010  Interval_Info_Null() {
17011  }
17012  void clear() {
17013  }
17014  void clear_boundary_properties(Boundary_Type) {
17015  }
17016
17017  template <typename Property>
17018  void set_boundary_property(Boundary_Type, const Property&, typename Property::Value = Property::default_value) {
17019  }
17020  template <typename Property>
17021  typename Property::Value get_boundary_property(Boundary_Type, const Property&) const {
17022    return Property::unsupported_value;
17023  }
17024  template <typename Property>
17025  void set_interval_property(const Property&, typename Property::Value = Property::default_value) {
17026  }
17027  template <typename Property>
17028  typename Property::Value get_interval_property(const Property&) const {
17029    return Property::unsupported_value;
17030  }
17031
17032  //! Swaps \p *this with \p y.
17033  void m_swap(Interval_Info_Null& y);
17034
17035  void ascii_dump(std::ostream& s) const;
17036  bool ascii_load(std::istream& s);
17037};
17038
17039template <typename Policy>
17040class Interval_Info_Null_Open : public Interval_Info_Null<Policy> {
17041public:
17042  const_bool_nodef(store_open, true);
17043  Interval_Info_Null_Open(bool o)
17044    : open(o) {
17045  }
17046  bool get_boundary_property(Boundary_Type,
17047                             const Boundary_NS::Property& p) const {
17048    if (p.type == Boundary_NS::Property::OPEN_) {
17049      return open;
17050    }
17051    else {
17052      return Boundary_NS::Property::unsupported_value;
17053    }
17054  }
17055
17056  void ascii_dump(std::ostream& s) const;
17057  bool ascii_load(std::istream& s);
17058
17059private:
17060  bool open;
17061};
17062
17063
17064template <typename T, typename Policy>
17065class Interval_Info_Bitset {
17066public:
17067  const_bool_nodef(may_be_empty, Policy::may_be_empty);
17068  const_bool_nodef(may_contain_infinity, Policy::may_contain_infinity);
17069  const_bool_nodef(check_inexact, Policy::check_inexact);
17070  const_bool_nodef(store_special, Policy::store_special);
17071  const_bool_nodef(store_open, Policy::store_open);
17072  const_bool_nodef(cache_empty, Policy::cache_empty);
17073  const_bool_nodef(cache_singleton, Policy::cache_singleton);
17074  const_int_nodef(lower_special_bit, Policy::next_bit);
17075  const_int_nodef(lower_open_bit, lower_special_bit + (store_special ? 1 : 0));
17076  const_int_nodef(upper_special_bit, lower_open_bit + (store_open ? 1 : 0));
17077  const_int_nodef(upper_open_bit, upper_special_bit + (store_special ? 1 : 0));
17078  const_int_nodef(cardinality_is_bit, upper_open_bit + (store_open ? 1 : 0));
17079  const_int_nodef(cardinality_0_bit, cardinality_is_bit
17080                  + ((cache_empty || cache_singleton) ? 1 : 0));
17081  const_int_nodef(cardinality_1_bit, cardinality_0_bit + (cache_empty ? 1 : 0));
17082  const_int_nodef(next_bit, cardinality_1_bit + (cache_singleton ? 1 : 0));
17083
17084  Interval_Info_Bitset() {
17085    // FIXME: would we have speed benefits with uninitialized info?
17086    // (Dirty_Temp)
17087    clear();
17088  }
17089
17090  void clear() {
17091    reset_bits(bitset);
17092  }
17093  void clear_boundary_properties(Boundary_Type t) {
17094    set_boundary_property(t, SPECIAL, false);
17095    set_boundary_property(t, OPEN, false);
17096  }
17097  void set_boundary_property(Boundary_Type t,
17098                             const Boundary_NS::Property& p,
17099                             bool value = true) {
17100    switch (p.type) {
17101    case Boundary_NS::Property::SPECIAL_:
17102      if (store_special) {
17103        if (t == LOWER) {
17104          set_bit(bitset, lower_special_bit, value);
17105        }
17106        else {
17107          set_bit(bitset, upper_special_bit, value);
17108        }
17109      }
17110      break;
17111    case Boundary_NS::Property::OPEN_:
17112      if (store_open) {
17113        if (t == LOWER) {
17114          set_bit(bitset, lower_open_bit, value);
17115        }
17116        else {
17117          set_bit(bitset, upper_open_bit, value);
17118        }
17119      }
17120      break;
17121    default:
17122      break;
17123    }
17124  }
17125  bool get_boundary_property(Boundary_Type t, const Boundary_NS::Property& p) const {
17126    switch (p.type) {
17127    case Boundary_NS::Property::SPECIAL_:
17128      if (!store_special) {
17129        return false;
17130      }
17131      if (t == LOWER) {
17132        return get_bit(bitset, lower_special_bit);
17133      }
17134      else {
17135        return get_bit(bitset, upper_special_bit);
17136      }
17137    case Boundary_NS::Property::OPEN_:
17138      if (!store_open) {
17139        return false;
17140      }
17141      else if (t == LOWER) {
17142        return get_bit(bitset, lower_open_bit);
17143      }
17144      else {
17145        return get_bit(bitset, upper_open_bit);
17146      }
17147    default:
17148      return false;
17149    }
17150  }
17151  void set_interval_property(const Interval_NS::Property& p, bool value = true) {
17152    switch (p.type) {
17153    case Interval_NS::Property::CARDINALITY_0_:
17154      if (cache_empty) {
17155        set_bit(bitset, cardinality_0_bit, value);
17156      }
17157      break;
17158    case Interval_NS::Property::CARDINALITY_1_:
17159      if (cache_singleton) {
17160        set_bit(bitset, cardinality_1_bit, value);
17161      }
17162      break;
17163    case Interval_NS::Property::CARDINALITY_IS_:
17164      if (cache_empty || cache_singleton) {
17165        set_bit(bitset, cardinality_is_bit, value);
17166      }
17167      break;
17168    default:
17169      break;
17170    }
17171  }
17172  bool get_interval_property(Interval_NS::Property p) const {
17173    switch (p.type) {
17174    case Interval_NS::Property::CARDINALITY_0_:
17175      return cache_empty && get_bit(bitset, cardinality_0_bit);
17176    case Interval_NS::Property::CARDINALITY_1_:
17177      return cache_singleton && get_bit(bitset, cardinality_1_bit);
17178    case Interval_NS::Property::CARDINALITY_IS_:
17179      return (cache_empty || cache_singleton)
17180        && get_bit(bitset, cardinality_is_bit);
17181    default:
17182      return false;
17183    }
17184  }
17185
17186  //! Swaps \p *this with \p y.
17187  void m_swap(Interval_Info_Bitset& y);
17188
17189  void ascii_dump(std::ostream& s) const;
17190  bool ascii_load(std::istream& s);
17191
17192protected:
17193  T bitset;
17194};
17195
17196}
17197
17198/* Automatically generated from PPL source file ../src/Interval_Info_inlines.hh line 1. */
17199/* Interval_Info class implementation: inline functions.
17200*/
17201
17202
17203#include <iomanip>
17204
17205namespace Parma_Polyhedra_Library {
17206
17207template <typename Policy>
17208inline void
17209Interval_Info_Null<Policy>::m_swap(Interval_Info_Null<Policy>&) {
17210}
17211
17212template <typename Policy>
17213inline void
17214Interval_Info_Null<Policy>::ascii_dump(std::ostream&) const {
17215}
17216
17217template <typename Policy>
17218inline bool
17219Interval_Info_Null<Policy>::ascii_load(std::istream&) {
17220  return true;
17221}
17222
17223template <typename Policy>
17224inline void
17225Interval_Info_Null_Open<Policy>::ascii_dump(std::ostream& s) const {
17226  s << (open ? "open" : "closed");
17227}
17228
17229template <typename Policy>
17230inline bool
17231Interval_Info_Null_Open<Policy>::ascii_load(std::istream& s) {
17232  std::string str;
17233  if (!(s >> str)) {
17234    return false;
17235  }
17236  if (str == "open") {
17237    open = true;
17238    return true;
17239  }
17240  if (str == "closed") {
17241    open = false;
17242    return true;
17243  }
17244  return false;
17245}
17246
17247template <typename T, typename Policy>
17248inline void
17249Interval_Info_Bitset<T, Policy>::m_swap(Interval_Info_Bitset<T, Policy>& y) {
17250  using std::swap;
17251  swap(bitset, y.bitset);
17252}
17253
17254template <typename T, typename Policy>
17255inline void
17256Interval_Info_Bitset<T, Policy>::ascii_dump(std::ostream& s) const {
17257  const std::ios::fmtflags old_flags = s.setf(std::ios::hex,
17258                                              std::ios::basefield);
17259  s << bitset;
17260  s.flags(old_flags);
17261}
17262
17263template <typename T, typename Policy>
17264inline bool
17265Interval_Info_Bitset<T, Policy>::ascii_load(std::istream& s) {
17266  const std::ios::fmtflags old_flags = s.setf(std::ios::hex,
17267                                              std::ios::basefield);
17268  s >> bitset;
17269  s.flags(old_flags);
17270  return !s.fail();
17271}
17272
17273#ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
17274/*! \relates Interval_Info_Null */
17275#endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
17276template <typename Policy>
17277inline void
17278swap(Interval_Info_Null<Policy>& x, Interval_Info_Null<Policy>& y) {
17279  x.m_swap(y);
17280}
17281
17282#ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
17283/*! \relates Interval_Info_Bitset */
17284#endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
17285template <typename T, typename Policy>
17286inline void
17287swap(Interval_Info_Bitset<T, Policy>& x, Interval_Info_Bitset<T, Policy>& y) {
17288  x.m_swap(y);
17289}
17290
17291} // namespace Parma_Polyhedra_Library
17292
17293/* Automatically generated from PPL source file ../src/Interval_Info_defs.hh line 300. */
17294
17295/* Automatically generated from PPL source file ../src/Interval_defs.hh line 33. */
17296#include <iosfwd>
17297
17298namespace Parma_Polyhedra_Library {
17299
17300enum Ternary { T_YES, T_NO, T_MAYBE };
17301
17302inline I_Result
17303combine(Result l, Result u) {
17304  const unsigned res
17305    = static_cast<unsigned>(l) | (static_cast<unsigned>(u) << 6);
17306  return static_cast<I_Result>(res);
17307}
17308
17309struct Interval_Base {
17310};
17311
17312using namespace Boundary_NS;
17313using namespace Interval_NS;
17314
17315template <typename T, typename Enable = void>
17316struct Is_Singleton : public Is_Native_Or_Checked<T> {};
17317
17318template <typename T>
17319struct Is_Interval : public Is_Same_Or_Derived<Interval_Base, T> {};
17320
17321//! A generic, not necessarily closed, possibly restricted interval.
17322/*! \ingroup PPL_CXX_interface
17323  The class template type parameter \p Boundary represents the type
17324  of the interval boundaries, and can be chosen, among other possibilities,
17325  within one of the following number families:
17326
17327  - a bounded precision native integer type (that is,
17328    from <CODE>signed char</CODE> to <CODE>long long</CODE>
17329    and from <CODE>int8_t</CODE> to <CODE>int64_t</CODE>);
17330  - a bounded precision floating point type (<CODE>float</CODE>,
17331    <CODE>double</CODE> or <CODE>long double</CODE>);
17332  - an unbounded integer or rational type, as provided by the C++ interface
17333    of GMP (<CODE>mpz_class</CODE> or <CODE>mpq_class</CODE>).
17334
17335  The class template type parameter \p Info allows to control a number
17336  of features of the class, among which:
17337
17338  - the ability to support open as well as closed boundaries;
17339  - the ability to represent empty intervals in addition to nonempty ones;
17340  - the ability to represent intervals of extended number families
17341    that contain positive and negative infinities;
17342*/
17343template <typename Boundary, typename Info>
17344class Interval : public Interval_Base, private Info {
17345private:
17346  PPL_COMPILE_TIME_CHECK(!Info::store_special
17347                         || !std::numeric_limits<Boundary>::has_infinity,
17348                         "store_special is meaningless"
17349                         " when boundary type may contains infinity");
17350  Info& w_info() const {
17351    return const_cast<Interval&>(*this);
17352  }
17353
17354public:
17355  typedef Boundary boundary_type;
17356  typedef Info info_type;
17357
17358  typedef Interval_NS::Property Property;
17359
17360  template <typename T>
17361  typename Enable_If<Is_Singleton<T>::value || Is_Interval<T>::value, Interval&>::type
17362  operator=(const T& x) {
17363    assign(x);
17364    return *this;
17365  }
17366
17367  template <typename T>
17368  typename Enable_If<Is_Singleton<T>::value || Is_Interval<T>::value, Interval&>::type
17369  operator+=(const T& x) {
17370    add_assign(*this, x);
17371    return *this;
17372  }
17373  template <typename T>
17374  typename Enable_If<Is_Singleton<T>::value || Is_Interval<T>::value, Interval&>::type
17375  operator-=(const T& x) {
17376    sub_assign(*this, x);
17377    return *this;
17378  }
17379  template <typename T>
17380  typename Enable_If<Is_Singleton<T>::value || Is_Interval<T>::value, Interval&>::type
17381  operator*=(const T& x) {
17382    mul_assign(*this, x);
17383    return *this;
17384  }
17385  template <typename T>
17386  typename Enable_If<Is_Singleton<T>::value || Is_Interval<T>::value, Interval&>::type
17387  operator/=(const T& x) {
17388    div_assign(*this, x);
17389    return *this;
17390  }
17391
17392  //! Swaps \p *this with \p y.
17393  void m_swap(Interval& y);
17394
17395  Info& info() {
17396    return *this;
17397  }
17398
17399  const Info& info() const {
17400    return *this;
17401  }
17402
17403  Boundary& lower() {
17404    return lower_;
17405  }
17406
17407  const Boundary& lower() const {
17408    return lower_;
17409  }
17410
17411  Boundary& upper() {
17412    return upper_;
17413  }
17414
17415  const Boundary& upper() const {
17416    return upper_;
17417  }
17418
17419  I_Constraint<boundary_type> lower_constraint() const {
17420    PPL_ASSERT(!is_empty());
17421    if (info().get_boundary_property(LOWER, SPECIAL)) {
17422      return I_Constraint<boundary_type>();
17423    }
17424    return i_constraint(lower_is_open() ? GREATER_THAN : GREATER_OR_EQUAL,
17425                        lower(), true);
17426  }
17427  I_Constraint<boundary_type> upper_constraint() const {
17428    PPL_ASSERT(!is_empty());
17429    if (info().get_boundary_property(UPPER, SPECIAL)) {
17430      return I_Constraint<boundary_type>();
17431    }
17432    return i_constraint(upper_is_open() ? LESS_THAN : LESS_OR_EQUAL,
17433                        upper(), true);
17434  }
17435
17436  bool is_empty() const {
17437    return lt(UPPER, upper(), info(), LOWER, lower(), info());
17438  }
17439
17440  bool check_empty(I_Result r) const {
17441    return (r & I_ANY) == I_EMPTY
17442      || ((r & I_ANY) != I_NOT_EMPTY && is_empty());
17443  }
17444
17445  bool is_singleton() const {
17446    return eq(LOWER, lower(), info(), UPPER, upper(), info());
17447  }
17448
17449  bool lower_is_open() const {
17450    PPL_ASSERT(OK());
17451    return is_open(LOWER, lower(), info());
17452  }
17453
17454  bool upper_is_open() const {
17455    PPL_ASSERT(OK());
17456    return is_open(UPPER, upper(), info());
17457  }
17458
17459  bool lower_is_boundary_infinity() const {
17460    PPL_ASSERT(OK());
17461    return Boundary_NS::is_boundary_infinity(LOWER, lower(), info());
17462  }
17463
17464  bool upper_is_boundary_infinity() const {
17465    PPL_ASSERT(OK());
17466    return Boundary_NS::is_boundary_infinity(UPPER, upper(), info());
17467  }
17468
17469  bool lower_is_domain_inf() const {
17470    PPL_ASSERT(OK());
17471    return Boundary_NS::is_domain_inf(LOWER, lower(), info());
17472  }
17473
17474  bool upper_is_domain_sup() const {
17475    PPL_ASSERT(OK());
17476    return Boundary_NS::is_domain_sup(UPPER, upper(), info());
17477  }
17478
17479  bool is_bounded() const {
17480    PPL_ASSERT(OK());
17481    return !lower_is_boundary_infinity() && !upper_is_boundary_infinity();
17482  }
17483
17484  bool is_universe() const {
17485    PPL_ASSERT(OK());
17486    return lower_is_domain_inf() && upper_is_domain_sup();
17487  }
17488
17489  I_Result lower_extend() {
17490    info().clear_boundary_properties(LOWER);
17491    set_unbounded(LOWER, lower(), info());
17492    return I_ANY;
17493  }
17494
17495  template <typename C>
17496  typename Enable_If<Is_Same_Or_Derived<I_Constraint_Base, C>::value, I_Result>::type
17497  lower_extend(const C& c);
17498
17499  I_Result upper_extend() {
17500    info().clear_boundary_properties(UPPER);
17501    set_unbounded(UPPER, upper(), info());
17502    return I_ANY;
17503  }
17504
17505  template <typename C>
17506  typename Enable_If<Is_Same_Or_Derived<I_Constraint_Base, C>::value, I_Result>::type
17507  upper_extend(const C& c);
17508
17509  I_Result build() {
17510    return assign(UNIVERSE);
17511  }
17512
17513  template <typename C>
17514  typename Enable_If<Is_Same_Or_Derived<I_Constraint_Base, C>::value, I_Result>::type
17515  build(const C& c) {
17516    Relation_Symbol rs;
17517    switch (c.rel()) {
17518    case V_LGE:
17519    case V_GT_MINUS_INFINITY:
17520    case V_LT_PLUS_INFINITY:
17521      return assign(UNIVERSE);
17522    default:
17523      return assign(EMPTY);
17524    case V_LT:
17525    case V_LE:
17526    case V_GT:
17527    case V_GE:
17528    case V_EQ:
17529    case V_NE:
17530      assign(UNIVERSE);
17531      rs = static_cast<Relation_Symbol>(c.rel());
17532      return refine_existential(rs, c.value());
17533    }
17534  }
17535
17536  template <typename C1, typename C2>
17537  typename Enable_If<Is_Same_Or_Derived<I_Constraint_Base, C1>::value
17538                     &&
17539                     Is_Same_Or_Derived<I_Constraint_Base, C2>::value,
17540                     I_Result>::type
17541  build(const C1& c1, const C2& c2) {
17542    switch (c1.rel()) {
17543    case V_LGE:
17544      return build(c2);
17545    case V_NAN:
17546      return assign(EMPTY);
17547    default:
17548      break;
17549    }
17550    switch (c2.rel()) {
17551    case V_LGE:
17552      return build(c1);
17553    case V_NAN:
17554      return assign(EMPTY);
17555    default:
17556      break;
17557    }
17558    build(c1);
17559    const I_Result r = add_constraint(c2);
17560    return r - (I_CHANGED | I_UNCHANGED);
17561  }
17562
17563  template <typename C>
17564  typename Enable_If<Is_Same_Or_Derived<I_Constraint_Base, C>::value, I_Result>::type
17565  add_constraint(const C& c) {
17566    Interval x;
17567    x.build(c);
17568    return intersect_assign(x);
17569  }
17570
17571  I_Result assign(Degenerate_Element e) {
17572    I_Result r;
17573    info().clear();
17574    switch (e) {
17575    case EMPTY:
17576      lower_ = 1;
17577      upper_ = 0;
17578      r = I_EMPTY | I_EXACT;
17579      break;
17580    case UNIVERSE:
17581      set_unbounded(LOWER, lower(), info());
17582      set_unbounded(UPPER, upper(), info());
17583      r = I_UNIVERSE | I_EXACT;
17584      break;
17585    default:
17586      PPL_UNREACHABLE;
17587      r = I_EMPTY;
17588      break;
17589    }
17590    PPL_ASSERT(OK());
17591    return r;
17592  }
17593
17594  template <typename From>
17595  typename Enable_If<Is_Special<From>::value, I_Result>::type
17596  assign(const From&) {
17597    info().clear();
17598    Result rl;
17599    Result ru;
17600    switch (From::vclass) {
17601    case VC_MINUS_INFINITY:
17602      rl = Boundary_NS::set_minus_infinity(LOWER, lower(), info());
17603      ru = Boundary_NS::set_minus_infinity(UPPER, upper(), info());
17604      break;
17605    case VC_PLUS_INFINITY:
17606      rl = Boundary_NS::set_plus_infinity(LOWER, lower(), info());
17607      ru = Boundary_NS::set_plus_infinity(UPPER, upper(), info());
17608      break;
17609    default:
17610      PPL_UNREACHABLE;
17611      rl = V_NAN;
17612      ru = V_NAN;
17613      break;
17614    }
17615    PPL_ASSERT(OK());
17616    return combine(rl, ru);
17617  }
17618
17619  I_Result set_infinities() {
17620    info().clear();
17621    Result rl = Boundary_NS::set_minus_infinity(LOWER, lower(), info());
17622    Result ru = Boundary_NS::set_plus_infinity(UPPER, upper(), info());
17623    PPL_ASSERT(OK());
17624    return combine(rl, ru);
17625  }
17626
17627  static bool is_always_topologically_closed() {
17628    return !Info::store_open;
17629  }
17630
17631  bool is_topologically_closed() const {
17632    PPL_ASSERT(OK());
17633    return is_always_topologically_closed()
17634      || is_empty()
17635      || ((lower_is_boundary_infinity() || !lower_is_open())
17636          && (upper_is_boundary_infinity() || !upper_is_open()));
17637  }
17638
17639  //! Assigns to \p *this its topological closure.
17640  void topological_closure_assign() {
17641    if (!Info::store_open || is_empty()) {
17642      return;
17643    }
17644    if (lower_is_open() && !lower_is_boundary_infinity()) {
17645      info().set_boundary_property(LOWER, OPEN, false);
17646    }
17647    if (upper_is_open() && !upper_is_boundary_infinity()) {
17648      info().set_boundary_property(UPPER, OPEN, false);
17649    }
17650  }
17651
17652  void remove_inf() {
17653    PPL_ASSERT(!is_empty());
17654    if (!Info::store_open) {
17655      return;
17656    }
17657    info().set_boundary_property(LOWER, OPEN, true);
17658  }
17659
17660  void remove_sup() {
17661    PPL_ASSERT(!is_empty());
17662    if (!Info::store_open) {
17663      return;
17664    }
17665    info().set_boundary_property(UPPER, OPEN, true);
17666  }
17667
17668  int infinity_sign() const {
17669    PPL_ASSERT(OK());
17670    if (is_reverse_infinity(LOWER, lower(), info())) {
17671      return 1;
17672    }
17673    else if (is_reverse_infinity(UPPER, upper(), info())) {
17674      return -1;
17675    }
17676    else {
17677      return 0;
17678    }
17679  }
17680
17681  bool contains_integer_point() const {
17682    PPL_ASSERT(OK());
17683    if (is_empty()) {
17684      return false;
17685    }
17686    if (!is_bounded()) {
17687      return true;
17688    }
17689    Boundary l;
17690    if (lower_is_open()) {
17691      add_assign_r(l, lower(), Boundary(1), ROUND_DOWN);
17692      floor_assign_r(l, l, ROUND_DOWN);
17693    }
17694    else {
17695      ceil_assign_r(l, lower(), ROUND_DOWN);
17696    }
17697    Boundary u;
17698    if (upper_is_open()) {
17699      sub_assign_r(u, upper(), Boundary(1), ROUND_UP);
17700      ceil_assign_r(u, u, ROUND_UP);
17701    }
17702    else {
17703      floor_assign_r(u, upper(), ROUND_UP);
17704    }
17705    return u >= l;
17706  }
17707
17708  void drop_some_non_integer_points() {
17709    if (is_empty()) {
17710      return;
17711    }
17712    if (lower_is_open() && !lower_is_boundary_infinity()) {
17713      add_assign_r(lower(), lower(), Boundary(1), ROUND_DOWN);
17714      floor_assign_r(lower(), lower(), ROUND_DOWN);
17715      info().set_boundary_property(LOWER, OPEN, false);
17716    }
17717    else {
17718      ceil_assign_r(lower(), lower(), ROUND_DOWN);
17719    }
17720    if (upper_is_open() && !upper_is_boundary_infinity()) {
17721      sub_assign_r(upper(), upper(), Boundary(1), ROUND_UP);
17722      ceil_assign_r(upper(), upper(), ROUND_UP);
17723      info().set_boundary_property(UPPER, OPEN, false);
17724    }
17725    else {
17726      floor_assign_r(upper(), upper(), ROUND_UP);
17727    }
17728  }
17729
17730  template <typename From>
17731  typename Enable_If<Is_Singleton<From>::value || Is_Interval<From>::value, I_Result>::type
17732  wrap_assign(Bounded_Integer_Type_Width w,
17733              Bounded_Integer_Type_Representation r,
17734              const From& refinement) {
17735    if (is_empty()) {
17736      return I_EMPTY;
17737    }
17738    if (lower_is_boundary_infinity() || upper_is_boundary_infinity()) {
17739      return assign(refinement);
17740    }
17741    PPL_DIRTY_TEMP(Boundary, u);
17742    Result result = sub_2exp_assign_r(u, upper(), w, ROUND_UP);
17743    if (result_overflow(result) == 0 && u > lower()) {
17744      return assign(refinement);
17745    }
17746    info().clear();
17747    switch (r) {
17748    case UNSIGNED:
17749      umod_2exp_assign(LOWER, lower(), info(),
17750                       LOWER, lower(), info(), w);
17751      umod_2exp_assign(UPPER, upper(), info(),
17752                       UPPER, upper(), info(), w);
17753      break;
17754    case SIGNED_2_COMPLEMENT:
17755      smod_2exp_assign(LOWER, lower(), info(),
17756                       LOWER, lower(), info(), w);
17757      smod_2exp_assign(UPPER, upper(), info(),
17758                       UPPER, upper(), info(), w);
17759      break;
17760    default:
17761      PPL_UNREACHABLE;
17762      break;
17763    }
17764    if (le(LOWER, lower(), info(), UPPER, upper(), info())) {
17765      return intersect_assign(refinement);
17766    }
17767    PPL_DIRTY_TEMP(Interval, tmp);
17768    tmp.info().clear();
17769    Boundary_NS::assign(LOWER, tmp.lower(), tmp.info(),
17770                        LOWER, lower(), info());
17771    set_unbounded(UPPER, tmp.upper(), tmp.info());
17772    tmp.intersect_assign(refinement);
17773    lower_extend();
17774    intersect_assign(refinement);
17775    return join_assign(tmp);
17776  }
17777
17778  //! Returns the total size in bytes of the memory occupied by \p *this.
17779  memory_size_type total_memory_in_bytes() const;
17780
17781  //! Returns the size in bytes of the memory managed by \p *this.
17782  memory_size_type external_memory_in_bytes() const;
17783
17784  void ascii_dump(std::ostream& s) const;
17785  bool ascii_load(std::istream& s);
17786
17787  bool OK() const {
17788    if (!Info::may_be_empty && is_empty()) {
17789#ifndef NDEBUG
17790      std::cerr << "The interval is unexpectedly empty.\n";
17791#endif
17792      return false;
17793    }
17794
17795    if (is_open(LOWER, lower(), info())) {
17796      if (is_plus_infinity(LOWER, lower(), info())) {
17797#ifndef NDEBUG
17798        std::cerr << "The lower boundary is +inf open.\n";
17799#endif
17800      }
17801    }
17802    else if (!Info::may_contain_infinity
17803             && (is_minus_infinity(LOWER, lower(), info())
17804                 || is_plus_infinity(LOWER, lower(), info()))) {
17805#ifndef NDEBUG
17806      std::cerr << "The lower boundary is unexpectedly infinity.\n";
17807#endif
17808      return false;
17809    }
17810    if (!info().get_boundary_property(LOWER, SPECIAL)) {
17811      if (is_not_a_number(lower())) {
17812#ifndef NDEBUG
17813        std::cerr << "The lower boundary is not a number.\n";
17814#endif
17815        return false;
17816      }
17817    }
17818
17819    if (is_open(UPPER, upper(), info())) {
17820      if (is_minus_infinity(UPPER, upper(), info())) {
17821#ifndef NDEBUG
17822        std::cerr << "The upper boundary is -inf open.\n";
17823#endif
17824      }
17825    }
17826    else if (!Info::may_contain_infinity
17827             && (is_minus_infinity(UPPER, upper(), info())
17828                 || is_plus_infinity(UPPER, upper(), info()))) {
17829#ifndef NDEBUG
17830      std::cerr << "The upper boundary is unexpectedly infinity."
17831                << std::endl;
17832#endif
17833      return false;
17834    }
17835    if (!info().get_boundary_property(UPPER, SPECIAL)) {
17836      if (is_not_a_number(upper())) {
17837#ifndef NDEBUG
17838        std::cerr << "The upper boundary is not a number.\n";
17839#endif
17840        return false;
17841      }
17842    }
17843
17844    // Everything OK.
17845    return true;
17846  }
17847
17848  Interval() {
17849  }
17850
17851  template <typename T>
17852  explicit Interval(const T& x) {
17853    assign(x);
17854  }
17855
17856  /*! \brief
17857    Builds the smallest interval containing the number whose textual
17858    representation is contained in \p s.
17859  */
17860  explicit Interval(const char* s);
17861
17862  template <typename T>
17863  typename Enable_If<Is_Singleton<T>::value
17864                     || Is_Interval<T>::value, bool>::type
17865  contains(const T& y) const;
17866
17867  template <typename T>
17868  typename Enable_If<Is_Singleton<T>::value
17869                     || Is_Interval<T>::value, bool>::type
17870  strictly_contains(const T& y) const;
17871
17872  template <typename T>
17873  typename Enable_If<Is_Singleton<T>::value
17874                     || Is_Interval<T>::value, bool>::type
17875  is_disjoint_from(const T& y) const;
17876
17877
17878  template <typename From>
17879  typename Enable_If<Is_Singleton<From>::value
17880                     || Is_Interval<From>::value, I_Result>::type
17881  assign(const From& x);
17882
17883  template <typename Type>
17884  typename Enable_If<Is_Singleton<Type>::value
17885                     || Is_Interval<Type>::value, bool>::type
17886  can_be_exactly_joined_to(const Type& x) const;
17887
17888  template <typename From>
17889  typename Enable_If<Is_Singleton<From>::value
17890                     || Is_Interval<From>::value, I_Result>::type
17891  join_assign(const From& x);
17892
17893  template <typename From1, typename From2>
17894  typename Enable_If<((Is_Singleton<From1>::value
17895                       || Is_Interval<From1>::value)
17896                      && (Is_Singleton<From2>::value
17897                          || Is_Interval<From2>::value)), I_Result>::type
17898  join_assign(const From1& x, const From2& y);
17899
17900  template <typename From>
17901  typename Enable_If<Is_Singleton<From>::value
17902                     || Is_Interval<From>::value, I_Result>::type
17903  intersect_assign(const From& x);
17904
17905  template <typename From1, typename From2>
17906  typename Enable_If<((Is_Singleton<From1>::value
17907                       || Is_Interval<From1>::value)
17908                      && (Is_Singleton<From2>::value
17909                          || Is_Interval<From2>::value)), I_Result>::type
17910  intersect_assign(const From1& x, const From2& y);
17911
17912  /*! \brief
17913    Assigns to \p *this the smallest interval containing the set-theoretic
17914    difference of \p *this and \p x.
17915  */
17916  template <typename From>
17917  typename Enable_If<Is_Singleton<From>::value
17918                     || Is_Interval<From>::value, I_Result>::type
17919  difference_assign(const From& x);
17920
17921  /*! \brief
17922    Assigns to \p *this the smallest interval containing the set-theoretic
17923    difference of \p x and \p y.
17924  */
17925  template <typename From1, typename From2>
17926  typename Enable_If<((Is_Singleton<From1>::value
17927                       || Is_Interval<From1>::value)
17928                      && (Is_Singleton<From2>::value
17929                          || Is_Interval<From2>::value)), I_Result>::type
17930  difference_assign(const From1& x, const From2& y);
17931
17932  /*! \brief
17933    Assigns to \p *this the largest interval contained in the set-theoretic
17934    difference of \p *this and \p x.
17935  */
17936  template <typename From>
17937  typename Enable_If<Is_Singleton<From>::value
17938                     || Is_Interval<From>::value, I_Result>::type
17939  lower_approximation_difference_assign(const From& x);
17940
17941  /*! \brief
17942    Assigns to \p *this a \ref Meet_Preserving_Simplification
17943    "meet-preserving simplification" of \p *this with respect to \p y.
17944
17945    \return
17946    \c false if and only if the meet of \p *this and \p y is empty.
17947  */
17948  template <typename From>
17949  typename Enable_If<Is_Interval<From>::value, bool>::type
17950  simplify_using_context_assign(const From& y);
17951
17952  /*! \brief
17953    Assigns to \p *this an interval having empty intersection with \p y.
17954    The assigned interval should be as large as possible.
17955  */
17956  template <typename From>
17957  typename Enable_If<Is_Interval<From>::value, void>::type
17958  empty_intersection_assign(const From& y);
17959
17960  /*! \brief
17961    Refines \p to according to the existential relation \p rel with \p x.
17962
17963    The \p to interval is restricted to become, upon successful exit,
17964    the smallest interval of its type that contains the set
17965    \f[
17966      \{\,
17967        a \in \mathtt{to}
17968      \mid
17969        \exists b \in \mathtt{x} \st a \mathrel{\mathtt{rel}} b
17970      \,\}.
17971    \f]
17972    \return
17973    ???
17974  */
17975  template <typename From>
17976  typename Enable_If<Is_Singleton<From>::value
17977                     || Is_Interval<From>::value, I_Result>::type
17978  refine_existential(Relation_Symbol rel, const From& x);
17979
17980  /*! \brief
17981    Refines \p to so that it satisfies the universal relation \p rel with \p x.
17982
17983    The \p to interval is restricted to become, upon successful exit,
17984    the smallest interval of its type that contains the set
17985    \f[
17986      \{\,
17987        a \in \mathtt{to}
17988      \mid
17989        \forall b \in \mathtt{x} \itc a \mathrel{\mathtt{rel}} b
17990      \,\}.
17991    \f]
17992    \return
17993    ???
17994  */
17995  template <typename From>
17996  typename Enable_If<Is_Singleton<From>::value
17997                     || Is_Interval<From>::value, I_Result>::type
17998  refine_universal(Relation_Symbol rel, const From& x);
17999
18000  template <typename From>
18001  typename Enable_If<Is_Singleton<From>::value
18002                     || Is_Interval<From>::value, I_Result>::type
18003  neg_assign(const From& x);
18004
18005  template <typename From1, typename From2>
18006  typename Enable_If<((Is_Singleton<From1>::value || Is_Interval<From1>::value)
18007                      && (Is_Singleton<From2>::value || Is_Interval<From2>::value)), I_Result>::type
18008  add_assign(const From1& x, const From2& y);
18009
18010  template <typename From1, typename From2>
18011  typename Enable_If<((Is_Singleton<From1>::value || Is_Interval<From1>::value)
18012                      && (Is_Singleton<From2>::value || Is_Interval<From2>::value)), I_Result>::type
18013  sub_assign(const From1& x, const From2& y);
18014
18015  template <typename From1, typename From2>
18016  typename Enable_If<((Is_Singleton<From1>::value || Is_Interval<From1>::value)
18017                      && (Is_Singleton<From2>::value || Is_Interval<From2>::value)), I_Result>::type
18018  mul_assign(const From1& x, const From2& y);
18019
18020  template <typename From1, typename From2>
18021  typename Enable_If<((Is_Singleton<From1>::value || Is_Interval<From1>::value)
18022                      && (Is_Singleton<From2>::value || Is_Interval<From2>::value)), I_Result>::type
18023  div_assign(const From1& x, const From2& y);
18024
18025  template <typename From, typename Iterator>
18026  typename Enable_If<Is_Interval<From>::value, void>::type
18027  CC76_widening_assign(const From& y, Iterator first, Iterator last);
18028
18029private:
18030  Boundary lower_;
18031  Boundary upper_;
18032};
18033
18034//! Swaps \p x with \p y.
18035/*! \relates Interval */
18036template <typename Boundary, typename Info>
18037void swap(Interval<Boundary, Info>& x, Interval<Boundary, Info>& y);
18038
18039} // namespace Parma_Polyhedra_Library
18040
18041/* Automatically generated from PPL source file ../src/Interval_inlines.hh line 1. */
18042/* Inline functions for the Interval class and its constituents.
18043*/
18044
18045
18046namespace Parma_Polyhedra_Library {
18047
18048template <typename Boundary, typename Info>
18049inline memory_size_type
18050Interval<Boundary, Info>::external_memory_in_bytes() const {
18051  return Parma_Polyhedra_Library::external_memory_in_bytes(lower())
18052    + Parma_Polyhedra_Library::external_memory_in_bytes(upper());
18053}
18054
18055template <typename Boundary, typename Info>
18056inline memory_size_type
18057Interval<Boundary, Info>::total_memory_in_bytes() const {
18058  return sizeof(*this) + external_memory_in_bytes();
18059}
18060
18061template <typename Boundary, typename Info>
18062inline void
18063Interval<Boundary, Info>::m_swap(Interval<Boundary, Info>& y) {
18064  using std::swap;
18065  swap(lower(), y.lower());
18066  swap(upper(), y.upper());
18067  swap(info(), y.info());
18068}
18069
18070template <typename Boundary, typename Info>
18071inline bool
18072f_is_empty(const Interval<Boundary, Info>& x) {
18073  return x.is_empty();
18074}
18075template <typename Boundary, typename Info>
18076inline bool
18077f_is_singleton(const Interval<Boundary, Info>& x) {
18078  return x.is_singleton();
18079}
18080template <typename Boundary, typename Info>
18081inline int
18082infinity_sign(const Interval<Boundary, Info>& x) {
18083  return x.infinity_sign();
18084}
18085
18086namespace Interval_NS {
18087
18088template <typename Boundary, typename Info>
18089inline const Boundary&
18090f_lower(const Interval<Boundary, Info>& x) {
18091  return x.lower();
18092}
18093template <typename Boundary, typename Info>
18094inline const Boundary&
18095f_upper(const Interval<Boundary, Info>& x) {
18096  return x.upper();
18097}
18098template <typename Boundary, typename Info>
18099inline const Info&
18100f_info(const Interval<Boundary, Info>& x) {
18101  return x.info();
18102}
18103
18104struct Scalar_As_Interval_Policy {
18105  const_bool_nodef(may_be_empty, true);
18106  const_bool_nodef(may_contain_infinity, true);
18107  const_bool_nodef(check_inexact, false);
18108};
18109
18110typedef Interval_Info_Null<Scalar_As_Interval_Policy>
18111Scalar_As_Interval_Info;
18112
18113const Scalar_As_Interval_Info SCALAR_INFO;
18114
18115typedef Interval_Info_Null_Open<Scalar_As_Interval_Policy>
18116Scalar_As_Interval_Info_Open;
18117
18118template <typename T>
18119inline typename Enable_If<Is_Singleton<T>::value, const T&>::type
18120f_lower(const T& x) {
18121  return x;
18122}
18123template <typename T>
18124inline typename Enable_If<Is_Singleton<T>::value, const T&>::type
18125f_upper(const T& x) {
18126  return x;
18127}
18128template <typename T>
18129inline typename Enable_If<Is_Singleton<T>::value,
18130                          const Scalar_As_Interval_Info&>::type
18131f_info(const T&) {
18132  return SCALAR_INFO;
18133}
18134template <typename T>
18135inline typename Enable_If<Is_Singleton<T>::value,
18136                          Scalar_As_Interval_Info_Open>::type
18137f_info(const T&, bool open) {
18138  return Scalar_As_Interval_Info_Open(open);
18139}
18140
18141template <typename T>
18142inline typename Enable_If<Is_Singleton<T>::value, bool>::type
18143f_is_empty(const T& x) {
18144  return is_not_a_number(x);
18145}
18146
18147template <typename T>
18148inline typename Enable_If<Is_Singleton<T>::value, bool>::type
18149f_is_singleton(const T& x) {
18150  return !f_is_empty(x);
18151}
18152
18153} // namespace Interval_NS
18154
18155template <typename T>
18156inline typename Enable_If<Is_Singleton<T>::value
18157                          || Is_Interval<T>::value, bool>::type
18158is_singleton_integer(const T& x) {
18159  return is_singleton(x) && is_integer(f_lower(x));
18160}
18161
18162template <typename T>
18163inline typename Enable_If<Is_Singleton<T>::value
18164                          || Is_Interval<T>::value, bool>::type
18165check_empty_arg(const T& x) {
18166  if (f_info(x).may_be_empty) {
18167    return f_is_empty(x);
18168  }
18169  else {
18170    PPL_ASSERT(!f_is_empty(x));
18171    return false;
18172  }
18173}
18174
18175template <typename T1, typename T2>
18176inline typename Enable_If<((Is_Singleton<T1>::value
18177                            || Is_Interval<T1>::value)
18178                           && (Is_Singleton<T2>::value
18179                               || Is_Interval<T2>::value)
18180                           && (Is_Interval<T1>::value
18181                               || Is_Interval<T2>::value)),
18182                          bool>::type
18183operator==(const T1& x, const T2& y) {
18184  PPL_ASSERT(f_OK(x));
18185  PPL_ASSERT(f_OK(y));
18186  if (check_empty_arg(x)) {
18187    return check_empty_arg(y);
18188  }
18189  else if (check_empty_arg(y)) {
18190    return false;
18191  }
18192  return eq(LOWER, f_lower(x), f_info(x), LOWER, f_lower(y), f_info(y))
18193    && eq(UPPER, f_upper(x), f_info(x), UPPER, f_upper(y), f_info(y));
18194}
18195
18196template <typename T1, typename T2>
18197inline typename Enable_If<((Is_Singleton<T1>::value
18198                            || Is_Interval<T1>::value)
18199                           && (Is_Singleton<T2>::value
18200                               || Is_Interval<T2>::value)
18201                           && (Is_Interval<T1>::value
18202                               || Is_Interval<T2>::value)),
18203                          bool>::type
18204operator!=(const T1& x, const T2& y) {
18205  return !(x == y);
18206}
18207
18208template <typename Boundary, typename Info>
18209template <typename T>
18210inline typename Enable_If<Is_Singleton<T>::value
18211                          || Is_Interval<T>::value, bool>::type
18212Interval<Boundary, Info>::contains(const T& y) const {
18213  PPL_ASSERT(OK());
18214  PPL_ASSERT(f_OK(y));
18215  if (check_empty_arg(y)) {
18216    return true;
18217  }
18218  if (check_empty_arg(*this)) {
18219    return false;
18220  }
18221  return le(LOWER, lower(), info(), LOWER, f_lower(y), f_info(y))
18222    && ge(UPPER, upper(), info(), UPPER, f_upper(y), f_info(y));
18223}
18224
18225template <typename Boundary, typename Info>
18226template <typename T>
18227inline typename Enable_If<Is_Singleton<T>::value
18228                          || Is_Interval<T>::value, bool>::type
18229Interval<Boundary, Info>::strictly_contains(const T& y) const {
18230  PPL_ASSERT(OK());
18231  PPL_ASSERT(f_OK(y));
18232  if (check_empty_arg(y)) {
18233    return !check_empty_arg(*this);
18234  }
18235  if (check_empty_arg(*this)) {
18236    return false;
18237  }
18238  return (lt(LOWER, lower(), info(), LOWER, f_lower(y), f_info(y))
18239          && ge(UPPER, upper(), info(), UPPER, f_upper(y), f_info(y)))
18240    || (le(LOWER, lower(), info(), LOWER, f_lower(y), f_info(y))
18241        && gt(UPPER, upper(), info(), UPPER, f_upper(y), f_info(y)));
18242}
18243
18244template <typename Boundary, typename Info>
18245template <typename T>
18246inline typename Enable_If<Is_Singleton<T>::value
18247                          || Is_Interval<T>::value, bool>::type
18248Interval<Boundary, Info>::is_disjoint_from(const T& y) const {
18249  PPL_ASSERT(OK());
18250  PPL_ASSERT(f_OK(y));
18251  if (check_empty_arg(*this) || check_empty_arg(y)) {
18252    return true;
18253  }
18254  return gt(LOWER, lower(), info(), UPPER, f_upper(y), f_info(y))
18255    || lt(UPPER, upper(), info(), LOWER, f_lower(y), f_info(y));
18256}
18257
18258template <typename To_Boundary, typename To_Info>
18259template <typename From>
18260inline typename Enable_If<Is_Singleton<From>::value
18261                          || Is_Interval<From>::value, I_Result>::type
18262Interval<To_Boundary, To_Info>::assign(const From& x) {
18263  PPL_ASSERT(f_OK(x));
18264  if (check_empty_arg(x)) {
18265    return assign(EMPTY);
18266  }
18267  PPL_DIRTY_TEMP(To_Info, to_info);
18268  to_info.clear();
18269  const Result rl = Boundary_NS::assign(LOWER, lower(), to_info,
18270                                        LOWER, f_lower(x), f_info(x));
18271  const Result ru = Boundary_NS::assign(UPPER, upper(), to_info,
18272                                        UPPER, f_upper(x), f_info(x));
18273  assign_or_swap(info(), to_info);
18274  PPL_ASSERT(OK());
18275  return combine(rl, ru);
18276}
18277
18278template <typename To_Boundary, typename To_Info>
18279template <typename From>
18280inline typename Enable_If<Is_Singleton<From>::value
18281                          || Is_Interval<From>::value, I_Result>::type
18282Interval<To_Boundary, To_Info>::join_assign(const From& x) {
18283  PPL_ASSERT(f_OK(x));
18284  if (check_empty_arg(*this)) {
18285    return assign(x);
18286  }
18287  if (check_empty_arg(x)) {
18288    return combine(V_EQ, V_EQ);
18289  }
18290  Result rl;
18291  Result ru;
18292  rl = min_assign(LOWER, lower(), info(), LOWER, f_lower(x), f_info(x));
18293  ru = max_assign(UPPER, upper(), info(), UPPER, f_upper(x), f_info(x));
18294  PPL_ASSERT(OK());
18295  return combine(rl, ru);
18296}
18297
18298template <typename To_Boundary, typename To_Info>
18299template <typename From1, typename From2>
18300inline typename Enable_If<((Is_Singleton<From1>::value
18301                            || Is_Interval<From1>::value)
18302                           && (Is_Singleton<From2>::value
18303                               || Is_Interval<From2>::value)), I_Result>::type
18304Interval<To_Boundary, To_Info>::join_assign(const From1& x, const From2& y) {
18305  PPL_ASSERT(f_OK(x));
18306  PPL_ASSERT(f_OK(y));
18307  if (check_empty_arg(x)) {
18308    return assign(y);
18309  }
18310  if (check_empty_arg(y)) {
18311    return assign(x);
18312  }
18313  PPL_DIRTY_TEMP(To_Info, to_info);
18314  to_info.clear();
18315  Result rl;
18316  Result ru;
18317  rl = min_assign(LOWER, lower(), to_info,
18318                  LOWER, f_lower(x), f_info(x),
18319                  LOWER, f_lower(y), f_info(y));
18320  ru = max_assign(UPPER, upper(), to_info,
18321                  UPPER, f_upper(x), f_info(x),
18322                  UPPER, f_upper(y), f_info(y));
18323  assign_or_swap(info(), to_info);
18324  PPL_ASSERT(OK());
18325  return combine(rl, ru);
18326}
18327
18328template <typename Boundary, typename Info>
18329template <typename Type>
18330inline typename Enable_If<Is_Singleton<Type>::value
18331                          || Is_Interval<Type>::value, bool>::type
18332Interval<Boundary, Info>::can_be_exactly_joined_to(const Type& x) const {
18333  PPL_DIRTY_TEMP(Boundary, b);
18334  if (gt(LOWER, lower(), info(), UPPER, f_upper(x), f_info(x))) {
18335    b = lower();
18336    return eq(LOWER, b, info(), UPPER, f_upper(x), f_info(x));
18337  }
18338  else if (lt(UPPER, upper(), info(), LOWER, f_lower(x), f_info(x))) {
18339    b = upper();
18340    return eq(UPPER, b, info(), LOWER, f_lower(x), f_info(x));
18341  }
18342  return true;
18343}
18344
18345
18346template <typename To_Boundary, typename To_Info>
18347template <typename From>
18348inline typename Enable_If<Is_Singleton<From>::value
18349                          || Is_Interval<From>::value, I_Result>::type
18350Interval<To_Boundary, To_Info>::intersect_assign(const From& x) {
18351  PPL_ASSERT(f_OK(x));
18352  max_assign(LOWER, lower(), info(), LOWER, f_lower(x), f_info(x));
18353  min_assign(UPPER, upper(), info(), UPPER, f_upper(x), f_info(x));
18354  PPL_ASSERT(OK());
18355  return I_ANY;
18356}
18357
18358template <typename To_Boundary, typename To_Info>
18359template <typename From1, typename From2>
18360inline typename Enable_If<((Is_Singleton<From1>::value
18361                            || Is_Interval<From1>::value)
18362                           && (Is_Singleton<From2>::value
18363                               || Is_Interval<From2>::value)), I_Result>::type
18364Interval<To_Boundary, To_Info>::intersect_assign(const From1& x,
18365                                                 const From2& y) {
18366  PPL_ASSERT(f_OK(x));
18367  PPL_ASSERT(f_OK(y));
18368  PPL_DIRTY_TEMP(To_Info, to_info);
18369  to_info.clear();
18370  max_assign(LOWER, lower(), to_info,
18371             LOWER, f_lower(x), f_info(x),
18372             LOWER, f_lower(y), f_info(y));
18373  min_assign(UPPER, upper(), to_info,
18374             UPPER, f_upper(x), f_info(x),
18375             UPPER, f_upper(y), f_info(y));
18376  assign_or_swap(info(), to_info);
18377  PPL_ASSERT(OK());
18378  return I_NOT_EMPTY;
18379}
18380
18381template <typename To_Boundary, typename To_Info>
18382template <typename From>
18383inline typename Enable_If<Is_Singleton<From>::value
18384                          || Is_Interval<From>::value, I_Result>::type
18385Interval<To_Boundary, To_Info>::difference_assign(const From& x) {
18386  PPL_ASSERT(f_OK(x));
18387  if (lt(UPPER, upper(), info(), LOWER, f_lower(x), f_info(x))
18388      || gt(LOWER, lower(), info(), UPPER, f_upper(x), f_info(x))) {
18389    return combine(V_EQ, V_EQ);
18390  }
18391  bool nl = ge(LOWER, lower(), info(), LOWER, f_lower(x), f_info(x));
18392  bool nu = le(UPPER, upper(), info(), UPPER, f_upper(x), f_info(x));
18393  Result rl = V_EQ;
18394  Result ru = V_EQ;
18395  if (nl) {
18396    if (nu) {
18397      return assign(EMPTY);
18398    }
18399    else {
18400      info().clear_boundary_properties(LOWER);
18401      rl = complement(LOWER, lower(), info(), UPPER, f_upper(x), f_info(x));
18402    }
18403  }
18404  else if (nu) {
18405    info().clear_boundary_properties(UPPER);
18406    ru = complement(UPPER, upper(), info(), LOWER, f_lower(x), f_info(x));
18407  }
18408  PPL_ASSERT(OK());
18409  return combine(rl, ru);
18410}
18411
18412template <typename To_Boundary, typename To_Info>
18413template <typename From1, typename From2>
18414inline typename Enable_If<((Is_Singleton<From1>::value
18415                            || Is_Interval<From1>::value)
18416                           && (Is_Singleton<From2>::value
18417                               || Is_Interval<From2>::value)), I_Result>::type
18418Interval<To_Boundary, To_Info>::difference_assign(const From1& x,
18419                                                  const From2& y) {
18420  PPL_ASSERT(f_OK(x));
18421  PPL_ASSERT(f_OK(y));
18422  PPL_DIRTY_TEMP(To_Info, to_info);
18423  to_info.clear();
18424  if (lt(UPPER, f_upper(x), f_info(x), LOWER, f_lower(y), f_info(y))
18425      || gt(LOWER, f_lower(x), f_info(x), UPPER, f_upper(y), f_info(y))) {
18426    return assign(x);
18427  }
18428  bool nl = ge(LOWER, f_lower(x), f_info(x), LOWER, f_lower(y), f_info(y));
18429  bool nu = le(UPPER, f_upper(x), f_info(x), UPPER, f_upper(y), f_info(y));
18430  Result rl = V_EQ;
18431  Result ru = V_EQ;
18432  if (nl) {
18433    if (nu) {
18434      return assign(EMPTY);
18435    }
18436    else {
18437      rl = complement(LOWER, lower(), info(), UPPER, f_upper(y), f_info(y));
18438      ru = Boundary_NS::assign(UPPER, upper(), info(), UPPER, f_upper(x), f_info(x));
18439    }
18440  }
18441  else if (nu) {
18442    ru = complement(UPPER, upper(), info(), LOWER, f_lower(y), f_info(y));
18443    rl = Boundary_NS::assign(LOWER, lower(), info(),
18444                             LOWER, f_lower(x), f_info(x));
18445  }
18446  assign_or_swap(info(), to_info);
18447  PPL_ASSERT(OK());
18448  return combine(rl, ru);
18449}
18450
18451template <typename To_Boundary, typename To_Info>
18452template <typename From>
18453inline typename Enable_If<Is_Singleton<From>::value
18454                          || Is_Interval<From>::value, I_Result>::type
18455Interval<To_Boundary, To_Info>
18456::refine_existential(Relation_Symbol rel, const From& x) {
18457  PPL_ASSERT(OK());
18458  PPL_ASSERT(f_OK(x));
18459  if (check_empty_arg(x)) {
18460    return assign(EMPTY);
18461  }
18462  switch (rel) {
18463  case LESS_THAN:
18464    {
18465      if (lt(UPPER, upper(), info(), UPPER, f_upper(x), f_info(x))) {
18466        return combine(V_EQ, V_EQ);
18467      }
18468      info().clear_boundary_properties(UPPER);
18469      Boundary_NS::assign(UPPER, upper(), info(),
18470                          UPPER, f_upper(x), f_info(x), true);
18471      return I_ANY;
18472    }
18473  case LESS_OR_EQUAL:
18474    {
18475      if (le(UPPER, upper(), info(), UPPER, f_upper(x), f_info(x))) {
18476        return combine(V_EQ, V_EQ);
18477      }
18478      info().clear_boundary_properties(UPPER);
18479      Boundary_NS::assign(UPPER, upper(), info(),
18480                          UPPER, f_upper(x), f_info(x));
18481      return I_ANY;
18482    }
18483  case GREATER_THAN:
18484    {
18485      if (gt(LOWER, lower(), info(), LOWER, f_lower(x), f_info(x))) {
18486        return combine(V_EQ, V_EQ);
18487      }
18488      info().clear_boundary_properties(LOWER);
18489      Boundary_NS::assign(LOWER, lower(), info(),
18490                          LOWER, f_lower(x), f_info(x), true);
18491      return I_ANY;
18492    }
18493  case GREATER_OR_EQUAL:
18494    {
18495      if (ge(LOWER, lower(), info(), LOWER, f_lower(x), f_info(x))) {
18496        return combine(V_EQ, V_EQ);
18497      }
18498      info().clear_boundary_properties(LOWER);
18499      Boundary_NS::assign(LOWER, lower(), info(),
18500                          LOWER, f_lower(x), f_info(x));
18501      return I_ANY;
18502    }
18503  case EQUAL:
18504    return intersect_assign(x);
18505  case NOT_EQUAL:
18506    {
18507      if (!f_is_singleton(x)) {
18508        return combine(V_EQ, V_EQ);
18509      }
18510      if (check_empty_arg(*this)) {
18511        return I_EMPTY;
18512      }
18513      if (eq(LOWER, lower(), info(), LOWER, f_lower(x), f_info(x))) {
18514        remove_inf();
18515      }
18516      if (eq(UPPER, upper(), info(), UPPER, f_upper(x), f_info(x))) {
18517        remove_sup();
18518      }
18519      return I_ANY;
18520    }
18521  default:
18522    PPL_UNREACHABLE;
18523    return I_EMPTY;
18524  }
18525}
18526
18527template <typename To_Boundary, typename To_Info>
18528template <typename From>
18529inline typename Enable_If<Is_Singleton<From>::value
18530                          || Is_Interval<From>::value, I_Result>::type
18531Interval<To_Boundary, To_Info>::refine_universal(Relation_Symbol rel,
18532                                                 const From& x) {
18533  PPL_ASSERT(OK());
18534  PPL_ASSERT(f_OK(x));
18535  if (check_empty_arg(x)) {
18536    return combine(V_EQ, V_EQ);
18537  }
18538  switch (rel) {
18539  case LESS_THAN:
18540    {
18541      if (lt(UPPER, upper(), info(), LOWER, f_lower(x), f_info(x))) {
18542        return combine(V_EQ, V_EQ);
18543      }
18544      info().clear_boundary_properties(UPPER);
18545      Result ru = Boundary_NS::assign(UPPER, upper(), info(),
18546                                      LOWER, f_lower(x), SCALAR_INFO,
18547                                      !is_open(LOWER, f_lower(x), f_info(x)));
18548      PPL_USED(ru);
18549      return I_ANY;
18550    }
18551  case LESS_OR_EQUAL:
18552    {
18553      if (le(UPPER, upper(), info(), LOWER, f_lower(x), f_info(x))) {
18554        return combine(V_EQ, V_EQ);
18555      }
18556      info().clear_boundary_properties(UPPER);
18557      Result ru = Boundary_NS::assign(UPPER, upper(), info(),
18558                                      LOWER, f_lower(x), SCALAR_INFO);
18559      PPL_USED(ru);
18560      return I_ANY;
18561    }
18562  case GREATER_THAN:
18563    {
18564      if (gt(LOWER, lower(), info(), UPPER, f_upper(x), f_info(x))) {
18565        return combine(V_EQ, V_EQ);
18566      }
18567      info().clear_boundary_properties(LOWER);
18568      Result rl = Boundary_NS::assign(LOWER, lower(), info(),
18569                                      UPPER, f_upper(x), SCALAR_INFO,
18570                                      !is_open(UPPER, f_upper(x), f_info(x)));
18571      PPL_USED(rl);
18572      return I_ANY;
18573    }
18574  case GREATER_OR_EQUAL:
18575    {
18576      if (ge(LOWER, lower(), info(), UPPER, f_upper(x), f_info(x))) {
18577        return combine(V_EQ, V_EQ);
18578      }
18579      info().clear_boundary_properties(LOWER);
18580      Result rl = Boundary_NS::assign(LOWER, lower(), info(),
18581                                      UPPER, f_upper(x), SCALAR_INFO);
18582      PPL_USED(rl);
18583      return I_ANY;
18584    }
18585  case EQUAL:
18586    if (!f_is_singleton(x)) {
18587      return assign(EMPTY);
18588    }
18589    return intersect_assign(x);
18590  case NOT_EQUAL:
18591    {
18592      if (check_empty_arg(*this)) {
18593        return I_EMPTY;
18594      }
18595      if (eq(LOWER, lower(), info(), LOWER, f_lower(x), f_info(x))) {
18596        remove_inf();
18597      }
18598      if (eq(UPPER, upper(), info(), UPPER, f_upper(x), f_info(x))) {
18599        remove_sup();
18600      }
18601      return I_ANY;
18602    }
18603  default:
18604    PPL_UNREACHABLE;
18605    return I_EMPTY;
18606  }
18607}
18608
18609template <typename To_Boundary, typename To_Info>
18610template <typename From>
18611inline typename Enable_If<Is_Singleton<From>::value
18612                          || Is_Interval<From>::value, I_Result>::type
18613Interval<To_Boundary, To_Info>::neg_assign(const From& x) {
18614  PPL_ASSERT(f_OK(x));
18615  if (check_empty_arg(x)) {
18616    return assign(EMPTY);
18617  }
18618  PPL_DIRTY_TEMP(To_Info, to_info);
18619  to_info.clear();
18620  Result rl;
18621  Result ru;
18622  PPL_DIRTY_TEMP(To_Boundary, to_lower);
18623  rl = Boundary_NS::neg_assign(LOWER, to_lower, to_info, UPPER, f_upper(x), f_info(x));
18624  ru = Boundary_NS::neg_assign(UPPER, upper(), to_info, LOWER, f_lower(x), f_info(x));
18625  assign_or_swap(lower(), to_lower);
18626  assign_or_swap(info(), to_info);
18627  PPL_ASSERT(OK());
18628  return combine(rl, ru);
18629}
18630
18631template <typename To_Boundary, typename To_Info>
18632template <typename From1, typename From2>
18633inline typename Enable_If<((Is_Singleton<From1>::value
18634                            || Is_Interval<From1>::value)
18635                           && (Is_Singleton<From2>::value
18636                               || Is_Interval<From2>::value)), I_Result>::type
18637Interval<To_Boundary, To_Info>::add_assign(const From1& x, const From2& y) {
18638  PPL_ASSERT(f_OK(x));
18639  PPL_ASSERT(f_OK(y));
18640  if (check_empty_arg(x) || check_empty_arg(y)) {
18641    return assign(EMPTY);
18642  }
18643  int inf_sign = Parma_Polyhedra_Library::infinity_sign(x);
18644  if (inf_sign != 0) {
18645    if (Parma_Polyhedra_Library::infinity_sign(y) == -inf_sign) {
18646      return assign(EMPTY);
18647    }
18648  }
18649  else {
18650    inf_sign = Parma_Polyhedra_Library::infinity_sign(y);
18651  }
18652  if (inf_sign < 0) {
18653    return assign(MINUS_INFINITY);
18654  }
18655  else if (inf_sign > 0) {
18656    return assign(PLUS_INFINITY);
18657  }
18658  PPL_DIRTY_TEMP(To_Info, to_info);
18659  to_info.clear();
18660  Result rl = Boundary_NS::add_assign(LOWER, lower(), to_info,
18661                                      LOWER, f_lower(x), f_info(x),
18662                                      LOWER, f_lower(y), f_info(y));
18663  Result ru = Boundary_NS::add_assign(UPPER, upper(), to_info,
18664                                      UPPER, f_upper(x), f_info(x),
18665                                      UPPER, f_upper(y), f_info(y));
18666  assign_or_swap(info(), to_info);
18667  PPL_ASSERT(OK());
18668  return combine(rl, ru);
18669}
18670
18671template <typename To_Boundary, typename To_Info>
18672template <typename From1, typename From2>
18673inline typename Enable_If<((Is_Singleton<From1>::value
18674                            || Is_Interval<From1>::value)
18675                           && (Is_Singleton<From2>::value
18676                               || Is_Interval<From2>::value)), I_Result>::type
18677Interval<To_Boundary, To_Info>::sub_assign(const From1& x, const From2& y) {
18678  PPL_ASSERT(f_OK(x));
18679  PPL_ASSERT(f_OK(y));
18680  if (check_empty_arg(x) || check_empty_arg(y)) {
18681    return assign(EMPTY);
18682  }
18683  int inf_sign = Parma_Polyhedra_Library::infinity_sign(x);
18684  if (inf_sign != 0) {
18685    if (Parma_Polyhedra_Library::infinity_sign(y) == inf_sign) {
18686      return assign(EMPTY);
18687    }
18688  }
18689  else {
18690    inf_sign = -Parma_Polyhedra_Library::infinity_sign(y);
18691  }
18692  if (inf_sign < 0) {
18693    return assign(MINUS_INFINITY);
18694  }
18695  else if (inf_sign > 0) {
18696    return assign(PLUS_INFINITY);
18697  }
18698  PPL_DIRTY_TEMP(To_Info, to_info);
18699  to_info.clear();
18700  Result rl;
18701  Result ru;
18702  PPL_DIRTY_TEMP(To_Boundary, to_lower);
18703  rl = Boundary_NS::sub_assign(LOWER, to_lower, to_info,
18704                               LOWER, f_lower(x), f_info(x),
18705                               UPPER, f_upper(y), f_info(y));
18706  ru = Boundary_NS::sub_assign(UPPER, upper(), to_info,
18707                               UPPER, f_upper(x), f_info(x),
18708                               LOWER, f_lower(y), f_info(y));
18709  assign_or_swap(lower(), to_lower);
18710  assign_or_swap(info(), to_info);
18711  PPL_ASSERT(OK());
18712  return combine(rl, ru);
18713}
18714
18715/**
18716+---------+-----------+-----------+-----------------+
18717|    *    |  yl > 0   |  yu < 0   |  yl < 0, yu > 0 |
18718+---------+-----------+-----------+-----------------+
18719| xl > 0  |xl*yl,xu*yu|xu*yl,xl*yu|   xu*yl,xu*yu   |
18720+---------+-----------+-----------+-----------------+
18721| xu < 0  |xl*yu,xu*yl|xu*yu,xl*yl|   xl*yu,xl*yl   |
18722+---------+-----------+-----------+-----------------+
18723|xl<0 xu>0|xl*yu,xu*yu|xu*yl,xl*yl|min(xl*yu,xu*yl),|
18724|         |           |           |max(xl*yl,xu*yu) |
18725+---------+-----------+-----------+-----------------+
18726**/
18727template <typename To_Boundary, typename To_Info>
18728template <typename From1, typename From2>
18729inline typename Enable_If<((Is_Singleton<From1>::value
18730                            || Is_Interval<From1>::value)
18731                           && (Is_Singleton<From2>::value
18732                               || Is_Interval<From2>::value)), I_Result>::type
18733Interval<To_Boundary, To_Info>::mul_assign(const From1& x, const From2& y) {
18734  PPL_ASSERT(f_OK(x));
18735  PPL_ASSERT(f_OK(y));
18736  if (check_empty_arg(x) || check_empty_arg(y)) {
18737    return assign(EMPTY);
18738  }
18739  int xls = sgn_b(LOWER, f_lower(x), f_info(x));
18740  int xus = (xls > 0) ? 1 : sgn_b(UPPER, f_upper(x), f_info(x));
18741  int yls = sgn_b(LOWER, f_lower(y), f_info(y));
18742  int yus = (yls > 0) ? 1 : sgn_b(UPPER, f_upper(y), f_info(y));
18743  int inf_sign = Parma_Polyhedra_Library::infinity_sign(x);
18744  int ls;
18745  int us;
18746  if (inf_sign != 0) {
18747    ls = yls;
18748    us = yus;
18749    goto inf;
18750  }
18751  else {
18752    inf_sign = Parma_Polyhedra_Library::infinity_sign(y);
18753    if (inf_sign != 0) {
18754      ls = xls;
18755      us = xus;
18756    inf:
18757      if (ls == 0 && us == 0) {
18758        return assign(EMPTY);
18759      }
18760      if (ls == -us) {
18761        return set_infinities();
18762      }
18763      if (ls < 0 || us < 0) {
18764        inf_sign = -inf_sign;
18765      }
18766      if (inf_sign < 0) {
18767        return assign(MINUS_INFINITY);
18768      }
18769      else {
18770        return assign(PLUS_INFINITY);
18771      }
18772    }
18773  }
18774
18775  PPL_DIRTY_TEMP(To_Info, to_info);
18776  to_info.clear();
18777  Result rl;
18778  Result ru;
18779  PPL_DIRTY_TEMP(To_Boundary, to_lower);
18780
18781  if (xls >= 0) {
18782    if (yls >= 0) {
18783      // 0 <= xl <= xu, 0 <= yl <= yu
18784      rl = mul_assign_z(LOWER, to_lower, to_info,
18785                        LOWER, f_lower(x), f_info(x), xls,
18786                        LOWER, f_lower(y), f_info(y), yls);
18787      ru = mul_assign_z(UPPER, upper(), to_info,
18788                        UPPER, f_upper(x), f_info(x), xus,
18789                        UPPER, f_upper(y), f_info(y), yus);
18790    }
18791    else if (yus <= 0) {
18792      // 0 <= xl <= xu, yl <= yu <= 0
18793      rl = mul_assign_z(LOWER, to_lower, to_info,
18794                        UPPER, f_upper(x), f_info(x), xus,
18795                        LOWER, f_lower(y), f_info(y), yls);
18796      ru = mul_assign_z(UPPER, upper(), to_info,
18797                        LOWER, f_lower(x), f_info(x), xls,
18798                        UPPER, f_upper(y), f_info(y), yus);
18799    }
18800    else {
18801      // 0 <= xl <= xu, yl < 0 < yu
18802      rl = mul_assign_z(LOWER, to_lower, to_info,
18803                        UPPER, f_upper(x), f_info(x), xus,
18804                        LOWER, f_lower(y), f_info(y), yls);
18805      ru = mul_assign_z(UPPER, upper(), to_info,
18806                        UPPER, f_upper(x), f_info(x), xus,
18807                        UPPER, f_upper(y), f_info(y), yus);
18808    }
18809  }
18810  else if (xus <= 0) {
18811    if (yls >= 0) {
18812      // xl <= xu <= 0, 0 <= yl <= yu
18813      rl = mul_assign_z(LOWER, to_lower, to_info,
18814                        LOWER, f_lower(x), f_info(x), xls,
18815                        UPPER, f_upper(y), f_info(y), yus);
18816      ru = mul_assign_z(UPPER, upper(), to_info,
18817                        UPPER, f_upper(x), f_info(x), xus,
18818                        LOWER, f_lower(y), f_info(y), yls);
18819    }
18820    else if (yus <= 0) {
18821      // xl <= xu <= 0, yl <= yu <= 0
18822      rl = mul_assign_z(LOWER, to_lower, to_info,
18823                        UPPER, f_upper(x), f_info(x), xus,
18824                        UPPER, f_upper(y), f_info(y), yus);
18825      ru = mul_assign_z(UPPER, upper(), to_info,
18826                        LOWER, f_lower(x), f_info(x), xls,
18827                        LOWER, f_lower(y), f_info(y), yls);
18828    }
18829    else {
18830      // xl <= xu <= 0, yl < 0 < yu
18831      rl = mul_assign_z(LOWER, to_lower, to_info,
18832                        LOWER, f_lower(x), f_info(x), xls,
18833                        UPPER, f_upper(y), f_info(y), yus);
18834      ru = mul_assign_z(UPPER, upper(), to_info,
18835                        LOWER, f_lower(x), f_info(x), xls,
18836                        LOWER, f_lower(y), f_info(y), yls);
18837    }
18838  }
18839  else if (yls >= 0) {
18840    // xl < 0 < xu, 0 <= yl <= yu
18841    rl = mul_assign_z(LOWER, to_lower, to_info,
18842                      LOWER, f_lower(x), f_info(x), xls,
18843                      UPPER, f_upper(y), f_info(y), yus);
18844    ru = mul_assign_z(UPPER, upper(), to_info,
18845                      UPPER, f_upper(x), f_info(x), xus,
18846                      UPPER, f_upper(y), f_info(y), yus);
18847  }
18848  else if (yus <= 0) {
18849    // xl < 0 < xu, yl <= yu <= 0
18850    rl = mul_assign_z(LOWER, to_lower, to_info,
18851                      UPPER, f_upper(x), f_info(x), xus,
18852                      LOWER, f_lower(y), f_info(y), yls);
18853    ru = mul_assign_z(UPPER, upper(), to_info,
18854                      LOWER, f_lower(x), f_info(x), xls,
18855                      LOWER, f_lower(y), f_info(y), yls);
18856  }
18857  else {
18858    // xl < 0 < xu, yl < 0 < yu
18859    PPL_DIRTY_TEMP(To_Boundary, tmp);
18860    PPL_DIRTY_TEMP(To_Info, tmp_info);
18861    tmp_info.clear();
18862    Result tmp_r;
18863    tmp_r = Boundary_NS::mul_assign(LOWER, tmp, tmp_info,
18864                                    UPPER, f_upper(x), f_info(x),
18865                                    LOWER, f_lower(y), f_info(y));
18866    rl = Boundary_NS::mul_assign(LOWER, to_lower, to_info,
18867                                 LOWER, f_lower(x), f_info(x),
18868                                 UPPER, f_upper(y), f_info(y));
18869    if (gt(LOWER, to_lower, to_info, LOWER, tmp, tmp_info)) {
18870      to_lower = tmp;
18871      rl = tmp_r;
18872    }
18873    tmp_info.clear();
18874    tmp_r = Boundary_NS::mul_assign(UPPER, tmp, tmp_info,
18875                                    UPPER, f_upper(x), f_info(x),
18876                                    UPPER, f_upper(y), f_info(y));
18877    ru = Boundary_NS::mul_assign(UPPER, upper(), to_info,
18878                                 LOWER, f_lower(x), f_info(x),
18879                                 LOWER, f_lower(y), f_info(y));
18880    if (lt(UPPER, upper(), to_info, UPPER, tmp, tmp_info)) {
18881      upper() = tmp;
18882      ru = tmp_r;
18883    }
18884  }
18885  assign_or_swap(lower(), to_lower);
18886  assign_or_swap(info(), to_info);
18887  PPL_ASSERT(OK());
18888  return combine(rl, ru);
18889}
18890
18891/**
18892+-----------+-----------+-----------+
18893|     /     |  yu < 0   |  yl > 0   |
18894+-----------+-----------+-----------+
18895|   xu<=0   |xu/yl,xl/yu|xl/yl,xu/yu|
18896+-----------+-----------+-----------+
18897|xl<=0 xu>=0|xu/yu,xl/yu|xl/yl,xu/yl|
18898+-----------+-----------+-----------+
18899|   xl>=0   |xu/yu,xl/yl|xl/yu,xu/yl|
18900+-----------+-----------+-----------+
18901**/
18902template <typename To_Boundary, typename To_Info>
18903template <typename From1, typename From2>
18904inline typename Enable_If<((Is_Singleton<From1>::value
18905                            || Is_Interval<From1>::value)
18906                           && (Is_Singleton<From2>::value
18907                               || Is_Interval<From2>::value)), I_Result>::type
18908Interval<To_Boundary, To_Info>::div_assign(const From1& x, const From2& y) {
18909  PPL_ASSERT(f_OK(x));
18910  PPL_ASSERT(f_OK(y));
18911  if (check_empty_arg(x) || check_empty_arg(y)) {
18912    return assign(EMPTY);
18913  }
18914  int yls = sgn_b(LOWER, f_lower(y), f_info(y));
18915  int yus = (yls > 0) ? 1 : sgn_b(UPPER, f_upper(y), f_info(y));
18916  if (yls == 0 && yus == 0) {
18917    return assign(EMPTY);
18918  }
18919  int inf_sign = Parma_Polyhedra_Library::infinity_sign(x);
18920  if (inf_sign != 0) {
18921    if (Parma_Polyhedra_Library::infinity_sign(y) != 0) {
18922      return assign(EMPTY);
18923    }
18924    if (yls == -yus) {
18925      return set_infinities();
18926    }
18927    if (yls < 0 || yus < 0) {
18928      inf_sign = -inf_sign;
18929    }
18930    if (inf_sign < 0) {
18931      return assign(MINUS_INFINITY);
18932    }
18933    else {
18934      return assign(PLUS_INFINITY);
18935    }
18936  }
18937  int xls = sgn_b(LOWER, f_lower(x), f_info(x));
18938  int xus = (xls > 0) ? 1 : sgn_b(UPPER, f_upper(x), f_info(x));
18939
18940  PPL_DIRTY_TEMP(To_Info, to_info);
18941  to_info.clear();
18942  Result rl;
18943  Result ru;
18944  PPL_DIRTY_TEMP(To_Boundary, to_lower);
18945  if (yls >= 0) {
18946    if (xls >= 0) {
18947      rl = div_assign_z(LOWER, to_lower, to_info,
18948                        LOWER, f_lower(x), f_info(x), xls,
18949                        UPPER, f_upper(y), f_info(y), yus);
18950      ru = div_assign_z(UPPER, upper(), to_info,
18951                        UPPER, f_upper(x), f_info(x), xus,
18952                        LOWER, f_lower(y), f_info(y), yls);
18953    }
18954    else if (xus <= 0) {
18955      rl = div_assign_z(LOWER, to_lower, to_info,
18956                        LOWER, f_lower(x), f_info(x), xls,
18957                        LOWER, f_lower(y), f_info(y), yls);
18958      ru = div_assign_z(UPPER, upper(), to_info,
18959                        UPPER, f_upper(x), f_info(x), xus,
18960                        UPPER, f_upper(y), f_info(y), yus);
18961    }
18962    else {
18963      rl = div_assign_z(LOWER, to_lower, to_info,
18964                        LOWER, f_lower(x), f_info(x), xls,
18965                        LOWER, f_lower(y), f_info(y), yls);
18966      ru = div_assign_z(UPPER, upper(), to_info,
18967                        UPPER, f_upper(x), f_info(x), xus,
18968                        LOWER, f_lower(y), f_info(y), yls);
18969    }
18970  }
18971  else if (yus <= 0) {
18972    if (xls >= 0) {
18973      rl = div_assign_z(LOWER, to_lower, to_info,
18974                        UPPER, f_upper(x), f_info(x), xus,
18975                        UPPER, f_upper(y), f_info(y), yus);
18976      ru = div_assign_z(UPPER, upper(), to_info,
18977                        LOWER, f_lower(x), f_info(x), xls,
18978                        LOWER, f_lower(y), f_info(y), yls);
18979    }
18980    else if (xus <= 0) {
18981      rl = div_assign_z(LOWER, to_lower, to_info,
18982                        UPPER, f_upper(x), f_info(x), xus,
18983                        LOWER, f_lower(y), f_info(y), yls);
18984      ru = div_assign_z(UPPER, upper(), to_info,
18985                        LOWER, f_lower(x), f_info(x), xls,
18986                        UPPER, f_upper(y), f_info(y), yus);
18987    }
18988    else {
18989      rl = div_assign_z(LOWER, to_lower, to_info,
18990                        UPPER, f_upper(x), f_info(x), xus,
18991                        UPPER, f_upper(y), f_info(y), yus);
18992      ru = div_assign_z(UPPER, upper(), to_info,
18993                        LOWER, f_lower(x), f_info(x), xls,
18994                        UPPER, f_upper(y), f_info(y), yus);
18995    }
18996  }
18997  else {
18998    return static_cast<I_Result>(assign(UNIVERSE) | I_SINGULARITIES);
18999  }
19000  assign_or_swap(lower(), to_lower);
19001  assign_or_swap(info(), to_info);
19002  PPL_ASSERT(OK());
19003  return combine(rl, ru);
19004}
19005
19006template <typename B, typename Info, typename T>
19007inline typename Enable_If<Is_Singleton<T>::value, Interval<B, Info> >::type
19008operator+(const Interval<B, Info>& x, const T& y) {
19009  Interval<B, Info> z;
19010  z.add_assign(x, y);
19011  return z;
19012}
19013
19014template <typename B, typename Info, typename T>
19015inline typename Enable_If<Is_Singleton<T>::value, Interval<B, Info> >::type
19016operator+(const T& x, const Interval<B, Info>& y) {
19017  Interval<B, Info> z;
19018  z.add_assign(x, y);
19019  return z;
19020}
19021
19022template <typename B, typename Info>
19023inline Interval<B, Info>
19024operator+(const Interval<B, Info>& x, const Interval<B, Info>& y) {
19025  Interval<B, Info> z;
19026  z.add_assign(x, y);
19027  return z;
19028}
19029
19030template <typename B, typename Info, typename T>
19031inline typename Enable_If<Is_Singleton<T>::value, Interval<B, Info> >::type
19032operator-(const Interval<B, Info>& x, const T& y) {
19033  Interval<B, Info> z;
19034  z.sub_assign(x, y);
19035  return z;
19036}
19037
19038template <typename B, typename Info, typename T>
19039inline typename Enable_If<Is_Singleton<T>::value, Interval<B, Info> >::type
19040operator-(const T& x, const Interval<B, Info>& y) {
19041  Interval<B, Info> z;
19042  z.sub_assign(x, y);
19043  return z;
19044}
19045
19046template <typename B, typename Info>
19047inline Interval<B, Info>
19048operator-(const Interval<B, Info>& x, const Interval<B, Info>& y) {
19049  Interval<B, Info> z;
19050  z.sub_assign(x, y);
19051  return z;
19052}
19053
19054template <typename B, typename Info, typename T>
19055inline typename Enable_If<Is_Singleton<T>::value, Interval<B, Info> >::type
19056operator*(const Interval<B, Info>& x, const T& y) {
19057  Interval<B, Info> z;
19058  z.mul_assign(x, y);
19059  return z;
19060}
19061
19062template <typename B, typename Info, typename T>
19063inline typename Enable_If<Is_Singleton<T>::value, Interval<B, Info> >::type
19064operator*(const T& x, const Interval<B, Info>& y) {
19065  Interval<B, Info> z;
19066  z.mul_assign(x, y);
19067  return z;
19068}
19069
19070template <typename B, typename Info>
19071inline Interval<B, Info>
19072operator*(const Interval<B, Info>& x, const Interval<B, Info>& y) {
19073  Interval<B, Info> z;
19074  z.mul_assign(x, y);
19075  return z;
19076}
19077
19078template <typename B, typename Info, typename T>
19079inline typename Enable_If<Is_Singleton<T>::value, Interval<B, Info> >::type
19080operator/(const Interval<B, Info>& x, const T& y) {
19081  Interval<B, Info> z;
19082  z.div_assign(x, y);
19083  return z;
19084}
19085
19086template <typename B, typename Info, typename T>
19087inline typename Enable_If<Is_Singleton<T>::value, Interval<B, Info> >::type
19088operator/(const T& x, const Interval<B, Info>& y) {
19089  Interval<B, Info> z;
19090  z.div_assign(x, y);
19091  return z;
19092}
19093
19094template <typename B, typename Info>
19095inline Interval<B, Info>
19096operator/(const Interval<B, Info>& x, const Interval<B, Info>& y) {
19097  Interval<B, Info> z;
19098  z.div_assign(x, y);
19099  return z;
19100}
19101
19102template <typename Boundary, typename Info>
19103inline std::ostream&
19104operator<<(std::ostream& os, const Interval<Boundary, Info>& x) {
19105  if (check_empty_arg(x)) {
19106    return os << "[]";
19107  }
19108  if (x.is_singleton()) {
19109    output(os, x.lower(), Numeric_Format(), ROUND_NOT_NEEDED);
19110    return os;
19111  }
19112  os << (x.lower_is_open() ? "(" : "[");
19113  if (x.info().get_boundary_property(LOWER, SPECIAL)) {
19114    os << "-inf";
19115  }
19116  else {
19117    output(os, x.lower(), Numeric_Format(), ROUND_NOT_NEEDED);
19118  }
19119  os << ", ";
19120  if (x.info().get_boundary_property(UPPER, SPECIAL)) {
19121    os << "+inf";
19122  }
19123  else {
19124    output(os, x.upper(), Numeric_Format(), ROUND_NOT_NEEDED);
19125  }
19126  os << (x.upper_is_open() ? ")" : "]");
19127  return os;
19128}
19129
19130template <typename Boundary, typename Info>
19131inline void
19132Interval<Boundary, Info>::ascii_dump(std::ostream& s) const {
19133  using Parma_Polyhedra_Library::ascii_dump;
19134  s << "info ";
19135  info().ascii_dump(s);
19136  s << " lower ";
19137  ascii_dump(s, lower());
19138  s << " upper ";
19139  ascii_dump(s, upper());
19140  s << '\n';
19141}
19142
19143template <typename Boundary, typename Info>
19144inline bool
19145Interval<Boundary, Info>::ascii_load(std::istream& s) {
19146  using Parma_Polyhedra_Library::ascii_load;
19147  std::string str;
19148  if (!(s >> str) || str != "info") {
19149    return false;
19150  }
19151  if (!info().ascii_load(s)) {
19152    return false;
19153  }
19154  if (!(s >> str) || str != "lower") {
19155    return false;
19156  }
19157  if (!ascii_load(s, lower())) {
19158    return false;
19159  }
19160  if (!(s >> str) || str != "upper") {
19161    return false;
19162  }
19163  if (!ascii_load(s, upper())) {
19164    return false;
19165  }
19166  PPL_ASSERT(OK());
19167  return true;
19168}
19169
19170/*! \brief
19171  Helper class to select the appropriate numerical type to perform
19172  boundary computations so as to reduce the chances of overflow without
19173  incurring too much overhead.
19174*/
19175template <typename Interval_Boundary_Type> struct Select_Temp_Boundary_Type;
19176
19177template <typename Interval_Boundary_Type>
19178struct Select_Temp_Boundary_Type {
19179  typedef Interval_Boundary_Type type;
19180};
19181
19182#if PPL_SUPPORTED_DOUBLE
19183template <>
19184struct Select_Temp_Boundary_Type<float> {
19185  typedef double type;
19186};
19187#endif
19188
19189template <>
19190struct Select_Temp_Boundary_Type<char> {
19191  typedef signed long long type;
19192};
19193
19194template <>
19195struct Select_Temp_Boundary_Type<signed char> {
19196  typedef signed long long type;
19197};
19198
19199template <>
19200struct Select_Temp_Boundary_Type<unsigned char> {
19201  typedef signed long long type;
19202};
19203
19204template <>
19205struct Select_Temp_Boundary_Type<signed short> {
19206  typedef signed long long type;
19207};
19208
19209template <>
19210struct Select_Temp_Boundary_Type<unsigned short> {
19211  typedef signed long long type;
19212};
19213
19214template <>
19215struct Select_Temp_Boundary_Type<signed int> {
19216  typedef signed long long type;
19217};
19218
19219template <>
19220struct Select_Temp_Boundary_Type<unsigned int> {
19221  typedef signed long long type;
19222};
19223
19224template <>
19225struct Select_Temp_Boundary_Type<signed long> {
19226  typedef signed long long type;
19227};
19228
19229template <>
19230struct Select_Temp_Boundary_Type<unsigned long> {
19231  typedef signed long long type;
19232};
19233
19234template <>
19235struct Select_Temp_Boundary_Type<unsigned long long> {
19236  typedef signed long long type;
19237};
19238
19239/*! \relates Interval */
19240template <typename Boundary, typename Info>
19241inline void
19242swap(Interval<Boundary, Info>& x, Interval<Boundary, Info>& y) {
19243  x.m_swap(y);
19244}
19245
19246} // namespace Parma_Polyhedra_Library
19247
19248/* Automatically generated from PPL source file ../src/Interval_templates.hh line 1. */
19249/* Interval class implementation: non-inline template functions.
19250*/
19251
19252
19253#include <algorithm>
19254
19255namespace Parma_Polyhedra_Library {
19256
19257template <typename Boundary, typename Info>
19258template <typename C>
19259typename Enable_If<Is_Same_Or_Derived<I_Constraint_Base, C>::value, I_Result>::type
19260Interval<Boundary, Info>::lower_extend(const C& c) {
19261  PPL_ASSERT(OK());
19262  bool open;
19263  switch (c.rel()) {
19264  case V_LGE:
19265    return lower_extend();
19266  case V_NAN:
19267    return I_NOT_EMPTY | I_EXACT | I_UNCHANGED;
19268  case V_GT:
19269    open = true;
19270    break;
19271  case V_GE: // Fall through.
19272  case V_EQ:
19273    open = false;
19274    break;
19275  default:
19276    PPL_UNREACHABLE;
19277    return I_NOT_EMPTY | I_EXACT | I_UNCHANGED;
19278  }
19279  min_assign(LOWER, lower(), info(), LOWER, c.value(), f_info(c.value(), open));
19280  PPL_ASSERT(OK());
19281  return I_ANY;
19282}
19283
19284template <typename Boundary, typename Info>
19285template <typename C>
19286typename Enable_If<Is_Same_Or_Derived<I_Constraint_Base, C>::value, I_Result>::type
19287Interval<Boundary, Info>::upper_extend(const C& c) {
19288  PPL_ASSERT(OK());
19289  bool open;
19290  switch (c.rel()) {
19291  case V_LGE:
19292    return lower_extend();
19293  case V_NAN:
19294    return I_NOT_EMPTY | I_EXACT | I_UNCHANGED;
19295  case V_LT:
19296    open = true;
19297    break;
19298  case V_LE: // Fall through.
19299  case V_EQ:
19300    open = false;
19301    break;
19302  default:
19303    PPL_UNREACHABLE;
19304    return I_NOT_EMPTY | I_EXACT | I_UNCHANGED;
19305  }
19306  max_assign(UPPER, upper(), info(), UPPER, c.value(), f_info(c.value(), open));
19307  PPL_ASSERT(OK());
19308  return I_ANY;
19309}
19310
19311template <typename Boundary, typename Info>
19312template <typename From, typename Iterator>
19313typename Enable_If<Is_Interval<From>::value, void>::type
19314Interval<Boundary, Info>::CC76_widening_assign(const From& y,
19315                                               Iterator first,
19316                                               Iterator last) {
19317  // We assume that `y' is contained in or equal to `*this'.
19318  PPL_ASSERT(contains(y));
19319  Interval<Boundary, Info>& x = *this;
19320
19321  // Upper bound.
19322  if (!x.upper_is_boundary_infinity()) {
19323    Boundary& x_ub = x.upper();
19324    const Boundary& y_ub = y.upper();
19325    PPL_ASSERT(!y.upper_is_boundary_infinity() && y_ub <= x_ub);
19326    if (y_ub < x_ub) {
19327      Iterator k = std::lower_bound(first, last, x_ub);
19328      if (k != last) {
19329        if (x_ub < *k) {
19330          x_ub = *k;
19331        }
19332      }
19333      else {
19334        x.upper_extend();
19335      }
19336    }
19337  }
19338
19339  // Lower bound.
19340  if (!x.lower_is_boundary_infinity()) {
19341    Boundary& x_lb = x.lower();
19342    const Boundary& y_lb = y.lower();
19343    PPL_ASSERT(!y.lower_is_boundary_infinity() && y_lb >= x_lb);
19344    if (y_lb > x_lb) {
19345      Iterator k = std::lower_bound(first, last, x_lb);
19346      if (k != last) {
19347        if (x_lb < *k) {
19348          if (k != first) {
19349            x_lb = *--k;
19350          }
19351          else {
19352            x.lower_extend();
19353          }
19354        }
19355      }
19356      else {
19357        if (k != first) {
19358          x_lb = *--k;
19359        }
19360        else {
19361          x.lower_extend();
19362        }
19363      }
19364    }
19365  }
19366}
19367
19368template <typename Boundary, typename Info>
19369Interval<Boundary, Info>::Interval(const char* s) {
19370  // Get the lower bound.
19371  Boundary lower_bound;
19372  Result lower_r = assign_r(lower_bound, s, ROUND_DOWN);
19373  if (lower_r == V_CVT_STR_UNK || lower_r == V_NAN) {
19374    throw std::invalid_argument("PPL::Interval(const char* s)"
19375                                " with s invalid");
19376  }
19377  lower_r = result_relation_class(lower_r);
19378
19379  // Get the upper bound.
19380  Boundary upper_bound;
19381  Result upper_r = assign_r(upper_bound, s, ROUND_UP);
19382  PPL_ASSERT(upper_r != V_CVT_STR_UNK && upper_r != V_NAN);
19383  upper_r = result_relation_class(upper_r);
19384
19385  // Build the interval.
19386  bool lower_open = false;
19387  bool upper_open = false;
19388  bool lower_boundary_infinity = false;
19389  bool upper_boundary_infinity = false;
19390  switch (lower_r) {
19391  case V_EQ: // Fall through.
19392  case V_GE:
19393    break;
19394  case V_GT:
19395    lower_open = true;
19396    break;
19397  case V_GT_MINUS_INFINITY:
19398    lower_open = true;
19399    // Fall through.
19400  case V_EQ_MINUS_INFINITY:
19401    lower_boundary_infinity = true;
19402    break;
19403  case V_EQ_PLUS_INFINITY: // Fall through.
19404  case V_LT_PLUS_INFINITY:
19405    if (upper_r == V_EQ_PLUS_INFINITY || upper_r == V_LT_PLUS_INFINITY) {
19406      assign(UNIVERSE);
19407    }
19408    else {
19409      assign(EMPTY);
19410    }
19411    break;
19412  default:
19413    PPL_UNREACHABLE;
19414    break;
19415  }
19416  switch (upper_r) {
19417  case V_EQ: // Fall through.
19418  case V_LE:
19419    break;
19420  case V_LT:
19421    upper_open = true;
19422    break;
19423  case V_EQ_MINUS_INFINITY: // Fall through.
19424  case V_GT_MINUS_INFINITY:
19425    if (lower_r == V_EQ_MINUS_INFINITY || lower_r == V_GT_MINUS_INFINITY) {
19426      assign(UNIVERSE);
19427    }
19428    else {
19429      assign(EMPTY);
19430    }
19431    break;
19432  case V_LT_PLUS_INFINITY:
19433    upper_open = true;
19434    // Fall through.
19435  case V_EQ_PLUS_INFINITY:
19436    upper_boundary_infinity = true;
19437    break;
19438  default:
19439    PPL_UNREACHABLE;
19440    break;
19441  }
19442
19443  if (!lower_boundary_infinity
19444      && !upper_boundary_infinity
19445      && (lower_bound > upper_bound
19446          || (lower_open && lower_bound == upper_bound))) {
19447    assign(EMPTY);
19448  }
19449  else {
19450    if (lower_boundary_infinity) {
19451      set_minus_infinity(LOWER, lower(), info(), lower_open);
19452    }
19453    else {
19454      Boundary_NS::assign(LOWER, lower(), info(),
19455                          LOWER, lower_bound, SCALAR_INFO, lower_open);
19456    }
19457    if (upper_boundary_infinity) {
19458      set_plus_infinity(UPPER, upper(), info(), upper_open);
19459    }
19460    else {
19461      Boundary_NS::assign(UPPER, upper(), info(),
19462                          UPPER, upper_bound, SCALAR_INFO, upper_open);
19463    }
19464  }
19465}
19466
19467
19468template <typename Boundary, typename Info>
19469inline std::istream&
19470operator>>(std::istream& is, Interval<Boundary, Info>& x) {
19471  Boundary lower_bound;
19472  Boundary upper_bound;
19473  bool lower_boundary_infinity = false;
19474  bool upper_boundary_infinity = false;
19475  bool lower_open = false;
19476  bool upper_open = false;
19477  Result lower_r;
19478  Result upper_r;
19479
19480  // Eat leading white space.
19481  char c;
19482  do {
19483    if (!is.get(c)) {
19484      goto fail;
19485    }
19486  } while (is_space(c));
19487
19488  // Get the opening parenthesis and handle the empty interval case.
19489  if (c == '(') {
19490    lower_open = true;
19491  }
19492  else if (c == '[') {
19493    if (!is.get(c)) {
19494      goto fail;
19495    }
19496    if (c == ']') {
19497      // Empty interval.
19498      x.assign(EMPTY);
19499      return is;
19500    }
19501    else {
19502      is.unget();
19503    }
19504  }
19505  else {
19506    goto unexpected_char;
19507  }
19508
19509  // Get the lower bound.
19510  lower_r = input(lower_bound, is, ROUND_DOWN);
19511  if (lower_r == V_CVT_STR_UNK || lower_r == V_NAN) {
19512    goto fail;
19513  }
19514  lower_r = result_relation_class(lower_r);
19515
19516  // Match the comma separating the lower and upper bounds.
19517  do {
19518    if (!is.get(c)) {
19519      goto fail;
19520    }
19521  } while (is_space(c));
19522  if (c != ',') {
19523    goto unexpected_char;
19524  }
19525
19526  // Get the upper bound.
19527  upper_r = input(upper_bound, is, ROUND_UP);
19528  if (upper_r == V_CVT_STR_UNK || upper_r == V_NAN) {
19529    goto fail;
19530  }
19531  upper_r = result_relation_class(upper_r);
19532
19533  // Get the closing parenthesis.
19534  do {
19535    if (!is.get(c)) {
19536      goto fail;
19537    }
19538  } while (is_space(c));
19539  if (c == ')') {
19540    upper_open = true;
19541  }
19542  else if (c != ']') {
19543  unexpected_char:
19544    is.unget();
19545  fail:
19546    is.setstate(std::ios::failbit);
19547    return is;
19548  }
19549
19550  // Build interval.
19551  switch (lower_r) {
19552  case V_EQ: // Fall through.
19553  case V_GE:
19554    break;
19555  case V_GT:
19556    lower_open = true;
19557    break;
19558  case V_GT_MINUS_INFINITY:
19559    lower_open = true;
19560    // Fall through.
19561  case V_EQ_MINUS_INFINITY:
19562    lower_boundary_infinity = true;
19563    break;
19564  case V_EQ_PLUS_INFINITY: // Fall through.
19565  case V_LT_PLUS_INFINITY:
19566    if (upper_r == V_EQ_PLUS_INFINITY || upper_r == V_LT_PLUS_INFINITY) {
19567      x.assign(UNIVERSE);
19568    }
19569    else {
19570      x.assign(EMPTY);
19571    }
19572    return is;
19573  default:
19574    PPL_UNREACHABLE;
19575    break;
19576  }
19577  switch (upper_r) {
19578  case V_EQ: // Fall through.
19579  case V_LE:
19580    break;
19581  case V_LT:
19582    upper_open = true;
19583    break;
19584  case V_GT_MINUS_INFINITY:
19585    upper_open = true;
19586    // Fall through.
19587  case V_EQ_MINUS_INFINITY:
19588    if (lower_r == V_EQ_MINUS_INFINITY || lower_r == V_GT_MINUS_INFINITY) {
19589      x.assign(UNIVERSE);
19590    }
19591    else {
19592      x.assign(EMPTY);
19593    }
19594    return is;
19595  case V_EQ_PLUS_INFINITY: // Fall through.
19596  case V_LT_PLUS_INFINITY:
19597    upper_boundary_infinity = true;
19598    break;
19599  default:
19600    PPL_UNREACHABLE;
19601    break;
19602  }
19603
19604  if (!lower_boundary_infinity
19605      && !upper_boundary_infinity
19606      && (lower_bound > upper_bound
19607          || (lower_open && lower_bound == upper_bound))) {
19608    x.assign(EMPTY);
19609  }
19610  else {
19611    if (lower_boundary_infinity) {
19612      set_minus_infinity(LOWER, x.lower(), x.info(), lower_open);
19613    }
19614    else {
19615      assign(LOWER, x.lower(), x.info(),
19616             LOWER, lower_bound, SCALAR_INFO, lower_open);
19617    }
19618    if (upper_boundary_infinity) {
19619      set_plus_infinity(UPPER, x.upper(), x.info(), upper_open);
19620    }
19621    else {
19622      assign(UPPER, x.upper(), x.info(),
19623             UPPER, upper_bound, SCALAR_INFO, upper_open);
19624    }
19625  }
19626  return is;
19627}
19628
19629template <typename Boundary, typename Info>
19630template <typename From>
19631typename Enable_If<Is_Interval<From>::value, bool>::type
19632Interval<Boundary, Info>::simplify_using_context_assign(const From& y) {
19633  // FIXME: the following code wrongly assumes that intervals are closed
19634  if (lt(UPPER, upper(), info(), LOWER, f_lower(y), f_info(y))) {
19635    lower_extend();
19636    return false;
19637  }
19638  if (gt(LOWER, lower(), info(), UPPER, f_upper(y), f_info(y))) {
19639    upper_extend();
19640    return false;
19641  }
19642  // Weakening the upper bound.
19643  if (!upper_is_boundary_infinity() && !y.upper_is_boundary_infinity()
19644      && y.upper() <= upper()) {
19645    upper_extend();
19646  }
19647  // Weakening the lower bound.
19648  if (!lower_is_boundary_infinity() && !y.lower_is_boundary_infinity()
19649      && y.lower() >= lower()) {
19650    lower_extend();
19651  }
19652  return true;
19653}
19654
19655template <typename Boundary, typename Info>
19656template <typename From>
19657typename Enable_If<Is_Interval<From>::value, void>::type
19658Interval<Boundary, Info>::empty_intersection_assign(const From&) {
19659  // FIXME: write me.
19660  assign(EMPTY);
19661}
19662
19663} // namespace Parma_Polyhedra_Library
19664
19665/* Automatically generated from PPL source file ../src/Interval_defs.hh line 780. */
19666
19667/* Automatically generated from PPL source file ../src/Integer_Interval.hh line 28. */
19668#include <gmpxx.h>
19669
19670namespace Parma_Polyhedra_Library {
19671
19672struct Integer_Interval_Info_Policy {
19673  const_bool_nodef(store_special, true);
19674  const_bool_nodef(store_open, false);
19675  const_bool_nodef(cache_empty, true);
19676  const_bool_nodef(cache_singleton, true);
19677  const_int_nodef(next_bit, 0);
19678  const_bool_nodef(may_be_empty, true);
19679  const_bool_nodef(may_contain_infinity, false);
19680  const_bool_nodef(check_empty_result, false);
19681  const_bool_nodef(check_inexact, false);
19682};
19683
19684typedef Interval_Info_Bitset<unsigned int, Integer_Interval_Info_Policy> Integer_Interval_Info;
19685
19686#ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
19687//! An interval with integral, necessarily closed boundaries.
19688#endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
19689typedef Interval<mpz_class, Integer_Interval_Info> Integer_Interval;
19690
19691} // namespace Parma_Polyhedra_Library
19692
19693/* Automatically generated from PPL source file ../src/initializer.hh line 1. */
19694/* Nifty counter object for the initialization of the library.
19695*/
19696
19697
19698/* Automatically generated from PPL source file ../src/Init_defs.hh line 1. */
19699/* Init class declaration.
19700*/
19701
19702
19703/* Automatically generated from PPL source file ../src/Init_defs.hh line 29. */
19704
19705namespace Parma_Polyhedra_Library {
19706
19707/*! \brief
19708  Sets the FPU rounding mode so that the PPL abstractions based on
19709  floating point numbers work correctly.
19710
19711  This is performed automatically at initialization-time.  Calling
19712  this function is needed only if restore_pre_PPL_rounding() has been
19713  previously called.
19714*/
19715void set_rounding_for_PPL();
19716
19717/*! \brief
19718  Sets the FPU rounding mode as it was before initialization of the PPL.
19719
19720  This is important if the application uses floating-point computations
19721  outside the PPL.  It is crucial when the application uses functions
19722  from a mathematical library that are not guaranteed to work correctly
19723  under all rounding modes.
19724
19725  After calling this function it is absolutely necessary to call
19726  set_rounding_for_PPL() before using any PPL abstractions based on
19727  floating point numbers.
19728  This is performed automatically at finalization-time.
19729*/
19730void restore_pre_PPL_rounding();
19731
19732} // namespace Parma_Polyhedra_Library
19733
19734#ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
19735//! Class for initialization and finalization.
19736/*! \ingroup PPL_CXX_interface
19737  <EM>Nifty Counter</EM> initialization class,
19738  ensuring that the library is initialized only once
19739  and before its first use.
19740  A count of the number of translation units using the library
19741  is maintained. A static object of Init type will be declared
19742  by each translation unit using the library.  As a result,
19743  only one of them will initialize and properly finalize
19744  the library.
19745*/
19746#endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
19747class Parma_Polyhedra_Library::Init {
19748public:
19749  //! Initializes the PPL.
19750  Init();
19751
19752  //! Finalizes the PPL.
19753  ~Init();
19754
19755private:
19756  /*! \brief
19757    Default precision parameter used for irrational calculations.
19758
19759    The default is chosen to have a precision greater than most
19760    precise IEC 559 floating point (112 bits of mantissa).
19761  */
19762  static const unsigned DEFAULT_IRRATIONAL_PRECISION = 128U;
19763
19764  //! Count the number of objects created.
19765  static unsigned int count;
19766  static fpu_rounding_direction_type old_rounding_direction;
19767
19768  friend void set_rounding_for_PPL();
19769  friend void restore_pre_PPL_rounding();
19770};
19771
19772/* Automatically generated from PPL source file ../src/Init_inlines.hh line 1. */
19773/* Init class implementation: inline functions.
19774*/
19775
19776
19777/* Automatically generated from PPL source file ../src/Init_inlines.hh line 29. */
19778
19779namespace Parma_Polyhedra_Library {
19780
19781inline void
19782set_rounding_for_PPL() {
19783#if PPL_CAN_CONTROL_FPU
19784    fpu_set_rounding_direction(round_fpu_dir(ROUND_DIRECT));
19785#endif
19786}
19787
19788inline void
19789restore_pre_PPL_rounding() {
19790#if PPL_CAN_CONTROL_FPU
19791  fpu_set_rounding_direction(Init::old_rounding_direction);
19792#endif
19793}
19794
19795} // namespace Parma_Polyhedra_Library
19796
19797/* Automatically generated from PPL source file ../src/Init_defs.hh line 98. */
19798
19799
19800/* Automatically generated from PPL source file ../src/initializer.hh line 28. */
19801
19802#ifndef PPL_NO_AUTOMATIC_INITIALIZATION
19803
19804static Parma_Polyhedra_Library::Init Parma_Polyhedra_Library_initializer;
19805
19806#else
19807
19808namespace Parma_Polyhedra_Library {
19809
19810namespace Implementation {
19811
19812void initialize_aux();
19813void finalize_aux();
19814
19815} // namespace Implementation
19816
19817} // namespace Parma_Polyhedra_Library
19818
19819#endif
19820
19821namespace Parma_Polyhedra_Library {
19822
19823//! Initializes the library.
19824inline void
19825initialize() {
19826#ifdef PPL_NO_AUTOMATIC_INITIALIZATION
19827  Implementation::initialize_aux();
19828#endif
19829}
19830
19831//! Finalizes the library.
19832inline void
19833finalize() {
19834#ifdef PPL_NO_AUTOMATIC_INITIALIZATION
19835  Implementation::finalize_aux();
19836#endif
19837}
19838
19839} //namespace Parma_Polyhedra_Library
19840
19841/* Automatically generated from PPL source file ../src/Linear_Expression_Impl_defs.hh line 1. */
19842/* Linear_Expression_Impl class declaration.
19843*/
19844
19845
19846/* Automatically generated from PPL source file ../src/Linear_Expression_Impl_types.hh line 1. */
19847
19848
19849namespace Parma_Polyhedra_Library {
19850
19851template <typename Row>
19852class Linear_Expression_Impl;
19853
19854} // namespace Parma_Polyhedra_Library
19855
19856/* Automatically generated from PPL source file ../src/Linear_Expression_Interface_defs.hh line 1. */
19857/* Linear_Expression_Interface class declaration.
19858*/
19859
19860
19861/* Automatically generated from PPL source file ../src/Linear_Expression_Interface_types.hh line 1. */
19862
19863
19864namespace Parma_Polyhedra_Library {
19865
19866class Linear_Expression_Interface;
19867
19868} // namespace Parma_Polyhedra_Library
19869
19870/* Automatically generated from PPL source file ../src/Coefficient_defs.hh line 1. */
19871/* Coefficient class declaration.
19872*/
19873
19874
19875/* Automatically generated from PPL source file ../src/Coefficient_types.hh line 1. */
19876
19877
19878/* Automatically generated from PPL source file ../src/Coefficient_types.hh line 17. */
19879
19880#ifdef PPL_GMP_INTEGERS
19881/* Automatically generated from PPL source file ../src/GMP_Integer_types.hh line 1. */
19882
19883
19884/* Automatically generated from PPL source file ../src/GMP_Integer_types.hh line 18. */
19885#include <gmpxx.h>
19886
19887namespace Parma_Polyhedra_Library {
19888
19889/*! \class Parma_Polyhedra_Library::GMP_Integer
19890  \brief
19891  Unbounded integers as provided by the GMP library.
19892
19893  \ingroup PPL_CXX_interface
19894  GMP_Integer is an alias for the <CODE>mpz_class</CODE> type
19895  defined in the C++ interface of the GMP library.
19896  For more information, see <CODE>http://gmplib.org/</CODE>
19897*/
19898typedef mpz_class GMP_Integer;
19899
19900#ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
19901//! Coefficient traits specialization for unbounded integers.
19902/*! \ingroup PPL_CXX_interface */
19903#endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
19904template <>
19905struct Coefficient_traits_template<GMP_Integer> {
19906  //! The type used for references to const unbounded integers.
19907  typedef const GMP_Integer& const_reference;
19908};
19909
19910} // namespace Parma_Polyhedra_Library
19911
19912/* Automatically generated from PPL source file ../src/Coefficient_types.hh line 20. */
19913#endif
19914
19915#if defined(PPL_CHECKED_INTEGERS) || defined(PPL_NATIVE_INTEGERS)
19916
19917namespace Parma_Polyhedra_Library {
19918
19919//! A policy for checked bounded integer coefficients.
19920/*! \ingroup PPL_CXX_interface */
19921struct Bounded_Integer_Coefficient_Policy {
19922  //! Check for overflowed result.
19923  const_bool_nodef(check_overflow, true);
19924
19925  //! Do not check for attempts to add infinities with different sign.
19926  const_bool_nodef(check_inf_add_inf, false);
19927
19928  //! Do not check for attempts to subtract infinities with same sign.
19929  const_bool_nodef(check_inf_sub_inf, false);
19930
19931  //! Do not check for attempts to multiply infinities by zero.
19932  const_bool_nodef(check_inf_mul_zero, false);
19933
19934  //! Do not check for attempts to divide by zero.
19935  const_bool_nodef(check_div_zero, false);
19936
19937  //! Do not check for attempts to divide infinities.
19938  const_bool_nodef(check_inf_div_inf, false);
19939
19940  //! Do not check for attempts to compute remainder of infinities.
19941  const_bool_nodef(check_inf_mod, false);
19942
19943  //! Do not checks for attempts to take the square root of a negative number.
19944  const_bool_nodef(check_sqrt_neg, false);
19945
19946  //! Do not handle not-a-number special value.
19947  const_bool_nodef(has_nan, false);
19948
19949  //! Do not handle infinity special values.
19950  const_bool_nodef(has_infinity, false);
19951
19952  /*! \brief
19953    The checked number can always be safely converted to the
19954    underlying type \p T and vice-versa.
19955  */
19956  const_bool_nodef(convertible, true);
19957
19958  //! Do not honor requests to check for FPU inexact results.
19959  const_bool_nodef(fpu_check_inexact, false);
19960
19961  //! Do not make extra checks to detect FPU NaN results.
19962  const_bool_nodef(fpu_check_nan_result, true);
19963
19964  /*! \brief
19965    For constructors, by default use the same rounding used by
19966    underlying type.
19967  */
19968  static const Rounding_Dir ROUND_DEFAULT_CONSTRUCTOR = ROUND_NATIVE;
19969
19970  /*! \brief
19971    For overloaded operators (operator+(), operator-(), ...), by
19972    default use the same rounding used by the underlying type.
19973  */
19974  static const Rounding_Dir ROUND_DEFAULT_OPERATOR = ROUND_NATIVE;
19975
19976  /*! \brief
19977    For input functions, by default use the same rounding used by
19978    the underlying type.
19979  */
19980  static const Rounding_Dir ROUND_DEFAULT_INPUT = ROUND_NATIVE;
19981
19982  /*! \brief
19983    For output functions, by default use the same rounding used by
19984    the underlying type.
19985  */
19986  static const Rounding_Dir ROUND_DEFAULT_OUTPUT = ROUND_NATIVE;
19987
19988  /*! \brief
19989    For all other functions, by default use the same rounding used by
19990    the underlying type.
19991  */
19992  static const Rounding_Dir ROUND_DEFAULT_FUNCTION = ROUND_NATIVE;
19993
19994  /*! \brief
19995    Handles \p r: called by all constructors, operators and functions that
19996    do not return a Result value.
19997  */
19998  static void handle_result(Result r);
19999};
20000
20001#ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
20002//! Coefficient traits specialization for 8 bits checked integers.
20003/*! \ingroup PPL_CXX_interface */
20004#endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
20005template <typename Policy>
20006struct Coefficient_traits_template<Checked_Number<int8_t, Policy> > {
20007  //! The type used for references to const 8 bit checked integers.
20008  typedef Checked_Number<int8_t, Policy> const_reference;
20009};
20010
20011#ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
20012//! Coefficient traits specialization for 16 bits checked integers.
20013/*! \ingroup PPL_CXX_interface */
20014#endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
20015template <typename Policy>
20016struct Coefficient_traits_template<Checked_Number<int16_t, Policy> > {
20017  //! The type used for references to const 16 bit checked integers.
20018  typedef Checked_Number<int16_t, Policy> const_reference;
20019};
20020
20021#ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
20022//! Coefficient traits specialization for 32 bits checked integers.
20023/*! \ingroup PPL_CXX_interface */
20024#endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
20025template <typename Policy>
20026struct Coefficient_traits_template<Checked_Number<int32_t, Policy> > {
20027  //! The type used for references to const 32 bit checked integers.
20028  typedef Checked_Number<int32_t, Policy> const_reference;
20029};
20030
20031#ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
20032//! Coefficient traits specialization for 64 bits checked integers.
20033/*! \ingroup PPL_CXX_interface */
20034#endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
20035template <typename Policy>
20036struct Coefficient_traits_template<Checked_Number<int64_t, Policy> > {
20037  //! The type used for references to const 64 bit checked integers.
20038  typedef const Checked_Number<int64_t, Policy>& const_reference;
20039};
20040
20041} // namespace Parma_Polyhedra_Library
20042
20043#endif // defined(PPL_CHECKED_INTEGERS) || defined(PPL_NATIVE_INTEGERS)
20044
20045namespace Parma_Polyhedra_Library {
20046
20047//! An alias for easily naming the type of PPL coefficients.
20048/*! \ingroup PPL_CXX_interface
20049  Objects of type Coefficient are used to implement the integral valued
20050  coefficients occurring in linear expressions, constraints, generators,
20051  intervals, bounding boxes and so on.  Depending on the chosen
20052  configuration options (see file <CODE>README.configure</CODE>),
20053  a Coefficient may actually be:
20054    - The GMP_Integer type, which in turn is an alias for the
20055      <CODE>mpz_class</CODE> type implemented by the C++ interface
20056      of the GMP library (this is the default configuration).
20057    - An instance of the Checked_Number class template: with the policy
20058      Bounded_Integer_Coefficient_Policy, this implements overflow
20059      detection on top of a native integral type (available template
20060      instances include checked integers having 8, 16, 32 or 64 bits);
20061      with the Checked_Number_Transparent_Policy, this is a wrapper
20062      for native integral types with no overflow detection
20063      (available template instances are as above).
20064*/
20065typedef PPL_COEFFICIENT_TYPE Coefficient;
20066
20067#ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
20068//! An alias for easily naming the coefficient traits.
20069/*! \ingroup PPL_CXX_interface */
20070#endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
20071typedef Coefficient_traits_template<Coefficient> Coefficient_traits;
20072
20073} // namespace Parma_Polyhedra_Library
20074
20075/* Automatically generated from PPL source file ../src/Coefficient_defs.hh line 28. */
20076
20077#if defined(PPL_CHECKED_INTEGERS) || defined(PPL_NATIVE_INTEGERS)
20078/* Automatically generated from PPL source file ../src/Coefficient_defs.hh line 32. */
20079#endif
20080
20081#ifdef PPL_GMP_INTEGERS
20082/* Automatically generated from PPL source file ../src/GMP_Integer_defs.hh line 1. */
20083/* GMP_Integer class declaration.
20084*/
20085
20086
20087/* Automatically generated from PPL source file ../src/GMP_Integer_defs.hh line 29. */
20088#include <cstddef>
20089
20090namespace Parma_Polyhedra_Library {
20091
20092//! \name Accessor Functions
20093//@{
20094
20095//! Returns a const reference to the underlying integer value.
20096/*! \relates GMP_Integer */
20097const mpz_class& raw_value(const GMP_Integer& x);
20098
20099//! Returns a reference to the underlying integer value.
20100/*! \relates GMP_Integer */
20101mpz_class& raw_value(GMP_Integer& x);
20102
20103//@} // Accessor Functions
20104
20105//! \name Arithmetic Operators
20106//@{
20107
20108//! Assigns to \p x its negation.
20109/*! \relates GMP_Integer */
20110void neg_assign(GMP_Integer& x);
20111
20112//! Assigns to \p x the negation of \p y.
20113/*! \relates GMP_Integer */
20114void neg_assign(GMP_Integer& x, const GMP_Integer& y);
20115
20116//! Assigns to \p x its absolute value.
20117/*! \relates GMP_Integer */
20118void abs_assign(GMP_Integer& x);
20119
20120//! Assigns to \p x the absolute value of \p y.
20121/*! \relates GMP_Integer */
20122void abs_assign(GMP_Integer& x, const GMP_Integer& y);
20123
20124//! Assigns to \p x the remainder of the division of \p y by \p z.
20125/*! \relates GMP_Integer */
20126void rem_assign(GMP_Integer& x,
20127                const GMP_Integer& y, const GMP_Integer& z);
20128
20129//! Assigns to \p x the greatest common divisor of \p y and \p z.
20130/*! \relates GMP_Integer */
20131void gcd_assign(GMP_Integer& x,
20132                const GMP_Integer& y, const GMP_Integer& z);
20133
20134//! Extended GCD.
20135/*! \relates GMP_Integer
20136  Assigns to \p x the greatest common divisor of \p y and \p z, and to
20137  \p s and \p t the values such that \p y * \p s + \p z * \p t = \p x.
20138*/
20139void gcdext_assign(GMP_Integer& x, GMP_Integer& s, GMP_Integer& t,
20140                   const GMP_Integer& y, const GMP_Integer& z);
20141
20142//! Assigns to \p x the least common multiple of \p y and \p z.
20143/*! \relates GMP_Integer */
20144void lcm_assign(GMP_Integer& x,
20145                const GMP_Integer& y, const GMP_Integer& z);
20146
20147//! Assigns to \p x the value <CODE>x + y * z</CODE>.
20148/*! \relates GMP_Integer */
20149void add_mul_assign(GMP_Integer& x,
20150                    const GMP_Integer& y, const GMP_Integer& z);
20151
20152//! Assigns to \p x the value <CODE>x - y * z</CODE>.
20153/*! \relates GMP_Integer */
20154void sub_mul_assign(GMP_Integer& x,
20155                    const GMP_Integer& y, const GMP_Integer& z);
20156
20157//! Assigns to \p x the value \f$ y \cdot 2^\mathtt{exp} \f$.
20158/*! \relates GMP_Integer */
20159void mul_2exp_assign(GMP_Integer& x, const GMP_Integer& y, unsigned int exp);
20160
20161//! Assigns to \p x the value \f$ y / 2^\mathtt{exp} \f$.
20162/*! \relates GMP_Integer */
20163void div_2exp_assign(GMP_Integer& x, const GMP_Integer& y, unsigned int exp);
20164
20165/*! \brief
20166  If \p z divides \p y, assigns to \p x the quotient of the integer
20167  division of \p y and \p z.
20168
20169  \relates GMP_Integer
20170  The behavior is undefined if \p z does not divide \p y.
20171*/
20172void exact_div_assign(GMP_Integer& x,
20173                      const GMP_Integer& y, const GMP_Integer& z);
20174
20175//! Assigns to \p x the integer square root of \p y.
20176/*! \relates GMP_Integer */
20177void sqrt_assign(GMP_Integer& x, const GMP_Integer& y);
20178
20179/*! \brief
20180  Returns a negative, zero or positive value depending on whether
20181  \p x is lower than, equal to or greater than \p y, respectively.
20182
20183  \relates GMP_Integer
20184*/
20185int cmp(const GMP_Integer& x, const GMP_Integer& y);
20186
20187//@} // Arithmetic Operators
20188
20189} // namespace Parma_Polyhedra_Library
20190
20191/* Automatically generated from PPL source file ../src/GMP_Integer_inlines.hh line 1. */
20192/* GMP_Integer class implementation: inline functions.
20193*/
20194
20195
20196/* Automatically generated from PPL source file ../src/GMP_Integer_inlines.hh line 28. */
20197
20198namespace Parma_Polyhedra_Library {
20199
20200inline void
20201neg_assign(GMP_Integer& x) {
20202  mpz_neg(x.get_mpz_t(), x.get_mpz_t());
20203}
20204
20205inline void
20206neg_assign(GMP_Integer& x, const GMP_Integer& y) {
20207  mpz_neg(x.get_mpz_t(), y.get_mpz_t());
20208}
20209
20210inline void
20211abs_assign(GMP_Integer& x) {
20212  mpz_abs(x.get_mpz_t(), x.get_mpz_t());
20213}
20214
20215inline void
20216abs_assign(GMP_Integer& x, const GMP_Integer& y) {
20217  mpz_abs(x.get_mpz_t(), y.get_mpz_t());
20218}
20219
20220inline void
20221gcd_assign(GMP_Integer& x, const GMP_Integer& y, const GMP_Integer& z) {
20222  mpz_gcd(x.get_mpz_t(), y.get_mpz_t(), z.get_mpz_t());
20223}
20224
20225inline void
20226rem_assign(GMP_Integer& x, const GMP_Integer& y, const GMP_Integer& z) {
20227  mpz_tdiv_r(x.get_mpz_t(), y.get_mpz_t(), z.get_mpz_t());
20228}
20229
20230inline void
20231gcdext_assign(GMP_Integer& x, GMP_Integer& s, GMP_Integer& t,
20232              const GMP_Integer& y, const GMP_Integer& z) {
20233  mpz_gcdext(x.get_mpz_t(),
20234             s.get_mpz_t(), t.get_mpz_t(),
20235             y.get_mpz_t(), z.get_mpz_t());
20236}
20237
20238inline void
20239lcm_assign(GMP_Integer& x, const GMP_Integer& y, const GMP_Integer& z) {
20240  mpz_lcm(x.get_mpz_t(), y.get_mpz_t(), z.get_mpz_t());
20241}
20242
20243inline void
20244add_mul_assign(GMP_Integer& x, const GMP_Integer& y, const GMP_Integer& z) {
20245  mpz_addmul(x.get_mpz_t(), y.get_mpz_t(), z.get_mpz_t());
20246}
20247
20248inline void
20249sub_mul_assign(GMP_Integer& x, const GMP_Integer& y, const GMP_Integer& z) {
20250  mpz_submul(x.get_mpz_t(), y.get_mpz_t(), z.get_mpz_t());
20251}
20252
20253inline void
20254mul_2exp_assign(GMP_Integer& x, const GMP_Integer& y, unsigned int exp) {
20255  mpz_mul_2exp(x.get_mpz_t(), y.get_mpz_t(), exp);
20256}
20257
20258inline void
20259div_2exp_assign(GMP_Integer& x, const GMP_Integer& y, unsigned int exp) {
20260  mpz_tdiv_q_2exp(x.get_mpz_t(), y.get_mpz_t(), exp);
20261}
20262
20263inline void
20264exact_div_assign(GMP_Integer& x, const GMP_Integer& y, const GMP_Integer& z) {
20265  PPL_ASSERT(y % z == 0);
20266  mpz_divexact(x.get_mpz_t(), y.get_mpz_t(), z.get_mpz_t());
20267}
20268
20269inline void
20270sqrt_assign(GMP_Integer& x, const GMP_Integer& y) {
20271  mpz_sqrt(x.get_mpz_t(), y.get_mpz_t());
20272}
20273
20274inline int
20275cmp(const GMP_Integer& x, const GMP_Integer& y) {
20276  return mpz_cmp(x.get_mpz_t(), y.get_mpz_t());
20277}
20278
20279inline const mpz_class&
20280raw_value(const GMP_Integer& x) {
20281  return x;
20282}
20283
20284inline mpz_class&
20285raw_value(GMP_Integer& x) {
20286  return x;
20287}
20288
20289} // namespace Parma_Polyhedra_Library
20290
20291/* Automatically generated from PPL source file ../src/GMP_Integer_defs.hh line 133. */
20292
20293/* Automatically generated from PPL source file ../src/Coefficient_defs.hh line 36. */
20294#endif
20295
20296#include <iosfwd>
20297
20298namespace Parma_Polyhedra_Library {
20299
20300#ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
20301//! Initializes the Coefficient constants.
20302#endif
20303void Coefficient_constants_initialize();
20304
20305#ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
20306//! Finalizes the Coefficient constants.
20307#endif
20308void Coefficient_constants_finalize();
20309
20310//! Returns a const reference to a Coefficient with value 0.
20311Coefficient_traits::const_reference Coefficient_zero();
20312
20313//! Returns a const reference to a Coefficient with value 1.
20314Coefficient_traits::const_reference Coefficient_one();
20315
20316} // namespace Parma_Polyhedra_Library
20317
20318/* Automatically generated from PPL source file ../src/Coefficient_inlines.hh line 1. */
20319/* Coefficient class implementation: inline functions.
20320*/
20321
20322
20323namespace Parma_Polyhedra_Library {
20324
20325#ifdef PPL_CHECKED_INTEGERS
20326inline void
20327Bounded_Integer_Coefficient_Policy::handle_result(Result r) {
20328  // Note that the input functions can return VC_NAN.
20329  if (result_overflow(r) || result_class(r) == VC_NAN) {
20330    throw_result_exception(r);
20331  }
20332}
20333#endif // PPL_CHECKED_INTEGERS
20334
20335
20336#if defined(PPL_CHECKED_INTEGERS) || defined(PPL_NATIVE_INTEGERS)
20337inline Coefficient_traits::const_reference
20338Coefficient_zero() {
20339  // FIXME: is there a way to avoid this static variable?
20340  static Coefficient zero(0);
20341  return zero;
20342}
20343
20344inline Coefficient_traits::const_reference
20345Coefficient_one() {
20346  // FIXME: is there a way to avoid this static variable?
20347  static Coefficient one(1);
20348  return one;
20349}
20350#endif // defined(PPL_CHECKED_INTEGERS) || defined(PPL_NATIVE_INTEGERS)
20351
20352#ifdef PPL_GMP_INTEGERS
20353inline Coefficient_traits::const_reference
20354Coefficient_zero() {
20355  extern const Coefficient* Coefficient_zero_p;
20356  return *Coefficient_zero_p;
20357}
20358
20359inline Coefficient_traits::const_reference
20360Coefficient_one() {
20361  extern const Coefficient* Coefficient_one_p;
20362  PPL_ASSERT(*Coefficient_one_p != 0);
20363  return *Coefficient_one_p;
20364}
20365#endif // PPL_GMP_INTEGERS
20366
20367} // namespace Parma_Polyhedra_Library
20368
20369/* Automatically generated from PPL source file ../src/Coefficient_defs.hh line 61. */
20370
20371/* Automatically generated from PPL source file ../src/Variables_Set_types.hh line 1. */
20372
20373
20374namespace Parma_Polyhedra_Library {
20375
20376class Variables_Set;
20377
20378} // namespace Parma_Polyhedra_Library
20379
20380/* Automatically generated from PPL source file ../src/Dense_Row_types.hh line 1. */
20381
20382
20383namespace Parma_Polyhedra_Library {
20384
20385class Dense_Row;
20386
20387} // namespace Parma_Polyhedra_Library
20388
20389/* Automatically generated from PPL source file ../src/Sparse_Row_types.hh line 1. */
20390
20391
20392namespace Parma_Polyhedra_Library {
20393
20394class Sparse_Row;
20395
20396} // namespace Parma_Polyhedra_Library
20397
20398/* Automatically generated from PPL source file ../src/Linear_Expression_Interface_defs.hh line 33. */
20399#include <vector>
20400#include <set>
20401#include <cstddef>
20402
20403#ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
20404//! A linear expression.
20405/*! \ingroup PPL_CXX_interface
20406  An object of a class implementing Linear_Expression_Interface
20407  represents a linear expression
20408  \f[
20409    \sum_{i=0}^{n-1} a_i x_i + b
20410  \f]
20411  where \f$n\f$ is the dimension of the vector space,
20412  each \f$a_i\f$ is the integer coefficient
20413  of the \f$i\f$-th variable \f$x_i\f$
20414  and \f$b\f$ is the integer for the inhomogeneous term.
20415*/
20416#endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
20417class Parma_Polyhedra_Library::Linear_Expression_Interface {
20418public:
20419  virtual ~Linear_Expression_Interface();
20420
20421  virtual bool OK() const = 0;
20422
20423  //! Returns the current representation of this linear expression.
20424  virtual Representation representation() const = 0;
20425
20426  //! An interface for const iterators on the expression (homogeneous)
20427  //! coefficients that are nonzero.
20428  /*!
20429    These iterators are invalidated by operations that modify the expression.
20430  */
20431  class const_iterator_interface {
20432  public:
20433    typedef std::bidirectional_iterator_tag iterator_category;
20434    typedef const Coefficient value_type;
20435    typedef std::ptrdiff_t difference_type;
20436    typedef value_type* pointer;
20437    typedef Coefficient_traits::const_reference reference;
20438
20439    //! Returns a copy of *this.
20440    //! This returns a pointer to dynamic-allocated memory. The caller has the
20441    //! duty to free the memory when it's not needed anymore.
20442    virtual const_iterator_interface* clone() const = 0;
20443
20444    virtual ~const_iterator_interface();
20445
20446    //! Navigates to the next nonzero coefficient.
20447    //! Note that this method does *not* return a reference, to increase
20448    //! efficiency since it's virtual.
20449    virtual void operator++() = 0;
20450
20451    //! Navigates to the previous nonzero coefficient.
20452    //! Note that this method does *not* return a reference, to increase
20453    //! efficiency since it's virtual.
20454    virtual void operator--() = 0;
20455
20456    //! Returns the current element.
20457    virtual reference operator*() const = 0;
20458
20459    //! Returns the variable of the coefficient pointed to by \c *this.
20460    /*!
20461      \returns the variable of the coefficient pointed to by \c *this.
20462    */
20463    virtual Variable variable() const = 0;
20464
20465    //! Compares \p *this with x .
20466    /*!
20467      \param x
20468      The %iterator that will be compared with *this.
20469    */
20470    virtual bool operator==(const const_iterator_interface& x) const = 0;
20471  };
20472
20473  //! This returns a pointer to dynamic-allocated memory. The caller has the
20474  //! duty to free the memory when it's not needed anymore.
20475  virtual const_iterator_interface* begin() const = 0;
20476
20477  //! This returns a pointer to dynamic-allocated memory. The caller has the
20478  //! duty to free the memory when it's not needed anymore.
20479  virtual const_iterator_interface* end() const = 0;
20480
20481  //! This returns a pointer to dynamic-allocated memory. The caller has the
20482  //! duty to free the memory when it's not needed anymore.
20483  //! Returns (a pointer to) an iterator that points to the first nonzero
20484  //! coefficient of a variable greater than or equal to v, or at end if no
20485  //! such coefficient exists.
20486  virtual const_iterator_interface* lower_bound(Variable v) const = 0;
20487
20488  //! Returns the dimension of the vector space enclosing \p *this.
20489  virtual dimension_type space_dimension() const = 0;
20490
20491  //! Sets the dimension of the vector space enclosing \p *this to \p n .
20492  virtual void set_space_dimension(dimension_type n) = 0;
20493
20494  //! Returns the coefficient of \p v in \p *this.
20495  virtual Coefficient_traits::const_reference
20496  coefficient(Variable v) const = 0;
20497
20498  //! Sets the coefficient of \p v in \p *this to \p n.
20499  virtual void
20500  set_coefficient(Variable v, Coefficient_traits::const_reference n) = 0;
20501
20502  //! Returns the inhomogeneous term of \p *this.
20503  virtual Coefficient_traits::const_reference inhomogeneous_term() const = 0;
20504
20505  //! Sets the inhomogeneous term of \p *this to \p n.
20506  virtual void
20507  set_inhomogeneous_term(Coefficient_traits::const_reference n) = 0;
20508
20509  //! Linearly combines \p *this with \p y so that the coefficient of \p v
20510  //! is 0.
20511  /*!
20512    \param y
20513    The expression that will be combined with \p *this object;
20514
20515    \param v
20516    The variable whose coefficient has to become \f$0\f$.
20517
20518    Computes a linear combination of \p *this and \p y having
20519    the coefficient of variable \p v equal to \f$0\f$. Then it assigns
20520    the resulting expression to \p *this.
20521
20522    \p *this and \p y must have the same space dimension.
20523  */
20524  virtual void
20525  linear_combine(const Linear_Expression_Interface& y, Variable v) = 0;
20526
20527  //! Equivalent to <CODE>*this = *this * c1 + y * c2</CODE>, but assumes that
20528  //! \p *this and \p y have the same space dimension.
20529  virtual void linear_combine(const Linear_Expression_Interface& y,
20530                              Coefficient_traits::const_reference c1,
20531                              Coefficient_traits::const_reference c2) = 0;
20532
20533  //! Equivalent to <CODE>*this = *this * c1 + y * c2</CODE>.
20534  //! c1 and c2 may be 0.
20535  virtual void linear_combine_lax(const Linear_Expression_Interface& y,
20536                                  Coefficient_traits::const_reference c1,
20537                                  Coefficient_traits::const_reference c2) = 0;
20538
20539  //! Swaps the coefficients of the variables \p v1 and \p v2 .
20540  virtual void swap_space_dimensions(Variable v1, Variable v2) = 0;
20541
20542  //! Removes all the specified dimensions from the expression.
20543  /*!
20544    The space dimension of the variable with the highest space
20545    dimension in \p vars must be at most the space dimension
20546    of \p this.
20547  */
20548  virtual void remove_space_dimensions(const Variables_Set& vars) = 0;
20549
20550  //! Shift by \p n positions the coefficients of variables, starting from
20551  //! the coefficient of \p v. This increases the space dimension by \p n.
20552  virtual void shift_space_dimensions(Variable v, dimension_type n) = 0;
20553
20554  //! Permutes the space dimensions of the expression.
20555  /*!
20556    \param cycle
20557    A vector representing a cycle of the permutation according to which the
20558    space dimensions must be rearranged.
20559
20560    The \p cycle vector represents a cycle of a permutation of space
20561    dimensions.
20562    For example, the permutation
20563    \f$ \{ x_1 \mapsto x_2, x_2 \mapsto x_3, x_3 \mapsto x_1 \}\f$ can be
20564    represented by the vector containing \f$ x_1, x_2, x_3 \f$.
20565  */
20566  virtual void
20567  permute_space_dimensions(const std::vector<Variable>& cycle) = 0;
20568
20569  //! Returns <CODE>true</CODE> if and only if \p *this is \f$0\f$.
20570  virtual bool is_zero() const = 0;
20571
20572  /*! \brief
20573    Returns <CODE>true</CODE> if and only if all the homogeneous
20574    terms of \p *this are \f$0\f$.
20575  */
20576  virtual bool all_homogeneous_terms_are_zero() const = 0;
20577
20578  /*! \brief
20579    Returns a lower bound to the total size in bytes of the memory
20580    occupied by \p *this.
20581  */
20582  virtual memory_size_type total_memory_in_bytes() const = 0;
20583
20584  //! Returns the size in bytes of the memory managed by \p *this.
20585  virtual memory_size_type external_memory_in_bytes() const = 0;
20586
20587  //! Writes to \p s an ASCII representation of \p *this.
20588  virtual void ascii_dump(std::ostream& s) const = 0;
20589
20590  /*! \brief
20591    Loads from \p s an ASCII representation (as produced by
20592    ascii_dump(std::ostream&) const) and sets \p *this accordingly.
20593    Returns <CODE>true</CODE> if successful, <CODE>false</CODE> otherwise.
20594  */
20595  virtual bool ascii_load(std::istream& s) = 0;
20596
20597  //! Returns \p true if *this is equal to \p x.
20598  //! Note that (*this == x) has a completely different meaning.
20599  virtual bool is_equal_to(const Linear_Expression_Interface& x) const = 0;
20600
20601  //! Normalizes the modulo of the coefficients and of the inhomogeneous term
20602  //! so that they are mutually prime.
20603  /*!
20604    Computes the Greatest Common Divisor (GCD) among the coefficients
20605    and the inhomogeneous term and normalizes them by the GCD itself.
20606  */
20607  virtual void normalize() = 0;
20608
20609  //! Ensures that the first nonzero homogeneous coefficient is positive,
20610  //! by negating the row if necessary.
20611  virtual void sign_normalize() = 0;
20612
20613  /*! \brief
20614    Negates the elements from index \p first (included)
20615    to index \p last (excluded).
20616  */
20617  virtual void negate(dimension_type first, dimension_type last) = 0;
20618
20619  virtual Linear_Expression_Interface&
20620  operator+=(Coefficient_traits::const_reference n) = 0;
20621  virtual Linear_Expression_Interface&
20622  operator-=(Coefficient_traits::const_reference n) = 0;
20623
20624  //! The basic comparison function.
20625  /*! \relates Linear_Expression_Interface
20626
20627    \returns -1 or -2 if x is less than y, 0 if they are equal and 1 or 2 is y
20628            is greater. The absolute value of the result is 1 if the difference
20629            is only in the inhomogeneous terms, 2 otherwise
20630
20631    The order is a lexicographic. It starts comparing the variables'
20632    coefficient, starting from Variable(0), and at the end it compares
20633    the inhomogeneous terms.
20634  */
20635  virtual int compare(const Linear_Expression_Interface& y) const = 0;
20636
20637  virtual Linear_Expression_Interface&
20638  operator+=(const Linear_Expression_Interface& e2) = 0;
20639  virtual Linear_Expression_Interface&
20640  operator+=(const Variable v) = 0;
20641  virtual Linear_Expression_Interface&
20642  operator-=(const Linear_Expression_Interface& e2) = 0;
20643  virtual Linear_Expression_Interface&
20644  operator-=(const Variable v) = 0;
20645  virtual Linear_Expression_Interface&
20646  operator*=(Coefficient_traits::const_reference n) = 0;
20647  virtual Linear_Expression_Interface&
20648  operator/=(Coefficient_traits::const_reference n) = 0;
20649
20650  virtual void negate() = 0;
20651
20652  virtual Linear_Expression_Interface&
20653  add_mul_assign(Coefficient_traits::const_reference n, const Variable v) = 0;
20654
20655  virtual Linear_Expression_Interface&
20656  sub_mul_assign(Coefficient_traits::const_reference n, const Variable v) = 0;
20657
20658  virtual void add_mul_assign(Coefficient_traits::const_reference factor,
20659                              const Linear_Expression_Interface& e2) = 0;
20660
20661  virtual void sub_mul_assign(Coefficient_traits::const_reference factor,
20662                              const Linear_Expression_Interface& e2) = 0;
20663
20664  virtual void print(std::ostream& s) const = 0;
20665
20666  /*! \brief
20667    Returns <CODE>true</CODE> if the coefficient of each variable in
20668    \p vars[i] is \f$0\f$.
20669  */
20670  virtual bool all_zeroes(const Variables_Set& vars) const = 0;
20671
20672  //! Returns true if there is a variable in [first,last) whose coefficient
20673  //! is nonzero in both *this and x.
20674  virtual bool have_a_common_variable(const Linear_Expression_Interface& x,
20675                                      Variable first, Variable last) const = 0;
20676
20677  // NOTE: This method is public, but it's not exposed in Linear_Expression,
20678  // so that it can be used internally in the PPL, by friends of
20679  // Linear_Expression.
20680  //! Returns the i-th coefficient.
20681  virtual Coefficient_traits::const_reference get(dimension_type i) const = 0;
20682
20683  // NOTE: This method is public, but it's not exposed in Linear_Expression,
20684  // so that it can be used internally in the PPL, by friends of
20685  // Linear_Expression.
20686  //! Sets the i-th coefficient to n.
20687  virtual void set(dimension_type i, Coefficient_traits::const_reference n) = 0;
20688
20689  // NOTE: This method is public, but it's not exposed in Linear_Expression,
20690  // so that it can be used internally in the PPL, by friends of
20691  // Linear_Expression.
20692  /*! \brief
20693    Returns <CODE>true</CODE> if (*this)[i] is \f$0\f$, for each i in
20694    [start, end).
20695  */
20696  virtual bool all_zeroes(dimension_type start, dimension_type end) const = 0;
20697
20698  // NOTE: This method is public, but it's not exposed in Linear_Expression,
20699  // so that it can be used internally in the PPL, by friends of
20700  // Linear_Expression.
20701  /*! \brief
20702    Returns the number of zero coefficient in [start, end).
20703  */
20704  virtual dimension_type
20705  num_zeroes(dimension_type start, dimension_type end) const = 0;
20706
20707  // NOTE: This method is public, but it's not exposed in Linear_Expression,
20708  // so that it can be used internally in the PPL, by friends of
20709  // Linear_Expression.
20710  /*! \brief
20711    Returns the gcd of the nonzero coefficients in [start,end). If all the
20712    coefficients in this range are 0 returns 0.
20713  */
20714  virtual Coefficient gcd(dimension_type start, dimension_type end) const = 0;
20715
20716  // NOTE: This method is public, but it's not exposed in Linear_Expression,
20717  // so that it can be used internally in the PPL, by friends of
20718  // Linear_Expression.
20719  virtual void exact_div_assign(Coefficient_traits::const_reference c,
20720                                dimension_type start, dimension_type end) = 0;
20721
20722  // NOTE: This method is public, but it's not exposed in Linear_Expression,
20723  // so that it can be used internally in the PPL, by friends of
20724  // Linear_Expression.
20725  //! Equivalent to <CODE>(*this)[i] *= n</CODE>, for each i in [start, end).
20726  virtual void mul_assign(Coefficient_traits::const_reference n,
20727                          dimension_type start, dimension_type end) = 0;
20728
20729  // NOTE: This method is public, but it's not exposed in Linear_Expression,
20730  // so that it can be used internally in the PPL, by friends of
20731  // Linear_Expression.
20732  //! Linearly combines \p *this with \p y so that the coefficient of \p v
20733  //! is 0.
20734  /*!
20735    \param y
20736    The expression that will be combined with \p *this object;
20737
20738    \param i
20739    The index of the coefficient that has to become \f$0\f$.
20740
20741    Computes a linear combination of \p *this and \p y having
20742    the i-th coefficient equal to \f$0\f$. Then it assigns
20743    the resulting expression to \p *this.
20744
20745    \p *this and \p y must have the same space dimension.
20746  */
20747  virtual void
20748  linear_combine(const Linear_Expression_Interface& y, dimension_type i) = 0;
20749
20750  // NOTE: This method is public, but it's not exposed in Linear_Expression,
20751  // so that it can be used internally in the PPL, by friends of
20752  // Linear_Expression.
20753  //! Equivalent to <CODE>(*this)[i] = (*this)[i] * c1 + y[i] * c2</CODE>,
20754  //! for each i in [start, end).
20755  virtual void linear_combine(const Linear_Expression_Interface& y,
20756                              Coefficient_traits::const_reference c1,
20757                              Coefficient_traits::const_reference c2,
20758                              dimension_type start, dimension_type end) = 0;
20759
20760  // NOTE: This method is public, but it's not exposed in Linear_Expression,
20761  // so that it can be used internally in the PPL, by friends of
20762  // Linear_Expression.
20763  //! Equivalent to <CODE>(*this)[i] = (*this)[i] * c1 + y[i] * c2</CODE>,
20764  //! for each i in [start, end). c1 and c2 may be zero.
20765  virtual void linear_combine_lax(const Linear_Expression_Interface& y,
20766                                  Coefficient_traits::const_reference c1,
20767                                  Coefficient_traits::const_reference c2,
20768                                  dimension_type start, dimension_type end) = 0;
20769
20770  // NOTE: This method is public, but it's not exposed in Linear_Expression,
20771  // so that it can be used internally in the PPL, by friends of
20772  // Linear_Expression.
20773  //! Returns the index of the last nonzero element, or 0 if there are no
20774  //! nonzero elements.
20775  virtual dimension_type last_nonzero() const = 0;
20776
20777  // NOTE: This method is public, but it's not exposed in Linear_Expression,
20778  // so that it can be used internally in the PPL, by friends of
20779  // Linear_Expression.
20780  //! Returns the index of the last nonzero element in [first,last), or last
20781  //! if there are no nonzero elements.
20782  virtual dimension_type
20783  last_nonzero(dimension_type first, dimension_type last) const = 0;
20784
20785  //! Returns the index of the first nonzero element, or \p last if there are no
20786  //! nonzero elements, considering only elements in [first,last).
20787  virtual dimension_type
20788  first_nonzero(dimension_type first, dimension_type last) const = 0;
20789
20790  // NOTE: This method is public, but it's not exposed in Linear_Expression,
20791  // so that it can be used internally in the PPL, by friends of
20792  // Linear_Expression.
20793  /*! \brief
20794    Returns <CODE>true</CODE> if each coefficient in [start,end) is *not* in
20795    \f$0\f$, disregarding coefficients of variables in \p vars.
20796  */
20797  virtual bool
20798  all_zeroes_except(const Variables_Set& vars,
20799                    dimension_type start, dimension_type end) const = 0;
20800
20801  // NOTE: This method is public, but it's not exposed in Linear_Expression,
20802  // so that it can be used internally in the PPL, by friends of
20803  // Linear_Expression.
20804  //! Sets results to the sum of (*this)[i]*y[i], for each i in [start,end).
20805  virtual void
20806  scalar_product_assign(Coefficient& result,
20807                        const Linear_Expression_Interface& y,
20808                        dimension_type start, dimension_type end) const = 0;
20809
20810  // NOTE: This method is public, but it's not exposed in Linear_Expression,
20811  // so that it can be used internally in the PPL, by friends of
20812  // Linear_Expression.
20813  //! Computes the sign of the sum of (*this)[i]*y[i],
20814  //! for each i in [start,end).
20815  virtual int
20816  scalar_product_sign(const Linear_Expression_Interface& y,
20817                      dimension_type start, dimension_type end) const = 0;
20818
20819  // NOTE: This method is public, but it's not exposed in Linear_Expression,
20820  // so that it can be used internally in the PPL, by friends of
20821  // Linear_Expression.
20822  //! Removes from the set x all the indexes of nonzero elements of *this.
20823  virtual void
20824  has_a_free_dimension_helper(std::set<dimension_type>& x) const = 0;
20825
20826  // NOTE: This method is public, but it's not exposed in Linear_Expression,
20827  // so that it can be used internally in the PPL, by friends of
20828  // Linear_Expression.
20829  //! Returns \p true if (*this)[i] is equal to x[i], for each i in [start,end).
20830  virtual bool is_equal_to(const Linear_Expression_Interface& x,
20831                           dimension_type start, dimension_type end) const = 0;
20832
20833  // NOTE: This method is public, but it's not exposed in Linear_Expression,
20834  // so that it can be used internally in the PPL, by friends of
20835  // Linear_Expression.
20836  //! Returns \p true if (*this)[i]*c1 is equal to x[i]*c2, for each i in
20837  //! [start,end).
20838  virtual bool is_equal_to(const Linear_Expression_Interface& x,
20839                           Coefficient_traits::const_reference c1,
20840                           Coefficient_traits::const_reference c2,
20841                           dimension_type start, dimension_type end) const = 0;
20842
20843  // NOTE: This method is public, but it is not exposed in
20844  // Linear_Expression, so that it can be used internally in the PPL,
20845  // by friends of Linear_Expression.
20846  //! Sets \p r to a copy of the row that implements \p *this.
20847  virtual void get_row(Dense_Row& r) const = 0;
20848
20849  // NOTE: This method is public, but it is not exposed in
20850  // Linear_Expression, so that it can be used internally in the PPL,
20851  // by friends of Linear_Expression.
20852  //! Sets \p r to a copy of the row that implements \p *this.
20853  virtual void get_row(Sparse_Row& r) const = 0;
20854};
20855
20856/* Automatically generated from PPL source file ../src/Variables_Set_defs.hh line 1. */
20857/* Variables_Set class declaration.
20858*/
20859
20860
20861/* Automatically generated from PPL source file ../src/Variables_Set_defs.hh line 30. */
20862#include <iosfwd>
20863#include <set>
20864
20865namespace Parma_Polyhedra_Library {
20866
20867namespace IO_Operators {
20868
20869//! Output operator.
20870/*! \relates Parma_Polyhedra_Library::Variables_Set */
20871std::ostream&
20872operator<<(std::ostream& s, const Variables_Set& vs);
20873
20874} // namespace IO_Operators
20875
20876} // namespace Parma_Polyhedra_Library
20877
20878//! An std::set of variables' indexes.
20879class Parma_Polyhedra_Library::Variables_Set
20880  : public std::set<dimension_type> {
20881private:
20882  typedef std::set<dimension_type> Base;
20883
20884public:
20885  //! Builds the empty set of variable indexes.
20886  Variables_Set();
20887
20888  //! Builds the singleton set of indexes containing <CODE>v.id()</CODE>;
20889  explicit Variables_Set(const Variable v);
20890
20891  /*! \brief
20892    Builds the set of variables's indexes in the range from
20893    <CODE>v.id()</CODE> to <CODE>w.id()</CODE>.
20894
20895    If <CODE>v.id() <= w.id()</CODE>, this constructor builds the
20896    set of variables' indexes
20897    <CODE>v.id()</CODE>, <CODE>v.id()+1</CODE>, ..., <CODE>w.id()</CODE>.
20898    The empty set is built otherwise.
20899  */
20900  Variables_Set(const Variable v, const Variable w);
20901
20902  //! Returns the maximum space dimension a Variables_Set can handle.
20903  static dimension_type max_space_dimension();
20904
20905  /*! \brief
20906    Returns the dimension of the smallest vector space enclosing all
20907    the variables whose indexes are in the set.
20908  */
20909  dimension_type space_dimension() const;
20910
20911  //! Inserts the index of variable \p v into the set.
20912  void insert(Variable v);
20913
20914  // The `insert' method above overloads (instead of hiding) the
20915  // other `insert' method of std::set.
20916  using Base::insert;
20917
20918  /*! \brief
20919    Loads from \p s an ASCII representation (as produced by
20920    ascii_dump(std::ostream&) const) and sets \p *this accordingly.
20921    Returns <CODE>true</CODE> if successful, <CODE>false</CODE> otherwise.
20922  */
20923  bool ascii_load(std::istream& s);
20924
20925  //! Returns the total size in bytes of the memory occupied by \p *this.
20926  memory_size_type total_memory_in_bytes() const;
20927
20928  //! Returns the size in bytes of the memory managed by \p *this.
20929  memory_size_type external_memory_in_bytes() const;
20930
20931  //! Checks if all the invariants are satisfied.
20932  bool OK() const;
20933
20934  PPL_OUTPUT_DECLARATIONS
20935};
20936
20937/* Automatically generated from PPL source file ../src/Variables_Set_inlines.hh line 1. */
20938/* Variables_Set class implementation: inline functions.
20939*/
20940
20941
20942/* Automatically generated from PPL source file ../src/Variables_Set_inlines.hh line 28. */
20943#include <stdexcept>
20944
20945namespace Parma_Polyhedra_Library {
20946
20947inline
20948Variables_Set::Variables_Set()
20949  : Base() {
20950}
20951
20952inline void
20953Variables_Set::insert(const Variable v) {
20954  insert(v.id());
20955}
20956
20957inline
20958Variables_Set::Variables_Set(const Variable v)
20959  : Base() {
20960  insert(v);
20961}
20962
20963inline dimension_type
20964Variables_Set::max_space_dimension() {
20965  return Variable::max_space_dimension();
20966}
20967
20968inline dimension_type
20969Variables_Set::space_dimension() const {
20970  reverse_iterator i = rbegin();
20971  return (i == rend()) ? 0 : (*i + 1);
20972}
20973
20974inline memory_size_type
20975Variables_Set::external_memory_in_bytes() const {
20976  // We assume sets are implemented by means of red-black trees that
20977  // require to store the color (we assume an enum) and three pointers
20978  // to the parent, left and right child, respectively.
20979  enum color { red, black };
20980  return size() * (sizeof(color) + 3*sizeof(void*) + sizeof(dimension_type));
20981}
20982
20983inline memory_size_type
20984Variables_Set::total_memory_in_bytes() const {
20985  return sizeof(*this) + external_memory_in_bytes();
20986}
20987
20988} // namespace Parma_Polyhedra_Library
20989
20990/* Automatically generated from PPL source file ../src/Variables_Set_defs.hh line 106. */
20991
20992/* Automatically generated from PPL source file ../src/Dense_Row_defs.hh line 1. */
20993/* Dense_Row class declaration.
20994*/
20995
20996
20997/* Automatically generated from PPL source file ../src/Dense_Row_defs.hh line 28. */
20998
20999/* Automatically generated from PPL source file ../src/Dense_Row_defs.hh line 30. */
21000
21001/* Automatically generated from PPL source file ../src/Dense_Row_defs.hh line 33. */
21002#include <memory>
21003#include <vector>
21004#include <limits>
21005#include <cstddef>
21006
21007#ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
21008//! A finite sequence of coefficients.
21009/*! \ingroup PPL_CXX_interface */
21010#endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
21011class Parma_Polyhedra_Library::Dense_Row {
21012public:
21013  class iterator;
21014  class const_iterator;
21015
21016  //! Constructs an empty row.
21017  Dense_Row();
21018
21019  explicit Dense_Row(const Sparse_Row& row);
21020
21021  //! Tight constructor: resizing may require reallocation.
21022  /*!
21023    Constructs a row with size and capacity \p sz.
21024  */
21025  Dense_Row(dimension_type sz);
21026
21027  //! Sizing constructor with capacity.
21028  /*!
21029    \param sz
21030    The size of the row that will be constructed;
21031
21032    \param capacity
21033    The capacity of the row that will be constructed;
21034
21035    The row that is constructed has storage for \p capacity elements,
21036    \p sz of which are default-constructed now.
21037  */
21038  Dense_Row(dimension_type sz, dimension_type capacity);
21039
21040  //! Ordinary copy constructor.
21041  Dense_Row(const Dense_Row& y);
21042
21043  //! Copy constructor with specified capacity.
21044  /*!
21045    It is assumed that \p capacity is greater than or equal to
21046    the size of \p y.
21047  */
21048  Dense_Row(const Dense_Row& y, dimension_type capacity);
21049
21050  //! Copy constructor with specified size and capacity.
21051  /*!
21052    It is assumed that \p sz is less than or equal to \p capacity.
21053  */
21054  Dense_Row(const Dense_Row& y, dimension_type sz, dimension_type capacity);
21055
21056  //! Copy constructor with specified size and capacity from a Sparse_Row.
21057  /*!
21058    It is assumed that \p sz is less than or equal to \p capacity.
21059  */
21060  Dense_Row(const Sparse_Row& y, dimension_type sz, dimension_type capacity);
21061
21062  //! Destructor.
21063  ~Dense_Row();
21064
21065  //! Assignment operator.
21066  Dense_Row& operator=(const Dense_Row& y);
21067
21068  //! Assignment operator.
21069  Dense_Row& operator=(const Sparse_Row& y);
21070
21071  //! Swaps \p *this with \p y.
21072  void m_swap(Dense_Row& y);
21073
21074  //! Resizes the row to \p sz.
21075  void resize(dimension_type sz);
21076
21077  //! Resizes the row to \p sz, with capacity \p capacity.
21078  void resize(dimension_type sz, dimension_type capacity);
21079
21080  //! Resets all the elements of this row.
21081  void clear();
21082
21083  //! Adds \p n zeroes before index \p i.
21084  /*!
21085    \param n
21086    The number of zeroes that will be added to the row.
21087
21088    \param i
21089    The index of the element before which the zeroes will be added.
21090
21091    Existing elements with index greater than or equal to \p i are shifted
21092    to the right by \p n positions. The size is increased by \p n.
21093
21094    Existing iterators are invalidated.
21095  */
21096  void add_zeroes_and_shift(dimension_type n, dimension_type i);
21097
21098  //! Expands the row to size \p new_size.
21099  /*!
21100    Adds new positions to the implementation of the row
21101    obtaining a new row with size \p new_size.
21102    It is assumed that \p new_size is between the current size
21103    and capacity of the row.
21104  */
21105  void expand_within_capacity(dimension_type new_size);
21106
21107  //! Shrinks the row by erasing elements at the end.
21108  /*!
21109    Destroys elements of the row implementation
21110    from position \p new_size to the end.
21111    It is assumed that \p new_size is not greater than the current size.
21112  */
21113  void shrink(dimension_type new_size);
21114
21115  //! Returns the size() of the largest possible Dense_Row.
21116  static dimension_type max_size();
21117
21118  //! Gives the number of coefficients currently in use.
21119  dimension_type size() const;
21120
21121  //! \name Subscript operators
21122  //@{
21123  //! Returns a reference to the element of the row indexed by \p k.
21124  Coefficient& operator[](dimension_type k);
21125
21126  //! Returns a constant reference to the element of the row indexed by \p k.
21127  Coefficient_traits::const_reference operator[](dimension_type k) const;
21128  //@} // Subscript operators
21129
21130  //! Normalizes the modulo of coefficients so that they are mutually prime.
21131  /*!
21132    Computes the Greatest Common Divisor (GCD) among the elements of
21133    the row and normalizes them by the GCD itself.
21134  */
21135  void normalize();
21136
21137  //! Swaps the i-th element with the j-th element.
21138  //! Provided for compatibility with Sparse_Row
21139  void swap_coefficients(dimension_type i, dimension_type j);
21140
21141  //! Swaps the element pointed to by i with the element pointed to by j.
21142  //! Provided for compatibility with Sparse_Row
21143  void swap_coefficients(iterator i, iterator j);
21144
21145  iterator begin();
21146  const_iterator begin() const;
21147
21148  iterator end();
21149  const_iterator end() const;
21150
21151  //! Resets the i-th element to 0.
21152  //! Provided for compatibility with Sparse_Row
21153  void reset(dimension_type i);
21154
21155  //! Resets the elements [first,last) to 0.
21156  //! Provided for compatibility with Sparse_Row
21157  void reset(dimension_type first, dimension_type last);
21158
21159  //! Resets the element pointed to by itr to 0.
21160  //! Provided for compatibility with Sparse_Row.
21161  iterator reset(iterator itr);
21162
21163  //! Gets the i-th element.
21164  //! Provided for compatibility with Sparse_Row.
21165  Coefficient_traits::const_reference get(dimension_type i) const;
21166
21167  //! Provided for compatibility with Sparse_Row.
21168  iterator find(dimension_type i);
21169
21170  //! Provided for compatibility with Sparse_Row.
21171  const_iterator find(dimension_type i) const;
21172
21173  //! Provided for compatibility with Sparse_Row.
21174  iterator find(iterator itr, dimension_type i);
21175
21176  //! Provided for compatibility with Sparse_Row.
21177  const_iterator find(const_iterator itr, dimension_type i) const;
21178
21179  //! Provided for compatibility with Sparse_Row.
21180  iterator lower_bound(dimension_type i);
21181
21182  //! Provided for compatibility with Sparse_Row.
21183  const_iterator lower_bound(dimension_type i) const;
21184
21185  //! Provided for compatibility with Sparse_Row.
21186  iterator lower_bound(iterator itr, dimension_type i);
21187
21188  //! Provided for compatibility with Sparse_Row.
21189  const_iterator lower_bound(const_iterator itr, dimension_type i) const;
21190
21191  //! Provided for compatibility with Sparse_Row.
21192  iterator insert(dimension_type i, Coefficient_traits::const_reference x);
21193
21194  //! Provided for compatibility with Sparse_Row.
21195  iterator insert(dimension_type i);
21196
21197  //! Provided for compatibility with Sparse_Row.
21198  iterator insert(iterator itr, dimension_type i,
21199                       Coefficient_traits::const_reference x);
21200
21201  //! Provided for compatibility with Sparse_Row.
21202  iterator insert(iterator itr, dimension_type i);
21203
21204  //! Calls g(x[i],y[i]), for each i.
21205  /*!
21206    \param y
21207    The row that will be combined with *this.
21208
21209    \param f
21210    A functor that should take a Coefficient&.
21211    f(c1) must be equivalent to g(c1, 0).
21212
21213    \param g
21214    A functor that should take a Coefficient& and a
21215    Coefficient_traits::const_reference.
21216    g(c1, c2) must do nothing when c1 is zero.
21217
21218    This method takes \f$O(n)\f$ time.
21219
21220    \note
21221    The functors will only be called when necessary, assuming the requested
21222    properties hold.
21223
21224    \see combine_needs_second
21225    \see combine
21226  */
21227  template <typename Func1, typename Func2>
21228  void combine_needs_first(const Dense_Row& y,
21229                           const Func1& f, const Func2& g);
21230
21231  //! Calls g(x[i],y[i]), for each i.
21232  /*!
21233    \param y
21234    The row that will be combined with *this.
21235
21236    \param g
21237    A functor that should take a Coefficient& and a
21238    Coefficient_traits::const_reference.
21239    g(c1, 0) must do nothing, for every c1.
21240
21241    \param h
21242    A functor that should take a Coefficient& and a
21243    Coefficient_traits::const_reference.
21244    h(c1, c2) must be equivalent to g(c1, c2) when c1 is zero.
21245
21246    This method takes \f$O(n)\f$ time.
21247
21248    \note
21249    The functors will only be called when necessary, assuming the requested
21250    properties hold.
21251
21252    \see combine_needs_first
21253    \see combine
21254  */
21255  template <typename Func1, typename Func2>
21256  void combine_needs_second(const Dense_Row& y,
21257                            const Func1& g, const Func2& h);
21258
21259  //! Calls g(x[i],y[i]), for each i.
21260  /*!
21261    \param y
21262    The row that will be combined with *this.
21263
21264    \param f
21265    A functor that should take a Coefficient&.
21266    f(c1) must be equivalent to g(c1, 0).
21267
21268    \param g
21269    A functor that should take a Coefficient& and a
21270    Coefficient_traits::const_reference.
21271    g(c1, c2) must do nothing when both c1 and c2 are zero.
21272
21273    \param h
21274    A functor that should take a Coefficient& and a
21275    Coefficient_traits::const_reference.
21276    h(c1, c2) must be equivalent to g(c1, c2) when c1 is zero.
21277
21278    This method takes \f$O(n)\f$ time.
21279
21280    \note
21281    The functors will only be called when necessary, assuming the requested
21282    properties hold.
21283
21284    \see combine_needs_first
21285    \see combine_needs_second
21286  */
21287  template <typename Func1, typename Func2, typename Func3>
21288  void combine(const Dense_Row& y,
21289               const Func1& f, const Func2& g, const Func3& h);
21290
21291  //! Executes <CODE>(*this)[i] = (*this)[i]*coeff1 + y[i]*coeff2</CODE>, for
21292  //! each i.
21293  /*!
21294    \param y
21295    The row that will be combined with *this.
21296
21297    \param coeff1
21298    The coefficient used for elements of *this.
21299    It must not be 0.
21300
21301    \param coeff2
21302    The coefficient used for elements of y.
21303    It must not be 0.
21304
21305    This method takes \f$O(n)\f$ time.
21306
21307    \see combine_needs_first
21308    \see combine_needs_second
21309    \see combine
21310  */
21311  void linear_combine(const Dense_Row& y,
21312                      Coefficient_traits::const_reference coeff1,
21313                      Coefficient_traits::const_reference coeff2);
21314
21315  //! Equivalent to <CODE>(*this)[i] = (*this)[i] * c1 + y[i] * c2</CODE>,
21316  //! for each i in [start, end).
21317  /*!
21318    This method detects when coeff1==1 and/or coeff2==1 or coeff2==-1 in
21319    order to save some work.
21320
21321    coeff1 and coeff2 must not be 0.
21322  */
21323  void linear_combine(const Dense_Row& y,
21324                      Coefficient_traits::const_reference c1,
21325                      Coefficient_traits::const_reference c2,
21326                      dimension_type start, dimension_type end);
21327
21328  PPL_OUTPUT_DECLARATIONS
21329
21330  /*! \brief
21331    Loads from \p s an ASCII representation (as produced by
21332    ascii_dump(std::ostream&) const) and sets \p *this accordingly.
21333    Returns <CODE>true</CODE> if successful, <CODE>false</CODE> otherwise.
21334  */
21335  bool ascii_load(std::istream& s);
21336
21337  /*! \brief
21338    Returns a lower bound to the total size in bytes of the memory
21339    occupied by \p *this.
21340  */
21341  memory_size_type total_memory_in_bytes() const;
21342
21343  /*! \brief
21344    Returns a lower bound to the size in bytes of the memory
21345    managed by \p *this.
21346  */
21347  memory_size_type external_memory_in_bytes() const;
21348
21349  /*! \brief
21350    Returns the total size in bytes of the memory occupied by \p *this,
21351    provided the capacity of \p *this is given by \p capacity.
21352  */
21353  memory_size_type total_memory_in_bytes(dimension_type capacity) const;
21354
21355  /*! \brief
21356    Returns the size in bytes of the memory managed by \p *this,
21357    provided the capacity of \p *this is given by \p capacity.
21358  */
21359  memory_size_type external_memory_in_bytes(dimension_type capacity) const;
21360
21361  //! Checks if all the invariants are satisfied.
21362  bool OK() const;
21363
21364  /*! \brief
21365    Checks if all the invariants are satisfied and that the actual
21366    size matches the value provided as argument.
21367  */
21368  bool OK(dimension_type row_size) const;
21369
21370private:
21371  void init(const Sparse_Row& row);
21372
21373  void destroy();
21374
21375  struct Impl {
21376
21377    Impl();
21378
21379    ~Impl();
21380
21381    //! The number of coefficients in the row.
21382    dimension_type size;
21383
21384    //! The capacity of the row.
21385    dimension_type capacity;
21386
21387    //! The allocator used to allocate/deallocate vec.
21388    std::allocator<Coefficient> coeff_allocator;
21389
21390    //! The vector of coefficients.
21391    //! An empty vector may be stored as NULL instead of using a valid pointer.
21392    Coefficient* vec;
21393  };
21394
21395  Impl impl;
21396
21397  //! Returns the capacity of the row.
21398  dimension_type capacity() const;
21399};
21400
21401class Parma_Polyhedra_Library::Dense_Row::iterator {
21402public:
21403
21404  typedef std::bidirectional_iterator_tag iterator_category;
21405  typedef Coefficient value_type;
21406  typedef std::ptrdiff_t difference_type;
21407  typedef value_type* pointer;
21408  typedef value_type& reference;
21409
21410  iterator();
21411  iterator(Dense_Row& r, dimension_type i);
21412
21413  Coefficient& operator*();
21414  Coefficient_traits::const_reference operator*() const;
21415
21416  //! Returns the index of the element pointed to by \c *this.
21417  /*!
21418    If itr is a valid iterator for row, <CODE>row[itr.index()]</CODE> is
21419    equivalent to *itr.
21420
21421    \returns the index of the element pointed to by \c *this.
21422  */
21423  dimension_type index() const;
21424
21425  iterator& operator++();
21426  iterator operator++(int);
21427
21428  iterator& operator--();
21429  iterator operator--(int);
21430
21431  bool operator==(const iterator& x) const;
21432  bool operator!=(const iterator& x) const;
21433
21434  operator const_iterator() const;
21435
21436  bool OK() const;
21437
21438private:
21439  Dense_Row* row;
21440  dimension_type idx;
21441};
21442
21443class Parma_Polyhedra_Library::Dense_Row::const_iterator {
21444public:
21445
21446  typedef const Coefficient value_type;
21447  typedef std::ptrdiff_t difference_type;
21448  typedef value_type* pointer;
21449  typedef Coefficient_traits::const_reference reference;
21450
21451  const_iterator();
21452  const_iterator(const Dense_Row& r, dimension_type i);
21453
21454  Coefficient_traits::const_reference operator*() const;
21455
21456  //! Returns the index of the element pointed to by \c *this.
21457  /*!
21458    If itr is a valid iterator for row, <CODE>row[itr.index()]</CODE> is
21459    equivalent to *itr.
21460
21461    \returns the index of the element pointed to by \c *this.
21462  */
21463  dimension_type index() const;
21464
21465  const_iterator& operator++();
21466  const_iterator operator++(int);
21467
21468  const_iterator& operator--();
21469  const_iterator operator--(int);
21470
21471  bool operator==(const const_iterator& x) const;
21472  bool operator!=(const const_iterator& x) const;
21473
21474  bool OK() const;
21475
21476private:
21477  const Dense_Row* row;
21478  dimension_type idx;
21479};
21480
21481
21482namespace Parma_Polyhedra_Library {
21483
21484#ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
21485//! Swaps \p x with \p y.
21486/*! \relates Dense_Row */
21487#endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
21488void swap(Dense_Row& x, Dense_Row& y);
21489
21490#ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
21491//! Swaps objects referred by \p x and \p y.
21492/*! \relates Dense_Row */
21493#endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
21494void iter_swap(std::vector<Dense_Row>::iterator x,
21495               std::vector<Dense_Row>::iterator y);
21496
21497#ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
21498//! Returns <CODE>true</CODE> if and only if \p x and \p y are equal.
21499/*! \relates Dense_Row */
21500#endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
21501bool operator==(const Dense_Row& x, const Dense_Row& y);
21502
21503#ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
21504//! Returns <CODE>true</CODE> if and only if \p x and \p y are different.
21505/*! \relates Dense_Row */
21506#endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
21507bool operator!=(const Dense_Row& x, const Dense_Row& y);
21508
21509#ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
21510/*! \relates Dense_Row */
21511#endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
21512void linear_combine(Dense_Row& x, const Dense_Row& y,
21513                    Coefficient_traits::const_reference coeff1,
21514                    Coefficient_traits::const_reference coeff2);
21515
21516#ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
21517//! Equivalent to <CODE>x[i] = x[i] * c1 + y[i] * c2</CODE>,
21518//! for each i in [start, end).
21519/*! \relates Dense_Row */
21520#endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
21521void linear_combine(Dense_Row& x, const Dense_Row& y,
21522                    Coefficient_traits::const_reference c1,
21523                    Coefficient_traits::const_reference c2,
21524                    dimension_type start, dimension_type end);
21525
21526} // namespace Parma_Polyhedra_Library
21527
21528/* Automatically generated from PPL source file ../src/Dense_Row_inlines.hh line 1. */
21529/* Dense_Row class implementation: inline functions.
21530*/
21531
21532
21533/* Automatically generated from PPL source file ../src/Dense_Row_inlines.hh line 28. */
21534#include <cstddef>
21535#include <limits>
21536#include <algorithm>
21537
21538namespace Parma_Polyhedra_Library {
21539
21540inline
21541Dense_Row::Impl::Impl()
21542  : size(0), capacity(0), coeff_allocator(), vec(0) {
21543}
21544
21545inline
21546Dense_Row::Impl::~Impl() {
21547  while (size != 0) {
21548    --size;
21549    vec[size].~Coefficient();
21550  }
21551  coeff_allocator.deallocate(vec, capacity);
21552}
21553
21554inline dimension_type
21555Dense_Row::max_size() {
21556  return std::numeric_limits<size_t>::max() / sizeof(Coefficient);
21557}
21558
21559inline dimension_type
21560Dense_Row::size() const {
21561  return impl.size;
21562}
21563
21564inline dimension_type
21565Dense_Row::capacity() const {
21566  return impl.capacity;
21567}
21568
21569inline
21570Dense_Row::Dense_Row()
21571  : impl() {
21572
21573  PPL_ASSERT(OK());
21574}
21575
21576inline
21577Dense_Row::Dense_Row(const dimension_type sz,
21578                     const dimension_type capacity)
21579  : impl() {
21580
21581  resize(sz, capacity);
21582
21583  PPL_ASSERT(size() == sz);
21584  PPL_ASSERT(impl.capacity == capacity);
21585  PPL_ASSERT(OK());
21586}
21587
21588inline
21589Dense_Row::Dense_Row(const dimension_type sz)
21590  : impl() {
21591
21592  resize(sz);
21593
21594  PPL_ASSERT(size() == sz);
21595  PPL_ASSERT(OK());
21596}
21597
21598inline
21599Dense_Row::Dense_Row(const Dense_Row& y)
21600  : impl() {
21601  impl.coeff_allocator = y.impl.coeff_allocator;
21602  if (y.impl.vec != 0) {
21603    impl.capacity = y.capacity();
21604    impl.vec = impl.coeff_allocator.allocate(impl.capacity);
21605    while (impl.size != y.size()) {
21606      new(&impl.vec[impl.size]) Coefficient(y[impl.size]);
21607      ++impl.size;
21608    }
21609  }
21610  PPL_ASSERT(size() == y.size());
21611  PPL_ASSERT(capacity() == y.capacity());
21612  PPL_ASSERT(OK());
21613}
21614
21615inline
21616Dense_Row::Dense_Row(const Dense_Row& y,
21617                     const dimension_type capacity)
21618  : impl() {
21619  PPL_ASSERT(y.size() <= capacity);
21620  PPL_ASSERT(capacity <= max_size());
21621
21622  impl.capacity = capacity;
21623  impl.coeff_allocator = y.impl.coeff_allocator;
21624  impl.vec = impl.coeff_allocator.allocate(impl.capacity);
21625
21626  if (y.impl.vec != 0) {
21627    while (impl.size != y.size()) {
21628      new(&impl.vec[impl.size]) Coefficient(y[impl.size]);
21629      ++impl.size;
21630    }
21631  }
21632
21633  PPL_ASSERT(size() == y.size());
21634  PPL_ASSERT(impl.capacity == capacity);
21635  PPL_ASSERT(OK());
21636}
21637
21638inline
21639Dense_Row::Dense_Row(const Dense_Row& y,
21640                     const dimension_type sz,
21641                     const dimension_type capacity)
21642  : impl() {
21643  PPL_ASSERT(sz <= capacity);
21644  PPL_ASSERT(capacity <= max_size());
21645  PPL_ASSERT(capacity != 0);
21646
21647  impl.capacity = capacity;
21648  impl.coeff_allocator = y.impl.coeff_allocator;
21649  impl.vec = impl.coeff_allocator.allocate(impl.capacity);
21650
21651  const dimension_type n = std::min(sz, y.size());
21652  while (impl.size != n) {
21653    new(&impl.vec[impl.size]) Coefficient(y[impl.size]);
21654    ++impl.size;
21655  }
21656  while (impl.size != sz) {
21657    new(&impl.vec[impl.size]) Coefficient();
21658    ++impl.size;
21659  }
21660
21661  PPL_ASSERT(size() == sz);
21662  PPL_ASSERT(impl.capacity == capacity);
21663  PPL_ASSERT(OK());
21664}
21665
21666inline
21667Dense_Row::~Dense_Row() {
21668  // The `impl' field will be destroyed automatically.
21669}
21670
21671inline void
21672Dense_Row::destroy() {
21673  resize(0);
21674  impl.coeff_allocator.deallocate(impl.vec, impl.capacity);
21675}
21676
21677inline void
21678Dense_Row::m_swap(Dense_Row& y) {
21679  using std::swap;
21680  swap(impl.size, y.impl.size);
21681  swap(impl.capacity, y.impl.capacity);
21682  swap(impl.coeff_allocator, y.impl.coeff_allocator);
21683  swap(impl.vec, y.impl.vec);
21684  PPL_ASSERT(OK());
21685  PPL_ASSERT(y.OK());
21686}
21687
21688inline Dense_Row&
21689Dense_Row::operator=(const Dense_Row& y) {
21690
21691  if (this != &y && size() == y.size()) {
21692    // Avoid reallocation.
21693
21694    for (dimension_type i = size(); i-- > 0; ) {
21695      (*this)[i] = y[i];
21696    }
21697
21698    return *this;
21699  }
21700
21701  Dense_Row x(y);
21702  swap(*this, x);
21703
21704  return *this;
21705}
21706
21707inline Coefficient&
21708Dense_Row::operator[](const dimension_type k) {
21709  PPL_ASSERT(impl.vec != 0);
21710  PPL_ASSERT(k < size());
21711  return impl.vec[k];
21712}
21713
21714inline Coefficient_traits::const_reference
21715Dense_Row::operator[](const dimension_type k) const {
21716  PPL_ASSERT(impl.vec != 0);
21717  PPL_ASSERT(k < size());
21718  return impl.vec[k];
21719}
21720
21721inline void
21722Dense_Row::swap_coefficients(dimension_type i, dimension_type j) {
21723  std::swap((*this)[i], (*this)[j]);
21724}
21725
21726inline void
21727Dense_Row::swap_coefficients(iterator i, iterator j) {
21728  std::swap(*i, *j);
21729}
21730
21731inline void
21732Dense_Row::reset(dimension_type i) {
21733  (*this)[i] = 0;
21734}
21735
21736inline Dense_Row::iterator
21737Dense_Row::reset(iterator itr) {
21738  *itr = 0;
21739  ++itr;
21740  return itr;
21741}
21742
21743inline Dense_Row::iterator
21744Dense_Row::begin() {
21745  return iterator(*this, 0);
21746}
21747
21748inline Dense_Row::const_iterator
21749Dense_Row::begin() const {
21750  return const_iterator(*this, 0);
21751}
21752
21753inline Dense_Row::iterator
21754Dense_Row::end() {
21755  return iterator(*this, size());
21756}
21757
21758inline Dense_Row::const_iterator
21759Dense_Row::end() const {
21760  return const_iterator(*this, size());
21761}
21762
21763inline Coefficient_traits::const_reference
21764Dense_Row::get(dimension_type i) const {
21765  return (*this)[i];
21766}
21767
21768inline Dense_Row::iterator
21769Dense_Row::find(dimension_type i) {
21770  return iterator(*this, i);
21771}
21772
21773inline Dense_Row::const_iterator
21774Dense_Row::find(dimension_type i) const {
21775  return const_iterator(*this, i);
21776}
21777
21778inline Dense_Row::iterator
21779Dense_Row::find(iterator itr, dimension_type i) {
21780  (void)itr;
21781  return iterator(*this, i);
21782}
21783
21784inline Dense_Row::const_iterator
21785Dense_Row::find(const_iterator itr, dimension_type i) const {
21786  (void)itr;
21787  return const_iterator(*this, i);
21788}
21789
21790inline Dense_Row::iterator
21791Dense_Row::lower_bound(dimension_type i) {
21792  return find(i);
21793}
21794
21795inline Dense_Row::const_iterator
21796Dense_Row::lower_bound(dimension_type i) const {
21797  return find(i);
21798}
21799
21800inline Dense_Row::iterator
21801Dense_Row::lower_bound(iterator itr, dimension_type i) {
21802  return find(itr, i);
21803}
21804
21805inline Dense_Row::const_iterator
21806Dense_Row::lower_bound(const_iterator itr, dimension_type i) const {
21807  return find(itr, i);
21808}
21809
21810inline Dense_Row::iterator
21811Dense_Row::insert(dimension_type i,
21812                  Coefficient_traits::const_reference x) {
21813  (*this)[i] = x;
21814  return find(i);
21815}
21816
21817inline Dense_Row::iterator
21818Dense_Row::insert(dimension_type i) {
21819  return find(i);
21820}
21821
21822inline Dense_Row::iterator
21823Dense_Row::insert(iterator itr, dimension_type i,
21824                  Coefficient_traits::const_reference x) {
21825  (void)itr;
21826  (*this)[i] = x;
21827  return find(i);
21828}
21829
21830inline Dense_Row::iterator
21831Dense_Row::insert(iterator itr, dimension_type i) {
21832  (void)itr;
21833  return find(i);
21834}
21835
21836inline memory_size_type
21837Dense_Row::total_memory_in_bytes() const {
21838  return sizeof(*this) + external_memory_in_bytes();
21839}
21840
21841inline memory_size_type
21842Dense_Row::total_memory_in_bytes(dimension_type capacity) const {
21843  return sizeof(*this) + external_memory_in_bytes(capacity);
21844}
21845
21846/*! \relates Dense_Row */
21847inline bool
21848operator!=(const Dense_Row& x, const Dense_Row& y) {
21849  return !(x == y);
21850}
21851
21852
21853inline
21854Dense_Row::iterator::iterator()
21855  : row(NULL), idx(0) {
21856  PPL_ASSERT(OK());
21857}
21858
21859inline
21860Dense_Row::iterator::iterator(Dense_Row& r, dimension_type i)
21861  : row(&r), idx(i) {
21862  PPL_ASSERT(OK());
21863}
21864
21865inline Coefficient&
21866Dense_Row::iterator::operator*() {
21867  PPL_ASSERT(idx < row->size());
21868  return (*row)[idx];
21869}
21870
21871inline Coefficient_traits::const_reference
21872Dense_Row::iterator::operator*() const {
21873  PPL_ASSERT(idx < row->size());
21874  return (*row)[idx];
21875}
21876
21877inline dimension_type
21878Dense_Row::iterator::index() const {
21879  return idx;
21880}
21881
21882inline Dense_Row::iterator&
21883Dense_Row::iterator::operator++() {
21884  PPL_ASSERT(idx < row->size());
21885  ++idx;
21886  PPL_ASSERT(OK());
21887  return *this;
21888}
21889
21890inline Dense_Row::iterator
21891Dense_Row::iterator::operator++(int) {
21892  iterator tmp(*this);
21893  ++(*this);
21894  return tmp;
21895}
21896
21897inline Dense_Row::iterator&
21898Dense_Row::iterator::operator--() {
21899  PPL_ASSERT(idx > 0);
21900  --idx;
21901  PPL_ASSERT(OK());
21902  return *this;
21903}
21904
21905inline Dense_Row::iterator
21906Dense_Row::iterator::operator--(int) {
21907  iterator tmp(*this);
21908  --(*this);
21909  return tmp;
21910}
21911
21912inline bool
21913Dense_Row::iterator::operator==(const iterator& x) const {
21914  return (row == x.row) && (idx == x.idx);
21915}
21916
21917inline bool
21918Dense_Row::iterator::operator!=(const iterator& x) const {
21919  return !(*this == x);
21920}
21921
21922inline
21923Dense_Row::iterator::operator const_iterator() const {
21924  return const_iterator(*row, idx);
21925}
21926
21927inline bool
21928Dense_Row::iterator::OK() const {
21929  if (row == NULL) {
21930    return true;
21931  }
21932  // i can be equal to row.size() for past-the-end iterators
21933  return (idx <= row->size());
21934}
21935
21936
21937inline
21938Dense_Row::const_iterator::const_iterator()
21939  : row(NULL), idx(0) {
21940  PPL_ASSERT(OK());
21941}
21942
21943inline
21944Dense_Row::const_iterator::const_iterator(const Dense_Row& r,
21945                                          dimension_type i)
21946  : row(&r), idx(i) {
21947  PPL_ASSERT(OK());
21948}
21949
21950inline Coefficient_traits::const_reference
21951Dense_Row::const_iterator::operator*() const {
21952  PPL_ASSERT(idx < row->size());
21953  return (*row)[idx];
21954}
21955
21956inline dimension_type
21957Dense_Row::const_iterator::index() const {
21958  return idx;
21959}
21960
21961inline Dense_Row::const_iterator&
21962Dense_Row::const_iterator::operator++() {
21963  PPL_ASSERT(idx < row->size());
21964  ++idx;
21965  PPL_ASSERT(OK());
21966  return *this;
21967}
21968
21969inline Dense_Row::const_iterator
21970Dense_Row::const_iterator::operator++(int) {
21971  const_iterator tmp(*this);
21972  ++(*this);
21973  return tmp;
21974}
21975
21976inline Dense_Row::const_iterator&
21977Dense_Row::const_iterator::operator--() {
21978  PPL_ASSERT(idx > 0);
21979  --idx;
21980  PPL_ASSERT(OK());
21981  return *this;
21982}
21983
21984inline Dense_Row::const_iterator
21985Dense_Row::const_iterator::operator--(int) {
21986  const_iterator tmp(*this);
21987  --(*this);
21988  return tmp;
21989}
21990
21991inline bool
21992Dense_Row::const_iterator::operator==(const const_iterator& x) const {
21993  return (row == x.row) && (idx == x.idx);
21994}
21995
21996inline bool
21997Dense_Row::const_iterator::operator!=(const const_iterator& x) const {
21998  return !(*this == x);
21999}
22000
22001inline bool
22002Dense_Row::const_iterator::OK() const {
22003  if (row == NULL) {
22004    return true;
22005  }
22006  // i can be equal to row.size() for past-the-end iterators
22007  return (idx <= row->size());
22008}
22009
22010inline void
22011linear_combine(Dense_Row& x, const Dense_Row& y,
22012               Coefficient_traits::const_reference coeff1,
22013               Coefficient_traits::const_reference coeff2) {
22014  x.linear_combine(y, coeff1, coeff2);
22015}
22016
22017inline void
22018linear_combine(Dense_Row& x, const Dense_Row& y,
22019               Coefficient_traits::const_reference c1,
22020               Coefficient_traits::const_reference c2,
22021               dimension_type start, dimension_type end) {
22022  x.linear_combine(y, c1, c2, start, end);
22023}
22024
22025/*! \relates Dense_Row */
22026inline void
22027swap(Dense_Row& x, Dense_Row& y) {
22028  x.m_swap(y);
22029}
22030
22031/*! \relates Dense_Row */
22032inline void
22033iter_swap(std::vector<Dense_Row>::iterator x,
22034          std::vector<Dense_Row>::iterator y) {
22035  swap(*x, *y);
22036}
22037
22038} // namespace Parma_Polyhedra_Library
22039
22040/* Automatically generated from PPL source file ../src/Dense_Row_templates.hh line 1. */
22041/* Dense_Row class implementation: non-inline template functions.
22042*/
22043
22044
22045namespace Parma_Polyhedra_Library {
22046
22047
22048template <typename Func1, typename Func2>
22049void
22050Dense_Row::combine_needs_first(const Dense_Row& y, const Func1& /* f */,
22051                               const Func2& g) {
22052  for (dimension_type i = size(); i-- > 0; ) {
22053    g((*this)[i], y[i]);
22054  }
22055}
22056
22057template <typename Func1, typename Func2>
22058void
22059Dense_Row::combine_needs_second(const Dense_Row& y, const Func1& g,
22060                                const Func2& /* h */) {
22061  for (dimension_type i = size(); i-- > 0; ) {
22062    g((*this)[i], y[i]);
22063  }
22064}
22065
22066template <typename Func1, typename Func2, typename Func3>
22067void
22068Dense_Row::combine(const Dense_Row& y, const Func1& /* f */, const Func2& g,
22069                   const Func3& /* h */) {
22070  for (dimension_type i = size(); i-- > 0; ) {
22071    g((*this)[i], y[i]);
22072  }
22073}
22074
22075} // namespace Parma_Polyhedra_Library
22076
22077/* Automatically generated from PPL source file ../src/Dense_Row_defs.hh line 561. */
22078
22079/* Automatically generated from PPL source file ../src/Sparse_Row_defs.hh line 1. */
22080/* Sparse_Row class declaration.
22081*/
22082
22083
22084/* Automatically generated from PPL source file ../src/Sparse_Row_defs.hh line 28. */
22085
22086/* Automatically generated from PPL source file ../src/CO_Tree_defs.hh line 1. */
22087/* CO_Tree class declaration.
22088*/
22089
22090
22091/* Automatically generated from PPL source file ../src/CO_Tree_types.hh line 1. */
22092
22093
22094namespace Parma_Polyhedra_Library {
22095
22096class CO_Tree;
22097
22098} // namespace Parma_Polyhedra_Library
22099
22100/* Automatically generated from PPL source file ../src/CO_Tree_defs.hh line 28. */
22101
22102/* Automatically generated from PPL source file ../src/CO_Tree_defs.hh line 30. */
22103#include <memory>
22104#include <cstddef>
22105
22106#ifndef PPL_CO_TREE_EXTRA_DEBUG
22107#ifdef PPL_ABI_BREAKING_EXTRA_DEBUG
22108#ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
22109/*!
22110  \brief
22111  Enables extra debugging information for class CO_Tree.
22112
22113  \ingroup PPL_CXX_interface
22114  When <CODE>PPL_CO_TREE_EXTRA_DEBUG</CODE> evaluates to <CODE>true</CODE>,
22115  each CO_Tree iterator and const_iterator carries a pointer to the associated
22116  tree; this enables extra consistency checks to be performed.
22117*/
22118#endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
22119#define PPL_CO_TREE_EXTRA_DEBUG 1
22120#else // !defined(PPL_ABI_BREAKING_EXTRA_DEBUG)
22121#define PPL_CO_TREE_EXTRA_DEBUG 0
22122#endif // !defined(PPL_ABI_BREAKING_EXTRA_DEBUG)
22123#endif // !defined(PPL_CO_TREE_EXTRA_DEBUG)
22124
22125
22126namespace Parma_Polyhedra_Library {
22127
22128#ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
22129//! A cache-oblivious binary search tree of pairs.
22130/*! \ingroup PPL_CXX_interface
22131  This class implements a binary search tree with keys of dimension_type type
22132  and data of Coefficient type, laid out in a dynamically-sized array.
22133
22134  The array-based layout saves calls to new/delete (to insert \f$n\f$ elements
22135  only \f$O(\log n)\f$ allocations are performed) and, more importantly, is
22136  much more cache-friendly than a standard (pointer-based) tree, because the
22137  elements are stored sequentially in memory (leaving some holes to allow
22138  fast insertion of new elements).
22139  The downside of this representation is that all iterators are invalidated
22140  when an element is added or removed, because the array could have been
22141  enlarged or shrunk. This is partially addressed by providing references to
22142  internal end iterators that are updated when needed.
22143
22144  B-trees are cache-friendly too, but the cache size is fixed (usually at
22145  compile-time). This raises two problems: firstly the cache size must be
22146  known in advance and those data structures do not perform well with other
22147  cache sizes and, secondly, even if the cache size is known, the
22148  optimizations target only one level of cache. This kind of data structures
22149  are called cache aware. This implementation, instead, is cache oblivious:
22150  it performs well with every cache size, and thus exploits all of the
22151  available caches.
22152
22153  Assuming \p n is the number of elements in the tree and \p B is the number
22154  of (dimension_type, Coefficient) pairs that fit in a cache line, the
22155  time and cache misses complexities are the following:
22156
22157  - Insertions/Queries/Deletions: \f$O(\log^2 n)\f$ time,
22158                                  \f$O(\log \frac{n}{B}))\f$ cache misses.
22159  - Tree traversal from begin() to end(), using an %iterator: \f$O(n)\f$ time,
22160         \f$O(\frac{n}{B})\f$  cache misses.
22161  - Queries with a hint: \f$O(\log k)\f$ time and \f$O(\log \frac{k}{B})\f$
22162    cache misses, where k is the distance between the given %iterator and the
22163    searched element (or the position where it would have been).
22164
22165  The binary search tree is embedded in a (slightly bigger) complete tree,
22166  that is enlarged and shrunk when needed. The complete tree is laid out
22167  in an in-order DFS layout in two arrays: one for the keys and one for the
22168  associated data.
22169  The indexes and values are stored in different arrays to reduce
22170  cache-misses during key queries.
22171
22172  The tree can store up to \f$(-(dimension_type)1)/100\f$ elements.
22173  This limit allows faster density computations, but can be removed if needed.
22174*/
22175#endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
22176class CO_Tree {
22177
22178public:
22179  class const_iterator;
22180  class iterator;
22181
22182private:
22183  //! This is used for node heights and depths in the tree.
22184  typedef unsigned height_t;
22185
22186  PPL_COMPILE_TIME_CHECK(C_Integer<height_t>::max
22187                         >= sizeof_to_bits(sizeof(dimension_type)),
22188                         "height_t is too small to store depths.");
22189
22190  class tree_iterator;
22191
22192  // This must be declared here, because it is a friend of const_iterator.
22193  //! Returns the index of the current element in the DFS layout of the
22194  //! complete tree.
22195  /*!
22196    \return the index of the current element in the DFS layout of the complete
22197            tree.
22198
22199    \param itr the iterator that points to the desired element.
22200  */
22201  dimension_type dfs_index(const_iterator itr) const;
22202
22203  // This must be declared here, because it is a friend of iterator.
22204  //! Returns the index of the current element in the DFS layout of the
22205  //! complete tree.
22206  /*!
22207    \return the index of the current element in the DFS layout of the complete
22208            tree.
22209
22210    \param itr the iterator that points to the desired element.
22211  */
22212  dimension_type dfs_index(iterator itr) const;
22213
22214public:
22215
22216  //! The type of the data elements associated with keys.
22217  /*!
22218    If this is changed, occurrences of Coefficient_zero() in the CO_Tree
22219    implementation have to be replaced with constants of the correct type.
22220  */
22221  typedef Coefficient data_type;
22222  typedef Coefficient_traits::const_reference data_type_const_reference;
22223
22224  //! A const %iterator on the tree elements, ordered by key.
22225  /*!
22226    Iterator increment and decrement operations are \f$O(1)\f$ time.
22227    These iterators are invalidated by operations that add or remove elements
22228    from the tree.
22229  */
22230  class const_iterator {
22231  private:
22232  public:
22233
22234    typedef std::bidirectional_iterator_tag iterator_category;
22235    typedef const data_type value_type;
22236    typedef std::ptrdiff_t difference_type;
22237    typedef value_type* pointer;
22238    typedef data_type_const_reference reference;
22239
22240    //! Constructs an invalid const_iterator.
22241    /*!
22242      This constructor takes \f$O(1)\f$ time.
22243    */
22244    explicit const_iterator();
22245
22246    //! Constructs an %iterator pointing to the first element of the tree.
22247    /*!
22248      \param tree
22249      The tree that the new %iterator will point to.
22250
22251      This constructor takes \f$O(1)\f$ time.
22252    */
22253    explicit const_iterator(const CO_Tree& tree);
22254
22255    //! Constructs a const_iterator pointing to the i-th node of the tree.
22256    /*!
22257      \param tree
22258      The tree that the new %iterator will point to.
22259
22260      \param i
22261      The index of the element in \p tree to which the %iterator will point
22262      to.
22263
22264      The i-th node must be a node with a value or end().
22265
22266      This constructor takes \f$O(1)\f$ time.
22267    */
22268    const_iterator(const CO_Tree& tree, dimension_type i);
22269
22270    //! The copy constructor.
22271    /*!
22272      \param itr
22273      The %iterator that will be copied.
22274
22275      This constructor takes \f$O(1)\f$ time.
22276    */
22277    const_iterator(const const_iterator& itr);
22278
22279    //! Converts an iterator into a const_iterator.
22280    /*!
22281      \param itr
22282      The iterator that will be converted into a const_iterator.
22283
22284      This constructor takes \f$O(1)\f$ time.
22285    */
22286    const_iterator(const iterator& itr);
22287
22288    //! Swaps itr with *this.
22289    /*!
22290      \param itr
22291      The %iterator that will be swapped with *this.
22292
22293      This method takes \f$O(1)\f$ time.
22294    */
22295    void m_swap(const_iterator& itr);
22296
22297    //! Assigns \p itr to *this .
22298    /*!
22299      \param itr
22300      The %iterator that will be assigned into *this.
22301
22302      This method takes \f$O(1)\f$ time.
22303    */
22304    const_iterator& operator=(const const_iterator& itr);
22305
22306    //! Assigns \p itr to *this .
22307    /*!
22308      \param itr
22309      The %iterator that will be assigned into *this.
22310
22311      This method takes \f$O(1)\f$ time.
22312    */
22313    const_iterator& operator=(const iterator& itr);
22314
22315    //! Navigates to the next element.
22316    /*!
22317      This method takes \f$O(1)\f$ time.
22318    */
22319    const_iterator& operator++();
22320
22321    //! Navigates to the previous element.
22322    /*!
22323      This method takes \f$O(1)\f$ time.
22324    */
22325    const_iterator& operator--();
22326
22327    //! Navigates to the next element.
22328    /*!
22329      This method takes \f$O(1)\f$ time.
22330    */
22331    const_iterator operator++(int);
22332
22333    //! Navigates to the previous element.
22334    /*!
22335      This method takes \f$O(1)\f$ time.
22336    */
22337    const_iterator operator--(int);
22338
22339    //! Returns the current element.
22340    data_type_const_reference operator*() const;
22341
22342    //! Returns the index of the element pointed to by \c *this.
22343    /*!
22344      \returns the index of the element pointed to by \c *this.
22345    */
22346    dimension_type index() const;
22347
22348    //! Compares \p *this with x .
22349    /*!
22350      \param x
22351      The %iterator that will be compared with *this.
22352    */
22353    bool operator==(const const_iterator& x) const;
22354
22355    //! Compares \p *this with x .
22356    /*!
22357      \param x
22358      The %iterator that will be compared with *this.
22359    */
22360    bool operator!=(const const_iterator& x) const;
22361
22362  private:
22363    //! Checks the internal invariants, in debug mode only.
22364    bool OK() const;
22365
22366    //! A pointer to the corresponding element of the tree's indexes[] array.
22367    const dimension_type* current_index;
22368
22369    //! A pointer to the corresponding element of the tree's data[] array.
22370    const data_type* current_data;
22371
22372#if PPL_CO_TREE_EXTRA_DEBUG
22373    //! A pointer to the corresponding tree, used for debug purposes only.
22374    const CO_Tree* tree;
22375#endif
22376
22377    friend dimension_type CO_Tree::dfs_index(const_iterator itr) const;
22378  };
22379
22380  //! An %iterator on the tree elements, ordered by key.
22381  /*!
22382    Iterator increment and decrement operations are \f$O(1)\f$ time.
22383    These iterators are invalidated by operations that add or remove elements
22384    from the tree.
22385  */
22386  class iterator {
22387  public:
22388
22389    typedef std::bidirectional_iterator_tag iterator_category;
22390    typedef data_type value_type;
22391    typedef std::ptrdiff_t difference_type;
22392    typedef value_type* pointer;
22393    typedef value_type& reference;
22394
22395    //! Constructs an invalid iterator.
22396    /*!
22397      This constructor takes \f$O(1)\f$ time.
22398    */
22399    iterator();
22400
22401    //! Constructs an %iterator pointing to first element of the tree.
22402    /*!
22403      \param tree
22404      The tree to which the new %iterator will point to.
22405
22406      This constructor takes \f$O(1)\f$ time.
22407    */
22408    explicit iterator(CO_Tree& tree);
22409
22410    //! Constructs an %iterator pointing to the i-th node.
22411    /*!
22412      \param tree
22413      The tree to which the new %iterator will point to.
22414
22415      \param i
22416      The index of the element in \p tree to which the new %iterator will
22417      point to.
22418
22419      The i-th node must be a node with a value or end().
22420
22421      This constructor takes \f$O(1)\f$ time.
22422    */
22423    iterator(CO_Tree& tree, dimension_type i);
22424
22425    //! The constructor from a tree_iterator.
22426    /*!
22427      \param itr
22428      The tree_iterator that will be converted into an iterator.
22429
22430      This is meant for use by CO_Tree only.
22431      This is not private to avoid the friend declaration.
22432
22433      This constructor takes \f$O(1)\f$ time.
22434    */
22435    explicit iterator(const tree_iterator& itr);
22436
22437    //! The copy constructor.
22438    /*!
22439      \param itr
22440      The %iterator that will be copied.
22441
22442      This constructor takes \f$O(1)\f$ time.
22443    */
22444    iterator(const iterator& itr);
22445
22446    //! Swaps itr with *this.
22447    /*!
22448      \param itr
22449      The %iterator that will be swapped with *this.
22450
22451      This method takes \f$O(1)\f$ time.
22452    */
22453    void m_swap(iterator& itr);
22454
22455    //! Assigns \p itr to *this .
22456    /*!
22457      \param itr
22458      The %iterator that will be assigned into *this.
22459
22460      This method takes \f$O(1)\f$ time.
22461    */
22462    iterator& operator=(const iterator& itr);
22463
22464    //! Assigns \p itr to *this .
22465    /*!
22466      \param itr
22467      The %iterator that will be assigned into *this.
22468
22469      This method takes \f$O(1)\f$ time.
22470    */
22471    iterator& operator=(const tree_iterator& itr);
22472
22473    //! Navigates to the next element in the tree.
22474    /*!
22475      This method takes \f$O(1)\f$ time.
22476    */
22477    iterator& operator++();
22478
22479    //! Navigates to the previous element in the tree.
22480    /*!
22481      This method takes \f$O(1)\f$ time.
22482    */
22483    iterator& operator--();
22484
22485    //! Navigates to the next element in the tree.
22486    /*!
22487      This method takes \f$O(1)\f$ time.
22488    */
22489    iterator operator++(int);
22490
22491    //! Navigates to the previous element in the tree.
22492    /*!
22493      This method takes \f$O(1)\f$ time.
22494    */
22495    iterator operator--(int);
22496
22497    //! Returns the current element.
22498    data_type& operator*();
22499
22500    //! Returns the current element.
22501    data_type_const_reference operator*() const;
22502
22503    //! Returns the index of the element pointed to by \c *this.
22504    /*!
22505      \returns the index of the element pointed to by \c *this.
22506    */
22507    dimension_type index() const;
22508
22509    //! Compares \p *this with x .
22510    /*!
22511      \param x
22512      The %iterator that will be compared with *this.
22513    */
22514    bool operator==(const iterator& x) const;
22515
22516    //! Compares \p *this with x .
22517    /*!
22518      \param x
22519      The %iterator that will be compared with *this.
22520    */
22521    bool operator!=(const iterator& x) const;
22522
22523  private:
22524    //! Checks the internal invariants, in debug mode only.
22525    bool OK() const;
22526
22527    //! A pointer to the corresponding element of the tree's indexes[] array.
22528    const dimension_type* current_index;
22529
22530    //! A pointer to the corresponding element of the tree's data[] array.
22531    data_type* current_data;
22532
22533#if PPL_CO_TREE_EXTRA_DEBUG
22534    //! A pointer to the corresponding tree, used for debug purposes only.
22535    CO_Tree* tree;
22536#endif
22537
22538    friend const_iterator& const_iterator::operator=(const iterator&);
22539    friend dimension_type CO_Tree::dfs_index(iterator itr) const;
22540  };
22541
22542  //! Constructs an empty tree.
22543  /*!
22544    This constructor takes \f$O(1)\f$ time.
22545  */
22546  CO_Tree();
22547
22548  //! The copy constructor.
22549  /*!
22550    \param y
22551    The tree that will be copied.
22552
22553    This constructor takes \f$O(n)\f$ time.
22554  */
22555  CO_Tree(const CO_Tree& y);
22556
22557  //! A constructor from a sequence of \p n elements.
22558  /*!
22559    \param i
22560    An iterator that points to the first element of the sequence.
22561
22562    \param n
22563    The number of elements in the [i, i_end) sequence.
22564
22565    i must be an input iterator on a sequence of data_type elements,
22566    sorted by index.
22567    Objects of Iterator type must have an index() method that returns the
22568    index with which the element pointed to by the iterator must be inserted.
22569
22570    This constructor takes \f$O(n)\f$ time, so it is more efficient than
22571    the construction of an empty tree followed by n insertions, that would
22572    take \f$O(n*\log^2 n)\f$ time.
22573  */
22574  template <typename Iterator>
22575  CO_Tree(Iterator i, dimension_type n);
22576
22577  //! The assignment operator.
22578  /*!
22579    \param y
22580    The tree that will be assigned to *this.
22581
22582    This method takes \f$O(n)\f$ time.
22583  */
22584  CO_Tree& operator=(const CO_Tree& y);
22585
22586  //! Removes all elements from the tree.
22587  /*!
22588    This method takes \f$O(n)\f$ time.
22589  */
22590  void clear();
22591
22592  //! The destructor.
22593  /*!
22594    This destructor takes \f$O(n)\f$ time.
22595  */
22596  ~CO_Tree();
22597
22598  //! Returns \p true if the tree has no elements.
22599  /*!
22600    This method takes \f$O(1)\f$ time.
22601  */
22602  bool empty() const;
22603
22604  //! Returns the number of elements stored in the tree.
22605  /*!
22606    This method takes \f$O(1)\f$ time.
22607  */
22608  dimension_type size() const;
22609
22610  //! Returns the size() of the largest possible CO_Tree.
22611  static dimension_type max_size();
22612
22613  //! Dumps the tree to stdout, for debugging purposes.
22614  void dump_tree() const;
22615
22616  //! Returns the size in bytes of the memory managed by \p *this.
22617  /*!
22618    This method takes \f$O(n)\f$ time.
22619  */
22620  dimension_type external_memory_in_bytes() const;
22621
22622  //! Inserts an element in the tree.
22623  /*!
22624    \returns
22625    An %iterator that points to the inserted pair.
22626
22627    \param key
22628    The key that will be inserted into the tree, associated with the default
22629    data.
22630
22631    If such a pair already exists, an %iterator pointing to that pair is
22632    returned.
22633
22634    This operation invalidates existing iterators.
22635
22636    This method takes \f$O(\log n)\f$ time if the element already exists, and
22637    \f$O(\log^2 n)\f$ amortized time otherwise.
22638  */
22639  iterator insert(dimension_type key);
22640
22641  //! Inserts an element in the tree.
22642  /*!
22643    \returns
22644    An %iterator that points to the inserted element.
22645
22646    \param key
22647    The key that will be inserted into the tree..
22648
22649    \param data
22650    The data that will be inserted into the tree.
22651
22652    If an element with the specified key already exists, its associated data
22653    is set to \p data and an %iterator pointing to that pair is returned.
22654
22655    This operation invalidates existing iterators.
22656
22657    This method takes \f$O(\log n)\f$ time if the element already exists, and
22658    \f$O(\log^2 n)\f$ amortized time otherwise.amortized
22659  */
22660  iterator insert(dimension_type key, data_type_const_reference data);
22661
22662  //! Inserts an element in the tree.
22663  /*!
22664    \return
22665    An %iterator that points to the inserted element.
22666
22667    \param itr
22668    The %iterator used as hint
22669
22670    \param key
22671    The key that will be inserted into the tree, associated with the default
22672    data.
22673
22674    This will be faster if \p itr points near to the place where the new
22675    element will be inserted (or where is already stored).
22676    However, the value of \p itr does not affect the result of this
22677    method, as long it is a valid %iterator for this tree. \p itr may even be
22678    end().
22679
22680    If an element with the specified key already exists, an %iterator pointing
22681    to that pair is returned.
22682
22683    This operation invalidates existing iterators.
22684
22685    This method takes \f$O(\log n)\f$ time if the element already exists, and
22686    \f$O(\log^2 n)\f$ amortized time otherwise.
22687  */
22688  iterator insert(iterator itr, dimension_type key);
22689
22690  //! Inserts an element in the tree.
22691  /*!
22692    \return
22693    An iterator that points to the inserted element.
22694
22695    \param itr
22696    The iterator used as hint
22697
22698    \param key
22699    The key that will be inserted into the tree.
22700
22701    \param data
22702    The data that will be inserted into the tree.
22703
22704    This will be faster if \p itr points near to the place where the new
22705    element will be inserted (or where is already stored).
22706    However, the value of \p itr does not affect the result of this
22707    method, as long it is a valid iterator for this tree. \p itr may even be
22708    end().
22709
22710    If an element with the specified key already exists, its associated data
22711    is set to \p data and an iterator pointing to that pair is returned.
22712
22713    This operation invalidates existing iterators.
22714
22715    This method takes \f$O(\log n)\f$ time if the element already exists,
22716    and \f$O(\log^2 n)\f$ amortized time otherwise.
22717  */
22718  iterator insert(iterator itr, dimension_type key,
22719                  data_type_const_reference data);
22720
22721  //! Erases the element with key \p key from the tree.
22722  /*!
22723    This operation invalidates existing iterators.
22724
22725    \returns an iterator to the next element (or end() if there are no
22726             elements with key greater than \p key ).
22727
22728    \param key
22729    The key of the element that will be erased from the tree.
22730
22731    This method takes \f$O(\log n)\f$ time if the element already exists,
22732    and \f$O(\log^2 n)\f$ amortized time otherwise.
22733  */
22734  iterator erase(dimension_type key);
22735
22736  //! Erases the element pointed to by \p itr from the tree.
22737  /*!
22738    This operation invalidates existing iterators.
22739
22740    \returns an iterator to the next element (or end() if there are no
22741             elements with key greater than \p key ).
22742
22743    \param itr
22744    An iterator pointing to the element that will be erased from the tree.
22745
22746    This method takes \f$O(\log n)\f$ time if the element already exists, and
22747    \f$O(\log^2 n)\f$ amortized time otherwise.
22748  */
22749  iterator erase(iterator itr);
22750
22751  /*!
22752    \brief Removes the element with key \p key (if it exists) and decrements
22753           by 1 all elements' keys that were greater than \p key.
22754
22755    \param key
22756    The key of the element that will be erased from the tree.
22757
22758    This operation invalidates existing iterators.
22759
22760    This method takes \f$O(k+\log^2 n)\f$ expected time, where k is the number
22761    of elements with keys greater than \p key.
22762  */
22763  void erase_element_and_shift_left(dimension_type key);
22764
22765  //! Adds \p n to all keys greater than or equal to \p key.
22766  /*!
22767    \param key
22768    The key of the first element whose key will be increased.
22769
22770    \param n
22771    Specifies how much the keys will be increased.
22772
22773    This method takes \f$O(k+\log n)\f$ expected time, where k is the number
22774    of elements with keys greater than or equal to \p key.
22775  */
22776  void increase_keys_from(dimension_type key, dimension_type n);
22777
22778  //! Sets to \p i the key of *itr. Assumes that i<=itr.index() and that there
22779  //! are no elements with keys in [i,itr.index()).
22780  /*!
22781    All existing iterators remain valid.
22782
22783    This method takes \f$O(1)\f$ time.
22784  */
22785  void fast_shift(dimension_type i, iterator itr);
22786
22787  //! Swaps x with *this.
22788  /*!
22789    \param x
22790    The tree that will be swapped with *this.
22791
22792    This operation invalidates existing iterators.
22793
22794    This method takes \f$O(1)\f$ time.
22795  */
22796  void m_swap(CO_Tree& x);
22797
22798  //! Returns an iterator that points at the first element.
22799  /*!
22800    This method takes \f$O(1)\f$ time.
22801  */
22802  iterator begin();
22803
22804  //! Returns an iterator that points after the last element.
22805  /*!
22806    This method always returns a reference to the same internal %iterator,
22807    that is updated at each operation that modifies the structure.
22808    Client code can keep a const reference to that %iterator instead of
22809    keep updating a local %iterator.
22810
22811    This method takes \f$O(1)\f$ time.
22812  */
22813  const iterator& end();
22814
22815  //! Equivalent to cbegin().
22816  const_iterator begin() const;
22817
22818  //! Equivalent to cend().
22819  const const_iterator& end() const;
22820
22821  //! Returns a const_iterator that points at the first element.
22822  /*!
22823    This method takes \f$O(1)\f$ time.
22824  */
22825  const_iterator cbegin() const;
22826
22827  //! Returns a const_iterator that points after the last element.
22828  /*!
22829    This method always returns a reference to the same internal %iterator,
22830    that is updated at each operation that modifies the structure.
22831    Client code can keep a const reference to that %iterator instead of
22832    keep updating a local %iterator.
22833
22834    This method takes \f$O(1)\f$ time.
22835  */
22836  const const_iterator& cend() const;
22837
22838  //! Searches an element with key \p key using bisection.
22839  /*!
22840    \param key
22841    The key that will be searched for.
22842
22843    If the element is found, an %iterator pointing to that element is
22844    returned; otherwise, the returned %iterator refers to the immediately
22845    preceding or succeeding value.
22846    If the tree is empty, end() is returned.
22847
22848    This method takes \f$O(\log n)\f$ time.
22849  */
22850  iterator bisect(dimension_type key);
22851
22852  //! Searches an element with key \p key using bisection.
22853  /*!
22854    \param key
22855    The key that will be searched for.
22856
22857    If the element is found, an %iterator pointing to that element is
22858    returned; otherwise, the returned %iterator refers to the immediately
22859    preceding or succeeding value.
22860    If the tree is empty, end() is returned.
22861
22862    This method takes \f$O(\log n)\f$ time.
22863  */
22864  const_iterator bisect(dimension_type key) const;
22865
22866  //! Searches an element with key \p key in [first, last] using bisection.
22867  /*!
22868    \param first
22869    An %iterator pointing to the first element in the range.
22870    It must not be end().
22871
22872    \param last
22873    An %iterator pointing to the last element in the range.
22874    Note that this is included in the search.
22875    It must not be end().
22876
22877    \param key
22878    The key that will be searched for.
22879
22880    \return
22881    If the specified key is found, an %iterator pointing to that element is
22882    returned; otherwise, the returned %iterator refers to the immediately
22883    preceding or succeeding value.
22884    If the tree is empty, end() is returned.
22885
22886    This method takes \f$O(\log(last - first + 1))\f$ time.
22887  */
22888  iterator bisect_in(iterator first, iterator last, dimension_type key);
22889
22890  //! Searches an element with key \p key in [first, last] using bisection.
22891  /*!
22892    \param first
22893    An %iterator pointing to the first element in the range.
22894    It must not be end().
22895
22896    \param last
22897    An %iterator pointing to the last element in the range.
22898    Note that this is included in the search.
22899    It must not be end().
22900
22901    \param key
22902    The key that will be searched for.
22903
22904    \return
22905    If the specified key is found, an %iterator pointing to that element is
22906    returned; otherwise, the returned %iterator refers to the immediately
22907    preceding or succeeding value.
22908    If the tree is empty, end() is returned.
22909
22910    This method takes \f$O(\log(last - first + 1))\f$ time.
22911  */
22912  const_iterator bisect_in(const_iterator first, const_iterator last,
22913                           dimension_type key) const;
22914
22915  //! Searches an element with key \p key near \p hint.
22916  /*!
22917    \param hint
22918    An %iterator used as a hint.
22919
22920    \param key
22921    The key that will be searched for.
22922
22923    If the element is found, the returned %iterator points to that element;
22924    otherwise, it points to the immediately preceding or succeeding value.
22925    If the tree is empty, end() is returned.
22926
22927    The value of \p itr does not affect the result of this method, as long it
22928    is a valid %iterator for this tree. \p itr may even be end().
22929
22930    This method takes \f$O(\log n)\f$ time. If the distance between the
22931    returned position and \p hint is \f$O(1)\f$ it takes \f$O(1)\f$ time.
22932  */
22933  iterator bisect_near(iterator hint, dimension_type key);
22934
22935  //! Searches an element with key \p key near \p hint.
22936  /*!
22937    \param hint
22938    An %iterator used as a hint.
22939
22940    \param key
22941    The key that will be searched for.
22942
22943    If the element is found, the returned %iterator points to that element;
22944    otherwise, it points to the immediately preceding or succeeding value.
22945    If the tree is empty, end() is returned.
22946
22947    The value of \p itr does not affect the result of this method, as long it
22948    is a valid %iterator for this tree. \p itr may even be end().
22949
22950    This method takes \f$O(\log n)\f$ time. If the distance between the
22951    returned position and \p hint is \f$O(1)\f$ it takes \f$O(1)\f$ time.
22952  */
22953  const_iterator bisect_near(const_iterator hint, dimension_type key) const;
22954
22955private:
22956
22957  //! Searches an element with key \p key in [first, last] using bisection.
22958  /*!
22959    \param first
22960    The index of the first element in the range.
22961    It must be the index of an element with a value.
22962
22963    \param last
22964    The index of the last element in the range.
22965    It must be the index of an element with a value.
22966    Note that this is included in the search.
22967
22968    \param key
22969    The key that will be searched for.
22970
22971    \return
22972    If the element is found, the index of that element is returned; otherwise,
22973    the returned index refers to the immediately preceding or succeeding
22974    value.
22975
22976    This method takes \f$O(\log n)\f$ time.
22977  */
22978  dimension_type bisect_in(dimension_type first, dimension_type last,
22979                           dimension_type key) const;
22980
22981  //! Searches an element with key \p key near \p hint.
22982  /*!
22983    \param hint
22984    An index used as a hint.
22985    It must be the index of an element with a value.
22986
22987    \param key
22988    The key that will be searched for.
22989
22990    \return
22991    If the element is found, the index of that element is returned; otherwise,
22992    the returned index refers to the immediately preceding or succeeding
22993    value.
22994
22995    This uses a binary progression and then a bisection, so this method is
22996    \f$O(\log n)\f$, and it is \f$O(1)\f$ if the distance between the returned
22997    position and \p hint is \f$O(1)\f$.
22998
22999    This method takes \f$O(\log n)\f$ time. If the distance between the
23000    returned position and \p hint is \f$O(1)\f$ it takes \f$O(1)\f$ time.
23001  */
23002  dimension_type bisect_near(dimension_type hint, dimension_type key) const;
23003
23004  //! Inserts an element in the tree.
23005  /*!
23006    If there is already an element with key \p key in the tree, its
23007    associated data is set to \p data.
23008
23009    This operation invalidates existing iterators.
23010
23011    \return
23012    An %iterator that points to the inserted element.
23013
23014    \param key
23015    The key that will be inserted into the tree.
23016
23017    \param data
23018    The data that will be associated with \p key.
23019
23020    \param itr
23021    It must point to the element in the tree with key \p key or, if no such
23022    element exists, it must point to the node that would be his parent.
23023
23024    This method takes \f$O(1)\f$ time if the element already exists, and
23025    \f$O(\log^2 n)\f$ amortized time otherwise.
23026  */
23027  tree_iterator insert_precise(dimension_type key,
23028                               data_type_const_reference data,
23029                               tree_iterator itr);
23030
23031  //! Helper for \c insert_precise.
23032  /*!
23033    This helper method takes the same arguments as \c insert_precise,
23034    but besides assuming that \p itr is a correct hint, it also assumes
23035    that \p key and \p data are not in the tree; namely, a proper
23036    insertion has to be done and the insertion can not invalidate \p data.
23037  */
23038  tree_iterator insert_precise_aux(dimension_type key,
23039                                   data_type_const_reference data,
23040                                   tree_iterator itr);
23041
23042  //! Inserts an element in the tree.
23043  /*!
23044
23045    \param key
23046    The key that will be inserted into the tree.
23047
23048    \param data
23049    The data that will be associated with \p key.
23050
23051    The tree must be empty.
23052
23053    This operation invalidates existing iterators.
23054
23055    This method takes \f$O(1)\f$ time.
23056  */
23057  void insert_in_empty_tree(dimension_type key,
23058                            data_type_const_reference data);
23059
23060  //! Erases from the tree the element pointed to by \p itr .
23061  /*!
23062    This operation invalidates existing iterators.
23063
23064    \returns
23065    An %iterator to the next element (or end() if there are no elements with
23066    key greater than \p key ).
23067
23068    \param itr
23069    An %iterator pointing to the element that will be erased.
23070
23071    This method takes \f$O(\log^2 n)\f$ amortized time.
23072  */
23073  iterator erase(tree_iterator itr);
23074
23075  //! Initializes a tree with reserved size at least \p n .
23076  /*!
23077    \param n
23078    A lower bound on the tree's desired reserved size.
23079
23080    This method takes \f$O(n)\f$ time.
23081  */
23082  void init(dimension_type n);
23083
23084  //! Deallocates the tree's dynamic arrays.
23085  /*!
23086    After this call, the tree fields are uninitialized, so init() must be
23087    called again before using the tree.
23088
23089    This method takes \f$O(n)\f$ time.
23090  */
23091  void destroy();
23092
23093  //! Checks the internal invariants, but not the densities.
23094  bool structure_OK() const;
23095
23096  //! Checks the internal invariants.
23097  bool OK() const;
23098
23099  //! Returns the floor of the base-2 logarithm of \p n .
23100  /*!
23101    \param n
23102    It must be greater than zero.
23103
23104    This method takes \f$O(\log n)\f$ time.
23105  */
23106  static unsigned integer_log2(dimension_type n);
23107
23108  //! Compares the fractions numer/denom with ratio/100.
23109  /*!
23110    \returns Returns true if the fraction numer/denom is less
23111    than the fraction ratio/100.
23112
23113    \param ratio
23114    It must be less than or equal to 100.
23115
23116    \param numer
23117    The numerator of the fraction.
23118
23119    \param denom
23120    The denominator of the fraction.
23121
23122    This method takes \f$O(1)\f$ time.
23123  */
23124  static bool is_less_than_ratio(dimension_type numer, dimension_type denom,
23125                                 dimension_type ratio);
23126
23127  //! Compares the fractions numer/denom with ratio/100.
23128  /*!
23129    \returns
23130    Returns true if the fraction numer/denom is greater than the fraction
23131    ratio/100.
23132
23133    \param ratio
23134    It must be less than or equal to 100.
23135
23136    \param numer
23137    The numerator of the fraction.
23138
23139    \param denom
23140    The denominator of the fraction.
23141
23142    This method takes \f$O(1)\f$ time.
23143  */
23144  static bool is_greater_than_ratio(dimension_type numer, dimension_type denom,
23145                                    dimension_type ratio);
23146
23147  //! Dumps the subtree rooted at \p itr to stdout, for debugging purposes.
23148  /*!
23149    \param itr
23150    A tree_iterator pointing to the root of the desired subtree.
23151  */
23152  static void dump_subtree(tree_iterator itr);
23153
23154  //! Increases the tree's reserved size.
23155  /*!
23156    This is called when the density is about to exceed the maximum density
23157    (specified by max_density_percent).
23158
23159    This method takes \f$O(n)\f$ time.
23160  */
23161  void rebuild_bigger_tree();
23162
23163  //! Decreases the tree's reserved size.
23164  /*!
23165    This is called when the density is about to become less than the minimum
23166    allowed density (specified by min_density_percent).
23167
23168    \p reserved_size must be greater than 3 (otherwise the tree can just be
23169    cleared).
23170
23171    This method takes \f$O(n)\f$ time.
23172  */
23173  void rebuild_smaller_tree();
23174
23175  //! Re-initializes the cached iterators.
23176  /*!
23177    This method must be called when the indexes[] and data[] vector are
23178    reallocated.
23179
23180    This method takes \f$O(1)\f$ time.
23181  */
23182  void refresh_cached_iterators();
23183
23184  //! Rebalances the tree.
23185  /*!
23186    For insertions, it adds the pair (key, value) in the process.
23187
23188    This operation invalidates existing iterators that point to nodes in the
23189    rebalanced subtree.
23190
23191    \returns an %iterator pointing to the root of the subtree that was
23192             rebalanced.
23193
23194    \param itr
23195    It points to the node where the new element has to be inserted or where an
23196    element has just been deleted.
23197
23198    \param key
23199    The index that will be inserted in the tree (for insertions only).
23200
23201    \param value
23202    The value that will be inserted in the tree (for insertions only).
23203
23204    This method takes \f$O(\log^2 n)\f$ amortized time.
23205  */
23206  tree_iterator rebalance(tree_iterator itr, dimension_type key,
23207                          data_type_const_reference value);
23208
23209  //! Moves all elements of a subtree to the rightmost end.
23210  /*!
23211    \returns
23212    The index of the rightmost unused node in the subtree after the process.
23213
23214    \param last_in_subtree
23215    It is the index of the last element in the subtree.
23216
23217    \param subtree_size
23218    It is the number of valid elements in the subtree.
23219    It must be greater than zero.
23220
23221    \param key
23222    The key that may be added to the tree if add_element is \c true.
23223
23224    \param value
23225    The value that may be added to the tree if add_element is \c true.
23226
23227    \param add_element
23228    If it is true, it tries to add an element with key \p key and value
23229    \p value in the process (but it may not).
23230
23231    This method takes \f$O(k)\f$ time, where k is \p subtree_size.
23232  */
23233  dimension_type compact_elements_in_the_rightmost_end(
23234    dimension_type last_in_subtree, dimension_type subtree_size,
23235    dimension_type key, data_type_const_reference value,
23236    bool add_element);
23237
23238  //! Redistributes the elements in the subtree rooted at \p root_index.
23239  /*!
23240    The subtree's elements must be compacted to the rightmost end.
23241
23242    \param root_index
23243    The index of the subtree's root node.
23244
23245    \param subtree_size
23246    It is the number of used elements in the subtree.
23247    It must be greater than zero.
23248
23249    \param last_used
23250    It points to the leftmost element with a value in the subtree.
23251
23252    \param add_element
23253    If it is true, this method adds an element with the specified key and
23254    value in the process.
23255
23256    \param key
23257    The key that will be added to the tree if \p add_element is \c true.
23258
23259    \param value
23260    The data that will be added to the tree if \p add_element is \c true.
23261
23262    This method takes \f$O(k)\f$ time, where k is \p subtree_size.
23263  */
23264  void redistribute_elements_in_subtree(dimension_type root_index,
23265                                        dimension_type subtree_size,
23266                                        dimension_type last_used,
23267                                        dimension_type key,
23268                                        data_type_const_reference value,
23269                                        bool add_element);
23270
23271  //! Moves all data in the tree \p tree into *this.
23272  /*!
23273    \param tree
23274    The tree from which the element will be moved into *this.
23275
23276    *this must be empty and big enough to contain all of tree's data without
23277    exceeding max_density.
23278
23279    This method takes \f$O(n)\f$ time.
23280  */
23281  void move_data_from(CO_Tree& tree);
23282
23283  //! Copies all data in the tree \p tree into *this.
23284  /*!
23285    \param tree
23286    The tree from which the element will be copied into *this.
23287
23288    *this must be empty and must have the same reserved size of \p tree.
23289    this->OK() may return false before this method is called, but
23290    this->structure_OK() must return true.
23291
23292    This method takes \f$O(n)\f$ time.
23293  */
23294  void copy_data_from(const CO_Tree& tree);
23295
23296  //! Counts the number of used elements in the subtree rooted at itr.
23297  /*!
23298    \param itr
23299    An %iterator pointing to the root of the desired subtree.
23300
23301    This method takes \f$O(k)\f$ time, where k is the number of elements in
23302    the subtree.
23303  */
23304  static dimension_type count_used_in_subtree(tree_iterator itr);
23305
23306  //! Moves the value of \p from in \p to .
23307  /*!
23308    \param from
23309    It must be a valid value.
23310
23311    \param to
23312    It must be a non-constructed chunk of memory.
23313
23314    After the move, \p from becomes a non-constructed chunk of memory and
23315    \p to gets the value previously stored by \p from.
23316
23317    The implementation of this method assumes that data_type values do not
23318    keep pointers to themselves nor to their fields.
23319
23320    This method takes \f$O(1)\f$ time.
23321  */
23322  static void move_data_element(data_type& to, data_type& from);
23323
23324  //! The maximum density of used nodes.
23325  /*!
23326    This must be greater than or equal to 50 and lower than 100.
23327  */
23328  static const dimension_type max_density_percent = 91;
23329
23330  //! The minimum density of used nodes.
23331  /*!
23332    Must be strictly lower than the half of max_density_percent.
23333  */
23334  static const dimension_type min_density_percent = 38;
23335
23336  //! The minimum density at the leaves' depth.
23337  /*!
23338    Must be greater than zero and strictly lower than min_density_percent.
23339
23340    Increasing the value is safe but leads to time inefficiencies
23341    (measured against ppl_lpsol on 24 August 2010), because it forces trees to
23342    be more balanced, increasing the cost of rebalancing.
23343  */
23344  static const dimension_type min_leaf_density_percent = 1;
23345
23346  //! An index used as a marker for unused nodes in the tree.
23347  /*!
23348    This must not be used as a key.
23349  */
23350  static const dimension_type unused_index = C_Integer<dimension_type>::max;
23351
23352  //! The %iterator returned by end().
23353  /*!
23354    It is updated when needed, to keep it valid.
23355  */
23356  iterator cached_end;
23357
23358  //! The %iterator returned by the const version of end().
23359  /*!
23360    It is updated when needed, to keep it valid.
23361  */
23362  const_iterator cached_const_end;
23363
23364  //! The depth of the leaves in the complete tree.
23365  height_t max_depth;
23366
23367  //! The vector that contains the keys in the tree.
23368  /*!
23369    If an element of this vector is \p unused_index , it means that that
23370    element and the corresponding element of data[] are not used.
23371
23372    Its size is reserved_size + 2, because the first and the last elements
23373    are used as markers for iterators.
23374  */
23375  dimension_type* indexes;
23376
23377  //! The allocator used to allocate/deallocate data.
23378  std::allocator<data_type> data_allocator;
23379
23380  //! The vector that contains the data of the keys in the tree.
23381  /*!
23382    If index[i] is \p unused_index, data[i] is unused.
23383    Otherwise, data[i] contains the data associated to the indexes[i] key.
23384
23385    Its size is reserved_size + 1, because the first element is not used (to
23386    allow using the same index in both indexes[] and data[] instead of
23387    adding 1 to access data[]).
23388  */
23389  data_type* data;
23390
23391  //! The number of nodes in the complete tree.
23392  /*!
23393    It is one less than a power of 2.
23394    If this is 0, data and indexes are set to NULL.
23395  */
23396  dimension_type reserved_size;
23397
23398  //! The number of values stored in the tree.
23399  dimension_type size_;
23400};
23401
23402class CO_Tree::tree_iterator {
23403
23404public:
23405
23406  /*!
23407    \brief Constructs a tree_iterator pointing at the root node of the
23408           specified tree
23409
23410    \param tree
23411    The tree to which the new %iterator will point to.
23412    It must not be empty.
23413  */
23414  explicit tree_iterator(CO_Tree& tree);
23415
23416  //! Constructs a tree_iterator pointing at the specified node of the tree.
23417  /*!
23418    \param tree
23419    The tree to which the new %iterator will point to.
23420    It must not be empty.
23421
23422    \param i
23423    The index of the element in \p tree to which the new %iterator will point
23424    to.
23425  */
23426  tree_iterator(CO_Tree& tree, dimension_type i);
23427
23428  //! Constructs a tree_iterator from an iterator.
23429  /*!
23430    \param itr
23431    The iterator that will be converted into a tree_iterator.
23432    It must not be end().
23433
23434    \param tree
23435    The tree to which the new %iterator will point to.
23436    It must not be empty.
23437  */
23438  tree_iterator(const iterator& itr, CO_Tree& tree);
23439
23440  //! The assignment operator.
23441  /*!
23442    \param itr
23443    The %iterator that will be assigned into *this.
23444  */
23445  tree_iterator& operator=(const tree_iterator& itr);
23446
23447  //! The assignment operator from an iterator.
23448  /*!
23449    \param itr
23450    The iterator that will be assigned into *this.
23451  */
23452  tree_iterator& operator=(const iterator& itr);
23453
23454  //! Compares *this with \p itr.
23455  /*!
23456    \param itr
23457    The %iterator that will compared with *this.
23458  */
23459  bool operator==(const tree_iterator& itr) const;
23460
23461  //! Compares *this with \p itr.
23462  /*!
23463    \param itr
23464    The %iterator that will compared with *this.
23465  */
23466  bool operator!=(const tree_iterator& itr) const;
23467
23468  //! Makes the %iterator point to the root of \p tree.
23469  /*!
23470    The values of all fields (beside tree) are overwritten.
23471
23472    This method takes \f$O(1)\f$ time.
23473  */
23474  void get_root();
23475
23476  //! Makes the %iterator point to the left child of the current node.
23477  /*!
23478    This method takes \f$O(1)\f$ time.
23479  */
23480  void get_left_child();
23481
23482  //! Makes the %iterator point to the right child of the current node.
23483  /*!
23484    This method takes \f$O(1)\f$ time.
23485  */
23486  void get_right_child();
23487
23488  //! Makes the %iterator point to the parent of the current node.
23489  /*!
23490    This method takes \f$O(1)\f$ time.
23491  */
23492  void get_parent();
23493
23494  /*!
23495    \brief Searches for an element with key \p key in the subtree rooted at
23496           \p *this.
23497
23498    \param key
23499    The searched for key.
23500
23501    After this method, *this points to the found node (if it exists) or to
23502    the node that would be his parent (otherwise).
23503
23504    This method takes \f$O(\log n)\f$ time.
23505  */
23506  void go_down_searching_key(dimension_type key);
23507
23508  /*!
23509    \brief Follows left children with a value, until it arrives at a leaf or at
23510           a node with no value.
23511
23512    This method takes \f$O(1)\f$ time.
23513  */
23514  void follow_left_children_with_value();
23515
23516  /*!
23517    \brief Follows right children with a value, until it arrives at a leaf or at
23518           a node with no value.
23519
23520    This method takes \f$O(1)\f$ time.
23521  */
23522  void follow_right_children_with_value();
23523
23524  //! Returns true if the pointed node is the root node.
23525  /*!
23526    This method takes \f$O(1)\f$ time.
23527  */
23528  bool is_root() const;
23529
23530  //! Returns true if the pointed node has a parent and is its right child.
23531  /*!
23532    This method takes \f$O(1)\f$ time.
23533  */
23534  bool is_right_child() const;
23535
23536  //! Returns true if the pointed node is a leaf of the complete tree.
23537  /*!
23538    This method takes \f$O(1)\f$ time.
23539  */
23540  bool is_leaf() const;
23541
23542  //! Returns the key and value of the current node.
23543  data_type& operator*();
23544
23545  //! Returns the key and value of the current node.
23546  Coefficient_traits::const_reference operator*() const;
23547
23548  //! Returns a reference to the index of the element pointed to by \c *this.
23549  /*!
23550    \returns a reference to the index of the element pointed to by \c *this.
23551  */
23552  dimension_type& index();
23553
23554  //! Returns the index of the element pointed to by \c *this.
23555  /*!
23556    \returns the index of the element pointed to by \c *this.
23557  */
23558  dimension_type index() const;
23559
23560  //! Returns the index of the node pointed to by \c *this.
23561  /*!
23562    \returns the key of the node pointed to by \c *this, or unused_index if
23563             the current node does not contain a valid element.
23564  */
23565  dimension_type key() const;
23566
23567  //! The tree containing the element pointed to by this %iterator.
23568  CO_Tree& tree;
23569
23570  /*!
23571    \brief Returns the index of the current node in the DFS layout of the
23572           complete tree.
23573  */
23574  dimension_type dfs_index() const;
23575
23576  /*!
23577    \brief Returns 2^h, with h the height of the current node in the tree,
23578           counting from 0.
23579
23580    Thus leaves have offset 1.
23581    This is faster than depth(), so it is useful to compare node depths.
23582
23583    This method takes \f$O(1)\f$ time.
23584  */
23585  dimension_type get_offset() const;
23586
23587  //! Returns the depth of the current node in the complete tree.
23588  /*!
23589    This method takes \f$O(\log n)\f$ time.
23590  */
23591  height_t depth() const;
23592
23593private:
23594  //! Checks the internal invariant.
23595  bool OK() const;
23596
23597  //! The index of the current node in the DFS layout of the complete tree.
23598  dimension_type i;
23599
23600  /*!
23601    \brief This is 2^h, with h the height of the current node in the tree,
23602           counting from 0.
23603
23604    Thus leaves have offset 1.
23605    This is equal to (i & -i), and is only stored to increase performance.
23606  */
23607  dimension_type offset;
23608};
23609
23610#ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
23611//! Swaps \p x with \p y.
23612/*! \relates CO_Tree */
23613#endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
23614void swap(CO_Tree& x, CO_Tree& y);
23615
23616#ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
23617//! Swaps \p x with \p y.
23618/*! \relates CO_Tree::const_iterator */
23619#endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
23620void swap(CO_Tree::const_iterator& x, CO_Tree::const_iterator& y);
23621
23622#ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
23623//! Swaps \p x with \p y.
23624/*! \relates CO_Tree::iterator */
23625#endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
23626void swap(CO_Tree::iterator& x, CO_Tree::iterator& y);
23627
23628} // namespace Parma_Polyhedra_Library
23629
23630/* Automatically generated from PPL source file ../src/CO_Tree_inlines.hh line 1. */
23631/* CO_Tree class implementation: inline functions.
23632*/
23633
23634
23635#include <cstddef>
23636
23637namespace Parma_Polyhedra_Library {
23638
23639inline dimension_type
23640CO_Tree::dfs_index(const_iterator itr) const {
23641  PPL_ASSERT(itr.current_index != 0);
23642  PPL_ASSERT(itr.current_index >= indexes + 1);
23643  PPL_ASSERT(itr.current_index <= indexes + reserved_size);
23644  const std::ptrdiff_t index = itr.current_index - indexes;
23645  return static_cast<dimension_type>(index);
23646}
23647
23648inline dimension_type
23649CO_Tree::dfs_index(iterator itr) const {
23650  PPL_ASSERT(itr.current_index != 0);
23651  PPL_ASSERT(itr.current_index >= indexes + 1);
23652  PPL_ASSERT(itr.current_index <= indexes + reserved_size);
23653  const std::ptrdiff_t index = itr.current_index - indexes;
23654  return static_cast<dimension_type>(index);
23655}
23656
23657inline
23658CO_Tree::CO_Tree() {
23659  init(0);
23660  PPL_ASSERT(OK());
23661}
23662
23663inline
23664CO_Tree::CO_Tree(const CO_Tree& y) {
23665  PPL_ASSERT(y.OK());
23666  data_allocator = y.data_allocator;
23667  init(y.reserved_size);
23668  copy_data_from(y);
23669}
23670
23671inline CO_Tree&
23672CO_Tree::operator=(const CO_Tree& y) {
23673  if (this != &y) {
23674    destroy();
23675    data_allocator = y.data_allocator;
23676    init(y.reserved_size);
23677    copy_data_from(y);
23678  }
23679  return *this;
23680}
23681
23682inline void
23683CO_Tree::clear() {
23684  *this = CO_Tree();
23685}
23686
23687inline
23688CO_Tree::~CO_Tree() {
23689
23690  destroy();
23691}
23692
23693inline bool
23694CO_Tree::empty() const {
23695  return size_ == 0;
23696}
23697
23698inline dimension_type
23699CO_Tree::size() const {
23700  return size_;
23701}
23702
23703inline dimension_type
23704CO_Tree::max_size() {
23705  return C_Integer<dimension_type>::max/100;
23706}
23707
23708inline void
23709CO_Tree::dump_tree() const {
23710  if (empty()) {
23711    std::cout << "(empty tree)" << std::endl;
23712  }
23713  else {
23714    dump_subtree(tree_iterator(*const_cast<CO_Tree*>(this)));
23715  }
23716}
23717
23718inline CO_Tree::iterator
23719CO_Tree::insert(const dimension_type key) {
23720  if (empty()) {
23721    return insert(key, Coefficient_zero());
23722  }
23723  else {
23724    tree_iterator itr(*this);
23725    itr.go_down_searching_key(key);
23726    if (itr.index() == key) {
23727      return iterator(itr);
23728    }
23729    else {
23730      return iterator(insert_precise(key, Coefficient_zero(), itr));
23731    }
23732  }
23733}
23734
23735inline CO_Tree::iterator
23736CO_Tree::insert(dimension_type key, data_type_const_reference data1) {
23737  if (empty()) {
23738    insert_in_empty_tree(key, data1);
23739    tree_iterator itr(*this);
23740    PPL_ASSERT(itr.index() != unused_index);
23741    return iterator(itr);
23742  }
23743  else {
23744    tree_iterator itr(*this);
23745    itr.go_down_searching_key(key);
23746    return iterator(insert_precise(key, data1, itr));
23747  }
23748}
23749
23750inline CO_Tree::iterator
23751CO_Tree::erase(dimension_type key) {
23752  PPL_ASSERT(key != unused_index);
23753
23754  if (empty()) {
23755    return end();
23756  }
23757
23758  tree_iterator itr(*this);
23759  itr.go_down_searching_key(key);
23760
23761  if (itr.index() == key) {
23762    return erase(itr);
23763  }
23764
23765  iterator result(itr);
23766  if (result.index() < key) {
23767    ++result;
23768  }
23769
23770  PPL_ASSERT(result == end() || result.index() > key);
23771#ifndef NDEBUG
23772  iterator last = end();
23773  --last;
23774  PPL_ASSERT((result == end()) == (last.index() < key));
23775#endif
23776
23777  return result;
23778}
23779
23780inline CO_Tree::iterator
23781CO_Tree::erase(iterator itr) {
23782  PPL_ASSERT(itr != end());
23783  return erase(tree_iterator(itr, *this));
23784}
23785
23786inline void
23787CO_Tree::m_swap(CO_Tree& x) {
23788  using std::swap;
23789  swap(max_depth, x.max_depth);
23790  swap(indexes, x.indexes);
23791  swap(data_allocator, x.data_allocator);
23792  swap(data, x.data);
23793  swap(reserved_size, x.reserved_size);
23794  swap(size_, x.size_);
23795  // Cached iterators have been invalidated by the swap,
23796  // they must be refreshed here.
23797  refresh_cached_iterators();
23798  x.refresh_cached_iterators();
23799  PPL_ASSERT(structure_OK());
23800  PPL_ASSERT(x.structure_OK());
23801}
23802
23803inline CO_Tree::iterator
23804CO_Tree::begin() {
23805  return iterator(*this);
23806}
23807
23808inline const CO_Tree::iterator&
23809CO_Tree::end() {
23810  return cached_end;
23811}
23812
23813inline CO_Tree::const_iterator
23814CO_Tree::begin() const {
23815  return const_iterator(*this);
23816}
23817
23818inline const CO_Tree::const_iterator&
23819CO_Tree::end() const {
23820  return cached_const_end;
23821}
23822
23823inline CO_Tree::const_iterator
23824CO_Tree::cbegin() const {
23825  return const_iterator(*this);
23826}
23827
23828inline const CO_Tree::const_iterator&
23829CO_Tree::cend() const {
23830  return cached_const_end;
23831}
23832
23833inline CO_Tree::iterator
23834CO_Tree::bisect(dimension_type key) {
23835  if (empty()) {
23836    return end();
23837  }
23838  iterator last = end();
23839  --last;
23840  return bisect_in(begin(), last, key);
23841}
23842
23843inline CO_Tree::const_iterator
23844CO_Tree::bisect(dimension_type key) const {
23845  if (empty()) {
23846    return end();
23847  }
23848  const_iterator last = end();
23849  --last;
23850  return bisect_in(begin(), last, key);
23851}
23852
23853inline CO_Tree::iterator
23854CO_Tree::bisect_in(iterator first, iterator last, dimension_type key) {
23855  PPL_ASSERT(first != end());
23856  PPL_ASSERT(last != end());
23857  const dimension_type index
23858    = bisect_in(dfs_index(first), dfs_index(last), key);
23859  return iterator(*this, index);
23860}
23861
23862inline CO_Tree::const_iterator
23863CO_Tree::bisect_in(const_iterator first, const_iterator last,
23864                   dimension_type key) const {
23865  PPL_ASSERT(first != end());
23866  PPL_ASSERT(last != end());
23867  const dimension_type index
23868    = bisect_in(dfs_index(first), dfs_index(last), key);
23869  return const_iterator(*this, index);
23870}
23871
23872inline CO_Tree::iterator
23873CO_Tree::bisect_near(iterator hint, dimension_type key) {
23874  if (hint == end()) {
23875    return bisect(key);
23876  }
23877  const dimension_type index
23878    = bisect_near(dfs_index(hint), key);
23879  return iterator(*this, index);
23880}
23881
23882inline CO_Tree::const_iterator
23883CO_Tree::bisect_near(const_iterator hint, dimension_type key) const {
23884  if (hint == end()) {
23885    return bisect(key);
23886  }
23887  const dimension_type index = bisect_near(dfs_index(hint), key);
23888  return const_iterator(*this, index);
23889}
23890
23891inline void
23892CO_Tree::fast_shift(dimension_type i, iterator itr) {
23893  PPL_ASSERT(itr != end());
23894  PPL_ASSERT(i <= itr.index());
23895  indexes[dfs_index(itr)] = i;
23896  PPL_ASSERT(OK());
23897}
23898
23899inline void
23900CO_Tree::insert_in_empty_tree(dimension_type key,
23901                              data_type_const_reference data1) {
23902  PPL_ASSERT(empty());
23903  rebuild_bigger_tree();
23904  tree_iterator itr(*this);
23905  PPL_ASSERT(itr.index() == unused_index);
23906  new(&(*itr)) data_type(data1);
23907  // Set the index afterwards, so that if the constructor above throws
23908  // the tree's structure is consistent.
23909  itr.index() = key;
23910  ++size_;
23911
23912  PPL_ASSERT(OK());
23913}
23914
23915inline bool
23916CO_Tree::is_less_than_ratio(dimension_type numer, dimension_type denom,
23917                            dimension_type ratio) {
23918  PPL_ASSERT(ratio <= 100);
23919  // If these are true, no overflows are possible.
23920  PPL_ASSERT(denom <= unused_index/100);
23921  PPL_ASSERT(numer <= unused_index/100);
23922  return 100*numer < ratio*denom;
23923}
23924
23925inline bool
23926CO_Tree::is_greater_than_ratio(dimension_type numer, dimension_type denom,
23927                               dimension_type ratio) {
23928  PPL_ASSERT(ratio <= 100);
23929  // If these are true, no overflows are possible.
23930  PPL_ASSERT(denom <= unused_index/100);
23931  PPL_ASSERT(numer <= unused_index/100);
23932  return 100*numer > ratio*denom;
23933}
23934
23935inline void
23936CO_Tree::rebuild_smaller_tree() {
23937  PPL_ASSERT(reserved_size > 3);
23938  CO_Tree new_tree;
23939  new_tree.init(reserved_size / 2);
23940  new_tree.move_data_from(*this);
23941  m_swap(new_tree);
23942  PPL_ASSERT(new_tree.structure_OK());
23943  PPL_ASSERT(structure_OK());
23944}
23945
23946inline void
23947CO_Tree::refresh_cached_iterators() {
23948  cached_end = iterator(*this, reserved_size + 1);
23949  cached_const_end = const_iterator(*this, reserved_size + 1);
23950}
23951
23952inline void
23953CO_Tree::move_data_element(data_type& to, data_type& from) {
23954  /*
23955    The following code is equivalent (but slower):
23956
23957    <CODE>
23958      new(&to) data_type(from);
23959      from.~data_type();
23960    </CODE>
23961  */
23962  std::memcpy(&to, &from, sizeof(data_type));
23963}
23964
23965
23966inline
23967CO_Tree::const_iterator::const_iterator()
23968  : current_index(0), current_data(0) {
23969#if PPL_CO_TREE_EXTRA_DEBUG
23970  tree = 0;
23971#endif
23972  PPL_ASSERT(OK());
23973}
23974
23975inline
23976CO_Tree::const_iterator::const_iterator(const CO_Tree& tree1)
23977  : current_index(&(tree1.indexes[1])), current_data(&(tree1.data[1])) {
23978#if PPL_CO_TREE_EXTRA_DEBUG
23979  tree = &tree1;
23980#endif
23981  if (!tree1.empty()) {
23982    while (*current_index == unused_index) {
23983      ++current_index;
23984      ++current_data;
23985    }
23986  }
23987  PPL_ASSERT(OK());
23988}
23989
23990inline
23991CO_Tree::const_iterator::const_iterator(const CO_Tree& tree1,
23992                                        dimension_type i)
23993  : current_index(&(tree1.indexes[i])), current_data(&(tree1.data[i])) {
23994#if PPL_CO_TREE_EXTRA_DEBUG
23995  tree = &tree1;
23996#endif
23997  PPL_ASSERT(i != 0);
23998  PPL_ASSERT(i <= tree1.reserved_size + 1);
23999  PPL_ASSERT(tree1.empty() || tree1.indexes[i] != unused_index);
24000  PPL_ASSERT(OK());
24001}
24002
24003inline
24004CO_Tree::const_iterator::const_iterator(const const_iterator& itr2) {
24005  (*this) = itr2;
24006  PPL_ASSERT(OK());
24007}
24008
24009inline
24010CO_Tree::const_iterator::const_iterator(const iterator& itr2) {
24011  (*this) = itr2;
24012  PPL_ASSERT(OK());
24013}
24014
24015inline void
24016CO_Tree::const_iterator::m_swap(const_iterator& itr) {
24017  using std::swap;
24018  swap(current_data, itr.current_data);
24019  swap(current_index, itr.current_index);
24020#if PPL_CO_TREE_EXTRA_DEBUG
24021  swap(tree, itr.tree);
24022#endif
24023  PPL_ASSERT(OK());
24024  PPL_ASSERT(itr.OK());
24025}
24026
24027inline CO_Tree::const_iterator&
24028CO_Tree::const_iterator::operator=(const const_iterator& itr2) {
24029  current_index = itr2.current_index;
24030  current_data = itr2.current_data;
24031#if PPL_CO_TREE_EXTRA_DEBUG
24032  tree = itr2.tree;
24033#endif
24034  PPL_ASSERT(OK());
24035  return *this;
24036}
24037
24038inline CO_Tree::const_iterator&
24039CO_Tree::const_iterator::operator=(const iterator& itr2) {
24040  current_index = itr2.current_index;
24041  current_data = itr2.current_data;
24042#if PPL_CO_TREE_EXTRA_DEBUG
24043  tree = itr2.tree;
24044#endif
24045  PPL_ASSERT(OK());
24046  return *this;
24047}
24048
24049inline CO_Tree::const_iterator&
24050CO_Tree::const_iterator::operator++() {
24051  PPL_ASSERT(current_index != 0);
24052  PPL_ASSERT(current_data != 0);
24053#if PPL_CO_TREE_EXTRA_DEBUG
24054  PPL_ASSERT(current_index != &(tree->indexes[tree->reserved_size + 1]));
24055#endif
24056  ++current_index;
24057  ++current_data;
24058  while (*current_index == unused_index) {
24059    ++current_index;
24060    ++current_data;
24061  }
24062  PPL_ASSERT(OK());
24063  return *this;
24064}
24065
24066inline CO_Tree::const_iterator&
24067CO_Tree::const_iterator::operator--() {
24068  PPL_ASSERT(current_index != 0);
24069  PPL_ASSERT(current_data != 0);
24070  --current_index;
24071  --current_data;
24072  while (*current_index == unused_index) {
24073    --current_index;
24074    --current_data;
24075  }
24076  PPL_ASSERT(OK());
24077  return *this;
24078}
24079
24080inline CO_Tree::const_iterator
24081CO_Tree::const_iterator::operator++(int) {
24082  const_iterator itr(*this);
24083  ++(*this);
24084  return itr;
24085}
24086
24087inline CO_Tree::const_iterator
24088CO_Tree::const_iterator::operator--(int) {
24089  const_iterator itr(*this);
24090  --(*this);
24091  return itr;
24092}
24093
24094inline Coefficient_traits::const_reference
24095CO_Tree::const_iterator::operator*() const {
24096  PPL_ASSERT(current_index != 0);
24097  PPL_ASSERT(current_data != 0);
24098  PPL_ASSERT(OK());
24099#if PPL_CO_TREE_EXTRA_DEBUG
24100  PPL_ASSERT(current_index != &(tree->indexes[tree->reserved_size + 1]));
24101#endif
24102  return *current_data;
24103}
24104
24105inline dimension_type
24106CO_Tree::const_iterator::index() const {
24107  PPL_ASSERT(current_index != 0);
24108  PPL_ASSERT(current_data != 0);
24109  PPL_ASSERT(OK());
24110#if PPL_CO_TREE_EXTRA_DEBUG
24111  PPL_ASSERT(current_index != &(tree->indexes[tree->reserved_size + 1]));
24112#endif
24113  return *current_index;
24114}
24115
24116inline bool
24117CO_Tree::const_iterator::operator==(const const_iterator& x) const {
24118  PPL_ASSERT((current_index == x.current_index)
24119             == (current_data == x.current_data));
24120  PPL_ASSERT(OK());
24121  return (current_index == x.current_index);
24122}
24123
24124inline bool
24125CO_Tree::const_iterator::operator!=(const const_iterator& x) const {
24126  return !(*this == x);
24127}
24128
24129
24130inline
24131CO_Tree::iterator::iterator()
24132  : current_index(0), current_data(0) {
24133#if PPL_CO_TREE_EXTRA_DEBUG
24134  tree = 0;
24135#endif
24136  PPL_ASSERT(OK());
24137}
24138
24139inline
24140CO_Tree::iterator::iterator(CO_Tree& tree1)
24141  : current_index(&(tree1.indexes[1])), current_data(&(tree1.data[1])) {
24142#if PPL_CO_TREE_EXTRA_DEBUG
24143  tree = &tree1;
24144#endif
24145  if (!tree1.empty()) {
24146    while (*current_index == unused_index) {
24147      ++current_index;
24148      ++current_data;
24149    }
24150  }
24151  PPL_ASSERT(OK());
24152}
24153
24154inline
24155CO_Tree::iterator::iterator(CO_Tree& tree1, dimension_type i)
24156  : current_index(&(tree1.indexes[i])), current_data(&(tree1.data[i])) {
24157#if PPL_CO_TREE_EXTRA_DEBUG
24158  tree = &tree1;
24159#endif
24160  PPL_ASSERT(i != 0);
24161  PPL_ASSERT(i <= tree1.reserved_size + 1);
24162  PPL_ASSERT(tree1.empty() || tree1.indexes[i] != unused_index);
24163  PPL_ASSERT(OK());
24164}
24165
24166inline
24167CO_Tree::iterator::iterator(const tree_iterator& itr) {
24168  *this = itr;
24169  PPL_ASSERT(OK());
24170}
24171
24172inline
24173CO_Tree::iterator::iterator(const iterator& itr2) {
24174  (*this) = itr2;
24175  PPL_ASSERT(OK());
24176}
24177
24178inline void
24179CO_Tree::iterator::m_swap(iterator& itr) {
24180  using std::swap;
24181  swap(current_data, itr.current_data);
24182  swap(current_index, itr.current_index);
24183#if PPL_CO_TREE_EXTRA_DEBUG
24184  swap(tree, itr.tree);
24185#endif
24186  PPL_ASSERT(OK());
24187  PPL_ASSERT(itr.OK());
24188}
24189
24190inline CO_Tree::iterator&
24191CO_Tree::iterator::operator=(const tree_iterator& itr) {
24192  current_index = &(itr.tree.indexes[itr.dfs_index()]);
24193  current_data = &(itr.tree.data[itr.dfs_index()]);
24194#if PPL_CO_TREE_EXTRA_DEBUG
24195  tree = &(itr.tree);
24196#endif
24197  PPL_ASSERT(OK());
24198  return *this;
24199}
24200
24201inline CO_Tree::iterator&
24202CO_Tree::iterator::operator=(const iterator& itr2) {
24203  current_index = itr2.current_index;
24204  current_data = itr2.current_data;
24205#if PPL_CO_TREE_EXTRA_DEBUG
24206  tree = itr2.tree;
24207#endif
24208  PPL_ASSERT(OK());
24209  return *this;
24210}
24211
24212inline CO_Tree::iterator&
24213CO_Tree::iterator::operator++() {
24214  PPL_ASSERT(current_index != 0);
24215  PPL_ASSERT(current_data != 0);
24216#if PPL_CO_TREE_EXTRA_DEBUG
24217  PPL_ASSERT(current_index != &(tree->indexes[tree->reserved_size + 1]));
24218#endif
24219  ++current_index;
24220  ++current_data;
24221  while (*current_index == unused_index) {
24222    ++current_index;
24223    ++current_data;
24224  }
24225
24226  PPL_ASSERT(OK());
24227  return *this;
24228}
24229
24230inline CO_Tree::iterator&
24231CO_Tree::iterator::operator--() {
24232  PPL_ASSERT(current_index != 0);
24233  PPL_ASSERT(current_data != 0);
24234  --current_index;
24235  --current_data;
24236  while (*current_index == unused_index) {
24237    --current_index;
24238    --current_data;
24239  }
24240
24241  PPL_ASSERT(OK());
24242  return *this;
24243}
24244
24245inline CO_Tree::iterator
24246CO_Tree::iterator::operator++(int) {
24247  iterator itr(*this);
24248  ++(*this);
24249  return itr;
24250}
24251
24252inline CO_Tree::iterator
24253CO_Tree::iterator::operator--(int) {
24254  iterator itr(*this);
24255  --(*this);
24256  return itr;
24257}
24258
24259inline CO_Tree::data_type&
24260CO_Tree::iterator::operator*() {
24261  PPL_ASSERT(current_index != 0);
24262  PPL_ASSERT(current_data != 0);
24263  PPL_ASSERT(OK());
24264#if PPL_CO_TREE_EXTRA_DEBUG
24265  PPL_ASSERT(current_index != &(tree->indexes[tree->reserved_size + 1]));
24266#endif
24267  return *current_data;
24268}
24269
24270inline Coefficient_traits::const_reference
24271CO_Tree::iterator::operator*() const {
24272  PPL_ASSERT(current_index != 0);
24273  PPL_ASSERT(current_data != 0);
24274  PPL_ASSERT(OK());
24275#if PPL_CO_TREE_EXTRA_DEBUG
24276  PPL_ASSERT(current_index != &(tree->indexes[tree->reserved_size + 1]));
24277#endif
24278  return *current_data;
24279}
24280
24281inline dimension_type
24282CO_Tree::iterator::index() const {
24283  PPL_ASSERT(current_index != 0);
24284  PPL_ASSERT(current_data != 0);
24285  PPL_ASSERT(OK());
24286#if PPL_CO_TREE_EXTRA_DEBUG
24287  PPL_ASSERT(current_index != &(tree->indexes[tree->reserved_size + 1]));
24288#endif
24289  return *current_index;
24290}
24291
24292inline bool
24293CO_Tree::iterator::operator==(const iterator& x) const {
24294  PPL_ASSERT((current_index == x.current_index)
24295             == (current_data == x.current_data));
24296  PPL_ASSERT(OK());
24297  return (current_index == x.current_index);
24298}
24299
24300inline bool
24301CO_Tree::iterator::operator!=(const iterator& x) const {
24302  return !(*this == x);
24303}
24304
24305
24306inline
24307CO_Tree::tree_iterator::tree_iterator(CO_Tree& tree1)
24308  : tree(tree1) {
24309  PPL_ASSERT(tree.reserved_size != 0);
24310  get_root();
24311  PPL_ASSERT(OK());
24312}
24313
24314inline
24315CO_Tree::tree_iterator::tree_iterator(CO_Tree& tree1, dimension_type i1)
24316  : tree(tree1) {
24317  PPL_ASSERT(tree.reserved_size != 0);
24318  PPL_ASSERT(i1 <= tree.reserved_size + 1);
24319  i = i1;
24320  offset = least_significant_one_mask(i);
24321  PPL_ASSERT(OK());
24322}
24323
24324inline
24325CO_Tree::tree_iterator::tree_iterator(const iterator& itr, CO_Tree& tree1)
24326  : tree(tree1) {
24327  PPL_ASSERT(tree.reserved_size != 0);
24328  *this = itr;
24329  PPL_ASSERT(OK());
24330}
24331
24332inline CO_Tree::tree_iterator&
24333CO_Tree::tree_iterator::operator=(const tree_iterator& itr) {
24334  PPL_ASSERT(&tree == &(itr.tree));
24335  i = itr.i;
24336  offset = itr.offset;
24337  return *this;
24338}
24339
24340inline CO_Tree::tree_iterator&
24341CO_Tree::tree_iterator::operator=(const iterator& itr) {
24342  PPL_ASSERT(itr != tree.end());
24343  i = tree.dfs_index(itr);
24344  offset = least_significant_one_mask(i);
24345  return *this;
24346}
24347
24348inline bool
24349CO_Tree::tree_iterator::operator==(const tree_iterator& itr) const {
24350  return i == itr.i;
24351}
24352
24353inline bool
24354CO_Tree::tree_iterator::operator!=(const tree_iterator& itr) const {
24355  return !(*this == itr);
24356}
24357
24358inline void
24359CO_Tree::tree_iterator::get_root() {
24360  i = tree.reserved_size / 2 + 1;
24361  offset = i;
24362  PPL_ASSERT(OK());
24363}
24364
24365inline void
24366CO_Tree::tree_iterator::get_left_child() {
24367  PPL_ASSERT(offset != 0);
24368  PPL_ASSERT(offset != 1);
24369  offset /= 2;
24370  i -= offset;
24371  PPL_ASSERT(OK());
24372}
24373
24374inline void
24375CO_Tree::tree_iterator::get_right_child() {
24376  PPL_ASSERT(offset != 0);
24377  PPL_ASSERT(offset != 1);
24378  offset /= 2;
24379  i += offset;
24380  PPL_ASSERT(OK());
24381}
24382
24383inline void
24384CO_Tree::tree_iterator::get_parent() {
24385  PPL_ASSERT(!is_root());
24386  PPL_ASSERT(offset != 0);
24387  i &= ~offset;
24388  offset *= 2;
24389  i |= offset;
24390  PPL_ASSERT(OK());
24391}
24392
24393inline void
24394CO_Tree::tree_iterator::follow_left_children_with_value() {
24395  PPL_ASSERT(index() != unused_index);
24396  const dimension_type* p = tree.indexes;
24397  p += i;
24398  p -= (offset - 1);
24399  while (*p == unused_index) {
24400    ++p;
24401  }
24402  const std::ptrdiff_t distance = p - tree.indexes;
24403  PPL_ASSERT(distance >= 0);
24404  i = static_cast<dimension_type>(distance);
24405  offset = least_significant_one_mask(i);
24406  PPL_ASSERT(OK());
24407}
24408
24409inline void
24410CO_Tree::tree_iterator::follow_right_children_with_value() {
24411  PPL_ASSERT(index() != unused_index);
24412  const dimension_type* p = tree.indexes;
24413  p += i;
24414  p += (offset - 1);
24415  while (*p == unused_index) {
24416    --p;
24417  }
24418  const std::ptrdiff_t distance = p - tree.indexes;
24419  PPL_ASSERT(distance >= 0);
24420  i = static_cast<dimension_type>(distance);
24421  offset = least_significant_one_mask(i);
24422  PPL_ASSERT(OK());
24423}
24424
24425inline bool
24426CO_Tree::tree_iterator::is_root() const {
24427  // This is implied by OK(), it is here for reference only.
24428  PPL_ASSERT(offset <= (tree.reserved_size / 2 + 1));
24429  return offset == (tree.reserved_size / 2 + 1);
24430}
24431
24432inline bool
24433CO_Tree::tree_iterator::is_right_child() const {
24434  if (is_root()) {
24435    return false;
24436  }
24437  return (i & (2*offset)) != 0;
24438}
24439
24440inline bool
24441CO_Tree::tree_iterator::is_leaf() const {
24442  return offset == 1;
24443}
24444
24445inline CO_Tree::data_type&
24446CO_Tree::tree_iterator::operator*() {
24447  return tree.data[i];
24448}
24449
24450inline Coefficient_traits::const_reference
24451CO_Tree::tree_iterator::operator*() const {
24452  return tree.data[i];
24453}
24454
24455inline dimension_type&
24456CO_Tree::tree_iterator::index() {
24457  return tree.indexes[i];
24458}
24459
24460inline dimension_type
24461CO_Tree::tree_iterator::index() const {
24462  return tree.indexes[i];
24463}
24464
24465inline dimension_type
24466CO_Tree::tree_iterator::dfs_index() const {
24467  return i;
24468}
24469
24470inline dimension_type
24471CO_Tree::tree_iterator::get_offset() const {
24472  return offset;
24473}
24474
24475inline CO_Tree::height_t
24476CO_Tree::tree_iterator::depth() const {
24477  return integer_log2((tree.reserved_size + 1) / offset);
24478}
24479
24480inline void
24481swap(CO_Tree& x, CO_Tree& y) {
24482  x.m_swap(y);
24483}
24484
24485inline void
24486swap(CO_Tree::const_iterator& x, CO_Tree::const_iterator& y) {
24487  x.m_swap(y);
24488}
24489
24490inline void
24491swap(CO_Tree::iterator& x, CO_Tree::iterator& y) {
24492  x.m_swap(y);
24493}
24494
24495} // namespace Parma_Polyhedra_Library
24496
24497/* Automatically generated from PPL source file ../src/CO_Tree_templates.hh line 1. */
24498/* CO_Tree class implementation: non-inline template functions.
24499*/
24500
24501
24502namespace Parma_Polyhedra_Library {
24503
24504template <typename Iterator>
24505CO_Tree::CO_Tree(Iterator i, dimension_type n) {
24506
24507  if (n == 0) {
24508    init(0);
24509    PPL_ASSERT(OK());
24510    return;
24511  }
24512
24513  const dimension_type new_max_depth = integer_log2(n) + 1;
24514  reserved_size = (static_cast<dimension_type>(1) << new_max_depth) - 1;
24515
24516  if (is_greater_than_ratio(n, reserved_size, max_density_percent)
24517      && reserved_size != 3) {
24518    reserved_size = reserved_size*2 + 1;
24519  }
24520
24521  init(reserved_size);
24522
24523  tree_iterator root(*this);
24524
24525  // This is static and with static allocation, to improve performance.
24526  // sizeof_to_bits(sizeof(dimension_type)) is the maximum k such that
24527  // 2^k-1 is a dimension_type, so it is the maximum tree height.
24528  // For each node level, the stack may contain up to 4 elements: two elements
24529  // with operation 0, one element with operation 2 and one element
24530  // with operation 3. An additional element with operation 1 can be at the
24531  // top of the tree.
24532  static std::pair<dimension_type, signed char>
24533    stack[4U * sizeof_to_bits(sizeof(dimension_type)) + 1U];
24534
24535  dimension_type stack_first_empty = 0;
24536
24537  // A pair (n, operation) in the stack means:
24538  //
24539  // * Go to the parent, if operation is 0.
24540  // * Go to the left child, then fill the current tree with n elements, if
24541  //   operation is 1.
24542  // * Go to the right child, then fill the current tree with n elements, if
24543  //   operation is 2.
24544  // * Fill the current tree with n elements, if operation is 3.
24545
24546  stack[0].first = n;
24547  stack[0].second = 3;
24548  ++stack_first_empty;
24549
24550  while (stack_first_empty != 0) {
24551
24552    // Implement
24553    //
24554    // <CODE>
24555    //   top_n         = stack.top().first;
24556    //   top_operation = stack.top().second;
24557    // </CODE>
24558    const dimension_type top_n = stack[stack_first_empty - 1].first;
24559    const signed char top_operation = stack[stack_first_empty - 1].second;
24560
24561    switch (top_operation) {
24562
24563    case 0:
24564      root.get_parent();
24565      --stack_first_empty;
24566      continue;
24567
24568    case 1:
24569      root.get_left_child();
24570      break;
24571
24572    case 2:
24573      root.get_right_child();
24574      break;
24575#ifndef NDEBUG
24576    case 3:
24577      break;
24578
24579    default:
24580      // We should not be here
24581      PPL_UNREACHABLE;
24582#endif
24583    }
24584
24585    // We now visit the current tree
24586
24587    if (top_n == 0) {
24588      --stack_first_empty;
24589    }
24590    else {
24591      if (top_n == 1) {
24592        PPL_ASSERT(root.index() == unused_index);
24593        root.index() = i.index();
24594        new(&(*root)) data_type(*i);
24595        ++i;
24596        --stack_first_empty;
24597      }
24598      else {
24599        PPL_ASSERT(stack_first_empty + 3 < sizeof(stack)/sizeof(stack[0]));
24600
24601        const dimension_type half = (top_n + 1) / 2;
24602        stack[stack_first_empty - 1].second = 0;
24603        stack[stack_first_empty    ] = std::make_pair(top_n - half, 2);
24604        stack[stack_first_empty + 1] = std::make_pair(1, 3);
24605        stack[stack_first_empty + 2].second = 0;
24606        stack[stack_first_empty + 3] = std::make_pair(half - 1, 1);
24607        stack_first_empty += 4;
24608      }
24609    }
24610  }
24611  size_ = n;
24612  PPL_ASSERT(OK());
24613}
24614
24615} // namespace Parma_Polyhedra_Library
24616
24617/* Automatically generated from PPL source file ../src/CO_Tree_defs.hh line 1559. */
24618
24619/* Automatically generated from PPL source file ../src/Sparse_Row_defs.hh line 32. */
24620
24621#ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
24622//! A finite sparse sequence of coefficients.
24623/*! \ingroup PPL_CXX_interface
24624  This class is implemented using a CO_Tree. See the documentation of CO_Tree
24625  for details on the implementation and the performance.
24626
24627  This class is a drop-in replacement of Dense_Row, meaning that code
24628  using Dense_Row can be ported to Sparse_Row changing only the type.
24629  The resulting code will work, but probably needs more CPU and memory (it
24630  does not exploit the sparse representation yet).
24631
24632  To take advantage of the sparse representation, the client code must then be
24633  modified to use methods which can have a faster implementation on sparse
24634  data structures.
24635
24636  The main changes are the replacement of calls to operator[] with calls to
24637  find(), lower_bound() or insert(), using hint iterators when possible.
24638  Sequential scanning of rows should probably be implemented using iterators
24639  rather than indexes, to improve performance.
24640  reset() should be called to zero elements.
24641
24642  \see Sparse_Matrix
24643  \see CO_Tree
24644*/
24645#endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
24646class Parma_Polyhedra_Library::Sparse_Row {
24647
24648public:
24649
24650  //! An %iterator on the row elements
24651  /*!
24652    This %iterator skips non-stored zeroes.
24653    \see CO_Tree::iterator
24654  */
24655  typedef CO_Tree::iterator iterator;
24656
24657  //! A const %iterator on the row elements
24658  /*!
24659    This %iterator skips non-stored zeroes.
24660    \see CO_Tree::const_iterator
24661  */
24662  typedef CO_Tree::const_iterator const_iterator;
24663
24664  //! Constructs a row with the specified size.
24665  /*!
24666    \param n
24667    The size for the new row.
24668
24669    The row will contain only non-stored zeroes.
24670
24671    This constructor takes \f$O(1)\f$ time.
24672  */
24673  explicit Sparse_Row(dimension_type n = 0);
24674
24675  //! Constructs a row with the specified size.
24676  /*!
24677    \param n
24678    The size for the new row.
24679
24680    \param capacity
24681    It is ignored. This parameter is needed for compatibility with Dense_Row.
24682
24683    The row will contain only non-stored zeroes.
24684
24685    This constructor takes \f$O(1)\f$ time.
24686  */
24687  Sparse_Row(dimension_type n, dimension_type capacity);
24688
24689  //! Copy constructor with specified capacity.
24690  /*!
24691    It is assumed that \p capacity is greater than or equal to
24692    the size of \p y.
24693  */
24694  Sparse_Row(const Sparse_Row& y, dimension_type capacity);
24695
24696  //! Copy constructor with specified size and capacity.
24697  /*!
24698    It is assumed that \p sz is less than or equal to \p capacity.
24699  */
24700  Sparse_Row(const Sparse_Row& y, dimension_type sz, dimension_type capacity);
24701
24702  //! Constructor from a Dense_Row.
24703  /*!
24704    \param row
24705    The row that will be copied into *this.
24706
24707    This constructor takes \f$O(n)\f$ time. Note that constructing of a row of
24708    zeroes and then inserting n elements costs \f$O(n*\log^2 n)\f$ time.
24709  */
24710  explicit Sparse_Row(const Dense_Row& row);
24711
24712  //! Copy constructor from a Dense_Row with specified size and capacity.
24713  /*!
24714    It is assumed that \p sz is less than or equal to \p capacity.
24715  */
24716  Sparse_Row(const Dense_Row& y, dimension_type sz, dimension_type capacity);
24717
24718  Sparse_Row& operator=(const Dense_Row& row);
24719
24720  //! Swaps *this and x.
24721  /*!
24722    \param x
24723    The row that will be swapped with *this.
24724
24725    This method takes \f$O(1)\f$ time.
24726  */
24727  void m_swap(Sparse_Row& x);
24728
24729  //! Returns the size of the row.
24730  /*!
24731    This method takes \f$O(1)\f$ time.
24732  */
24733  dimension_type size() const;
24734
24735  //! Returns the number of elements explicitly stored in the row.
24736  /*!
24737    This is equivalent to std::distance(begin(), end()), but it's much faster.
24738
24739    This method takes \f$O(1)\f$ time.
24740  */
24741  dimension_type num_stored_elements() const;
24742
24743  //! Resizes the row to the specified size.
24744  /*!
24745    \param n
24746    The new size for the row.
24747
24748    This method takes \f$O(k*\log^2 n)\f$ amortized time when shrinking the
24749    row and removing the trailing k elements.
24750    It takes \f$O(1)\f$ time when enlarging the row.
24751  */
24752  void resize(dimension_type n);
24753
24754  //! Resizes the row to size \p n.
24755  /*!
24756    \param n
24757    The new size for the row.
24758
24759    This method, with this signature, is needed for compatibility with
24760    Dense_Row.
24761
24762    This method takes \f$O(1)\f$ time.
24763  */
24764  void expand_within_capacity(dimension_type n);
24765
24766  //! Resizes the row to size \p n.
24767  /*!
24768    \param n
24769    The new size for the row.
24770
24771    This method, with this signature, is needed for compatibility with
24772    Dense_Row.
24773
24774    This method takes \f$O(k*\log^2 n)\f$ amortized time where k is the number
24775    of removed elements.
24776  */
24777  void shrink(dimension_type n);
24778
24779  /*!
24780    \brief Deletes the i-th element from the row, shifting the next elements
24781           to the left.
24782
24783    \param i
24784    The index of the element that will be deleted.
24785
24786    The size of the row is decreased by 1.
24787
24788    This operation invalidates existing iterators.
24789
24790    This method takes \f$O(k+\log^2 n)\f$ amortized time, where k is the
24791    number of elements with index greater than i.
24792  */
24793  void delete_element_and_shift(dimension_type i);
24794
24795  //! Adds \p n zeroes before index \p i.
24796  /*!
24797    \param n
24798    The number of non-stored zeroes that will be added to the row.
24799
24800    \param i
24801    The index of the element before which the zeroes will be added.
24802
24803    Existing elements with index greater than or equal to \p i are shifted to
24804    the right by \p n positions. The size is increased by \p n.
24805
24806    Existing iterators are not invalidated, but are shifted to the right
24807    by \p n if they pointed at or after index \p i (i.e., they point to
24808    the same, possibly shifted, values as before).
24809
24810    This method takes \f$O(k + \log m)\f$ expected time, where \f$k\f$ is
24811    the number of elements with index greater than or equal to \p i and
24812    \f$m\f$ the number of stored elements.
24813  */
24814  void add_zeroes_and_shift(dimension_type n, dimension_type i);
24815
24816  //! Returns an %iterator that points at the first stored element.
24817  /*!
24818    This method takes \f$O(1)\f$ time.
24819  */
24820  iterator begin();
24821
24822  //! Returns an %iterator that points after the last stored element.
24823  /*!
24824    This method always returns a reference to the same internal %iterator,
24825    that is kept valid.
24826    Client code can keep a const reference to that %iterator instead of
24827    keep updating a local %iterator.
24828
24829    This method takes \f$O(1)\f$ time.
24830  */
24831  const iterator& end();
24832
24833  //! Equivalent to <CODE>cbegin()</CODE>.
24834  const_iterator begin() const;
24835
24836  //! Equivalent to <CODE>cend()</CODE>.
24837  const const_iterator& end() const;
24838
24839  //! Returns an %iterator that points at the first element.
24840  /*!
24841    This method takes \f$O(1)\f$ time.
24842  */
24843  const_iterator cbegin() const;
24844
24845  //! Returns an %iterator that points after the last element.
24846  /*!
24847    This method always returns a reference to the same internal %iterator,
24848    that is updated at each operation that modifies the structure.
24849    Client code can keep a const reference to that %iterator instead of
24850    keep updating a local %iterator.
24851
24852    This method takes \f$O(1)\f$ time.
24853  */
24854  const const_iterator& cend() const;
24855
24856  //! Returns the size() of the largest possible Sparse_Row.
24857  static dimension_type max_size();
24858
24859  //! Resets all the elements of this row.
24860  /*!
24861    This method takes \f$O(n)\f$ time.
24862  */
24863  void clear();
24864
24865  //! Gets a reference to the i-th element.
24866  /*!
24867    \param i
24868    The index of the desired element.
24869
24870    For read-only access it's better to use get(), that avoids allocating
24871    space for zeroes.
24872
24873    If possible, use the insert(), find() or lower_bound() methods with
24874    a hint instead of this, to improve performance.
24875
24876    This operation invalidates existing iterators.
24877
24878    This method takes \f$O(\log n)\f$ amortized time when there is already an
24879    element with index \p i, and \f$O(\log^2 n)\f$ otherwise.
24880  */
24881  Coefficient& operator[](dimension_type i);
24882
24883  //! Equivalent to <CODE>get(i)</CODE>, provided for convenience.
24884  /*!
24885    This method takes \f$O(\log n)\f$ time.
24886  */
24887  Coefficient_traits::const_reference operator[](dimension_type i) const;
24888
24889  //! Gets the i-th element in the sequence.
24890  /*!
24891    \param i
24892    The index of the desired element.
24893
24894    If possible, use the insert(), find() or lower_bound() methods with
24895    a hint instead of this, to improve performance.
24896
24897    This method takes \f$O(\log n)\f$ time.
24898  */
24899  Coefficient_traits::const_reference get(dimension_type i) const;
24900
24901  //! Looks for an element with index i.
24902  /*!
24903    \param i
24904    The index of the desired element.
24905
24906    If possible, use the find() method that takes a hint %iterator, to improve
24907    performance.
24908
24909    This method takes \f$O(\log n)\f$ time.
24910  */
24911  iterator find(dimension_type i);
24912
24913  //! Looks for an element with index i.
24914  /*!
24915    \param i
24916    The index of the desired element.
24917
24918    \param itr
24919    It is used as a hint. This method will be faster if the searched element
24920    is near to \p itr.
24921
24922    The value of \p itr does not affect the result of this method, as long it
24923    is a valid %iterator for this row. \p itr may even be end().
24924
24925    This method takes \f$O(\log n)\f$ time.
24926    If the distance between \p itr and the searched position is \f$O(1)\f$,
24927    this method takes \f$O(1)\f$ time.
24928  */
24929  iterator find(iterator itr, dimension_type i);
24930
24931  //! Looks for an element with index i.
24932  /*!
24933    \param i
24934    The index of the desired element.
24935
24936    If possible, use the find() method that takes a hint %iterator, to improve
24937    performance.
24938
24939    This method takes \f$O(\log n)\f$ time.
24940  */
24941  const_iterator find(dimension_type i) const;
24942
24943  //! Looks for an element with index i.
24944  /*!
24945    \param i
24946    The index of the desired element.
24947
24948    \param itr
24949    It is used as a hint. This method will be faster if the searched element
24950    is near to \p itr.
24951
24952    The value of \p itr does not affect the result of this method, as long it
24953    is a valid %iterator for this row. \p itr may even be end().
24954
24955    This method takes \f$O(\log n)\f$ time.
24956    If the distance between \p itr and the searched position is \f$O(1)\f$,
24957    this method takes \f$O(1)\f$ time.
24958  */
24959  const_iterator find(const_iterator itr, dimension_type i) const;
24960
24961  //! Lower bound of index i.
24962  /*!
24963    \param i
24964    The index of the desired element.
24965
24966    \returns an %iterator to the first element with index greater than or
24967             equal to i.
24968             If there are no such elements, returns end().
24969
24970    If possible, use the find() method that takes a hint %iterator, to improve
24971    performance.
24972
24973    This method takes \f$O(\log n)\f$ time.
24974  */
24975  iterator lower_bound(dimension_type i);
24976
24977  //! Lower bound of index i.
24978  /*!
24979    \param i
24980    The index of the desired element.
24981
24982    \param itr
24983    It is used as a hint. This method will be faster if the searched element
24984    is near to \p itr.
24985
24986    \returns an %iterator to the first element with index greater than or
24987             equal to i.
24988             If there are no such elements, returns end().
24989
24990    The value of \p itr does not affect the result of this method, as long it
24991    is a valid %iterator for this row. \p itr may even be end().
24992
24993    This method takes \f$O(\log n)\f$ time.
24994    If the distance between \p itr and the searched position is \f$O(1)\f$,
24995    this method takes \f$O(1)\f$ time.
24996  */
24997  iterator lower_bound(iterator itr, dimension_type i);
24998
24999  //! Lower bound of index i.
25000  /*!
25001
25002    \param i
25003    The index of the desired element.
25004
25005    \returns an %iterator to the first element with index greater than or
25006             equal to i.
25007             If there are no such elements, returns end().
25008
25009    If possible, use the find() method that takes a hint %iterator, to improve
25010    performance.
25011
25012    This method takes \f$O(\log n)\f$ time.
25013  */
25014  const_iterator lower_bound(dimension_type i) const;
25015
25016  //! Lower bound of index i.
25017  /*!
25018    \param i
25019    The index of the desired element.
25020
25021    \param itr
25022    It is used as a hint. This method will be faster if the searched element
25023    is near to \p itr.
25024
25025    \returns an %iterator to the first element with index greater than or
25026             equal to i.
25027             If there are no such elements, returns end().
25028
25029    The value of \p itr does not affect the result of this method, as long it
25030    is a valid %iterator for this row. \p itr may even be end().
25031
25032    This method takes \f$O(\log n)\f$ time.
25033    If the distance between \p itr and the searched position is \f$O(1)\f$,
25034    this method takes \f$O(1)\f$ time.
25035  */
25036  const_iterator lower_bound(const_iterator itr, dimension_type i) const;
25037
25038  //! Equivalent to <CODE>(*this)[i] = x; find(i)</CODE>, but faster.
25039  /*!
25040    \param i
25041    The index of the desired element.
25042
25043    \param x
25044    The value that will be associated to the element.
25045
25046    If possible, use versions of this method that take a hint, to improve
25047    performance.
25048
25049    This operation invalidates existing iterators.
25050
25051    This method takes \f$O(\log^2 n)\f$ amortized time.
25052  */
25053  iterator insert(dimension_type i, Coefficient_traits::const_reference x);
25054
25055  //! Equivalent to <CODE>(*this)[i] = x; find(i)</CODE>, but faster.
25056  /*!
25057    \param i
25058    The index of the desired element.
25059
25060    \param x
25061    The value that will be associated to the element.
25062
25063    \param itr
25064    It is used as a hint. This method will be faster if the searched element
25065    is near to \p itr, even faster than <CODE>(*this)[i] = x</CODE>.
25066
25067    The value of \p itr does not affect the result of this method, as long it
25068    is a valid %iterator for this row. \p itr may even be end().
25069
25070    This operation invalidates existing iterators.
25071
25072    This method takes \f$O(\log^2 n)\f$ amortized time. If the distance
25073    between \p itr and the searched position is \f$O(1)\f$ and the row already
25074    contains an element with this index, this method takes \f$O(1)\f$ time.
25075  */
25076  iterator insert(iterator itr, dimension_type i,
25077                  Coefficient_traits::const_reference x);
25078
25079  //! Equivalent to <CODE>(*this)[i]; find(i)</CODE>, but faster.
25080  /*!
25081    \param i
25082    The index of the desired element.
25083
25084    If possible, use versions of this method that take a hint, to improve
25085    performance.
25086
25087    This operation invalidates existing iterators.
25088
25089    This method takes \f$O(\log^2 n)\f$ amortized time.
25090  */
25091  iterator insert(dimension_type i);
25092
25093  //! Equivalent to <CODE>(*this)[i]; find(i)</CODE>, but faster.
25094  /*!
25095    \param i
25096    The index of the desired element.
25097
25098    \param itr
25099    It is used as a hint. This method will be faster if the searched element
25100    is near to \p itr, even faster than <CODE>(*this)[i]</CODE>.
25101
25102    The value of \p itr does not affect the result of this method, as long it
25103    is a valid %iterator for this row. \p itr may even be end().
25104
25105    This operation invalidates existing iterators.
25106
25107    This method takes \f$O(\log^2 n)\f$ amortized time. If the distance
25108    between \p itr and the searched position is \f$O(1)\f$ and the row already
25109    contains an element with this index, this method takes \f$O(1)\f$ time.
25110  */
25111  iterator insert(iterator itr, dimension_type i);
25112
25113  //! Swaps the i-th element with the j-th element.
25114  /*!
25115    \param i
25116    The index of an element.
25117
25118    \param j
25119    The index of another element.
25120
25121    This operation invalidates existing iterators.
25122
25123    This method takes \f$O(\log^2 n)\f$ amortized time.
25124  */
25125  void swap_coefficients(dimension_type i, dimension_type j);
25126
25127  //! Equivalent to swap(i,itr.index()), but it assumes that
25128  //! lower_bound(i)==itr.
25129  /*!
25130    Iterators that pointed to the itr.index()-th element remain valid
25131    but now point to the i-th element. Other iterators are unaffected.
25132
25133    This method takes \f$O(1)\f$ time.
25134  */
25135  void fast_swap(dimension_type i, iterator itr);
25136
25137  //! Swaps the element pointed to by i with the element pointed to by j.
25138  /*!
25139    \param i
25140    An %iterator pointing to an element.
25141
25142    \param j
25143    An %iterator pointing to another element.
25144
25145    This method takes \f$O(1)\f$ time.
25146  */
25147  void swap_coefficients(iterator i, iterator j);
25148
25149  //! Resets to zero the value pointed to by i.
25150  /*!
25151    \param i
25152    An %iterator pointing to the element that will be reset (not stored
25153    anymore).
25154
25155    By calling this method instead of getting a reference to the value and
25156    setting it to zero, the element will no longer be stored.
25157
25158    This operation invalidates existing iterators.
25159
25160    This method takes \f$O(\log^2 n)\f$ amortized time.
25161  */
25162  iterator reset(iterator i);
25163
25164  //! Resets to zero the values in the range [first,last).
25165  /*!
25166    \param first
25167    An %iterator pointing to the first element to reset.
25168
25169    \param last
25170    An %iterator pointing after the last element to reset.
25171
25172    By calling this method instead of getting a reference to the values and
25173    setting them to zero, the elements will no longer be stored.
25174
25175    This operation invalidates existing iterators.
25176
25177    This method takes \f$O(k*\log^2 n)\f$ amortized time, where k is the
25178    number of elements in [first,last).
25179  */
25180  iterator reset(iterator first, iterator last);
25181
25182  //! Resets to zero the i-th element.
25183  /*!
25184    \param i
25185    The index of the element to reset.
25186
25187    By calling this method instead of getting a reference to the value and
25188    setting it to zero, the element will no longer be stored.
25189
25190    This operation invalidates existing iterators.
25191
25192    This method takes \f$O(\log^2 n)\f$ amortized time.
25193  */
25194  void reset(dimension_type i);
25195
25196  //! Resets to zero the elements with index greater than or equal to i.
25197  /*!
25198    \param i
25199    The index of the first element to reset.
25200
25201    By calling this method instead of getting a reference to the values and
25202    setting them to zero, the elements will no longer be stored.
25203
25204    This operation invalidates existing iterators.
25205
25206    This method takes \f$O(k*\log^2 n)\f$ amortized time, where k is the
25207    number of elements with index greater than or equal to i.
25208  */
25209  void reset_after(dimension_type i);
25210
25211  //! Normalizes the modulo of coefficients so that they are mutually prime.
25212  /*!
25213    Computes the Greatest Common Divisor (GCD) among the elements of the row
25214    and normalizes them by the GCD itself.
25215
25216    This method takes \f$O(n)\f$ time.
25217  */
25218  void normalize();
25219
25220  //! Calls g(x[i],y[i]), for each i.
25221  /*!
25222    \param y
25223    The row that will be combined with *this.
25224
25225    \param f
25226    A functor that should take a Coefficient&.
25227    f(c1) must be equivalent to g(c1, 0).
25228
25229    \param g
25230    A functor that should take a Coefficient& and a
25231    Coefficient_traits::const_reference.
25232    g(c1, c2) must do nothing when c1 is zero.
25233
25234    This method takes \f$O(n*\log^2 n)\f$ time.
25235
25236    \note
25237    The functors will only be called when necessary, assuming the requested
25238    properties hold.
25239
25240    \see combine_needs_second
25241    \see combine
25242  */
25243  template <typename Func1, typename Func2>
25244  void combine_needs_first(const Sparse_Row& y,
25245                           const Func1& f, const Func2& g);
25246
25247  //! Calls g(x[i],y[i]), for each i.
25248  /*!
25249    \param y
25250    The row that will be combined with *this.
25251
25252    \param g
25253    A functor that should take a Coefficient& and a
25254    Coefficient_traits::const_reference.
25255    g(c1, 0) must do nothing, for every c1.
25256
25257    \param h
25258    A functor that should take a Coefficient& and a
25259    Coefficient_traits::const_reference.
25260    h(c1, c2) must be equivalent to g(c1, c2) when c1 is zero.
25261
25262    This method takes \f$O(n*\log^2 n)\f$ time.
25263
25264    \note
25265    The functors will only be called when necessary, assuming the requested
25266    properties hold.
25267
25268    \see combine_needs_first
25269    \see combine
25270  */
25271  template <typename Func1, typename Func2>
25272  void combine_needs_second(const Sparse_Row& y,
25273                            const Func1& g, const Func2& h);
25274
25275  //! Calls g(x[i],y[i]), for each i.
25276  /*!
25277    \param y
25278    The row that will be combined with *this.
25279
25280    \param f
25281    A functor that should take a Coefficient&.
25282    f(c1) must be equivalent to g(c1, 0).
25283
25284    \param g
25285    A functor that should take a Coefficient& and a
25286    Coefficient_traits::const_reference.
25287    g(c1, c2) must do nothing when both c1 and c2 are zero.
25288
25289    \param h
25290    A functor that should take a Coefficient& and a
25291    Coefficient_traits::const_reference.
25292    h(c1, c2) must be equivalent to g(c1, c2) when c1 is zero.
25293
25294    This method takes \f$O(n*\log^2 n)\f$ time.
25295
25296    \note
25297    The functors will only be called when necessary, assuming the requested
25298    properties hold.
25299
25300    \see combine_needs_first
25301    \see combine_needs_second
25302  */
25303  template <typename Func1, typename Func2, typename Func3>
25304  void combine(const Sparse_Row& y,
25305               const Func1& f, const Func2& g, const Func3& h);
25306
25307  //! Executes <CODE>(*this)[i] = (*this)[i]*coeff1 + y[i]*coeff2</CODE>, for
25308  //! each i.
25309  /*!
25310    \param y
25311    The row that will be combined with *this.
25312
25313    \param coeff1
25314    The coefficient used for elements of *this.
25315    This must not be 0.
25316
25317    \param coeff2
25318    The coefficient used for elements of y.
25319    This must not be 0.
25320
25321    This method takes \f$O(n*\log^2 n)\f$ time.
25322
25323    \note
25324    The functors will only be called when necessary.
25325    This method can be implemented in user code, too. It is provided for
25326    convenience only.
25327
25328    \see combine_needs_first
25329    \see combine_needs_second
25330    \see combine
25331  */
25332  void linear_combine(const Sparse_Row& y,
25333                      Coefficient_traits::const_reference coeff1,
25334                      Coefficient_traits::const_reference coeff2);
25335
25336  //! Equivalent to <CODE>(*this)[i] = (*this)[i] * c1 + y[i] * c2</CODE>,
25337  //! for each i in [start, end).
25338  /*!
25339    This method, unlike the other linear_combine() method, detects when
25340    coeff1==1 and/or coeff2==1 or coeff2==-1 in order to save some work.
25341  */
25342  void linear_combine(const Sparse_Row& y,
25343                      Coefficient_traits::const_reference c1,
25344                      Coefficient_traits::const_reference c2,
25345                      dimension_type start, dimension_type end);
25346
25347  PPL_OUTPUT_DECLARATIONS
25348
25349  //! Loads the row from an ASCII representation generated using ascii_dump().
25350  /*!
25351    \param s
25352    The stream from which the ASCII representation will be loaded.
25353  */
25354  bool ascii_load(std::istream& s);
25355
25356  //! Returns the size in bytes of the memory managed by \p *this.
25357  /*!
25358    This method takes \f$O(n)\f$ time.
25359  */
25360  memory_size_type external_memory_in_bytes() const;
25361
25362  //! Returns the size in bytes of the memory managed by \p *this.
25363  /*!
25364    This method is provided for compatibility with Dense_Row.
25365
25366    This method takes \f$O(n)\f$ time.
25367
25368    \param capacity
25369    This parameter is ignored.
25370  */
25371  memory_size_type external_memory_in_bytes(dimension_type capacity) const;
25372
25373  //! Returns the size in bytes of the memory managed by \p *this.
25374  /*!
25375    This method takes \f$O(n)\f$ time.
25376  */
25377  memory_size_type total_memory_in_bytes() const;
25378
25379  //! Returns the size in bytes of the memory managed by \p *this.
25380  /*!
25381    This method is provided for compatibility with Dense_Row.
25382
25383    This method takes \f$O(n)\f$ time.
25384
25385    \param capacity
25386    This parameter is ignored.
25387  */
25388  memory_size_type total_memory_in_bytes(dimension_type capacity) const;
25389
25390  //! Checks the invariant.
25391  bool OK() const;
25392
25393  //! Checks the invariant.
25394  /*!
25395    This method is provided for compatibility with Dense_Row.
25396
25397    \param capacity
25398    This parameter is ignored.
25399  */
25400  bool OK(dimension_type capacity) const;
25401
25402private:
25403  //! The tree used to store the elements.
25404  CO_Tree tree;
25405
25406  //! The size of the row.
25407  /*!
25408    The elements contained in this row have indexes that are less than size_.
25409  */
25410  dimension_type size_;
25411};
25412
25413
25414namespace Parma_Polyhedra_Library {
25415
25416#ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
25417//! Swaps \p x with \p y.
25418/*! \relates Sparse_Row */
25419#endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
25420void swap(Parma_Polyhedra_Library::Sparse_Row& x,
25421          Parma_Polyhedra_Library::Sparse_Row& y);
25422
25423void swap(Parma_Polyhedra_Library::Sparse_Row& x,
25424          Parma_Polyhedra_Library::Dense_Row& y);
25425
25426void swap(Parma_Polyhedra_Library::Dense_Row& x,
25427          Parma_Polyhedra_Library::Sparse_Row& y);
25428
25429#ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
25430//! Returns <CODE>true</CODE> if and only if \p x and \p y are equal.
25431/*! \relates Sparse_Row */
25432#endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
25433bool operator==(const Sparse_Row& x, const Sparse_Row& y);
25434
25435#ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
25436//! Returns <CODE>true</CODE> if and only if \p x and \p y are different.
25437/*! \relates Sparse_Row */
25438#endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
25439bool operator!=(const Sparse_Row& x, const Sparse_Row& y);
25440
25441bool operator==(const Dense_Row& x, const Sparse_Row& y);
25442bool operator!=(const Dense_Row& x, const Sparse_Row& y);
25443
25444bool operator==(const Sparse_Row& x, const Dense_Row& y);
25445bool operator!=(const Sparse_Row& x, const Dense_Row& y);
25446
25447#ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
25448//! Equivalent to <CODE>x[i] = x[i] * c1 + y[i] * c2</CODE>,
25449//! for each i in [start, end).
25450/*! \relates Sparse_Row */
25451#endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
25452void linear_combine(Sparse_Row& x, const Dense_Row& y,
25453                    Coefficient_traits::const_reference coeff1,
25454                    Coefficient_traits::const_reference coeff2);
25455
25456#ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
25457//! Equivalent to <CODE>x[i] = x[i] * c1 + y[i] * c2</CODE>,
25458//! for each i in [start, end).
25459/*! \relates Sparse_Row
25460  This function detects when coeff1==1 and/or coeff2==1 or coeff2==-1 in
25461  order to save some work.
25462*/
25463#endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
25464void linear_combine(Sparse_Row& x, const Dense_Row& y,
25465                    Coefficient_traits::const_reference c1,
25466                    Coefficient_traits::const_reference c2,
25467                    dimension_type start, dimension_type end);
25468
25469#ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
25470//! Equivalent to <CODE>x[i] = x[i] * c1 + y[i] * c2</CODE>,
25471//! for each i in [start, end).
25472/*! \relates Sparse_Row */
25473#endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
25474void linear_combine(Dense_Row& x, const Sparse_Row& y,
25475                    Coefficient_traits::const_reference coeff1,
25476                    Coefficient_traits::const_reference coeff2);
25477
25478#ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
25479//! Equivalent to <CODE>x[i] = x[i] * c1 + y[i] * c2</CODE>,
25480//! for each i in [start, end).
25481/*! \relates Sparse_Row
25482  This function detects when coeff1==1 and/or coeff2==1 or coeff2==-1 in
25483  order to save some work.
25484*/
25485#endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
25486void linear_combine(Dense_Row& x, const Sparse_Row& y,
25487                    Coefficient_traits::const_reference c1,
25488                    Coefficient_traits::const_reference c2,
25489                    dimension_type start, dimension_type end);
25490
25491#ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
25492//! Equivalent to <CODE>x[i] = x[i] * c1 + y[i] * c2</CODE>,
25493//! for each i in [start, end).
25494/*! \relates Sparse_Row */
25495#endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
25496void linear_combine(Sparse_Row& x, const Sparse_Row& y,
25497                    Coefficient_traits::const_reference coeff1,
25498                    Coefficient_traits::const_reference coeff2);
25499
25500#ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
25501//! Equivalent to <CODE>x[i] = x[i] * c1 + y[i] * c2</CODE>,
25502//! for each i in [start, end).
25503/*! \relates Sparse_Row
25504  This function detects when coeff1==1 and/or coeff2==1 or coeff2==-1 in
25505  order to save some work.
25506*/
25507#endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
25508void linear_combine(Sparse_Row& x, const Sparse_Row& y,
25509                    Coefficient_traits::const_reference c1,
25510                    Coefficient_traits::const_reference c2,
25511                    dimension_type start, dimension_type end);
25512
25513} // namespace Parma_Polyhedra_Library
25514
25515/* Automatically generated from PPL source file ../src/Sparse_Row_inlines.hh line 1. */
25516/* Sparse_Row class implementation: inline functions.
25517*/
25518
25519
25520#include <algorithm>
25521
25522namespace Parma_Polyhedra_Library {
25523
25524inline
25525Sparse_Row::Sparse_Row(dimension_type n)
25526  : size_(n) {
25527  PPL_ASSERT(OK());
25528}
25529
25530inline
25531Sparse_Row::Sparse_Row(dimension_type n, dimension_type)
25532  : size_(n) {
25533  PPL_ASSERT(OK());
25534}
25535
25536inline
25537Sparse_Row::Sparse_Row(const Sparse_Row& y, dimension_type)
25538  : tree(y.tree), size_(y.size_) {
25539}
25540
25541inline
25542Sparse_Row::Sparse_Row(const Sparse_Row& y, dimension_type sz, dimension_type)
25543  : tree(y.begin(),
25544         std::distance(y.begin(), y.lower_bound(std::min(y.size(), sz)))),
25545    size_(sz) {
25546  PPL_ASSERT(OK());
25547}
25548
25549inline void
25550Sparse_Row::m_swap(Sparse_Row& x) {
25551  using std::swap;
25552  swap(tree, x.tree);
25553  swap(size_, x.size_);
25554  PPL_ASSERT(OK());
25555  PPL_ASSERT(x.OK());
25556}
25557
25558inline dimension_type
25559Sparse_Row::size() const {
25560  return size_;
25561}
25562
25563inline dimension_type
25564Sparse_Row::num_stored_elements() const {
25565  return tree.size();
25566}
25567
25568inline void
25569Sparse_Row::resize(dimension_type n) {
25570  if (n < size_) {
25571    reset_after(n);
25572  }
25573  size_ = n;
25574  PPL_ASSERT(OK());
25575}
25576
25577inline void
25578Sparse_Row::shrink(dimension_type n) {
25579  PPL_ASSERT(size() >= n);
25580  resize(n);
25581}
25582
25583inline void
25584Sparse_Row::expand_within_capacity(dimension_type n) {
25585  PPL_ASSERT(size() <= n);
25586  resize(n);
25587}
25588
25589inline void
25590Sparse_Row::delete_element_and_shift(dimension_type i) {
25591  PPL_ASSERT(i < size_);
25592  tree.erase_element_and_shift_left(i);
25593  --size_;
25594  PPL_ASSERT(OK());
25595}
25596
25597inline void
25598Sparse_Row::add_zeroes_and_shift(dimension_type n, dimension_type i) {
25599  PPL_ASSERT(i <= size_);
25600  tree.increase_keys_from(i, n);
25601  size_ += n;
25602  PPL_ASSERT(OK());
25603}
25604
25605inline Sparse_Row::iterator
25606Sparse_Row::begin() {
25607  return tree.begin();
25608}
25609
25610inline const Sparse_Row::iterator&
25611Sparse_Row::end() {
25612  return tree.end();
25613}
25614
25615inline Sparse_Row::const_iterator
25616Sparse_Row::begin() const {
25617  return tree.cbegin();
25618}
25619
25620inline const Sparse_Row::const_iterator&
25621Sparse_Row::end() const {
25622  return tree.cend();
25623}
25624
25625inline Sparse_Row::const_iterator
25626Sparse_Row::cbegin() const {
25627  return tree.cbegin();
25628}
25629
25630inline const Sparse_Row::const_iterator&
25631Sparse_Row::cend() const {
25632  return tree.cend();
25633}
25634
25635inline dimension_type
25636Sparse_Row::max_size() {
25637  return CO_Tree::max_size();
25638}
25639
25640inline void
25641Sparse_Row::clear() {
25642  tree.clear();
25643}
25644
25645inline Coefficient&
25646Sparse_Row::operator[](dimension_type i) {
25647  PPL_ASSERT(i < size_);
25648  iterator itr = insert(i);
25649  return *itr;
25650}
25651
25652inline Coefficient_traits::const_reference
25653Sparse_Row::operator[](dimension_type i) const {
25654  return get(i);
25655}
25656
25657inline Coefficient_traits::const_reference
25658Sparse_Row::get(dimension_type i) const {
25659  PPL_ASSERT(i < size_);
25660  if (tree.empty()) {
25661    return Coefficient_zero();
25662  }
25663  const_iterator itr = find(i);
25664  if (itr != end()) {
25665    return *itr;
25666  }
25667  else {
25668    return Coefficient_zero();
25669  }
25670}
25671
25672inline Sparse_Row::iterator
25673Sparse_Row::find(dimension_type i) {
25674  PPL_ASSERT(i < size());
25675
25676  iterator itr = tree.bisect(i);
25677
25678  if (itr != end() && itr.index() == i) {
25679    return itr;
25680  }
25681  return end();
25682}
25683
25684inline Sparse_Row::iterator
25685Sparse_Row::find(iterator hint, dimension_type i) {
25686  PPL_ASSERT(i < size());
25687
25688  iterator itr = tree.bisect_near(hint, i);
25689
25690  if (itr != end() && itr.index() == i) {
25691    return itr;
25692  }
25693  return end();
25694}
25695
25696inline Sparse_Row::const_iterator
25697Sparse_Row::find(dimension_type i) const {
25698  PPL_ASSERT(i < size());
25699
25700  const_iterator itr = tree.bisect(i);
25701
25702  if (itr != end() && itr.index() == i) {
25703    return itr;
25704  }
25705
25706  return end();
25707}
25708
25709inline Sparse_Row::const_iterator
25710Sparse_Row::find(const_iterator hint, dimension_type i) const {
25711  PPL_ASSERT(i < size());
25712
25713  const_iterator itr = tree.bisect_near(hint, i);
25714
25715  if (itr != end() && itr.index() == i) {
25716    return itr;
25717  }
25718  return end();
25719}
25720
25721inline Sparse_Row::iterator
25722Sparse_Row::lower_bound(dimension_type i) {
25723  PPL_ASSERT(i <= size());
25724
25725  iterator itr = tree.bisect(i);
25726
25727  if (itr == end()) {
25728    return end();
25729  }
25730
25731  if (itr.index() < i) {
25732    ++itr;
25733  }
25734
25735  PPL_ASSERT(itr == end() || itr.index() >= i);
25736
25737  return itr;
25738}
25739
25740inline Sparse_Row::iterator
25741Sparse_Row::lower_bound(iterator hint, dimension_type i) {
25742  PPL_ASSERT(i <= size());
25743
25744  iterator itr = tree.bisect_near(hint, i);
25745
25746  if (itr == end()) {
25747    return end();
25748  }
25749
25750  if (itr.index() < i) {
25751    ++itr;
25752  }
25753
25754  PPL_ASSERT(itr == end() || itr.index() >= i);
25755
25756  return itr;
25757}
25758
25759inline Sparse_Row::const_iterator
25760Sparse_Row::lower_bound(dimension_type i) const {
25761  PPL_ASSERT(i <= size());
25762
25763  const_iterator itr = tree.bisect(i);
25764
25765  if (itr == end()) {
25766    return end();
25767  }
25768
25769  if (itr.index() < i) {
25770    ++itr;
25771  }
25772
25773  PPL_ASSERT(itr == end() || itr.index() >= i);
25774
25775  return itr;
25776}
25777
25778inline Sparse_Row::const_iterator
25779Sparse_Row::lower_bound(const_iterator hint, dimension_type i) const {
25780  PPL_ASSERT(i <= size());
25781
25782  const_iterator itr = tree.bisect_near(hint, i);
25783
25784  if (itr == end()) {
25785    return end();
25786  }
25787
25788  if (itr.index() < i) {
25789    ++itr;
25790  }
25791
25792  PPL_ASSERT(itr == end() || itr.index() >= i);
25793
25794  return itr;
25795}
25796
25797inline Sparse_Row::iterator
25798Sparse_Row::insert(dimension_type i, Coefficient_traits::const_reference x) {
25799  PPL_ASSERT(i < size_);
25800  return tree.insert(i, x);
25801}
25802
25803inline Sparse_Row::iterator
25804Sparse_Row::insert(iterator itr, dimension_type i,
25805                   Coefficient_traits::const_reference x) {
25806  PPL_ASSERT(i < size_);
25807  return tree.insert(itr, i, x);
25808}
25809
25810inline Sparse_Row::iterator
25811Sparse_Row::insert(dimension_type i) {
25812  PPL_ASSERT(i < size_);
25813  return tree.insert(i);
25814}
25815
25816inline Sparse_Row::iterator
25817Sparse_Row::insert(iterator itr, dimension_type i) {
25818  PPL_ASSERT(i < size_);
25819  return tree.insert(itr, i);
25820}
25821
25822inline void
25823Sparse_Row::swap_coefficients(iterator i, iterator j) {
25824  PPL_ASSERT(i != end());
25825  PPL_ASSERT(j != end());
25826  using std::swap;
25827  swap(*i, *j);
25828  PPL_ASSERT(OK());
25829}
25830
25831inline void
25832Sparse_Row::fast_swap(dimension_type i, iterator itr) {
25833  PPL_ASSERT(lower_bound(i) == itr);
25834  PPL_ASSERT(itr != end());
25835  tree.fast_shift(i, itr);
25836  PPL_ASSERT(OK());
25837}
25838
25839inline Sparse_Row::iterator
25840Sparse_Row::reset(iterator i) {
25841  iterator res = tree.erase(i);
25842  PPL_ASSERT(OK());
25843  return res;
25844}
25845
25846inline void
25847Sparse_Row::reset(dimension_type i) {
25848  PPL_ASSERT(i < size());
25849
25850  tree.erase(i);
25851  PPL_ASSERT(OK());
25852}
25853
25854inline memory_size_type
25855Sparse_Row::external_memory_in_bytes() const {
25856  return tree.external_memory_in_bytes();
25857}
25858
25859inline memory_size_type
25860Sparse_Row::external_memory_in_bytes(dimension_type /* capacity */) const {
25861  return external_memory_in_bytes();
25862}
25863
25864inline memory_size_type
25865Sparse_Row::total_memory_in_bytes() const {
25866  return external_memory_in_bytes() + sizeof(*this);
25867}
25868
25869inline memory_size_type
25870Sparse_Row::total_memory_in_bytes(dimension_type /* capacity */) const {
25871  return total_memory_in_bytes();
25872}
25873
25874#ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
25875/*! \relates Sparse_Row */
25876#endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
25877inline void
25878swap(Sparse_Row& x, Sparse_Row& y) {
25879  x.m_swap(y);
25880}
25881
25882} // namespace Parma_Polyhedra_Library
25883
25884/* Automatically generated from PPL source file ../src/Sparse_Row_templates.hh line 1. */
25885/* Sparse_Row class implementation: non-inline template functions.
25886*/
25887
25888
25889namespace Parma_Polyhedra_Library {
25890
25891
25892template <typename Func1, typename Func2>
25893void
25894Sparse_Row::combine_needs_first(const Sparse_Row& y,
25895                                const Func1& f, const Func2& g) {
25896  if (this == &y) {
25897    for (iterator i = begin(), i_end = end(); i != i_end; ++i) {
25898      g(*i, *i);
25899    }
25900  }
25901  else {
25902    iterator i = begin();
25903    // This is a const reference to an internal iterator, that is kept valid.
25904    // If we just stored a copy, that would be invalidated by the calls to
25905    // reset().
25906    const iterator& i_end = end();
25907    const_iterator j = y.begin();
25908    const_iterator j_end = y.end();
25909    while (i != i_end && j != j_end) {
25910      if (i.index() == j.index()) {
25911        g(*i, *j);
25912        if (*i == 0) {
25913          i = reset(i);
25914        }
25915        else {
25916          ++i;
25917        }
25918        ++j;
25919      }
25920      else
25921        if (i.index() < j.index()) {
25922          f(*i);
25923          if (*i == 0) {
25924            i = reset(i);
25925          }
25926          else {
25927            ++i;
25928          }
25929        }
25930        else {
25931          j = y.lower_bound(j, i.index());
25932        }
25933    }
25934    while (i != i_end) {
25935      f(*i);
25936      if (*i == 0) {
25937        i = reset(i);
25938      }
25939      else {
25940        ++i;
25941      }
25942    }
25943  }
25944}
25945
25946template <typename Func1, typename Func2>
25947void
25948Sparse_Row::combine_needs_second(const Sparse_Row& y,
25949                                 const Func1& g,
25950                                 const Func2& /* h */) {
25951  iterator i = begin();
25952  for (const_iterator j = y.begin(), j_end = y.end(); j != j_end; ++j) {
25953    i = insert(i, j.index());
25954    g(*i, *j);
25955    if (*i == 0) {
25956      i = reset(i);
25957    }
25958  }
25959}
25960
25961template <typename Func1, typename Func2, typename Func3>
25962void
25963Sparse_Row::combine(const Sparse_Row& y, const Func1& f,
25964                    const Func2& g, const Func3& h) {
25965  if (this == &y) {
25966    for (iterator i = begin(), i_end = end(); i != i_end; ++i) {
25967      g(*i, *i);
25968    }
25969  }
25970  else {
25971    iterator i = begin();
25972    // This is a const reference to an internal iterator, that is kept valid.
25973    // If we just stored a copy, that would be invalidated by the calls to
25974    // reset() and insert().
25975    const iterator& i_end = end();
25976    const_iterator j = y.begin();
25977    const_iterator j_end = y.end();
25978    while (i != i_end && j != j_end) {
25979      if (i.index() == j.index()) {
25980        g(*i, *j);
25981        if (*i == 0) {
25982          i = reset(i);
25983        }
25984        else {
25985          ++i;
25986        }
25987        ++j;
25988      }
25989      else
25990        if (i.index() < j.index()) {
25991          f(*i);
25992          if (*i == 0) {
25993            i = reset(i);
25994          }
25995          else {
25996            ++i;
25997          }
25998        }
25999        else {
26000          PPL_ASSERT(i.index() > j.index());
26001          i = insert(i, j.index());
26002          h(*i, *j);
26003          if (*i == 0) {
26004            i = reset(i);
26005          }
26006          else {
26007            ++i;
26008          }
26009          ++j;
26010        }
26011    }
26012    PPL_ASSERT(i == i_end || j == j_end);
26013    while (i != i_end) {
26014      f(*i);
26015      if (*i == 0) {
26016        i = reset(i);
26017      }
26018      else {
26019        ++i;
26020      }
26021    }
26022    while (j != j_end) {
26023      i = insert(i, j.index());
26024      h(*i, *j);
26025      if (*i == 0) {
26026        i = reset(i);
26027      }
26028      ++j;
26029    }
26030  }
26031}
26032
26033} // namespace Parma_Polyhedra_Library
26034
26035/* Automatically generated from PPL source file ../src/Sparse_Row_defs.hh line 929. */
26036
26037/* Automatically generated from PPL source file ../src/Linear_Expression_Impl_defs.hh line 34. */
26038#include <cstddef>
26039
26040namespace Parma_Polyhedra_Library {
26041
26042namespace IO_Operators {
26043
26044#ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
26045//! Output operator.
26046/*! \relates Parma_Polyhedra_Library::Linear_Expression_Impl */
26047#endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
26048template <typename Row>
26049std::ostream&
26050operator<<(std::ostream& s, const Linear_Expression_Impl<Row>& e);
26051
26052} // namespace IO_Operators
26053
26054} // namespace Parma_Polyhedra_Library
26055
26056#ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
26057//! A linear expression.
26058/*! \ingroup PPL_CXX_interface
26059  An object of the class Linear_Expression_Impl represents the linear
26060  expression
26061  \f[
26062    \sum_{i=0}^{n-1} a_i x_i + b
26063  \f]
26064  where \f$n\f$ is the dimension of the vector space,
26065  each \f$a_i\f$ is the integer coefficient
26066  of the \f$i\f$-th variable \f$x_i\f$
26067  and \f$b\f$ is the integer for the inhomogeneous term.
26068
26069  \par How to build a linear expression.
26070
26071  Linear expressions are the basic blocks for defining
26072  both constraints (i.e., linear equalities or inequalities)
26073  and generators (i.e., lines, rays, points and closure points).
26074  A full set of functions is defined to provide a convenient interface
26075  for building complex linear expressions starting from simpler ones
26076  and from objects of the classes Variable and Coefficient:
26077  available operators include unary negation,
26078  binary addition and subtraction,
26079  as well as multiplication by a Coefficient.
26080  The space dimension of a linear expression is defined as the maximum
26081  space dimension of the arguments used to build it:
26082  in particular, the space dimension of a Variable <CODE>x</CODE>
26083  is defined as <CODE>x.id()+1</CODE>,
26084  whereas all the objects of the class Coefficient have space dimension zero.
26085
26086  \par Example
26087  The following code builds the linear expression \f$4x - 2y - z + 14\f$,
26088  having space dimension \f$3\f$:
26089  \code
26090  Linear_Expression_Impl e = 4*x - 2*y - z + 14;
26091  \endcode
26092  Another way to build the same linear expression is:
26093  \code
26094  Linear_Expression_Impl e1 = 4*x;
26095  Linear_Expression_Impl e2 = 2*y;
26096  Linear_Expression_Impl e3 = z;
26097  Linear_Expression_Impl e = Linear_Expression_Impl(14);
26098  e += e1 - e2 - e3;
26099  \endcode
26100  Note that \p e1, \p e2 and \p e3 have space dimension 1, 2 and 3,
26101  respectively; also, in the fourth line of code, \p e is created
26102  with space dimension zero and then extended to space dimension 3
26103  in the fifth line.
26104*/
26105#endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
26106template <typename Row>
26107class Parma_Polyhedra_Library::Linear_Expression_Impl
26108  : public Linear_Expression_Interface {
26109public:
26110  //! Default constructor: returns a copy of Linear_Expression_Impl::zero().
26111  Linear_Expression_Impl();
26112
26113  //! Ordinary copy constructor.
26114  Linear_Expression_Impl(const Linear_Expression_Impl& e);
26115
26116  //! Copy constructor for other row types.
26117  template <typename Row2>
26118  Linear_Expression_Impl(const Linear_Expression_Impl<Row2>& e);
26119
26120  //! Copy constructor from any implementation of Linear_Expression_Interface.
26121  Linear_Expression_Impl(const Linear_Expression_Interface& e);
26122
26123  //! Destructor.
26124  virtual ~Linear_Expression_Impl();
26125
26126  //! Checks if all the invariants are satisfied.
26127  virtual bool OK() const;
26128
26129  /*! \brief
26130    Builds the linear expression corresponding
26131    to the inhomogeneous term \p n.
26132  */
26133  explicit Linear_Expression_Impl(Coefficient_traits::const_reference n);
26134
26135  //! Builds the linear expression corresponding to the variable \p v.
26136  /*!
26137    \exception std::length_error
26138    Thrown if the space dimension of \p v exceeds
26139    <CODE>Linear_Expression_Impl::max_space_dimension()</CODE>.
26140  */
26141  Linear_Expression_Impl(Variable v);
26142
26143  //! Returns the current representation of this linear expression.
26144  virtual Representation representation() const;
26145
26146  //! An interface for const iterators on the expression (homogeneous)
26147  //! coefficients that are nonzero.
26148  /*!
26149    These iterators are invalidated by operations that modify the expression.
26150  */
26151  class const_iterator: public const_iterator_interface {
26152  public:
26153    explicit const_iterator(const Row& row, dimension_type i);
26154
26155    //! Returns a copy of *this.
26156    //! This returns a pointer to dynamic-allocated memory. The caller has the
26157    //! duty to free the memory when it's not needed anymore.
26158    virtual const_iterator_interface* clone() const;
26159
26160    //! Navigates to the next nonzero coefficient.
26161    //! Note that this method does *not* return a reference, to increase
26162    //! efficiency since it's virtual.
26163    virtual void operator++();
26164
26165    //! Navigates to the previous nonzero coefficient.
26166    //! Note that this method does *not* return a reference, to increase
26167    //! efficiency since it's virtual.
26168    virtual void operator--();
26169
26170    //! Returns the current element.
26171    virtual reference operator*() const;
26172
26173    //! Returns the variable of the coefficient pointed to by \c *this.
26174    /*!
26175      \returns the variable of the coefficient pointed to by \c *this.
26176    */
26177    virtual Variable variable() const;
26178
26179    //! Compares \p *this with x .
26180    /*!
26181      \param x
26182      The %iterator that will be compared with *this.
26183    */
26184    virtual bool operator==(const const_iterator_interface& x) const;
26185
26186  private:
26187
26188    void skip_zeroes_forward();
26189    void skip_zeroes_backward();
26190
26191    const Row* row;
26192    typename Row::const_iterator itr;
26193  };
26194
26195  //! This returns a pointer to dynamic-allocated memory. The caller has the
26196  //! duty to free the memory when it's not needed anymore.
26197  virtual const_iterator_interface* begin() const;
26198
26199  //! This returns a pointer to dynamic-allocated memory. The caller has the
26200  //! duty to free the memory when it's not needed anymore.
26201  virtual const_iterator_interface* end() const;
26202
26203  //! This returns a pointer to dynamic-allocated memory. The caller has the
26204  //! duty to free the memory when it's not needed anymore.
26205  //! Returns (a pointer to) an iterator that points to the first nonzero
26206  //! coefficient of a variable greater than or equal to v, or at end if no
26207  //! such coefficient exists.
26208  virtual const_iterator_interface* lower_bound(Variable v) const;
26209
26210  //! Returns the maximum space dimension a Linear_Expression_Impl can handle.
26211  static dimension_type max_space_dimension();
26212
26213  //! Returns the dimension of the vector space enclosing \p *this.
26214  virtual dimension_type space_dimension() const;
26215
26216  //! Sets the dimension of the vector space enclosing \p *this to \p n .
26217  virtual void set_space_dimension(dimension_type n);
26218
26219  //! Returns the coefficient of \p v in \p *this.
26220  virtual Coefficient_traits::const_reference coefficient(Variable v) const;
26221
26222  //! Sets the coefficient of \p v in \p *this to \p n.
26223  virtual void set_coefficient(Variable v,
26224                               Coefficient_traits::const_reference n);
26225
26226  //! Returns the inhomogeneous term of \p *this.
26227  virtual Coefficient_traits::const_reference inhomogeneous_term() const;
26228
26229  //! Sets the inhomogeneous term of \p *this to \p n.
26230  virtual void set_inhomogeneous_term(Coefficient_traits::const_reference n);
26231
26232  //! Linearly combines \p *this with \p y so that the coefficient of \p v
26233  //! is 0.
26234  /*!
26235    \param y
26236    The expression that will be combined with \p *this object;
26237
26238    \param v
26239    The variable whose coefficient has to become \f$0\f$.
26240
26241    Computes a linear combination of \p *this and \p y having
26242    the coefficient of variable \p v equal to \f$0\f$. Then it assigns
26243    the resulting expression to \p *this.
26244
26245    \p *this and \p y must have the same space dimension.
26246  */
26247  virtual void linear_combine(const Linear_Expression_Interface& y, Variable v);
26248
26249  //! Equivalent to <CODE>*this = *this * c1 + y * c2</CODE>, but assumes that
26250  //! \p *this and \p y have the same space dimension.
26251  virtual void linear_combine(const Linear_Expression_Interface& y,
26252                              Coefficient_traits::const_reference c1,
26253                              Coefficient_traits::const_reference c2);
26254
26255  //! Equivalent to <CODE>*this = *this * c1 + y * c2</CODE>.
26256  //! c1 and c2 may be 0.
26257  virtual void linear_combine_lax(const Linear_Expression_Interface& y,
26258                                  Coefficient_traits::const_reference c1,
26259                                  Coefficient_traits::const_reference c2);
26260
26261  //! Swaps the coefficients of the variables \p v1 and \p v2 .
26262  virtual void swap_space_dimensions(Variable v1, Variable v2);
26263
26264  //! Removes all the specified dimensions from the expression.
26265  /*!
26266    The space dimension of the variable with the highest space
26267    dimension in \p vars must be at most the space dimension
26268    of \p this.
26269  */
26270  virtual void remove_space_dimensions(const Variables_Set& vars);
26271
26272  //! Shift by \p n positions the coefficients of variables, starting from
26273  //! the coefficient of \p v. This increases the space dimension by \p n.
26274  virtual void shift_space_dimensions(Variable v, dimension_type n);
26275
26276  //! Permutes the space dimensions of the expression.
26277  /*!
26278    \param cycle
26279    A vector representing a cycle of the permutation according to which the
26280    space dimensions must be rearranged.
26281
26282    The \p cycle vector represents a cycle of a permutation of space
26283    dimensions.
26284    For example, the permutation
26285    \f$ \{ x_1 \mapsto x_2, x_2 \mapsto x_3, x_3 \mapsto x_1 \}\f$ can be
26286    represented by the vector containing \f$ x_1, x_2, x_3 \f$.
26287  */
26288  virtual void permute_space_dimensions(const std::vector<Variable>& cycle);
26289
26290  //! Returns <CODE>true</CODE> if and only if \p *this is \f$0\f$.
26291  virtual bool is_zero() const;
26292
26293  /*! \brief
26294    Returns <CODE>true</CODE> if and only if all the homogeneous
26295    terms of \p *this are \f$0\f$.
26296  */
26297  virtual bool all_homogeneous_terms_are_zero() const;
26298
26299  /*! \brief
26300    Returns a lower bound to the total size in bytes of the memory
26301    occupied by \p *this.
26302  */
26303  virtual memory_size_type total_memory_in_bytes() const;
26304
26305  //! Returns the size in bytes of the memory managed by \p *this.
26306  virtual memory_size_type external_memory_in_bytes() const;
26307
26308  //! Writes to \p s an ASCII representation of \p *this.
26309  virtual void ascii_dump(std::ostream& s) const;
26310
26311  /*! \brief
26312    Loads from \p s an ASCII representation (as produced by
26313    ascii_dump(std::ostream&) const) and sets \p *this accordingly.
26314    Returns <CODE>true</CODE> if successful, <CODE>false</CODE> otherwise.
26315  */
26316  virtual bool ascii_load(std::istream& s);
26317
26318  //! Copy constructor with a specified space dimension.
26319  Linear_Expression_Impl(const Linear_Expression_Interface& e,
26320                         dimension_type space_dim);
26321
26322  //! Returns \p true if *this is equal to \p x.
26323  //! Note that (*this == x) has a completely different meaning.
26324  virtual bool is_equal_to(const Linear_Expression_Interface& x) const;
26325
26326  //! Normalizes the modulo of the coefficients and of the inhomogeneous term
26327  //! so that they are mutually prime.
26328  /*!
26329    Computes the Greatest Common Divisor (GCD) among the coefficients
26330    and the inhomogeneous term and normalizes them by the GCD itself.
26331  */
26332  virtual void normalize();
26333
26334  //! Ensures that the first nonzero homogeneous coefficient is positive,
26335  //! by negating the row if necessary.
26336  virtual void sign_normalize();
26337
26338  /*! \brief
26339    Negates the elements from index \p first (included)
26340    to index \p last (excluded).
26341  */
26342  virtual void negate(dimension_type first, dimension_type last);
26343
26344  virtual Linear_Expression_Impl&
26345  operator+=(Coefficient_traits::const_reference n);
26346  virtual Linear_Expression_Impl&
26347  operator-=(Coefficient_traits::const_reference n);
26348
26349  //! The basic comparison function.
26350  /*! \relates Linear_Expression_Impl
26351
26352    \returns
26353    -1 or -2 if x is less than y, 0 if they are equal and 1 or 2 is y
26354    is greater. The absolute value of the result is 1 if the difference
26355    is only in the inhomogeneous terms, 2 otherwise.
26356
26357    The order is a lexicographic. It starts comparing the variables'
26358    coefficient, starting from Variable(0), and at the end it compares
26359    the inhomogeneous terms.
26360  */
26361  virtual int compare(const Linear_Expression_Interface& y) const;
26362
26363  virtual Linear_Expression_Impl&
26364  operator+=(const Linear_Expression_Interface& e2);
26365  virtual Linear_Expression_Impl& operator+=(const Variable v);
26366  virtual Linear_Expression_Impl&
26367  operator-=(const Linear_Expression_Interface& e2);
26368  virtual Linear_Expression_Impl& operator-=(const Variable v);
26369  virtual Linear_Expression_Impl&
26370  operator*=(Coefficient_traits::const_reference n);
26371  virtual Linear_Expression_Impl&
26372  operator/=(Coefficient_traits::const_reference n);
26373
26374  virtual void negate();
26375
26376  virtual Linear_Expression_Impl&
26377  add_mul_assign(Coefficient_traits::const_reference n, const Variable v);
26378
26379  virtual Linear_Expression_Impl&
26380  sub_mul_assign(Coefficient_traits::const_reference n, const Variable v);
26381
26382  virtual void add_mul_assign(Coefficient_traits::const_reference factor,
26383                              const Linear_Expression_Interface& e2);
26384
26385  virtual void sub_mul_assign(Coefficient_traits::const_reference factor,
26386                              const Linear_Expression_Interface& e2);
26387
26388  virtual void print(std::ostream& s) const;
26389
26390  /*! \brief
26391    Returns <CODE>true</CODE> if the coefficient of each variable in
26392    \p vars[i] is \f$0\f$.
26393  */
26394  virtual bool all_zeroes(const Variables_Set& vars) const;
26395
26396  //! Returns true if there is a variable in [first,last) whose coefficient
26397  //! is nonzero in both *this and x.
26398  virtual bool have_a_common_variable(const Linear_Expression_Interface& x,
26399                                      Variable first, Variable last) const;
26400
26401  // NOTE: This method is public, but it's not exposed in Linear_Expression,
26402  // so that it can be used internally in the PPL, by friends of
26403  // Linear_Expression.
26404  //! Returns the i-th coefficient.
26405  virtual Coefficient_traits::const_reference get(dimension_type i) const;
26406
26407  // NOTE: This method is public, but it's not exposed in Linear_Expression,
26408  // so that it can be used internally in the PPL, by friends of
26409  // Linear_Expression.
26410  //! Sets the i-th coefficient to n.
26411  virtual void set(dimension_type i, Coefficient_traits::const_reference n);
26412
26413  // NOTE: This method is public, but it's not exposed in Linear_Expression,
26414  // so that it can be used internally in the PPL, by friends of
26415  // Linear_Expression.
26416  /*! \brief
26417    Returns <CODE>true</CODE> if (*this)[i] is \f$0\f$, for each i in
26418    [start, end).
26419  */
26420  virtual bool all_zeroes(dimension_type start, dimension_type end) const;
26421
26422  // NOTE: This method is public, but it's not exposed in Linear_Expression,
26423  // so that it can be used internally in the PPL, by friends of
26424  // Linear_Expression.
26425  /*! \brief
26426    Returns the number of zero coefficient in [start, end).
26427  */
26428  virtual dimension_type num_zeroes(dimension_type start, dimension_type end) const;
26429
26430  // NOTE: This method is public, but it's not exposed in Linear_Expression,
26431  // so that it can be used internally in the PPL, by friends of
26432  // Linear_Expression.
26433  /*! \brief
26434    Returns the gcd of the nonzero coefficients in [start,end). If all the
26435    coefficients in this range are 0 returns 0.
26436  */
26437  virtual Coefficient gcd(dimension_type start, dimension_type end) const;
26438
26439  // NOTE: This method is public, but it's not exposed in Linear_Expression,
26440  // so that it can be used internally in the PPL, by friends of
26441  // Linear_Expression.
26442  virtual void exact_div_assign(Coefficient_traits::const_reference c,
26443                                dimension_type start, dimension_type end);
26444
26445  // NOTE: This method is public, but it's not exposed in Linear_Expression,
26446  // so that it can be used internally in the PPL, by friends of
26447  // Linear_Expression.
26448  //! Equivalent to <CODE>(*this)[i] *= n</CODE>, for each i in [start, end).
26449  virtual void mul_assign(Coefficient_traits::const_reference n,
26450                          dimension_type start, dimension_type end);
26451
26452  // NOTE: This method is public, but it's not exposed in Linear_Expression,
26453  // so that it can be used internally in the PPL, by friends of
26454  // Linear_Expression.
26455  //! Linearly combines \p *this with \p y so that the coefficient of \p v
26456  //! is 0.
26457  /*!
26458    \param y
26459    The expression that will be combined with \p *this object;
26460
26461    \param i
26462    The index of the coefficient that has to become \f$0\f$.
26463
26464    Computes a linear combination of \p *this and \p y having
26465    the i-th coefficient equal to \f$0\f$. Then it assigns
26466    the resulting expression to \p *this.
26467
26468    \p *this and \p y must have the same space dimension.
26469  */
26470  virtual void
26471  linear_combine(const Linear_Expression_Interface& y, dimension_type i);
26472
26473  // NOTE: This method is public, but it's not exposed in Linear_Expression,
26474  // so that it can be used internally in the PPL, by friends of
26475  // Linear_Expression.
26476  //! Equivalent to <CODE>(*this)[i] = (*this)[i] * c1 + y[i] * c2</CODE>,
26477  //! for each i in [start, end).
26478  virtual void linear_combine(const Linear_Expression_Interface& y,
26479                              Coefficient_traits::const_reference c1,
26480                              Coefficient_traits::const_reference c2,
26481                              dimension_type start, dimension_type end);
26482
26483  // NOTE: This method is public, but it's not exposed in Linear_Expression,
26484  // so that it can be used internally in the PPL, by friends of
26485  // Linear_Expression.
26486  //! Equivalent to <CODE>(*this)[i] = (*this)[i] * c1 + y[i] * c2</CODE>,
26487  //! for each i in [start, end). c1 and c2 may be zero.
26488  virtual void linear_combine_lax(const Linear_Expression_Interface& y,
26489                                  Coefficient_traits::const_reference c1,
26490                                  Coefficient_traits::const_reference c2,
26491                                  dimension_type start, dimension_type end);
26492
26493  // NOTE: This method is public, but it's not exposed in Linear_Expression,
26494  // so that it can be used internally in the PPL, by friends of
26495  // Linear_Expression.
26496  //! Returns the index of the last nonzero element, or 0 if there are no
26497  //! nonzero elements.
26498  virtual dimension_type last_nonzero() const;
26499
26500  // NOTE: This method is public, but it's not exposed in Linear_Expression,
26501  // so that it can be used internally in the PPL, by friends of
26502  // Linear_Expression.
26503  /*! \brief
26504    Returns <CODE>true</CODE> if each coefficient in [start,end) is *not* in
26505    \f$0\f$, disregarding coefficients of variables in \p vars.
26506  */
26507  virtual bool
26508  all_zeroes_except(const Variables_Set& vars,
26509                    dimension_type start, dimension_type end) const;
26510
26511  // NOTE: This method is public, but it's not exposed in Linear_Expression,
26512  // so that it can be used internally in the PPL, by friends of
26513  // Linear_Expression.
26514  //! Sets results to the sum of (*this)[i]*y[i], for each i in [start,end).
26515  virtual void
26516  scalar_product_assign(Coefficient& result,
26517                        const Linear_Expression_Interface& y,
26518                        dimension_type start, dimension_type end) const;
26519
26520  // NOTE: This method is public, but it's not exposed in Linear_Expression,
26521  // so that it can be used internally in the PPL, by friends of
26522  // Linear_Expression.
26523  //! Computes the sign of the sum of (*this)[i]*y[i], for each i in [start,end).
26524  virtual int
26525  scalar_product_sign(const Linear_Expression_Interface& y,
26526                      dimension_type start, dimension_type end) const;
26527
26528  // NOTE: This method is public, but it's not exposed in Linear_Expression,
26529  // so that it can be used internally in the PPL, by friends of
26530  // Linear_Expression.
26531  //! Returns the index of the first nonzero element, or \p last if there are no
26532  //! nonzero elements, considering only elements in [first,last).
26533  virtual dimension_type
26534  first_nonzero(dimension_type first, dimension_type last) const;
26535
26536  // NOTE: This method is public, but it's not exposed in Linear_Expression,
26537  // so that it can be used internally in the PPL, by friends of
26538  // Linear_Expression.
26539  //! Returns the index of the last nonzero element in [first,last), or last
26540  //! if there are no nonzero elements.
26541  virtual dimension_type
26542  last_nonzero(dimension_type first, dimension_type last) const;
26543
26544  // NOTE: This method is public, but it's not exposed in Linear_Expression,
26545  // so that it can be used internally in the PPL, by friends of
26546  // Linear_Expression.
26547  //! Removes from the set x all the indexes of nonzero elements of *this.
26548  virtual void has_a_free_dimension_helper(std::set<dimension_type>& x) const;
26549
26550  // NOTE: This method is public, but it's not exposed in Linear_Expression,
26551  // so that it can be used internally in the PPL, by friends of
26552  // Linear_Expression.
26553  //! Returns \p true if (*this)[i] is equal to x[i], for each i in [start,end).
26554  virtual bool is_equal_to(const Linear_Expression_Interface& x,
26555                           dimension_type start, dimension_type end) const;
26556
26557  // NOTE: This method is public, but it's not exposed in Linear_Expression,
26558  // so that it can be used internally in the PPL, by friends of
26559  // Linear_Expression.
26560  //! Returns \p true if (*this)[i]*c1 is equal to x[i]*c2, for each i in
26561  //! [start,end).
26562  virtual bool is_equal_to(const Linear_Expression_Interface& x,
26563                           Coefficient_traits::const_reference c1,
26564                           Coefficient_traits::const_reference c2,
26565                           dimension_type start, dimension_type end) const;
26566
26567  // NOTE: This method is public, but it is not exposed in
26568  // Linear_Expression, so that it can be used internally in the PPL,
26569  // by friends of Linear_Expression.
26570  //! Sets \p r to a copy of the row that implements \p *this.
26571  virtual void get_row(Dense_Row& r) const;
26572
26573  // NOTE: This method is public, but it is not exposed in
26574  // Linear_Expression, so that it can be used internally in the PPL,
26575  // by friends of Linear_Expression.
26576  //! Sets \p r to a copy of the row that implements \p *this.
26577  virtual void get_row(Sparse_Row& r) const;
26578
26579  //! Implementation sizing constructor.
26580  /*!
26581    The bool parameter is just to avoid problems with the constructor
26582    Linear_Expression_Impl(Coefficient_traits::const_reference n).
26583  */
26584  Linear_Expression_Impl(dimension_type space_dim, bool);
26585
26586  //! Linearly combines \p *this with \p y so that the coefficient of \p v
26587  //! is 0.
26588  /*!
26589    \param y
26590    The expression that will be combined with \p *this object;
26591
26592    \param v
26593    The variable whose coefficient has to become \f$0\f$.
26594
26595    Computes a linear combination of \p *this and \p y having
26596    the coefficient of variable \p v equal to \f$0\f$. Then it assigns
26597    the resulting expression to \p *this.
26598
26599    \p *this and \p y must have the same space dimension.
26600  */
26601  template <typename Row2>
26602  void linear_combine(const Linear_Expression_Impl<Row2>& y, Variable v);
26603
26604  //! Equivalent to <CODE>*this = *this * c1 + y * c2</CODE>, but assumes that
26605  //! \p *this and \p y have the same space dimension.
26606  template <typename Row2>
26607  void linear_combine(const Linear_Expression_Impl<Row2>& y,
26608                      Coefficient_traits::const_reference c1,
26609                      Coefficient_traits::const_reference c2);
26610
26611  //! Equivalent to <CODE>*this = *this * c1 + y * c2</CODE>.
26612  //! c1 and c2 may be 0.
26613  template <typename Row2>
26614  void linear_combine_lax(const Linear_Expression_Impl<Row2>& y,
26615                          Coefficient_traits::const_reference c1,
26616                          Coefficient_traits::const_reference c2);
26617
26618  //! Returns \p true if *this is equal to \p x.
26619  //! Note that (*this == x) has a completely different meaning.
26620  template <typename Row2>
26621  bool is_equal_to(const Linear_Expression_Impl<Row2>& x) const;
26622
26623  template <typename Row2>
26624  Linear_Expression_Impl& operator+=(const Linear_Expression_Impl<Row2>& e2);
26625  template <typename Row2>
26626  Linear_Expression_Impl& operator-=(const Linear_Expression_Impl<Row2>& e2);
26627
26628  template <typename Row2>
26629  Linear_Expression_Impl&
26630  sub_mul_assign(Coefficient_traits::const_reference n,
26631                 const Linear_Expression_Impl<Row2>& y,
26632                 dimension_type start, dimension_type end);
26633
26634  template <typename Row2>
26635  void add_mul_assign(Coefficient_traits::const_reference factor,
26636                      const Linear_Expression_Impl<Row2>& e2);
26637
26638  template <typename Row2>
26639  void sub_mul_assign(Coefficient_traits::const_reference factor,
26640                      const Linear_Expression_Impl<Row2>& e2);
26641
26642  //! Linearly combines \p *this with \p y so that the coefficient of \p v
26643  //! is 0.
26644  /*!
26645    \param y
26646    The expression that will be combined with \p *this object;
26647
26648    \param i
26649    The index of the coefficient that has to become \f$0\f$.
26650
26651    Computes a linear combination of \p *this and \p y having
26652    the i-th coefficient equal to \f$0\f$. Then it assigns
26653    the resulting expression to \p *this.
26654
26655    \p *this and \p y must have the same space dimension.
26656  */
26657  template <typename Row2>
26658  void linear_combine(const Linear_Expression_Impl<Row2>& y, dimension_type i);
26659
26660  //! Equivalent to <CODE>(*this)[i] = (*this)[i] * c1 + y[i] * c2</CODE>,
26661  //! for each i in [start, end).
26662  template <typename Row2>
26663  void linear_combine(const Linear_Expression_Impl<Row2>& y,
26664                      Coefficient_traits::const_reference c1,
26665                      Coefficient_traits::const_reference c2,
26666                      dimension_type start, dimension_type end);
26667
26668  //! Equivalent to <CODE>(*this)[i] = (*this)[i] * c1 + y[i] * c2</CODE>,
26669  //! for each i in [start, end). c1 and c2 may be zero.
26670  template <typename Row2>
26671  void linear_combine_lax(const Linear_Expression_Impl<Row2>& y,
26672                          Coefficient_traits::const_reference c1,
26673                          Coefficient_traits::const_reference c2,
26674                          dimension_type start, dimension_type end);
26675
26676  //! The basic comparison function.
26677  /*! \relates Linear_Expression_Impl
26678
26679    \returns
26680    -1 or -2 if x is less than y, 0 if they are equal and 1 or 2 is y
26681    is greater. The absolute value of the result is 1 if the difference
26682    is only in the inhomogeneous terms, 2 otherwise.
26683
26684    The order is a lexicographic. It starts comparing the variables'
26685    coefficient, starting from Variable(0), and at the end it compares
26686    the inhomogeneous terms.
26687  */
26688  template <typename Row2>
26689  int compare(const Linear_Expression_Impl<Row2>& y) const;
26690
26691  //! Sets results to the sum of (*this)[i]*y[i], for each i in [start,end).
26692  template <typename Row2>
26693  void
26694  scalar_product_assign(Coefficient& result,
26695                        const Linear_Expression_Impl<Row2>& y,
26696                        dimension_type start, dimension_type end) const;
26697
26698  //! Computes the sign of the sum of (*this)[i]*y[i],
26699  //! for each i in [start,end).
26700  template <typename Row2>
26701  int scalar_product_sign(const Linear_Expression_Impl<Row2>& y,
26702                          dimension_type start, dimension_type end) const;
26703
26704  //! Returns \p true if (*this)[i] is equal to x[i], for each i in [start,end).
26705  template <typename Row2>
26706  bool is_equal_to(const Linear_Expression_Impl<Row2>& x,
26707                   dimension_type start, dimension_type end) const;
26708
26709  //! Returns \p true if (*this)[i]*c1 is equal to x[i]*c2, for each i in
26710  //! [start,end).
26711  template <typename Row2>
26712  bool is_equal_to(const Linear_Expression_Impl<Row2>& x,
26713                   Coefficient_traits::const_reference c1,
26714                   Coefficient_traits::const_reference c2,
26715                   dimension_type start, dimension_type end) const;
26716
26717  //! Returns true if there is a variable in [first,last) whose coefficient
26718  //! is nonzero in both *this and x.
26719  template <typename Row2>
26720  bool have_a_common_variable(const Linear_Expression_Impl<Row2>& x,
26721                              Variable first, Variable last) const;
26722
26723private:
26724
26725  void construct(const Linear_Expression_Interface& e);
26726  void construct(const Linear_Expression_Interface& e,
26727                 dimension_type space_dim);
26728
26729  template <typename Row2>
26730  void construct(const Linear_Expression_Impl<Row2>& e);
26731  template <typename Row2>
26732  void construct(const Linear_Expression_Impl<Row2>& e,
26733                 dimension_type space_dim);
26734
26735  Row row;
26736
26737  template <typename Row2>
26738  friend class Linear_Expression_Impl;
26739
26740}; // class Parma_Polyhedra_Library::Linear_Expression_Impl
26741
26742
26743namespace Parma_Polyhedra_Library {
26744
26745// NOTE: declaring explicit specializations.
26746
26747template <>
26748bool
26749Linear_Expression_Impl<Dense_Row>::OK() const;
26750template <>
26751bool
26752Linear_Expression_Impl<Sparse_Row>::OK() const;
26753
26754template <>
26755bool
26756Linear_Expression_Impl<Dense_Row>::all_homogeneous_terms_are_zero() const;
26757template <>
26758bool
26759Linear_Expression_Impl<Sparse_Row>::all_homogeneous_terms_are_zero() const;
26760
26761template <>
26762bool
26763Linear_Expression_Impl<Dense_Row>::all_zeroes(dimension_type start,
26764                                              dimension_type end) const;
26765template <>
26766bool
26767Linear_Expression_Impl<Sparse_Row>::all_zeroes(dimension_type start,
26768                                               dimension_type end) const;
26769
26770template <>
26771bool
26772Linear_Expression_Impl<Dense_Row>
26773::all_zeroes(const Variables_Set& vars) const;
26774template <>
26775bool
26776Linear_Expression_Impl<Sparse_Row>
26777::all_zeroes(const Variables_Set& vars) const;
26778
26779template <>
26780bool
26781Linear_Expression_Impl<Dense_Row>
26782::all_zeroes_except(const Variables_Set& vars,
26783                    dimension_type start, dimension_type end) const;
26784template <>
26785bool
26786Linear_Expression_Impl<Sparse_Row>
26787::all_zeroes_except(const Variables_Set& vars,
26788                    dimension_type start, dimension_type end) const;
26789
26790template <>
26791dimension_type
26792Linear_Expression_Impl<Dense_Row>
26793::first_nonzero(dimension_type first, dimension_type last) const;
26794template <>
26795dimension_type
26796Linear_Expression_Impl<Sparse_Row>
26797::first_nonzero(dimension_type first, dimension_type last) const;
26798
26799template <>
26800Coefficient
26801Linear_Expression_Impl<Dense_Row>::gcd(dimension_type start,
26802                                       dimension_type end) const;
26803template <>
26804Coefficient
26805Linear_Expression_Impl<Sparse_Row>::gcd(dimension_type start,
26806                                        dimension_type end) const;
26807
26808template <>
26809void
26810Linear_Expression_Impl<Dense_Row>
26811::has_a_free_dimension_helper(std::set<dimension_type>& x) const;
26812template <>
26813void
26814Linear_Expression_Impl<Sparse_Row>
26815::has_a_free_dimension_helper(std::set<dimension_type>& x) const;
26816
26817template <>
26818template <>
26819bool
26820Linear_Expression_Impl<Dense_Row>
26821::have_a_common_variable(const Linear_Expression_Impl<Dense_Row>& y,
26822                         Variable first, Variable last) const;
26823template <>
26824template <>
26825bool
26826Linear_Expression_Impl<Dense_Row>
26827::have_a_common_variable(const Linear_Expression_Impl<Sparse_Row>& y,
26828                         Variable first, Variable last) const;
26829template <>
26830template <>
26831bool
26832Linear_Expression_Impl<Sparse_Row>
26833::have_a_common_variable(const Linear_Expression_Impl<Dense_Row>& y,
26834                         Variable first, Variable last) const;
26835template <>
26836template <>
26837bool
26838Linear_Expression_Impl<Sparse_Row>
26839::have_a_common_variable(const Linear_Expression_Impl<Sparse_Row>& y,
26840                         Variable first, Variable last) const;
26841
26842template <>
26843bool
26844Linear_Expression_Impl<Dense_Row>::is_zero() const;
26845template <>
26846bool
26847Linear_Expression_Impl<Sparse_Row>::is_zero() const;
26848
26849template <>
26850dimension_type
26851Linear_Expression_Impl<Dense_Row>::last_nonzero() const;
26852template <>
26853dimension_type
26854Linear_Expression_Impl<Sparse_Row>::last_nonzero() const;
26855
26856template <>
26857dimension_type
26858Linear_Expression_Impl<Dense_Row>
26859::last_nonzero(dimension_type first, dimension_type last) const;
26860template <>
26861dimension_type
26862Linear_Expression_Impl<Sparse_Row>
26863::last_nonzero(dimension_type first, dimension_type last) const;
26864
26865template <>
26866dimension_type
26867Linear_Expression_Impl<Dense_Row>::num_zeroes(dimension_type start,
26868                                              dimension_type end) const;
26869template <>
26870dimension_type
26871Linear_Expression_Impl<Sparse_Row>::num_zeroes(dimension_type start,
26872                                               dimension_type end) const;
26873
26874template <>
26875void
26876Linear_Expression_Impl<Dense_Row>
26877::remove_space_dimensions(const Variables_Set& vars);
26878template <>
26879void
26880Linear_Expression_Impl<Sparse_Row>
26881::remove_space_dimensions(const Variables_Set& vars);
26882
26883template <>
26884Representation
26885Linear_Expression_Impl<Dense_Row>::representation() const;
26886template <>
26887Representation
26888Linear_Expression_Impl<Sparse_Row>::representation() const;
26889
26890template <>
26891void
26892Linear_Expression_Impl<Dense_Row>::const_iterator::skip_zeroes_backward();
26893template <>
26894void
26895Linear_Expression_Impl<Sparse_Row>::const_iterator::skip_zeroes_backward();
26896
26897template <>
26898void
26899Linear_Expression_Impl<Dense_Row>::const_iterator::skip_zeroes_forward();
26900template <>
26901void
26902Linear_Expression_Impl<Sparse_Row>::const_iterator::skip_zeroes_forward();
26903
26904} // namespace Parma_Polyhedra_Library
26905
26906
26907/* Automatically generated from PPL source file ../src/Linear_Expression_Impl_inlines.hh line 1. */
26908/* Linear_Expression_Impl class implementation: inline functions.
26909*/
26910
26911
26912/* Automatically generated from PPL source file ../src/math_utilities_defs.hh line 1. */
26913/* Declarations of some math utility functions.
26914*/
26915
26916
26917/* Automatically generated from PPL source file ../src/math_utilities_defs.hh line 29. */
26918#include <gmpxx.h>
26919
26920namespace Parma_Polyhedra_Library {
26921
26922#ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
26923//! Extract the numerator and denominator components of \p from.
26924#endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
26925template <typename T>
26926typename Enable_If<Is_Native_Or_Checked<T>::value, void>::type
26927numer_denom(const T& from,
26928            Coefficient& numer, Coefficient& denom);
26929
26930#ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
26931//! Divides \p x by \p y into \p to, rounding the result towards plus infinity.
26932#endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
26933template <typename T>
26934typename Enable_If<Is_Native_Or_Checked<T>::value, void>::type
26935div_round_up(T& to,
26936             Coefficient_traits::const_reference x,
26937             Coefficient_traits::const_reference y);
26938
26939#ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
26940//! Assigns to \p x the minimum between \p x and \p y.
26941#endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
26942template <typename N>
26943void
26944min_assign(N& x, const N& y);
26945
26946#ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
26947//! Assigns to \p x the maximum between \p x and \p y.
26948#endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
26949template <typename N>
26950void
26951max_assign(N& x, const N& y);
26952
26953#ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
26954//! Returns <CODE>true</CODE> if and only if \p x is an even number.
26955#endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
26956template <typename T>
26957typename Enable_If<Is_Native_Or_Checked<T>::value, bool>::type
26958is_even(const T& x);
26959
26960#ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
26961//! Returns <CODE>true</CODE> if and only if \f$x = -y\f$.
26962#endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
26963template <typename T>
26964typename Enable_If<Is_Native_Or_Checked<T>::value, bool>::type
26965is_additive_inverse(const T& x, const T& y);
26966
26967#ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
26968/*! \brief
26969  If \f$g\f$ is the GCD of \p x and \p y, the values of \p x and \p y
26970  divided by \f$g\f$ are assigned to \p n_x and \p n_y, respectively.
26971
26972  \note
26973  \p x and \p n_x may be the same object and likewise for
26974  \p y and \p n_y.  Any other aliasing results in undefined behavior.
26975*/
26976#endif
26977void
26978normalize2(Coefficient_traits::const_reference x,
26979           Coefficient_traits::const_reference y,
26980           Coefficient& n_x, Coefficient& n_y);
26981
26982#ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
26983//! Returns <CODE>true</CODE> if and only if \p x is in canonical form.
26984#endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
26985bool
26986is_canonical(const mpq_class& x);
26987
26988#ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
26989//! Returns a mask for the lowest \p n bits,
26990#endif
26991template <typename T>
26992T
26993low_bits_mask(unsigned n);
26994
26995} // namespace Parma_Polyhedra_Library
26996
26997/* Automatically generated from PPL source file ../src/math_utilities_inlines.hh line 1. */
26998/* Implementation of some math utility functions: inline functions.
26999*/
27000
27001
27002/* Automatically generated from PPL source file ../src/math_utilities_inlines.hh line 29. */
27003#include <limits>
27004
27005namespace Parma_Polyhedra_Library {
27006
27007inline void
27008normalize2(Coefficient_traits::const_reference x,
27009           Coefficient_traits::const_reference y,
27010           Coefficient& n_x, Coefficient& n_y) {
27011  PPL_DIRTY_TEMP_COEFFICIENT(gcd);
27012  gcd_assign(gcd, x, y);
27013  exact_div_assign(n_x, x, gcd);
27014  exact_div_assign(n_y, y, gcd);
27015}
27016
27017template <typename T>
27018inline T
27019low_bits_mask(const unsigned n) {
27020  PPL_ASSERT(n < unsigned(std::numeric_limits<T>::digits));
27021  return ~((~static_cast<T>(0)) << n);
27022}
27023
27024template <typename T>
27025inline typename Enable_If<Is_Native_Or_Checked<T>::value, void>::type
27026numer_denom(const T& from,
27027            Coefficient& numer, Coefficient& denom) {
27028  PPL_ASSERT(!is_not_a_number(from)
27029         && !is_minus_infinity(from)
27030         && !is_plus_infinity(from));
27031  PPL_DIRTY_TEMP(mpq_class, q);
27032  assign_r(q, from, ROUND_NOT_NEEDED);
27033  numer = q.get_num();
27034  denom = q.get_den();
27035}
27036
27037template <typename T>
27038inline typename Enable_If<Is_Native_Or_Checked<T>::value, void>::type
27039div_round_up(T& to,
27040             Coefficient_traits::const_reference x,
27041             Coefficient_traits::const_reference y) {
27042  PPL_DIRTY_TEMP(mpq_class, q_x);
27043  PPL_DIRTY_TEMP(mpq_class, q_y);
27044  // Note: this code assumes that a Coefficient is always convertible
27045  // to an mpq_class without loss of precision.
27046  assign_r(q_x, x, ROUND_NOT_NEEDED);
27047  assign_r(q_y, y, ROUND_NOT_NEEDED);
27048  div_assign_r(q_x, q_x, q_y, ROUND_NOT_NEEDED);
27049  assign_r(to, q_x, ROUND_UP);
27050}
27051
27052template <typename N>
27053inline void
27054min_assign(N& x, const N& y) {
27055  if (x > y) {
27056    x = y;
27057  }
27058}
27059
27060template <typename N>
27061inline void
27062max_assign(N& x, const N& y) {
27063  if (x < y) {
27064    x = y;
27065  }
27066}
27067
27068template <typename T>
27069inline typename Enable_If<Is_Native_Or_Checked<T>::value, bool>::type
27070is_even(const T& x) {
27071  T mod;
27072  return umod_2exp_assign_r(mod, x, 1, ROUND_DIRECT | ROUND_STRICT_RELATION) == V_EQ
27073    && mod == 0;
27074}
27075
27076template <typename T>
27077inline typename Enable_If<Is_Native_Or_Checked<T>::value, bool>::type
27078is_additive_inverse(const T& x, const T& y) {
27079  T negated_x;
27080  return neg_assign_r(negated_x, x, ROUND_DIRECT | ROUND_STRICT_RELATION) == V_EQ
27081    && negated_x == y;
27082}
27083
27084inline bool
27085is_canonical(const mpq_class& x) {
27086  if (x.get_den() <= 0) {
27087    return false;
27088  }
27089  PPL_DIRTY_TEMP(mpq_class, temp);
27090  temp = x;
27091  temp.canonicalize();
27092  return temp.get_num() == x.get_num();
27093}
27094
27095} // namespace Parma_Polyhedra_Library
27096
27097/* Automatically generated from PPL source file ../src/math_utilities_defs.hh line 109. */
27098
27099/* Automatically generated from PPL source file ../src/Linear_Expression_Impl_inlines.hh line 28. */
27100#include <stdexcept>
27101
27102namespace Parma_Polyhedra_Library {
27103
27104template <typename Row>
27105inline dimension_type
27106Linear_Expression_Impl<Row>::max_space_dimension() {
27107  return Row::max_size() - 1;
27108}
27109
27110template <typename Row>
27111inline
27112Linear_Expression_Impl<Row>::Linear_Expression_Impl()
27113  : row(1) {
27114  PPL_ASSERT(OK());
27115}
27116
27117template <typename Row>
27118inline
27119Linear_Expression_Impl<Row>
27120::Linear_Expression_Impl(dimension_type space_dim, bool)
27121  : row(space_dim + 1) {
27122  PPL_ASSERT(OK());
27123}
27124
27125template <typename Row>
27126inline
27127Linear_Expression_Impl<Row>::~Linear_Expression_Impl() {
27128}
27129
27130template <typename Row>
27131inline
27132Linear_Expression_Impl<Row>
27133::Linear_Expression_Impl(Coefficient_traits::const_reference n)
27134  : row(1) {
27135  if (n != 0) {
27136    row.insert(0, n);
27137  }
27138  PPL_ASSERT(OK());
27139}
27140
27141template <typename Row>
27142inline dimension_type
27143Linear_Expression_Impl<Row>::space_dimension() const {
27144  return row.size() - 1;
27145}
27146
27147template <typename Row>
27148inline void
27149Linear_Expression_Impl<Row>::set_space_dimension(dimension_type n) {
27150  row.resize(n + 1);
27151  PPL_ASSERT(OK());
27152}
27153
27154template <typename Row>
27155inline Coefficient_traits::const_reference
27156Linear_Expression_Impl<Row>::coefficient(Variable v) const {
27157  if (v.space_dimension() > space_dimension()) {
27158    return Coefficient_zero();
27159  }
27160  return row.get(v.id() + 1);
27161}
27162
27163template <typename Row>
27164inline void
27165Linear_Expression_Impl<Row>
27166::set_coefficient(Variable v, Coefficient_traits::const_reference n) {
27167  PPL_ASSERT(v.space_dimension() <= space_dimension());
27168  const dimension_type i = v.space_dimension();
27169  if (n == 0) {
27170    row.reset(i);
27171  }
27172  else {
27173    row.insert(i, n);
27174  }
27175  PPL_ASSERT(OK());
27176}
27177
27178template <typename Row>
27179inline Coefficient_traits::const_reference
27180Linear_Expression_Impl<Row>::inhomogeneous_term() const {
27181  return row.get(0);
27182}
27183
27184template <typename Row>
27185inline void
27186Linear_Expression_Impl<Row>
27187::set_inhomogeneous_term(Coefficient_traits::const_reference n) {
27188  if (n == 0) {
27189    row.reset(0);
27190  }
27191  else {
27192    row.insert(0, n);
27193  }
27194  PPL_ASSERT(OK());
27195}
27196
27197template <typename Row>
27198inline void
27199Linear_Expression_Impl<Row>::swap_space_dimensions(Variable v1, Variable v2) {
27200  row.swap_coefficients(v1.space_dimension(), v2.space_dimension());
27201  PPL_ASSERT(OK());
27202}
27203
27204template <typename Row>
27205inline void
27206Linear_Expression_Impl<Row>::shift_space_dimensions(Variable v,
27207                                                    dimension_type n) {
27208  row.add_zeroes_and_shift(n, v.space_dimension());
27209  PPL_ASSERT(OK());
27210}
27211
27212template <typename Row>
27213inline memory_size_type
27214Linear_Expression_Impl<Row>::external_memory_in_bytes() const {
27215  return row.external_memory_in_bytes();
27216}
27217
27218template <typename Row>
27219inline memory_size_type
27220Linear_Expression_Impl<Row>::total_memory_in_bytes() const {
27221  return external_memory_in_bytes() + sizeof(*this);
27222}
27223
27224template <typename Row>
27225inline Linear_Expression_Impl<Row>&
27226Linear_Expression_Impl<Row>::operator+=(Coefficient_traits::const_reference n) {
27227  typename Row::iterator itr = row.insert(0);
27228  (*itr) += n;
27229  if (*itr == 0) {
27230    row.reset(itr);
27231  }
27232  PPL_ASSERT(OK());
27233  return *this;
27234}
27235
27236template <typename Row>
27237inline Linear_Expression_Impl<Row>&
27238Linear_Expression_Impl<Row>::operator-=(Coefficient_traits::const_reference n) {
27239  typename Row::iterator itr = row.insert(0);
27240  (*itr) -= n;
27241  if (*itr == 0) {
27242    row.reset(itr);
27243  }
27244  PPL_ASSERT(OK());
27245  return *this;
27246}
27247
27248template <typename Row>
27249inline void
27250Linear_Expression_Impl<Row>::normalize() {
27251  row.normalize();
27252  PPL_ASSERT(OK());
27253}
27254
27255template <>
27256inline bool
27257Linear_Expression_Impl<Sparse_Row>::is_zero() const {
27258  return row.num_stored_elements() == 0;
27259}
27260
27261template <>
27262inline bool
27263Linear_Expression_Impl<Sparse_Row>::all_homogeneous_terms_are_zero() const {
27264  return row.lower_bound(1) == row.end();
27265}
27266
27267template <>
27268inline bool
27269Linear_Expression_Impl<Sparse_Row>::all_zeroes(dimension_type start,
27270                                               dimension_type end) const {
27271  return row.lower_bound(start) == row.lower_bound(end);
27272}
27273
27274template <>
27275inline dimension_type
27276Linear_Expression_Impl<Sparse_Row>::num_zeroes(dimension_type start,
27277                                               dimension_type end) const {
27278  PPL_ASSERT(start <= end);
27279  return (end - start)
27280    - std::distance(row.lower_bound(start), row.lower_bound(end));
27281}
27282
27283template <>
27284inline dimension_type
27285Linear_Expression_Impl<Sparse_Row>::last_nonzero() const {
27286  if (row.num_stored_elements() == 0) {
27287    return 0;
27288  }
27289  Sparse_Row::const_iterator i = row.end();
27290  --i;
27291  return i.index();
27292}
27293
27294template <>
27295inline dimension_type
27296Linear_Expression_Impl<Sparse_Row>
27297::first_nonzero(dimension_type first, dimension_type last) const {
27298  PPL_ASSERT(first <= last);
27299  PPL_ASSERT(last <= row.size());
27300  Sparse_Row::const_iterator i = row.lower_bound(first);
27301
27302  if (i != row.end() && i.index() < last) {
27303    return i.index();
27304  }
27305  else {
27306    return last;
27307  }
27308}
27309
27310template <>
27311inline dimension_type
27312Linear_Expression_Impl<Sparse_Row>
27313::last_nonzero(dimension_type first, dimension_type last) const {
27314  PPL_ASSERT(first <= last);
27315  PPL_ASSERT(last <= row.size());
27316  Sparse_Row::const_iterator itr1 = row.lower_bound(first);
27317  Sparse_Row::const_iterator itr2 = row.lower_bound(last);
27318
27319  if (itr1 == itr2) {
27320    return last;
27321  }
27322
27323  --itr2;
27324  return itr2.index();
27325}
27326
27327template <>
27328inline Representation
27329Linear_Expression_Impl<Dense_Row>::representation() const {
27330  return DENSE;
27331}
27332
27333template <>
27334inline Representation
27335Linear_Expression_Impl<Sparse_Row>::representation() const {
27336  return SPARSE;
27337}
27338
27339template <>
27340inline void
27341Linear_Expression_Impl<Sparse_Row>::const_iterator
27342::skip_zeroes_forward() {
27343  // Nothing to do.
27344}
27345
27346template <>
27347inline void
27348Linear_Expression_Impl<Sparse_Row>::const_iterator
27349::skip_zeroes_backward() {
27350  // Nothing to do.
27351}
27352
27353namespace IO_Operators {
27354
27355template <typename Row>
27356inline std::ostream&
27357operator<<(std::ostream& s, const Linear_Expression_Impl<Row>& e) {
27358  e.print(s);
27359  return s;
27360}
27361
27362} // namespace IO_Operators
27363
27364} // namespace Parma_Polyhedra_Library
27365
27366/* Automatically generated from PPL source file ../src/Linear_Expression_Impl_templates.hh line 1. */
27367/* Linear_Expression_Impl class implementation: non-inline template functions.
27368*/
27369
27370
27371/* Automatically generated from PPL source file ../src/Linear_Expression_Impl_templates.hh line 29. */
27372
27373/* Automatically generated from PPL source file ../src/Constraint_defs.hh line 1. */
27374/* Constraint class declaration.
27375*/
27376
27377
27378/* Automatically generated from PPL source file ../src/Constraint_types.hh line 1. */
27379
27380
27381namespace Parma_Polyhedra_Library {
27382
27383class Constraint;
27384
27385} // namespace Parma_Polyhedra_Library
27386
27387/* Automatically generated from PPL source file ../src/Constraint_defs.hh line 28. */
27388
27389/* Automatically generated from PPL source file ../src/Congruence_types.hh line 1. */
27390
27391
27392namespace Parma_Polyhedra_Library {
27393
27394class Congruence;
27395
27396}
27397
27398/* Automatically generated from PPL source file ../src/Polyhedron_types.hh line 1. */
27399
27400
27401namespace Parma_Polyhedra_Library {
27402
27403class Polyhedron;
27404
27405} // namespace Parma_Polyhedra_Library
27406
27407/* Automatically generated from PPL source file ../src/termination_types.hh line 1. */
27408
27409
27410namespace Parma_Polyhedra_Library {
27411
27412class Termination_Helpers;
27413
27414} // namespace Parma_Polyhedra_Library
27415
27416/* Automatically generated from PPL source file ../src/Octagonal_Shape_types.hh line 1. */
27417
27418
27419namespace Parma_Polyhedra_Library {
27420
27421template <typename T>
27422class Octagonal_Shape;
27423
27424class Octagonal_Shape_Helper;
27425
27426}
27427
27428/* Automatically generated from PPL source file ../src/Grid_types.hh line 1. */
27429
27430
27431namespace Parma_Polyhedra_Library {
27432
27433class Grid;
27434
27435} // namespace Parma_Polyhedra_Library
27436
27437/* Automatically generated from PPL source file ../src/Constraint_defs.hh line 35. */
27438
27439/* Automatically generated from PPL source file ../src/Linear_Expression_defs.hh line 1. */
27440/* Linear_Expression class declaration.
27441*/
27442
27443
27444/* Automatically generated from PPL source file ../src/Linear_Expression_defs.hh line 28. */
27445
27446/* Automatically generated from PPL source file ../src/Generator_types.hh line 1. */
27447
27448
27449namespace Parma_Polyhedra_Library {
27450
27451class Generator;
27452
27453} // namespace Parma_Polyhedra_Library
27454
27455/* Automatically generated from PPL source file ../src/Grid_Generator_types.hh line 1. */
27456
27457
27458namespace Parma_Polyhedra_Library {
27459
27460class Grid_Generator;
27461
27462}
27463
27464/* Automatically generated from PPL source file ../src/Linear_System_types.hh line 1. */
27465
27466
27467namespace Parma_Polyhedra_Library {
27468
27469template <typename Row>
27470class Linear_System;
27471
27472template <typename Row>
27473class Linear_System_With_Bit_Matrix_iterator;
27474
27475} // namespace Parma_Polyhedra_Library
27476
27477/* Automatically generated from PPL source file ../src/Constraint_System_types.hh line 1. */
27478
27479
27480namespace Parma_Polyhedra_Library {
27481
27482class Constraint_System;
27483class Constraint_System_const_iterator;
27484
27485} // namespace Parma_Polyhedra_Library
27486
27487/* Automatically generated from PPL source file ../src/Congruence_System_types.hh line 1. */
27488
27489
27490namespace Parma_Polyhedra_Library {
27491
27492class Congruence_System;
27493
27494}
27495
27496/* Automatically generated from PPL source file ../src/PIP_Problem_types.hh line 1. */
27497
27498
27499namespace Parma_Polyhedra_Library {
27500
27501//! Possible outcomes of the PIP_Problem solver.
27502/*! \ingroup PPL_CXX_interface */
27503enum PIP_Problem_Status {
27504  //! The problem is unfeasible.
27505  UNFEASIBLE_PIP_PROBLEM,
27506  //! The problem has an optimal solution.
27507  OPTIMIZED_PIP_PROBLEM
27508};
27509
27510class PIP_Problem;
27511
27512} // namespace Parma_Polyhedra_Library
27513
27514/* Automatically generated from PPL source file ../src/BHRZ03_Certificate_types.hh line 1. */
27515
27516
27517namespace Parma_Polyhedra_Library {
27518
27519class BHRZ03_Certificate;
27520
27521} // namespace Parma_Polyhedra_Library
27522
27523/* Automatically generated from PPL source file ../src/Scalar_Products_types.hh line 1. */
27524
27525
27526namespace Parma_Polyhedra_Library {
27527
27528class Scalar_Products;
27529class Topology_Adjusted_Scalar_Product_Sign;
27530class Topology_Adjusted_Scalar_Product_Assign;
27531
27532} // namespace Parma_Polyhedra_Library
27533
27534/* Automatically generated from PPL source file ../src/MIP_Problem_types.hh line 1. */
27535
27536
27537namespace Parma_Polyhedra_Library {
27538
27539//! Possible outcomes of the MIP_Problem solver.
27540/*! \ingroup PPL_CXX_interface */
27541enum MIP_Problem_Status {
27542  //! The problem is unfeasible.
27543  UNFEASIBLE_MIP_PROBLEM,
27544  //! The problem is unbounded.
27545  UNBOUNDED_MIP_PROBLEM,
27546  //! The problem has an optimal solution.
27547  OPTIMIZED_MIP_PROBLEM
27548};
27549
27550class MIP_Problem;
27551
27552} // namespace Parma_Polyhedra_Library
27553
27554/* Automatically generated from PPL source file ../src/BD_Shape_types.hh line 1. */
27555
27556
27557namespace Parma_Polyhedra_Library {
27558
27559template <typename T>
27560class BD_Shape;
27561
27562class BD_Shape_Helpers;
27563
27564} // namespace Parma_Polyhedra_Library
27565
27566/* Automatically generated from PPL source file ../src/Linear_Expression_defs.hh line 47. */
27567
27568/* Automatically generated from PPL source file ../src/Expression_Adapter_defs.hh line 1. */
27569/* Expression_Adapter class declaration.
27570*/
27571
27572
27573/* Automatically generated from PPL source file ../src/Expression_Adapter_types.hh line 1. */
27574
27575
27576namespace Parma_Polyhedra_Library {
27577
27578class Expression_Adapter_Base;
27579
27580template <typename T>
27581class Expression_Adapter;
27582
27583template <typename T>
27584class Expression_Adapter_Transparent;
27585
27586} // namespace Parma_Polyhedra_Library
27587
27588/* Automatically generated from PPL source file ../src/Expression_Adapter_defs.hh line 32. */
27589
27590#ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
27591//! Adapters' base type (for template meta-programming).
27592#endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
27593class Parma_Polyhedra_Library::Expression_Adapter_Base {
27594};
27595
27596#ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
27597//! An adapter for Linear_Expression objects.
27598/*!
27599  The adapters are meant to provide read-only, customized access to the
27600  Linear_Expression members in Constraint, Generator, Congruence and
27601  Grid_Generator objects. They typically implement the user-level view
27602  of these expressions.
27603
27604  \note
27605  A few methods implement low-level access routines and will take
27606  bare indexes as arguments (rather than Variable objects):
27607  when such a bare index \c i is zero, the inhomogeneous term is meant;
27608  when the bare index \c i is greater than zero, the coefficient of the
27609  variable having id <CODE>i - 1</CODE> is meant.
27610*/
27611#endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
27612template <typename T>
27613class Parma_Polyhedra_Library::Expression_Adapter
27614  : public Expression_Adapter_Base {
27615public:
27616  //! The type of this object.
27617  typedef Expression_Adapter<T> const_reference;
27618  //! The type obtained by one-level unwrapping.
27619  typedef typename T::const_reference inner_type;
27620  //! The raw, completely unwrapped type.
27621  typedef typename T::raw_type raw_type;
27622
27623  //! Returns an adapter after one-level unwrapping.
27624  inner_type inner() const;
27625
27626  //! The type of const iterators on coefficients.
27627  typedef typename raw_type::const_iterator const_iterator;
27628
27629  //! Returns the current representation of \p *this.
27630  Representation representation() const;
27631
27632  //! Iterator pointing to the first nonzero variable coefficient.
27633  const_iterator begin() const;
27634
27635  //! Iterator pointing after the last nonzero variable coefficient.
27636  const_iterator end() const;
27637
27638  //! Iterator pointing to the first nonzero variable coefficient
27639  //! of a variable bigger than or equal to \p v.
27640  const_iterator lower_bound(Variable v) const;
27641
27642  //! Returns the dimension of the vector space enclosing \p *this.
27643  dimension_type space_dimension() const;
27644
27645  //! Returns the coefficient of \p v in \p *this.
27646  Coefficient_traits::const_reference coefficient(Variable v) const;
27647
27648  //! Returns the inhomogeneous term of \p *this.
27649  Coefficient_traits::const_reference inhomogeneous_term() const;
27650
27651  //! Returns <CODE>true</CODE> if and only if \p *this is zero.
27652  bool is_zero() const;
27653
27654  /*! \brief
27655    Returns <CODE>true</CODE> if and only if all the homogeneous
27656    terms of \p *this are zero.
27657  */
27658  bool all_homogeneous_terms_are_zero() const;
27659
27660  /*! \brief Returns \p true if \p *this is equal to \p y.
27661
27662    Note that <CODE>(*this == y)</CODE> has a completely different meaning.
27663  */
27664  template <typename Expression>
27665  bool is_equal_to(const Expression& y) const;
27666
27667  /*! \brief
27668    Returns <CODE>true</CODE> if the coefficient of each variable in
27669    \p vars is zero.
27670  */
27671  bool all_zeroes(const Variables_Set& vars) const;
27672
27673  //! Returns the \p i -th coefficient.
27674  Coefficient_traits::const_reference get(dimension_type i) const;
27675
27676  //! Returns the coefficient of variable \p v.
27677  Coefficient_traits::const_reference get(Variable v) const;
27678
27679  /*! \brief
27680    Returns <CODE>true</CODE> if (*this)[i] is zero,
27681    for each i in [start, end).
27682  */
27683  bool all_zeroes(dimension_type start, dimension_type end) const;
27684
27685  //! Returns the number of zero coefficient in [start, end).
27686  dimension_type num_zeroes(dimension_type start, dimension_type end) const;
27687
27688  /*! \brief
27689    Returns the gcd of the nonzero coefficients in [start,end).
27690    Returns zero if all the coefficients in the range are zero.
27691  */
27692  Coefficient gcd(dimension_type start, dimension_type end) const;
27693
27694  //! Returns the index of the last nonzero element, or zero if there are no
27695  //! nonzero elements.
27696  dimension_type last_nonzero() const;
27697
27698  //! Returns the index of the last nonzero element in [first,last),
27699  //! or \p last if there are no nonzero elements.
27700  dimension_type last_nonzero(dimension_type first, dimension_type last) const;
27701
27702  //! Returns the index of the first nonzero element, or \p last if there
27703  //! are no nonzero elements, considering only elements in [first,last).
27704  dimension_type first_nonzero(dimension_type first, dimension_type last) const;
27705
27706  /*! \brief
27707    Returns <CODE>true</CODE> if all coefficients in [start,end),
27708    except those corresponding to variables in \p vars, are zero.
27709  */
27710  bool all_zeroes_except(const Variables_Set& vars,
27711                         dimension_type start, dimension_type end) const;
27712
27713  //! Removes from set \p x all the indexes of nonzero elements in \p *this.
27714  void has_a_free_dimension_helper(std::set<dimension_type>& x) const;
27715
27716  //! Returns \c true if <CODE>(*this)[i]</CODE> is equal to <CODE>y[i]</CODE>,
27717  //! for each i in [start,end).
27718  template <typename Expression>
27719  bool is_equal_to(const Expression& y,
27720                   dimension_type start, dimension_type end) const;
27721
27722  //! Returns \c true if <CODE>(*this)[i]*c1</CODE> is equal to
27723  //! <CODE>y[i]*c2</CODE>, for each i in [start,end).
27724  template <typename Expression>
27725  bool is_equal_to(const Expression& y,
27726                   Coefficient_traits::const_reference c1,
27727                   Coefficient_traits::const_reference c2,
27728                   dimension_type start, dimension_type end) const;
27729
27730  //! Sets \p r to a copy of the row as adapted by \p *this.
27731  void get_row(Dense_Row& r) const;
27732
27733  //! Sets \p r to a copy of the row as adapted by \p *this.
27734  void get_row(Sparse_Row& r) const;
27735
27736  //! Returns \c true if there is a variable in [first,last) whose coefficient
27737  //! is nonzero in both \p *this and \p y.
27738  template <typename Expression>
27739  bool have_a_common_variable(const Expression& y,
27740                              Variable first, Variable last) const;
27741
27742protected:
27743  //! Constructor.
27744  explicit Expression_Adapter(const raw_type& expr);
27745  //! The raw, completely unwrapped object subject to adaptation.
27746  const raw_type& raw_;
27747};
27748
27749#ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
27750//! A transparent adapter for Linear_Expression objects.
27751#endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
27752template <typename T>
27753class Parma_Polyhedra_Library::Expression_Adapter_Transparent
27754  : public Expression_Adapter<T> {
27755  typedef Expression_Adapter<T> base_type;
27756public:
27757  //! The type of this object.
27758  typedef Expression_Adapter_Transparent<T> const_reference;
27759  //! The type obtained by one-level unwrapping.
27760  typedef typename base_type::inner_type inner_type;
27761  //! The raw, completely unwrapped type.
27762  typedef typename base_type::raw_type raw_type;
27763
27764  //! The type of const iterators on coefficients.
27765  typedef typename base_type::const_iterator const_iterator;
27766
27767  //! Constructor.
27768  explicit Expression_Adapter_Transparent(const raw_type& expr);
27769};
27770
27771/* Automatically generated from PPL source file ../src/Expression_Adapter_inlines.hh line 1. */
27772/* Expression_Adapter class implementation: inline functions.
27773*/
27774
27775
27776/* Automatically generated from PPL source file ../src/Expression_Adapter_inlines.hh line 28. */
27777
27778namespace Parma_Polyhedra_Library {
27779
27780template <typename T>
27781inline
27782Expression_Adapter<T>::Expression_Adapter(const raw_type& expr)
27783  : raw_(expr) {
27784}
27785
27786template <typename T>
27787inline typename Expression_Adapter<T>::inner_type
27788Expression_Adapter<T>::inner() const {
27789  return inner_type(raw_);
27790}
27791
27792template <typename T>
27793inline Representation
27794Expression_Adapter<T>::representation() const {
27795  return inner().representation();
27796}
27797
27798template <typename T>
27799inline typename Expression_Adapter<T>::const_iterator
27800Expression_Adapter<T>::begin() const {
27801  return inner().begin();
27802}
27803
27804template <typename T>
27805inline typename Expression_Adapter<T>::const_iterator
27806Expression_Adapter<T>::end() const {
27807  return inner().end();
27808}
27809
27810template <typename T>
27811inline typename Expression_Adapter<T>::const_iterator
27812Expression_Adapter<T>::lower_bound(Variable v) const {
27813  return inner().lower_bound(v);
27814}
27815
27816template <typename T>
27817inline dimension_type
27818Expression_Adapter<T>::space_dimension() const {
27819  return inner().space_dimension();
27820}
27821
27822template <typename T>
27823inline Coefficient_traits::const_reference
27824Expression_Adapter<T>::coefficient(Variable v) const {
27825  return inner().coefficient(v);
27826}
27827
27828template <typename T>
27829inline Coefficient_traits::const_reference
27830Expression_Adapter<T>::inhomogeneous_term() const {
27831  return inner().inhomogeneous_term();
27832}
27833
27834template <typename T>
27835inline bool
27836Expression_Adapter<T>::is_zero() const {
27837  return inner().is_zero();
27838}
27839
27840template <typename T>
27841inline bool
27842Expression_Adapter<T>::all_homogeneous_terms_are_zero() const {
27843  return inner().all_homogeneous_terms_are_zero();
27844}
27845
27846template <typename T>
27847template <typename Expression>
27848inline bool
27849Expression_Adapter<T>::is_equal_to(const Expression& y) const {
27850  return inner().is_equal_to(y);
27851}
27852
27853template <typename T>
27854inline bool
27855Expression_Adapter<T>
27856::all_zeroes(const Variables_Set& vars) const {
27857  return inner().all_zeroes(vars);
27858}
27859
27860template <typename T>
27861inline Coefficient_traits::const_reference
27862Expression_Adapter<T>::get(dimension_type i) const {
27863  return inner().get(i);
27864}
27865
27866template <typename T>
27867inline Coefficient_traits::const_reference
27868Expression_Adapter<T>::get(Variable v) const {
27869  return inner().get(v);
27870}
27871
27872template <typename T>
27873inline bool
27874Expression_Adapter<T>::all_zeroes(dimension_type start,
27875                                  dimension_type end) const {
27876  return inner().all_zeroes(start, end);
27877}
27878
27879template <typename T>
27880inline dimension_type
27881Expression_Adapter<T>::num_zeroes(dimension_type start,
27882                                  dimension_type end) const {
27883  return inner().num_zeroes(start, end);
27884}
27885
27886template <typename T>
27887inline Coefficient
27888Expression_Adapter<T>::gcd(dimension_type start,
27889                           dimension_type end) const {
27890  return inner().gcd(start, end);
27891}
27892
27893template <typename T>
27894inline dimension_type
27895Expression_Adapter<T>::last_nonzero() const {
27896  return inner().last_nonzero();
27897}
27898
27899template <typename T>
27900inline dimension_type
27901Expression_Adapter<T>::last_nonzero(dimension_type first,
27902                                    dimension_type last) const {
27903  return inner().last_nonzero(first, last);
27904}
27905
27906template <typename T>
27907inline dimension_type
27908Expression_Adapter<T>::first_nonzero(dimension_type first,
27909                                     dimension_type last) const {
27910  return inner().first_nonzero(first, last);
27911}
27912
27913template <typename T>
27914inline bool
27915Expression_Adapter<T>
27916::all_zeroes_except(const Variables_Set& vars,
27917                    dimension_type start, dimension_type end) const {
27918  return inner().all_zeroes_except(vars, start, end);
27919}
27920
27921template <typename T>
27922inline void
27923Expression_Adapter<T>
27924::has_a_free_dimension_helper(std::set<dimension_type>& x) const {
27925  inner().has_a_free_dimension_helper(x);
27926}
27927
27928template <typename T>
27929template <typename Expression>
27930inline bool
27931Expression_Adapter<T>
27932::is_equal_to(const Expression& y,
27933              dimension_type start, dimension_type end) const {
27934  return inner().is_equal_to(y, start, end);
27935}
27936
27937template <typename T>
27938template <typename Expression>
27939inline bool
27940Expression_Adapter<T>
27941::is_equal_to(const Expression& y,
27942              Coefficient_traits::const_reference c1,
27943              Coefficient_traits::const_reference c2,
27944              dimension_type start, dimension_type end) const {
27945  return inner().is_equal_to(y, c1, c2, start, end);
27946}
27947
27948template <typename T>
27949inline void
27950Expression_Adapter<T>::get_row(Dense_Row& r) const {
27951  inner().get_row(r);
27952}
27953
27954template <typename T>
27955inline void
27956Expression_Adapter<T>::get_row(Sparse_Row& r) const {
27957  inner().get_row(r);
27958}
27959
27960template <typename T>
27961template <typename Expression>
27962inline bool
27963Expression_Adapter<T>
27964::have_a_common_variable(const Expression& y,
27965                         Variable first, Variable last) const {
27966  return inner().have_a_common_variable(y, first, last);
27967}
27968
27969template <typename T>
27970inline
27971Expression_Adapter_Transparent<T>
27972::Expression_Adapter_Transparent(const raw_type& expr)
27973  : base_type(expr) {
27974}
27975
27976} // namespace Parma_Polyhedra_Library
27977
27978/* Automatically generated from PPL source file ../src/Expression_Adapter_defs.hh line 215. */
27979
27980/* Automatically generated from PPL source file ../src/Expression_Hide_Inhomo_types.hh line 1. */
27981
27982
27983namespace Parma_Polyhedra_Library {
27984
27985template <typename T>
27986class Expression_Hide_Inhomo;
27987
27988} // namespace Parma_Polyhedra_Library
27989
27990/* Automatically generated from PPL source file ../src/Expression_Hide_Last_types.hh line 1. */
27991
27992
27993namespace Parma_Polyhedra_Library {
27994
27995template <typename T>
27996class Expression_Hide_Last;
27997
27998} // namespace Parma_Polyhedra_Library
27999
28000/* Automatically generated from PPL source file ../src/Linear_Expression_defs.hh line 51. */
28001
28002/* Automatically generated from PPL source file ../src/Linear_Expression_defs.hh line 54. */
28003#include <cstddef>
28004
28005namespace Parma_Polyhedra_Library {
28006
28007// Put them in the namespace here to declare them friend later.
28008
28009//! Returns the linear expression \p e1 + \p e2.
28010/*! \relates Linear_Expression */
28011Linear_Expression
28012operator+(const Linear_Expression& e1, const Linear_Expression& e2);
28013
28014//! Returns the linear expression \p v + \p w.
28015/*! \relates Linear_Expression */
28016Linear_Expression
28017operator+(Variable v, Variable w);
28018
28019//! Returns the linear expression \p v + \p e.
28020/*! \relates Linear_Expression */
28021Linear_Expression
28022operator+(Variable v, const Linear_Expression& e);
28023
28024//! Returns the linear expression \p e + \p v.
28025/*! \relates Linear_Expression */
28026Linear_Expression
28027operator+(const Linear_Expression& e, Variable v);
28028
28029//! Returns the linear expression \p n + \p e.
28030/*! \relates Linear_Expression */
28031Linear_Expression
28032operator+(Coefficient_traits::const_reference n, const Linear_Expression& e);
28033
28034//! Returns the linear expression \p e + \p n.
28035/*! \relates Linear_Expression */
28036Linear_Expression
28037operator+(const Linear_Expression& e, Coefficient_traits::const_reference n);
28038
28039//! Returns the linear expression \p e.
28040/*! \relates Linear_Expression */
28041Linear_Expression
28042operator+(const Linear_Expression& e);
28043
28044//! Returns the linear expression - \p e.
28045/*! \relates Linear_Expression */
28046Linear_Expression
28047operator-(const Linear_Expression& e);
28048
28049//! Returns the linear expression \p e1 - \p e2.
28050/*! \relates Linear_Expression */
28051Linear_Expression
28052operator-(const Linear_Expression& e1, const Linear_Expression& e2);
28053
28054//! Returns the linear expression \p v - \p w.
28055/*! \relates Linear_Expression */
28056Linear_Expression
28057operator-(Variable v, Variable w);
28058
28059//! Returns the linear expression \p v - \p e.
28060/*! \relates Linear_Expression */
28061Linear_Expression
28062operator-(Variable v, const Linear_Expression& e);
28063
28064//! Returns the linear expression \p e - \p v.
28065/*! \relates Linear_Expression */
28066Linear_Expression
28067operator-(const Linear_Expression& e, Variable v);
28068
28069//! Returns the linear expression \p n - \p e.
28070/*! \relates Linear_Expression */
28071Linear_Expression
28072operator-(Coefficient_traits::const_reference n, const Linear_Expression& e);
28073
28074//! Returns the linear expression \p e - \p n.
28075/*! \relates Linear_Expression */
28076Linear_Expression
28077operator-(const Linear_Expression& e, Coefficient_traits::const_reference n);
28078
28079//! Returns the linear expression \p n * \p e.
28080/*! \relates Linear_Expression */
28081Linear_Expression
28082operator*(Coefficient_traits::const_reference n, const Linear_Expression& e);
28083
28084//! Returns the linear expression \p e * \p n.
28085/*! \relates Linear_Expression */
28086Linear_Expression
28087operator*(const Linear_Expression& e, Coefficient_traits::const_reference n);
28088
28089//! Returns the linear expression \p e1 + \p e2 and assigns it to \p e1.
28090/*! \relates Linear_Expression */
28091Linear_Expression&
28092operator+=(Linear_Expression& e1, const Linear_Expression& e2);
28093
28094//! Returns the linear expression \p e + \p v and assigns it to \p e.
28095/*! \relates Linear_Expression
28096  \exception std::length_error
28097  Thrown if the space dimension of \p v exceeds
28098  <CODE>Linear_Expression::max_space_dimension()</CODE>.
28099 */
28100Linear_Expression&
28101operator+=(Linear_Expression& e, Variable v);
28102
28103//! Returns the linear expression \p e + \p n and assigns it to \p e.
28104/*! \relates Linear_Expression */
28105Linear_Expression&
28106operator+=(Linear_Expression& e, Coefficient_traits::const_reference n);
28107
28108//! Returns the linear expression \p e1 - \p e2 and assigns it to \p e1.
28109/*! \relates Linear_Expression */
28110Linear_Expression&
28111operator-=(Linear_Expression& e1, const Linear_Expression& e2);
28112
28113//! Returns the linear expression \p e - \p v and assigns it to \p e.
28114/*! \relates Linear_Expression
28115  \exception std::length_error
28116  Thrown if the space dimension of \p v exceeds
28117  <CODE>Linear_Expression::max_space_dimension()</CODE>.
28118 */
28119Linear_Expression&
28120operator-=(Linear_Expression& e, Variable v);
28121
28122//! Returns the linear expression \p e - \p n and assigns it to \p e.
28123/*! \relates Linear_Expression */
28124Linear_Expression&
28125operator-=(Linear_Expression& e, Coefficient_traits::const_reference n);
28126
28127//! Returns the linear expression \p n * \p e and assigns it to \p e.
28128/*! \relates Linear_Expression */
28129Linear_Expression&
28130operator*=(Linear_Expression& e, Coefficient_traits::const_reference n);
28131
28132//! Returns the linear expression \p n / \p e and assigns it to \p e.
28133/*! \relates Linear_Expression */
28134Linear_Expression&
28135operator/=(Linear_Expression& e, Coefficient_traits::const_reference n);
28136
28137//! Assigns to \p e its own negation.
28138/*! \relates Linear_Expression */
28139void
28140neg_assign(Linear_Expression& e);
28141
28142//! Returns the linear expression \p e + \p n * \p v and assigns it to \p e.
28143/*! \relates Linear_Expression */
28144Linear_Expression&
28145add_mul_assign(Linear_Expression& e,
28146               Coefficient_traits::const_reference n, Variable v);
28147
28148//! Sums \p e2 multiplied by \p factor into \p e1.
28149/*! \relates Linear_Expression */
28150void add_mul_assign(Linear_Expression& e1,
28151                    Coefficient_traits::const_reference factor,
28152                    const Linear_Expression& e2);
28153
28154//! Subtracts \p e2 multiplied by \p factor from \p e1.
28155/*! \relates Linear_Expression */
28156void sub_mul_assign(Linear_Expression& e1,
28157                    Coefficient_traits::const_reference factor,
28158                    const Linear_Expression& e2);
28159
28160//! Returns the linear expression \p e - \p n * \p v and assigns it to \p e.
28161/*! \relates Linear_Expression */
28162Linear_Expression&
28163sub_mul_assign(Linear_Expression& e,
28164               Coefficient_traits::const_reference n, Variable v);
28165
28166#ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
28167//! The basic comparison function.
28168/*! \relates Linear_Expression
28169
28170  \returns -1 or -2 if x is less than y, 0 if they are equal and 1 or 2 is y
28171           is greater. The absolute value of the result is 1 if the difference
28172           is only in the inhomogeneous terms, 2 otherwise
28173
28174  The order is a lexicographic. It starts comparing the variables' coefficient,
28175  starting from Variable(0), and at the end it compares the inhomogeneous
28176  terms.
28177*/
28178#endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
28179int compare(const Linear_Expression& x, const Linear_Expression& y);
28180
28181namespace IO_Operators {
28182
28183//! Output operator.
28184/*! \relates Parma_Polyhedra_Library::Linear_Expression */
28185std::ostream& operator<<(std::ostream& s, const Linear_Expression& e);
28186
28187} // namespace IO_Operators
28188
28189} // namespace Parma_Polyhedra_Library
28190
28191//! A linear expression.
28192/*! \ingroup PPL_CXX_interface
28193  An object of the class Linear_Expression represents the linear expression
28194  \f[
28195    \sum_{i=0}^{n-1} a_i x_i + b
28196  \f]
28197  where \f$n\f$ is the dimension of the vector space,
28198  each \f$a_i\f$ is the integer coefficient
28199  of the \f$i\f$-th variable \f$x_i\f$
28200  and \f$b\f$ is the integer for the inhomogeneous term.
28201
28202  \par How to build a linear expression.
28203
28204  Linear expressions are the basic blocks for defining
28205  both constraints (i.e., linear equalities or inequalities)
28206  and generators (i.e., lines, rays, points and closure points).
28207  A full set of functions is defined to provide a convenient interface
28208  for building complex linear expressions starting from simpler ones
28209  and from objects of the classes Variable and Coefficient:
28210  available operators include unary negation,
28211  binary addition and subtraction,
28212  as well as multiplication by a Coefficient.
28213  The space dimension of a linear expression is defined as the maximum
28214  space dimension of the arguments used to build it:
28215  in particular, the space dimension of a Variable <CODE>x</CODE>
28216  is defined as <CODE>x.id()+1</CODE>,
28217  whereas all the objects of the class Coefficient have space dimension zero.
28218
28219  \par Example
28220  The following code builds the linear expression \f$4x - 2y - z + 14\f$,
28221  having space dimension \f$3\f$:
28222  \code
28223  Linear_Expression e = 4*x - 2*y - z + 14;
28224  \endcode
28225  Another way to build the same linear expression is:
28226  \code
28227  Linear_Expression e1 = 4*x;
28228  Linear_Expression e2 = 2*y;
28229  Linear_Expression e3 = z;
28230  Linear_Expression e = Linear_Expression(14);
28231  e += e1 - e2 - e3;
28232  \endcode
28233  Note that \p e1, \p e2 and \p e3 have space dimension 1, 2 and 3,
28234  respectively; also, in the fourth line of code, \p e is created
28235  with space dimension zero and then extended to space dimension 3
28236  in the fifth line.
28237*/
28238class Parma_Polyhedra_Library::Linear_Expression {
28239public:
28240  static const Representation default_representation = SPARSE;
28241
28242  //! Default constructor: returns a copy of Linear_Expression::zero().
28243  explicit Linear_Expression(Representation r = default_representation);
28244
28245  /*! \brief Ordinary copy constructor.
28246    \note
28247    The new expression will have the same representation as \p e
28248    (not necessarily the default_representation).
28249  */
28250  Linear_Expression(const Linear_Expression& e);
28251
28252  //! Copy constructor that takes also a Representation.
28253  Linear_Expression(const Linear_Expression& e, Representation r);
28254
28255  // Queried by expression adapters.
28256  typedef const Linear_Expression& const_reference;
28257  typedef Linear_Expression raw_type;
28258
28259  /*! \brief Copy constructor from a linear expression adapter.
28260    \note
28261    The new expression will have the same representation as \p e
28262    (not necessarily the default_representation).
28263  */
28264  template <typename LE_Adapter>
28265  explicit
28266  Linear_Expression(const LE_Adapter& e,
28267                    typename
28268                    Enable_If<Is_Same_Or_Derived<Expression_Adapter_Base,
28269                                                 LE_Adapter>::value,
28270                              void*>::type = 0);
28271
28272  /*! \brief Copy constructor from a linear expression adapter that takes a
28273    Representation.
28274  */
28275  template <typename LE_Adapter>
28276  Linear_Expression(const LE_Adapter& e,
28277                    Representation r,
28278                    typename
28279                    Enable_If<Is_Same_Or_Derived<Expression_Adapter_Base,
28280                                                 LE_Adapter>::value,
28281                              void*>::type = 0);
28282
28283  /*! \brief
28284    Copy constructor from a linear expression adapter that takes a
28285    space dimension.
28286    \note
28287    The new expression will have the same representation as \p e
28288    (not necessarily default_representation).
28289  */
28290  template <typename LE_Adapter>
28291  explicit
28292  Linear_Expression(const LE_Adapter& e,
28293                    dimension_type space_dim,
28294                    typename
28295                    Enable_If<Is_Same_Or_Derived<Expression_Adapter_Base,
28296                                                 LE_Adapter>::value,
28297                              void*>::type = 0);
28298
28299  /*! \brief
28300    Copy constructor from a linear expression adapter that takes a
28301    space dimension and a Representation.
28302  */
28303  template <typename LE_Adapter>
28304  Linear_Expression(const LE_Adapter& e,
28305                    dimension_type space_dim,
28306                    Representation r,
28307                    typename
28308                    Enable_If<Is_Same_Or_Derived<Expression_Adapter_Base,
28309                                                 LE_Adapter>::value,
28310                              void*>::type = 0);
28311
28312  //! Assignment operator.
28313  Linear_Expression& operator=(const Linear_Expression& e);
28314
28315  //! Destructor.
28316  ~Linear_Expression();
28317
28318  /*! \brief
28319    Builds the linear expression corresponding
28320    to the inhomogeneous term \p n.
28321  */
28322  explicit Linear_Expression(Coefficient_traits::const_reference n,
28323                             Representation r = default_representation);
28324
28325  //! Builds the linear expression corresponding to the variable \p v.
28326  /*!
28327    \exception std::length_error
28328    Thrown if the space dimension of \p v exceeds
28329    <CODE>Linear_Expression::max_space_dimension()</CODE>.
28330  */
28331  Linear_Expression(Variable v, Representation r = default_representation);
28332
28333  //! Returns the current representation of *this.
28334  Representation representation() const;
28335
28336  //! Converts *this to the specified representation.
28337  void set_representation(Representation r);
28338
28339  //! A const %iterator on the expression (homogeneous) coefficient that are
28340  //! nonzero.
28341  /*!
28342    These iterators are invalidated by operations that modify the expression.
28343  */
28344  class const_iterator {
28345  private:
28346  public:
28347    typedef std::bidirectional_iterator_tag iterator_category;
28348    typedef const Coefficient value_type;
28349    typedef std::ptrdiff_t difference_type;
28350    typedef value_type* pointer;
28351    typedef Coefficient_traits::const_reference reference;
28352
28353    //! Constructs an invalid const_iterator.
28354    /*!
28355      This constructor takes \f$O(1)\f$ time.
28356    */
28357    explicit const_iterator();
28358
28359    //! The copy constructor.
28360    /*!
28361      \param i
28362      The %iterator that will be copied.
28363
28364      This constructor takes \f$O(1)\f$ time.
28365    */
28366    const_iterator(const const_iterator& i);
28367
28368    ~const_iterator();
28369
28370    //! Swaps \p i with \p *this.
28371    /*!
28372      \param i
28373      The %iterator that will be swapped with \p *this.
28374
28375      This method takes \f$O(1)\f$ time.
28376    */
28377    void m_swap(const_iterator& i);
28378
28379    //! Assigns \p i to *this .
28380    /*!
28381      \param i
28382      The %iterator that will be assigned into *this.
28383
28384      This method takes \f$O(1)\f$ time.
28385    */
28386    const_iterator& operator=(const const_iterator& i);
28387
28388    //! Navigates to the next nonzero coefficient.
28389    /*!
28390      This method takes \f$O(n)\f$ time for dense expressions, and
28391      \f$O(1)\f$ time for sparse expressions.
28392    */
28393    const_iterator& operator++();
28394
28395    //! Navigates to the previous nonzero coefficient.
28396    /*!
28397      This method takes \f$O(n)\f$ time for dense expressions, and
28398      \f$O(1)\f$ time for sparse expressions.
28399    */
28400    const_iterator& operator--();
28401
28402    //! Returns the current element.
28403    reference operator*() const;
28404
28405    //! Returns the variable of the coefficient pointed to by \c *this.
28406    /*!
28407      \returns the variable of the coefficient pointed to by \c *this.
28408    */
28409    Variable variable() const;
28410
28411    //! Compares \p *this with \p i.
28412    /*!
28413      \param i
28414      The %iterator that will be compared with *this.
28415    */
28416    bool operator==(const const_iterator& i) const;
28417
28418    //! Compares \p *this with \p i .
28419    /*!
28420      \param i
28421      The %iterator that will be compared with *this.
28422    */
28423    bool operator!=(const const_iterator& i) const;
28424
28425  private:
28426    //! Constructor from a const_iterator_interface*.
28427    //! The new object takes ownership of the dynamic object.
28428    const_iterator(Linear_Expression_Interface::const_iterator_interface* i);
28429
28430    Linear_Expression_Interface::const_iterator_interface* itr;
28431
28432    friend class Linear_Expression;
28433  };
28434
28435  //! Returns an iterator that points to the first nonzero coefficient in the
28436  //! expression.
28437  const_iterator begin() const;
28438
28439  //! Returns an iterator that points to the last nonzero coefficient in the
28440  //! expression.
28441  const_iterator end() const;
28442
28443  //! Returns an iterator that points to the first nonzero coefficient of a
28444  //! variable bigger than or equal to v.
28445  const_iterator lower_bound(Variable v) const;
28446
28447  //! Returns the maximum space dimension a Linear_Expression can handle.
28448  static dimension_type max_space_dimension();
28449
28450  //! Returns the dimension of the vector space enclosing \p *this.
28451  dimension_type space_dimension() const;
28452
28453  //! Sets the dimension of the vector space enclosing \p *this to \p n .
28454  void set_space_dimension(dimension_type n);
28455
28456  //! Returns the coefficient of \p v in \p *this.
28457  Coefficient_traits::const_reference coefficient(Variable v) const;
28458
28459  //! Sets the coefficient of \p v in \p *this to \p n.
28460  void set_coefficient(Variable v,
28461                       Coefficient_traits::const_reference n);
28462
28463  //! Returns the inhomogeneous term of \p *this.
28464  Coefficient_traits::const_reference inhomogeneous_term() const;
28465
28466  //! Sets the inhomogeneous term of \p *this to \p n.
28467  void set_inhomogeneous_term(Coefficient_traits::const_reference n);
28468
28469  //! Linearly combines \p *this with \p y so that the coefficient of \p v
28470  //! is 0.
28471  /*!
28472    \param y
28473    The expression that will be combined with \p *this object;
28474
28475    \param v
28476    The variable whose coefficient has to become \f$0\f$.
28477
28478    Computes a linear combination of \p *this and \p y having
28479    the coefficient of variable \p v equal to \f$0\f$. Then it assigns
28480    the resulting expression to \p *this.
28481
28482    \p *this and \p y must have the same space dimension.
28483  */
28484  void linear_combine(const Linear_Expression& y, Variable v);
28485
28486  //! Equivalent to <CODE>*this = *this * c1 + y * c2</CODE>, but assumes that
28487  //! c1 and c2 are not 0.
28488  void linear_combine(const Linear_Expression& y,
28489                      Coefficient_traits::const_reference c1,
28490                      Coefficient_traits::const_reference c2);
28491
28492  //! Equivalent to <CODE>*this = *this * c1 + y * c2</CODE>.
28493  //! c1 and c2 may be 0.
28494  void linear_combine_lax(const Linear_Expression& y,
28495                          Coefficient_traits::const_reference c1,
28496                          Coefficient_traits::const_reference c2);
28497
28498  //! Swaps the coefficients of the variables \p v1 and \p v2 .
28499  void swap_space_dimensions(Variable v1, Variable v2);
28500
28501  //! Removes all the specified dimensions from the expression.
28502  /*!
28503    The space dimension of the variable with the highest space
28504    dimension in \p vars must be at most the space dimension
28505    of \p this.
28506  */
28507  void remove_space_dimensions(const Variables_Set& vars);
28508
28509  //! Shift by \p n positions the coefficients of variables, starting from
28510  //! the coefficient of \p v. This increases the space dimension by \p n.
28511  void shift_space_dimensions(Variable v, dimension_type n);
28512
28513  //! Permutes the space dimensions of the expression.
28514  /*!
28515    \param cycle
28516    A vector representing a cycle of the permutation according to which the
28517    space dimensions must be rearranged.
28518
28519    The \p cycle vector represents a cycle of a permutation of space
28520    dimensions.
28521    For example, the permutation
28522    \f$ \{ x_1 \mapsto x_2, x_2 \mapsto x_3, x_3 \mapsto x_1 \}\f$ can be
28523    represented by the vector containing \f$ x_1, x_2, x_3 \f$.
28524  */
28525  void permute_space_dimensions(const std::vector<Variable>& cycle);
28526
28527  //! Returns <CODE>true</CODE> if and only if \p *this is \f$0\f$.
28528  bool is_zero() const;
28529
28530  /*! \brief
28531    Returns <CODE>true</CODE> if and only if all the homogeneous
28532    terms of \p *this are \f$0\f$.
28533  */
28534  bool all_homogeneous_terms_are_zero() const;
28535
28536  //! Initializes the class.
28537  static void initialize();
28538
28539  //! Finalizes the class.
28540  static void finalize();
28541
28542  //! Returns the (zero-dimension space) constant 0.
28543  static const Linear_Expression& zero();
28544
28545  /*! \brief
28546    Returns a lower bound to the total size in bytes of the memory
28547    occupied by \p *this.
28548  */
28549  memory_size_type total_memory_in_bytes() const;
28550
28551  //! Returns the size in bytes of the memory managed by \p *this.
28552  memory_size_type external_memory_in_bytes() const;
28553
28554  //! Checks if all the invariants are satisfied.
28555  bool OK() const;
28556
28557  PPL_OUTPUT_DECLARATIONS
28558
28559  /*! \brief
28560    Loads from \p s an ASCII representation (as produced by
28561    ascii_dump(std::ostream&) const) and sets \p *this accordingly.
28562    Returns <CODE>true</CODE> if successful, <CODE>false</CODE> otherwise.
28563  */
28564  bool ascii_load(std::istream& s);
28565
28566  //! Swaps \p *this with \p y.
28567  void m_swap(Linear_Expression& y);
28568
28569  //! Copy constructor with a specified space dimension.
28570  Linear_Expression(const Linear_Expression& e, dimension_type space_dim);
28571
28572  //! Copy constructor with a specified space dimension and representation.
28573  Linear_Expression(const Linear_Expression& e, dimension_type space_dim,
28574                    Representation r);
28575
28576  //! Returns \p true if *this is equal to \p x.
28577  //! Note that (*this == x) has a completely different meaning.
28578  bool is_equal_to(const Linear_Expression& x) const;
28579
28580  //! Normalizes the modulo of the coefficients and of the inhomogeneous term
28581  //! so that they are mutually prime.
28582  /*!
28583    Computes the Greatest Common Divisor (GCD) among the coefficients
28584    and the inhomogeneous term and normalizes them by the GCD itself.
28585  */
28586  void normalize();
28587
28588  //! Ensures that the first nonzero homogeneous coefficient is positive,
28589  //! by negating the row if necessary.
28590  void sign_normalize();
28591
28592  /*! \brief
28593    Returns <CODE>true</CODE> if the coefficient of each variable in
28594    \p vars[i] is \f$0\f$.
28595  */
28596  bool all_zeroes(const Variables_Set& vars) const;
28597
28598private:
28599  /*! \brief
28600    Holds (between class initialization and finalization) a pointer to
28601    the (zero-dimension space) constant 0.
28602  */
28603  static const Linear_Expression* zero_p;
28604
28605  Linear_Expression_Interface* impl;
28606
28607  //! Implementation sizing constructor.
28608  /*!
28609    The bool parameter is just to avoid problems with
28610    the constructor Linear_Expression(Coefficient_traits::const_reference n).
28611  */
28612  Linear_Expression(dimension_type space_dim, bool,
28613                    Representation r = default_representation);
28614
28615  // NOTE: This method is public, but it's not exposed in Linear_Expression,
28616  // so that it can be used internally in the PPL, by friends of
28617  // Linear_Expression.
28618  //! Returns the i-th coefficient.
28619  Coefficient_traits::const_reference get(dimension_type i) const;
28620
28621  // NOTE: This method is public, but it's not exposed in Linear_Expression,
28622  // so that it can be used internally in the PPL, by friends of
28623  // Linear_Expression.
28624  //! Sets the i-th coefficient to n.
28625  void set(dimension_type i, Coefficient_traits::const_reference n);
28626
28627  // NOTE: This method is public, but it's not exposed in Linear_Expression,
28628  // so that it can be used internally in the PPL, by friends of
28629  // Linear_Expression.
28630  //! Returns the coefficient of v.
28631  Coefficient_traits::const_reference get(Variable v) const;
28632
28633  // NOTE: This method is public, but it's not exposed in Linear_Expression,
28634  // so that it can be used internally in the PPL, by friends of
28635  // Linear_Expression.
28636  //! Sets the coefficient of v to n.
28637  void set(Variable v, Coefficient_traits::const_reference n);
28638
28639  /*! \brief
28640    Returns <CODE>true</CODE> if (*this)[i] is \f$0\f$, for each i in
28641    [start, end).
28642  */
28643  bool all_zeroes(dimension_type start, dimension_type end) const;
28644
28645  /*! \brief
28646    Returns the number of zero coefficient in [start, end).
28647  */
28648  dimension_type num_zeroes(dimension_type start, dimension_type end) const;
28649
28650  /*! \brief
28651    Returns the gcd of the nonzero coefficients in [start,end). If all the
28652    coefficients in this range are 0 returns 0.
28653  */
28654  Coefficient gcd(dimension_type start, dimension_type end) const;
28655
28656  void exact_div_assign(Coefficient_traits::const_reference c,
28657                        dimension_type start, dimension_type end);
28658
28659  //! Linearly combines \p *this with \p y so that the coefficient of \p v
28660  //! is 0.
28661  /*!
28662    \param y
28663    The expression that will be combined with \p *this object;
28664
28665    \param i
28666    The index of the coefficient that has to become \f$0\f$.
28667
28668    Computes a linear combination of \p *this and \p y having
28669    the i-th coefficient equal to \f$0\f$. Then it assigns
28670    the resulting expression to \p *this.
28671
28672    \p *this and \p y must have the same space dimension.
28673  */
28674  void linear_combine(const Linear_Expression& y, dimension_type i);
28675
28676  //! Equivalent to <CODE>(*this)[i] = (*this)[i] * c1 + y[i] * c2</CODE>,
28677  //! for each i in [start, end). It assumes that c1 and c2 are nonzero.
28678  void linear_combine(const Linear_Expression& y,
28679                      Coefficient_traits::const_reference c1,
28680                      Coefficient_traits::const_reference c2,
28681                      dimension_type start, dimension_type end);
28682
28683  //! Equivalent to <CODE>(*this)[i] = (*this)[i] * c1 + y[i] * c2</CODE>,
28684  //! for each i in [start, end). c1 and c2 may be zero.
28685  void linear_combine_lax(const Linear_Expression& y,
28686                          Coefficient_traits::const_reference c1,
28687                          Coefficient_traits::const_reference c2,
28688                          dimension_type start, dimension_type end);
28689
28690  //! Equivalent to <CODE>(*this)[i] *= n</CODE>, for each i in [start, end).
28691  void mul_assign(Coefficient_traits::const_reference n,
28692                  dimension_type start, dimension_type end);
28693
28694  //! Returns the index of the last nonzero element, or 0 if there are no
28695  //! nonzero elements.
28696  dimension_type last_nonzero() const;
28697
28698  //! Returns the index of the last nonzero element in [first,last), or last
28699  //! if there are no nonzero elements.
28700  dimension_type last_nonzero(dimension_type first, dimension_type last) const;
28701
28702  //! Returns the index of the first nonzero element, or \p last if there are no
28703  //! nonzero elements, considering only elements in [first,last).
28704  dimension_type first_nonzero(dimension_type first, dimension_type last) const;
28705
28706  /*! \brief
28707    Returns <CODE>true</CODE> if all coefficients in [start,end),
28708    except those corresponding to variables in \p vars, are zero.
28709  */
28710  bool all_zeroes_except(const Variables_Set& vars,
28711                         dimension_type start, dimension_type end) const;
28712
28713  //! Sets results to the sum of (*this)[i]*y[i], for each i.
28714  void scalar_product_assign(Coefficient& result,
28715                             const Linear_Expression& y) const;
28716
28717  //! Sets results to the sum of (*this)[i]*y[i], for each i in [start,end).
28718  void scalar_product_assign(Coefficient& result, const Linear_Expression& y,
28719                             dimension_type start, dimension_type end) const;
28720
28721  //! Computes the sign of the sum of (*this)[i]*y[i], for each i.
28722  int scalar_product_sign(const Linear_Expression& y) const;
28723
28724  //! Computes the sign of the sum of (*this)[i]*y[i],
28725  //! for each i in [start,end).
28726  int scalar_product_sign(const Linear_Expression& y,
28727                          dimension_type start, dimension_type end) const;
28728
28729  //! Removes from the set x all the indexes of nonzero elements of *this.
28730  void has_a_free_dimension_helper(std::set<dimension_type>& x) const;
28731
28732  //! Returns \p true if (*this)[i] is equal to x[i], for each i in [start,end).
28733  bool is_equal_to(const Linear_Expression& x,
28734                   dimension_type start, dimension_type end) const;
28735
28736  //! Returns \p true if (*this)[i]*c1 is equal to x[i]*c2, for each i in
28737  //! [start,end).
28738  bool is_equal_to(const Linear_Expression& x,
28739                   Coefficient_traits::const_reference c1,
28740                   Coefficient_traits::const_reference c2,
28741                   dimension_type start, dimension_type end) const;
28742
28743  //! Sets \p r to a copy of the row that implements \p *this.
28744  void get_row(Dense_Row& r) const;
28745
28746  //! Sets \p r to a copy of the row that implements \p *this.
28747  void get_row(Sparse_Row& r) const;
28748
28749  /*! \brief
28750    Returns \p true if there is a variable from index \p first (included)
28751    to index \p last (excluded) whose coefficient is nonzero in both
28752    \p *this and \p x.
28753  */
28754  bool have_a_common_variable(const Linear_Expression& x,
28755                              Variable first, Variable last) const;
28756
28757  /*! \brief
28758    Negates the elements from index \p first (included)
28759    to index \p last (excluded).
28760  */
28761  void negate(dimension_type first, dimension_type last);
28762
28763  template <typename Row>
28764  friend class Linear_Expression_Impl;
28765
28766  // NOTE: The following classes are friends of Linear_Expression in order
28767  // to access its private methods.
28768  // Since they are *not* friend of Linear_Expression_Impl, they can only
28769  // access its public methods so they cannot break the class invariant of
28770  // Linear_Expression_Impl.
28771  friend class Grid;
28772  friend class Congruence;
28773  friend class Polyhedron;
28774  friend class PIP_Tree_Node;
28775  friend class Grid_Generator;
28776  friend class Generator;
28777  friend class Constraint;
28778  friend class Constraint_System;
28779  friend class PIP_Problem;
28780  friend class BHRZ03_Certificate;
28781  friend class Scalar_Products;
28782  friend class MIP_Problem;
28783  friend class Box_Helpers;
28784  friend class Congruence_System;
28785  friend class BD_Shape_Helpers;
28786  friend class Octagonal_Shape_Helper;
28787  friend class Termination_Helpers;
28788  template <typename T>
28789  friend class BD_Shape;
28790  template <typename T>
28791  friend class Octagonal_Shape;
28792  template <typename T>
28793  friend class Linear_System;
28794  template <typename T>
28795  friend class Box;
28796  template <typename T>
28797  friend class Expression_Adapter;
28798  template <typename T>
28799  friend class Expression_Hide_Inhomo;
28800  template <typename T>
28801  friend class Expression_Hide_Last;
28802
28803  friend Linear_Expression
28804  operator+(const Linear_Expression& e1, const Linear_Expression& e2);
28805  friend Linear_Expression
28806  operator+(Coefficient_traits::const_reference n, const Linear_Expression& e);
28807  friend Linear_Expression
28808  operator+(const Linear_Expression& e, Coefficient_traits::const_reference n);
28809  friend Linear_Expression
28810  operator+(Variable v, const Linear_Expression& e);
28811  friend Linear_Expression
28812  operator+(Variable v, Variable w);
28813
28814  friend Linear_Expression
28815  operator-(const Linear_Expression& e);
28816
28817  friend Linear_Expression
28818  operator-(const Linear_Expression& e1, const Linear_Expression& e2);
28819  friend Linear_Expression
28820  operator-(Variable v, Variable w);
28821  friend Linear_Expression
28822  operator-(Coefficient_traits::const_reference n, const Linear_Expression& e);
28823  friend Linear_Expression
28824  operator-(const Linear_Expression& e, Coefficient_traits::const_reference n);
28825  friend Linear_Expression
28826  operator-(Variable v, const Linear_Expression& e);
28827  friend Linear_Expression
28828  operator-(const Linear_Expression& e, Variable v);
28829
28830  friend Linear_Expression
28831  operator*(Coefficient_traits::const_reference n, const Linear_Expression& e);
28832  friend Linear_Expression
28833  operator*(const Linear_Expression& e, Coefficient_traits::const_reference n);
28834
28835  friend Linear_Expression&
28836  operator+=(Linear_Expression& e1, const Linear_Expression& e2);
28837  friend Linear_Expression&
28838  operator+=(Linear_Expression& e, Variable v);
28839  friend Linear_Expression&
28840  operator+=(Linear_Expression& e, Coefficient_traits::const_reference n);
28841
28842  friend Linear_Expression&
28843  operator-=(Linear_Expression& e1, const Linear_Expression& e2);
28844  friend Linear_Expression&
28845  operator-=(Linear_Expression& e, Variable v);
28846  friend Linear_Expression&
28847  operator-=(Linear_Expression& e, Coefficient_traits::const_reference n);
28848
28849  friend Linear_Expression&
28850  operator*=(Linear_Expression& e, Coefficient_traits::const_reference n);
28851  friend Linear_Expression&
28852  operator/=(Linear_Expression& e, Coefficient_traits::const_reference n);
28853
28854  friend void
28855  neg_assign(Linear_Expression& e);
28856
28857  friend Linear_Expression&
28858  add_mul_assign(Linear_Expression& e,
28859                 Coefficient_traits::const_reference n, Variable v);
28860  friend Linear_Expression&
28861  sub_mul_assign(Linear_Expression& e,
28862                 Coefficient_traits::const_reference n, Variable v);
28863
28864  friend void
28865  add_mul_assign(Linear_Expression& e1,
28866                 Coefficient_traits::const_reference factor,
28867                 const Linear_Expression& e2);
28868  friend void
28869  sub_mul_assign(Linear_Expression& e1,
28870                 Coefficient_traits::const_reference factor,
28871                 const Linear_Expression& e2);
28872
28873  friend int
28874  compare(const Linear_Expression& x, const Linear_Expression& y);
28875
28876  friend std::ostream&
28877  Parma_Polyhedra_Library::IO_Operators
28878  ::operator<<(std::ostream& s, const Linear_Expression& e);
28879};
28880
28881namespace Parma_Polyhedra_Library {
28882
28883//! Swaps \p x with \p y.
28884/*! \relates Linear_Expression */
28885void swap(Linear_Expression& x, Linear_Expression& y);
28886
28887//! Swaps \p x with \p y.
28888/*! \relates Linear_Expression::const_iterator */
28889void swap(Linear_Expression::const_iterator& x,
28890          Linear_Expression::const_iterator& y);
28891
28892} // namespace Parma_Polyhedra_Library
28893
28894/* Automatically generated from PPL source file ../src/Linear_Expression_inlines.hh line 1. */
28895/* Linear_Expression class implementation: inline functions.
28896*/
28897
28898
28899/* Automatically generated from PPL source file ../src/Linear_Expression_inlines.hh line 28. */
28900
28901namespace Parma_Polyhedra_Library {
28902
28903inline Linear_Expression&
28904Linear_Expression::operator=(const Linear_Expression& e) {
28905  Linear_Expression tmp = e;
28906  swap(*this, tmp);
28907  return *this;
28908}
28909
28910inline
28911Linear_Expression::~Linear_Expression() {
28912  delete impl;
28913}
28914
28915inline Representation
28916Linear_Expression::representation() const {
28917  return impl->representation();
28918}
28919
28920inline dimension_type
28921Linear_Expression::space_dimension() const {
28922  return impl->space_dimension();
28923}
28924
28925inline void
28926Linear_Expression::set_space_dimension(dimension_type n) {
28927  impl->set_space_dimension(n);
28928}
28929
28930inline Coefficient_traits::const_reference
28931Linear_Expression::coefficient(Variable v) const {
28932  return impl->coefficient(v);
28933}
28934
28935inline void
28936Linear_Expression
28937::set_coefficient(Variable v, Coefficient_traits::const_reference n) {
28938  impl->set_coefficient(v, n);
28939}
28940
28941inline Coefficient_traits::const_reference
28942Linear_Expression::inhomogeneous_term() const {
28943  return impl->inhomogeneous_term();
28944}
28945
28946inline void
28947Linear_Expression
28948::set_inhomogeneous_term(Coefficient_traits::const_reference n) {
28949  impl->set_inhomogeneous_term(n);
28950}
28951
28952inline void
28953Linear_Expression::swap_space_dimensions(Variable v1, Variable v2) {
28954  impl->swap_space_dimensions(v1, v2);
28955}
28956
28957inline void
28958Linear_Expression::shift_space_dimensions(Variable v, dimension_type n) {
28959  impl->shift_space_dimensions(v, n);
28960}
28961
28962inline bool
28963Linear_Expression::is_zero() const {
28964  return impl->is_zero();
28965}
28966
28967inline bool
28968Linear_Expression::all_homogeneous_terms_are_zero() const {
28969  return impl->all_homogeneous_terms_are_zero();
28970}
28971
28972inline const Linear_Expression&
28973Linear_Expression::zero() {
28974  PPL_ASSERT(zero_p != 0);
28975  return *zero_p;
28976}
28977
28978inline memory_size_type
28979Linear_Expression::external_memory_in_bytes() const {
28980  return impl->total_memory_in_bytes();
28981}
28982
28983inline memory_size_type
28984Linear_Expression::total_memory_in_bytes() const {
28985  return external_memory_in_bytes() + sizeof(*this);
28986}
28987
28988/*! \relates Linear_Expression */
28989inline Linear_Expression
28990operator+(const Linear_Expression& e) {
28991  return e;
28992}
28993
28994/*! \relates Linear_Expression */
28995inline Linear_Expression
28996operator+(const Linear_Expression& e, Coefficient_traits::const_reference n) {
28997  Linear_Expression x = e;
28998  x += n;
28999  return x;
29000}
29001
29002/*! \relates Linear_Expression */
29003inline Linear_Expression
29004operator+(const Linear_Expression& e, const Variable v) {
29005  Linear_Expression x = e;
29006  x += v;
29007  return x;
29008}
29009
29010/*! \relates Linear_Expression */
29011inline Linear_Expression
29012operator-(const Linear_Expression& e, Coefficient_traits::const_reference n) {
29013  Linear_Expression x = e;
29014  x -= n;
29015  return x;
29016}
29017
29018/*! \relates Linear_Expression */
29019inline Linear_Expression
29020operator-(const Variable v, const Variable w) {
29021  const dimension_type v_space_dim = v.space_dimension();
29022  const dimension_type w_space_dim = w.space_dimension();
29023  const dimension_type space_dim = std::max(v_space_dim, w_space_dim);
29024  if (space_dim > Linear_Expression::max_space_dimension()) {
29025    throw std::length_error("Linear_Expression "
29026                            "PPL::operator+(v, w):\n"
29027                            "v or w exceed the maximum allowed "
29028                            "space dimension.");
29029  }
29030  if (v_space_dim >= w_space_dim) {
29031    Linear_Expression e(v);
29032    e -= w;
29033    return e;
29034  }
29035  else {
29036    Linear_Expression e(w.space_dimension(), true);
29037    e -= w;
29038    e += v;
29039    return e;
29040  }
29041}
29042
29043/*! \relates Linear_Expression */
29044inline Linear_Expression
29045operator*(const Linear_Expression& e, Coefficient_traits::const_reference n) {
29046  Linear_Expression x = e;
29047  x *= n;
29048  return x;
29049}
29050
29051/*! \relates Linear_Expression */
29052inline Linear_Expression&
29053operator+=(Linear_Expression& e, Coefficient_traits::const_reference n) {
29054  *e.impl += n;
29055  return e;
29056}
29057
29058/*! \relates Linear_Expression */
29059inline Linear_Expression&
29060operator-=(Linear_Expression& e, Coefficient_traits::const_reference n) {
29061  *e.impl -= n;
29062  return e;
29063}
29064
29065inline void
29066Linear_Expression::m_swap(Linear_Expression& y) {
29067  using std::swap;
29068  swap(impl, y.impl);
29069}
29070
29071inline void
29072Linear_Expression::normalize() {
29073  impl->normalize();
29074}
29075
29076inline void
29077Linear_Expression::ascii_dump(std::ostream& s) const {
29078  impl->ascii_dump(s);
29079}
29080
29081inline bool
29082Linear_Expression::ascii_load(std::istream& s) {
29083  return impl->ascii_load(s);
29084}
29085
29086inline void
29087Linear_Expression::remove_space_dimensions(const Variables_Set& vars) {
29088  impl->remove_space_dimensions(vars);
29089}
29090
29091inline void
29092Linear_Expression::permute_space_dimensions(const std::vector<Variable>& cycle) {
29093  impl->permute_space_dimensions(cycle);
29094}
29095
29096/*! \relates Parma_Polyhedra_Library::Linear_Expression */
29097inline Linear_Expression
29098operator+(const Linear_Expression& e1, const Linear_Expression& e2) {
29099  if (e1.space_dimension() >= e2.space_dimension()) {
29100    Linear_Expression e = e1;
29101    e += e2;
29102    return e;
29103  }
29104  else {
29105    Linear_Expression e = e2;
29106    e += e1;
29107    return e;
29108  }
29109}
29110
29111/*! \relates Linear_Expression */
29112inline Linear_Expression
29113operator+(const Variable v, const Linear_Expression& e) {
29114  return e + v;
29115}
29116
29117/*! \relates Parma_Polyhedra_Library::Linear_Expression */
29118inline Linear_Expression
29119operator+(Coefficient_traits::const_reference n,
29120               const Linear_Expression& e) {
29121  return e + n;
29122}
29123
29124/*! \relates Linear_Expression */
29125inline Linear_Expression
29126operator+(const Variable v, const Variable w) {
29127  const dimension_type v_space_dim = v.space_dimension();
29128  const dimension_type w_space_dim = w.space_dimension();
29129  const dimension_type space_dim = std::max(v_space_dim, w_space_dim);
29130  if (space_dim > Linear_Expression::max_space_dimension()) {
29131    throw std::length_error("Linear_Expression "
29132                            "PPL::operator+(v, w):\n"
29133                            "v or w exceed the maximum allowed "
29134                            "space dimension.");
29135  }
29136  if (v_space_dim >= w_space_dim) {
29137    Linear_Expression e(v);
29138    e += w;
29139    return e;
29140  }
29141  else {
29142    Linear_Expression e(w);
29143    e += v;
29144    return e;
29145  }
29146}
29147
29148/*! \relates Parma_Polyhedra_Library::Linear_Expression */
29149inline Linear_Expression
29150operator-(const Linear_Expression& e) {
29151  Linear_Expression r(e);
29152  neg_assign(r);
29153  return r;
29154}
29155
29156/*! \relates Parma_Polyhedra_Library::Linear_Expression */
29157inline Linear_Expression
29158operator-(const Linear_Expression& e1, const Linear_Expression& e2) {
29159  if (e1.space_dimension() >= e2.space_dimension()) {
29160    Linear_Expression e = e1;
29161    e -= e2;
29162    return e;
29163  }
29164  else {
29165    Linear_Expression e = e2;
29166    neg_assign(e);
29167    e += e1;
29168    return e;
29169  }
29170}
29171
29172/*! \relates Parma_Polyhedra_Library::Linear_Expression */
29173inline Linear_Expression
29174operator-(const Variable v, const Linear_Expression& e) {
29175  Linear_Expression result(e, std::max(v.space_dimension(), e.space_dimension()));
29176  result.negate(0, e.space_dimension() + 1);
29177  result += v;
29178  return result;
29179}
29180
29181/*! \relates Linear_Expression */
29182inline Linear_Expression
29183operator-(const Linear_Expression& e, const Variable v) {
29184  Linear_Expression result(e, std::max(v.space_dimension(), e.space_dimension()));
29185  result -= v;
29186  return result;
29187}
29188
29189/*! \relates Parma_Polyhedra_Library::Linear_Expression */
29190inline Linear_Expression
29191operator-(Coefficient_traits::const_reference n,
29192               const Linear_Expression& e) {
29193  Linear_Expression result(e);
29194  neg_assign(result);
29195  result += n;
29196  return result;
29197}
29198
29199/*! \relates Parma_Polyhedra_Library::Linear_Expression */
29200inline Linear_Expression
29201operator*(Coefficient_traits::const_reference n,
29202               const Linear_Expression& e) {
29203  return e * n;
29204}
29205
29206/*! \relates Parma_Polyhedra_Library::Linear_Expression */
29207inline Linear_Expression&
29208operator+=(Linear_Expression& e1, const Linear_Expression& e2) {
29209  *e1.impl += *e2.impl;
29210  return e1;
29211}
29212
29213/*! \relates Parma_Polyhedra_Library::Linear_Expression */
29214inline Linear_Expression&
29215operator+=(Linear_Expression& e, const Variable v) {
29216  *e.impl += v;
29217  return e;
29218}
29219
29220/*! \relates Parma_Polyhedra_Library::Linear_Expression */
29221inline Linear_Expression&
29222operator-=(Linear_Expression& e1, const Linear_Expression& e2) {
29223  *e1.impl -= *e2.impl;
29224  return e1;
29225}
29226
29227/*! \relates Parma_Polyhedra_Library::Linear_Expression */
29228inline Linear_Expression&
29229operator-=(Linear_Expression& e, const Variable v) {
29230  *e.impl -= v;
29231  return e;
29232}
29233
29234/*! \relates Parma_Polyhedra_Library::Linear_Expression */
29235inline Linear_Expression&
29236operator*=(Linear_Expression& e, Coefficient_traits::const_reference n) {
29237  *e.impl *= n;
29238  return e;
29239}
29240
29241/*! \relates Parma_Polyhedra_Library::Linear_Expression */
29242inline Linear_Expression&
29243operator/=(Linear_Expression& e, Coefficient_traits::const_reference n) {
29244  *e.impl /= n;
29245  return e;
29246}
29247
29248/*! \relates Parma_Polyhedra_Library::Linear_Expression */
29249inline void
29250neg_assign(Linear_Expression& e) {
29251  e.impl->negate();
29252}
29253
29254/*! \relates Parma_Polyhedra_Library::Linear_Expression */
29255inline Linear_Expression&
29256add_mul_assign(Linear_Expression& e,
29257               Coefficient_traits::const_reference n,
29258               const Variable v) {
29259  e.impl->add_mul_assign(n, v);
29260  return e;
29261}
29262
29263/*! \relates Parma_Polyhedra_Library::Linear_Expression */
29264inline Linear_Expression&
29265sub_mul_assign(Linear_Expression& e,
29266                    Coefficient_traits::const_reference n,
29267                    const Variable v) {
29268  e.impl->sub_mul_assign(n, v);
29269  return e;
29270}
29271
29272inline void
29273add_mul_assign(Linear_Expression& e1,
29274               Coefficient_traits::const_reference factor,
29275               const Linear_Expression& e2) {
29276  e1.impl->add_mul_assign(factor, *e2.impl);
29277}
29278
29279inline void
29280sub_mul_assign(Linear_Expression& e1,
29281                    Coefficient_traits::const_reference factor,
29282                    const Linear_Expression& e2) {
29283  e1.impl->sub_mul_assign(factor, *e2.impl);
29284}
29285
29286inline Coefficient_traits::const_reference
29287Linear_Expression::get(dimension_type i) const {
29288  return impl->get(i);
29289}
29290
29291inline void
29292Linear_Expression::set(dimension_type i,
29293                       Coefficient_traits::const_reference n) {
29294  impl->set(i, n);
29295}
29296
29297inline Coefficient_traits::const_reference
29298Linear_Expression::get(Variable v) const {
29299  return impl->get(v.space_dimension());
29300}
29301
29302inline void
29303Linear_Expression::set(Variable v,
29304                       Coefficient_traits::const_reference n) {
29305  impl->set(v.space_dimension(), n);
29306}
29307
29308inline bool
29309Linear_Expression::all_zeroes(dimension_type start, dimension_type end) const {
29310  return impl->all_zeroes(start, end);
29311}
29312
29313inline dimension_type
29314Linear_Expression::num_zeroes(dimension_type start, dimension_type end) const {
29315  return impl->num_zeroes(start, end);
29316}
29317
29318inline Coefficient
29319Linear_Expression::gcd(dimension_type start, dimension_type end) const {
29320  return impl->gcd(start, end);
29321}
29322
29323inline void
29324Linear_Expression
29325::exact_div_assign(Coefficient_traits::const_reference c,
29326                   dimension_type start, dimension_type end) {
29327  impl->exact_div_assign(c, start, end);
29328}
29329
29330inline void
29331Linear_Expression
29332::mul_assign(Coefficient_traits::const_reference c,
29333             dimension_type start, dimension_type end) {
29334  impl->mul_assign(c, start, end);
29335}
29336
29337inline void
29338Linear_Expression::sign_normalize() {
29339  impl->sign_normalize();
29340}
29341
29342inline void
29343Linear_Expression::negate(dimension_type first, dimension_type last) {
29344  impl->negate(first, last);
29345}
29346
29347inline bool
29348Linear_Expression::all_zeroes(const Variables_Set& vars) const {
29349  return impl->all_zeroes(vars);
29350}
29351
29352inline bool
29353Linear_Expression::all_zeroes_except(const Variables_Set& vars,
29354                                     dimension_type start,
29355                                     dimension_type end) const {
29356  return impl->all_zeroes_except(vars, start, end);
29357}
29358
29359inline dimension_type
29360Linear_Expression::last_nonzero() const {
29361  return impl->last_nonzero();
29362}
29363
29364inline void
29365Linear_Expression
29366::scalar_product_assign(Coefficient& result, const Linear_Expression& y) const {
29367  scalar_product_assign(result, y, 0, space_dimension() + 1);
29368}
29369
29370inline void
29371Linear_Expression
29372::scalar_product_assign(Coefficient& result, const Linear_Expression& y,
29373                        dimension_type start, dimension_type end) const {
29374  impl->scalar_product_assign(result, *(y.impl), start, end);
29375}
29376
29377inline int
29378Linear_Expression
29379::scalar_product_sign(const Linear_Expression& y) const {
29380  return scalar_product_sign(y, 0, space_dimension() + 1);
29381}
29382
29383inline int
29384Linear_Expression
29385::scalar_product_sign(const Linear_Expression& y,
29386                      dimension_type start, dimension_type end) const {
29387  return impl->scalar_product_sign(*(y.impl), start, end);
29388}
29389
29390inline dimension_type
29391Linear_Expression
29392::first_nonzero(dimension_type first, dimension_type last) const {
29393  return impl->first_nonzero(first, last);
29394}
29395
29396inline dimension_type
29397Linear_Expression
29398::last_nonzero(dimension_type first, dimension_type last) const {
29399  return impl->last_nonzero(first, last);
29400}
29401
29402inline void
29403Linear_Expression
29404::has_a_free_dimension_helper(std::set<dimension_type>& x) const {
29405  return impl->has_a_free_dimension_helper(x);
29406}
29407
29408inline bool
29409Linear_Expression
29410::is_equal_to(const Linear_Expression& x,
29411              dimension_type start, dimension_type end) const {
29412  return impl->is_equal_to(*(x.impl), start, end);
29413}
29414
29415inline bool
29416Linear_Expression
29417::is_equal_to(const Linear_Expression& x,
29418              Coefficient_traits::const_reference c1,
29419              Coefficient_traits::const_reference c2,
29420              dimension_type start, dimension_type end) const {
29421  return impl->is_equal_to(*(x.impl), c1, c2, start, end);
29422}
29423
29424inline void
29425Linear_Expression
29426::get_row(Dense_Row& r) const {
29427  return impl->get_row(r);
29428}
29429
29430inline void
29431Linear_Expression
29432::get_row(Sparse_Row& r) const {
29433  return impl->get_row(r);
29434}
29435
29436inline void
29437Linear_Expression
29438::linear_combine(const Linear_Expression& y, dimension_type i) {
29439  impl->linear_combine(*y.impl, i);
29440}
29441
29442inline void
29443Linear_Expression
29444::linear_combine(const Linear_Expression& y,
29445                 Coefficient_traits::const_reference c1,
29446                 Coefficient_traits::const_reference c2) {
29447  impl->linear_combine(*y.impl, c1, c2);
29448}
29449
29450inline void
29451Linear_Expression
29452::linear_combine_lax(const Linear_Expression& y,
29453                     Coefficient_traits::const_reference c1,
29454                     Coefficient_traits::const_reference c2) {
29455  impl->linear_combine_lax(*y.impl, c1, c2);
29456}
29457
29458inline int
29459compare(const Linear_Expression& x, const Linear_Expression& y) {
29460  return x.impl->compare(*y.impl);
29461}
29462
29463inline bool
29464Linear_Expression::is_equal_to(const Linear_Expression& x) const {
29465  return impl->is_equal_to(*x.impl);
29466}
29467
29468inline void
29469Linear_Expression::linear_combine(const Linear_Expression& y,
29470                                  Coefficient_traits::const_reference c1,
29471                                  Coefficient_traits::const_reference c2,
29472                                  dimension_type start,
29473                                  dimension_type end) {
29474  impl->linear_combine(*y.impl, c1, c2, start, end);
29475}
29476
29477inline void
29478Linear_Expression::linear_combine_lax(const Linear_Expression& y,
29479                                      Coefficient_traits::const_reference c1,
29480                                      Coefficient_traits::const_reference c2,
29481                                      dimension_type start,
29482                                      dimension_type end) {
29483  impl->linear_combine_lax(*y.impl, c1, c2, start, end);
29484}
29485
29486inline bool
29487Linear_Expression
29488::have_a_common_variable(const Linear_Expression& x,
29489                         Variable first, Variable last) const {
29490  return impl->have_a_common_variable(*(x.impl), first, last);
29491}
29492
29493inline
29494Linear_Expression::const_iterator
29495::const_iterator()
29496  : itr(NULL) {
29497}
29498
29499inline
29500Linear_Expression::const_iterator
29501::const_iterator(const const_iterator& i)
29502  : itr(i.itr->clone()) {
29503}
29504
29505inline
29506Linear_Expression::const_iterator
29507::~const_iterator() {
29508  // Note that this does nothing if itr == NULL.
29509  delete itr;
29510}
29511
29512inline void
29513Linear_Expression::const_iterator::m_swap(const_iterator& i) {
29514  using std::swap;
29515  swap(itr, i.itr);
29516}
29517
29518inline Linear_Expression::const_iterator&
29519Linear_Expression::const_iterator
29520::operator=(const const_iterator& i) {
29521  const_iterator tmp = i;
29522  using std::swap;
29523  swap(*this, tmp);
29524  return *this;
29525}
29526
29527inline Linear_Expression::const_iterator&
29528Linear_Expression::const_iterator
29529::operator++() {
29530  PPL_ASSERT(itr != NULL);
29531  ++(*itr);
29532  return *this;
29533}
29534
29535inline Linear_Expression::const_iterator&
29536Linear_Expression::const_iterator
29537::operator--() {
29538  PPL_ASSERT(itr != NULL);
29539  --(*itr);
29540  return *this;
29541}
29542
29543inline Linear_Expression::const_iterator::reference
29544Linear_Expression::const_iterator
29545::operator*() const {
29546  PPL_ASSERT(itr != NULL);
29547  return *(*itr);
29548}
29549
29550inline Variable
29551Linear_Expression::const_iterator
29552::variable() const {
29553  PPL_ASSERT(itr != NULL);
29554  return itr->variable();
29555}
29556
29557inline bool
29558Linear_Expression::const_iterator
29559::operator==(const const_iterator& i) const {
29560  PPL_ASSERT(itr != NULL);
29561  PPL_ASSERT(i.itr != NULL);
29562  return *itr == *(i.itr);
29563}
29564
29565inline bool
29566Linear_Expression::const_iterator
29567::operator!=(const const_iterator& i) const {
29568  return !(*this == i);
29569}
29570
29571inline
29572Linear_Expression::const_iterator
29573::const_iterator(Linear_Expression_Interface::const_iterator_interface* i)
29574  : itr(i) {
29575  PPL_ASSERT(i != NULL);
29576}
29577
29578inline Linear_Expression::const_iterator
29579Linear_Expression
29580::begin() const {
29581  return const_iterator(impl->begin());
29582}
29583
29584inline Linear_Expression::const_iterator
29585Linear_Expression
29586::end() const {
29587  return const_iterator(impl->end());
29588}
29589
29590inline Linear_Expression::const_iterator
29591Linear_Expression
29592::lower_bound(Variable v) const {
29593  return const_iterator(impl->lower_bound(v));
29594}
29595
29596template <typename LE_Adapter>
29597inline
29598Linear_Expression
29599::Linear_Expression(const LE_Adapter& e,
29600                    typename Enable_If<Is_Same_Or_Derived<Expression_Adapter_Base,
29601                                                          LE_Adapter>::value,
29602                                       void*>::type)
29603  : impl(NULL) {
29604  Linear_Expression tmp(e.representation());
29605  tmp.set_space_dimension(e.space_dimension());
29606  tmp.set_inhomogeneous_term(e.inhomogeneous_term());
29607  for (typename LE_Adapter::const_iterator i = e.begin(),
29608         i_end = e.end(); i != i_end; ++i) {
29609    add_mul_assign(tmp, *i, i.variable());
29610  }
29611  using std::swap;
29612  swap(impl, tmp.impl);
29613}
29614
29615template <typename LE_Adapter>
29616inline
29617Linear_Expression
29618::Linear_Expression(const LE_Adapter& e,
29619                    Representation r,
29620                    typename Enable_If<Is_Same_Or_Derived<Expression_Adapter_Base,
29621                                                          LE_Adapter>::value,
29622                                       void*>::type)
29623  : impl(NULL) {
29624  Linear_Expression tmp(r);
29625  tmp.set_space_dimension(e.space_dimension());
29626  tmp.set_inhomogeneous_term(e.inhomogeneous_term());
29627  for (typename LE_Adapter::const_iterator i = e.begin(),
29628         i_end = e.end(); i != i_end; ++i) {
29629    add_mul_assign(tmp, *i, i.variable());
29630  }
29631  using std::swap;
29632  swap(impl, tmp.impl);
29633}
29634
29635template <typename LE_Adapter>
29636inline
29637Linear_Expression
29638::Linear_Expression(const LE_Adapter& e,
29639                    dimension_type space_dim,
29640                    typename Enable_If<Is_Same_Or_Derived<Expression_Adapter_Base,
29641                                                          LE_Adapter>::value,
29642                                       void*>::type)
29643  : impl(NULL) {
29644  Linear_Expression tmp(e.representation());
29645  tmp.set_space_dimension(space_dim);
29646  tmp.set_inhomogeneous_term(e.inhomogeneous_term());
29647  typedef typename LE_Adapter::const_iterator itr_t;
29648  itr_t i_end;
29649  if (space_dim <= e.space_dimension()) {
29650    i_end = e.lower_bound(Variable(space_dim));
29651  }
29652  else {
29653    i_end = e.end();
29654  }
29655  for (itr_t i = e.begin(); i != i_end; ++i) {
29656    add_mul_assign(tmp, *i, i.variable());
29657  }
29658  using std::swap;
29659  swap(impl, tmp.impl);
29660}
29661
29662template <typename LE_Adapter>
29663inline
29664Linear_Expression
29665::Linear_Expression(const LE_Adapter& e,
29666                    dimension_type space_dim,
29667                    Representation r,
29668                    typename Enable_If<Is_Same_Or_Derived<Expression_Adapter_Base,
29669                                                          LE_Adapter>::value,
29670                                       void*>::type)
29671  : impl(NULL) {
29672  Linear_Expression tmp(r);
29673  tmp.set_space_dimension(space_dim);
29674  tmp.set_inhomogeneous_term(e.inhomogeneous_term());
29675  typedef typename LE_Adapter::const_iterator itr_t;
29676  itr_t i_end;
29677  if (space_dim <= e.space_dimension()) {
29678    i_end = e.lower_bound(Variable(space_dim));
29679  }
29680  else {
29681    i_end = e.end();
29682  }
29683  for (itr_t i = e.begin(); i != i_end; ++i) {
29684    add_mul_assign(tmp, *i, i.variable());
29685  }
29686  using std::swap;
29687  swap(impl, tmp.impl);
29688}
29689
29690namespace IO_Operators {
29691
29692/*! \relates Parma_Polyhedra_Library::Linear_Expression */
29693inline std::ostream&
29694operator<<(std::ostream& s, const Linear_Expression& e) {
29695  e.impl->print(s);
29696  return s;
29697}
29698
29699} // namespace IO_Operators
29700
29701/*! \relates Parma_Polyhedra_Library::Linear_Expression */
29702inline void
29703swap(Linear_Expression& x, Linear_Expression& y) {
29704  x.m_swap(y);
29705}
29706
29707/*! \relates Linear_Expression::const_iterator */
29708inline void
29709swap(Linear_Expression::const_iterator& x,
29710     Linear_Expression::const_iterator& y) {
29711  x.m_swap(y);
29712}
29713
29714} // namespace Parma_Polyhedra_Library
29715
29716/* Automatically generated from PPL source file ../src/Linear_Expression_defs.hh line 946. */
29717
29718/* Automatically generated from PPL source file ../src/Topology_types.hh line 1. */
29719
29720
29721namespace Parma_Polyhedra_Library {
29722
29723#ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
29724//! Kinds of polyhedra domains.
29725/*! \ingroup PPL_CXX_interface */
29726#endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
29727enum Topology {
29728  NECESSARILY_CLOSED = 0,
29729  NOT_NECESSARILY_CLOSED = 1
29730};
29731
29732} // namespace Parma_Polyhedra_Library
29733
29734/* Automatically generated from PPL source file ../src/Expression_Hide_Last_defs.hh line 1. */
29735/* Expression_Hide_Last class declaration.
29736*/
29737
29738
29739/* Automatically generated from PPL source file ../src/Expression_Hide_Last_defs.hh line 28. */
29740
29741/* Automatically generated from PPL source file ../src/Expression_Hide_Last_defs.hh line 32. */
29742
29743#ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
29744//! An adapter for Linear_Expression that maybe hides the last coefficient.
29745#endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
29746template <typename T>
29747class Parma_Polyhedra_Library::Expression_Hide_Last
29748  : public Expression_Adapter<T> {
29749  typedef Expression_Adapter<T> base_type;
29750public:
29751  //! The type of this object.
29752  typedef Expression_Hide_Last<T> const_reference;
29753  //! The type obtained by one-level unwrapping.
29754  typedef typename base_type::inner_type inner_type;
29755  //! The raw, completely unwrapped type.
29756  typedef typename base_type::raw_type raw_type;
29757
29758  //! The type of const iterators on coefficients.
29759  typedef typename base_type::const_iterator const_iterator;
29760
29761  //! Constructor.
29762  explicit Expression_Hide_Last(const raw_type& expr, bool hide_last);
29763
29764  //! Iterator pointing after the last nonzero variable coefficient.
29765  const_iterator end() const;
29766
29767  //! Iterator pointing to the first nonzero variable coefficient
29768  //! of a variable bigger than or equal to \p v.
29769  const_iterator lower_bound(Variable v) const;
29770
29771  //! Returns the dimension of the vector space enclosing \p *this.
29772  dimension_type space_dimension() const;
29773
29774  //! Returns the coefficient of \p v in \p *this.
29775  Coefficient_traits::const_reference coefficient(Variable v) const;
29776
29777  //! Returns <CODE>true</CODE> if and only if \p *this is zero.
29778  bool is_zero() const;
29779
29780  /*! \brief
29781    Returns <CODE>true</CODE> if and only if all the homogeneous
29782    terms of \p *this are zero.
29783  */
29784  bool all_homogeneous_terms_are_zero() const;
29785
29786  /*! \brief Returns \p true if \p *this is equal to \p y.
29787
29788    Note that <CODE>(*this == y)</CODE> has a completely different meaning.
29789  */
29790  template <typename Expression>
29791  bool is_equal_to(const Expression& y) const;
29792
29793  /*! \brief
29794    Returns <CODE>true</CODE> if the coefficient of each variable in
29795    \p vars is zero.
29796  */
29797  bool all_zeroes(const Variables_Set& vars) const;
29798
29799  //! Returns the \p i -th coefficient.
29800  Coefficient_traits::const_reference get(dimension_type i) const;
29801
29802  //! Returns the coefficient of variable \p v.
29803  Coefficient_traits::const_reference get(Variable v) const;
29804
29805  /*! \brief
29806    Returns <CODE>true</CODE> if (*this)[i] is zero,
29807    for each i in [start, end).
29808  */
29809  bool all_zeroes(dimension_type start, dimension_type end) const;
29810
29811  //! Returns the number of zero coefficient in [start, end).
29812  dimension_type num_zeroes(dimension_type start, dimension_type end) const;
29813
29814  /*! \brief
29815    Returns the gcd of the nonzero coefficients in [start,end).
29816    Returns zero if all the coefficients in the range are zero.
29817  */
29818  Coefficient gcd(dimension_type start, dimension_type end) const;
29819
29820  //! Returns the index of the last nonzero element, or zero if there are no
29821  //! nonzero elements.
29822  dimension_type last_nonzero() const;
29823
29824  //! Returns the index of the last nonzero element in [first,last),
29825  //! or \p last if there are no nonzero elements.
29826  dimension_type last_nonzero(dimension_type first, dimension_type last) const;
29827
29828  //! Returns the index of the first nonzero element, or \p last if there are no
29829  //! nonzero elements, considering only elements in [first,last).
29830  dimension_type first_nonzero(dimension_type first, dimension_type last) const;
29831
29832  /*! \brief
29833    Returns <CODE>true</CODE> if all coefficients in [start,end),
29834    except those corresponding to variables in \p vars, are zero.
29835  */
29836  bool all_zeroes_except(const Variables_Set& vars,
29837                         dimension_type start, dimension_type end) const;
29838
29839  //! Removes from set \p x all the indexes of nonzero elements in \p *this.
29840  void has_a_free_dimension_helper(std::set<dimension_type>& x) const;
29841
29842  //! Returns \c true if <CODE>(*this)[i]</CODE> is equal to <CODE>y[i]</CODE>,
29843  //! for each i in [start,end).
29844  template <typename Expression>
29845  bool is_equal_to(const Expression& y,
29846                   dimension_type start, dimension_type end) const;
29847
29848  //! Returns \c true if <CODE>(*this)[i]*c1</CODE> is equal to
29849  //! <CODE>y[i]*c2</CODE>, for each i in [start,end).
29850  template <typename Expression>
29851  bool is_equal_to(const Expression& y,
29852                   Coefficient_traits::const_reference c1,
29853                   Coefficient_traits::const_reference c2,
29854                   dimension_type start, dimension_type end) const;
29855
29856  //! Sets \p r to a copy of the row as adapted by \p *this.
29857  void get_row(Dense_Row& r) const;
29858
29859  //! Sets \p r to a copy of the row as adapted by \p *this.
29860  void get_row(Sparse_Row& r) const;
29861
29862  //! Returns \c true if there is a variable in [first,last) whose coefficient
29863  //! is nonzero in both \p *this and \p y.
29864  template <typename Expression>
29865  bool have_a_common_variable(const Expression& y,
29866                              Variable first, Variable last) const;
29867
29868private:
29869  //! Whether or not the last coefficient is hidden.
29870  const bool hide_last_;
29871};
29872
29873/* Automatically generated from PPL source file ../src/Expression_Hide_Last_inlines.hh line 1. */
29874/* Expression_Hide_Last class implementation: inline functions.
29875*/
29876
29877
29878/* Automatically generated from PPL source file ../src/Expression_Hide_Last_inlines.hh line 28. */
29879
29880namespace Parma_Polyhedra_Library {
29881
29882template <typename T>
29883inline
29884Expression_Hide_Last<T>::Expression_Hide_Last(const raw_type& expr,
29885                                              const bool hide_last)
29886  : base_type(expr), hide_last_(hide_last) {
29887}
29888
29889template <typename T>
29890inline dimension_type
29891Expression_Hide_Last<T>::space_dimension() const {
29892  dimension_type dim = this->inner().space_dimension();
29893  if (hide_last_) {
29894    PPL_ASSERT(dim > 0);
29895    --dim;
29896  }
29897  return dim;
29898}
29899
29900template <typename T>
29901inline typename Expression_Hide_Last<T>::const_iterator
29902Expression_Hide_Last<T>::end() const {
29903  if (hide_last_) {
29904    return this->inner().lower_bound(Variable(space_dimension()));
29905  }
29906  else {
29907    return this->inner().end();
29908  }
29909}
29910
29911template <typename T>
29912inline typename Expression_Hide_Last<T>::const_iterator
29913Expression_Hide_Last<T>::lower_bound(Variable v) const {
29914  PPL_ASSERT(v.space_dimension() <= space_dimension() + 1);
29915  return this->inner().lower_bound(v);
29916}
29917
29918template <typename T>
29919inline Coefficient_traits::const_reference
29920Expression_Hide_Last<T>::coefficient(Variable v) const {
29921  PPL_ASSERT(v.space_dimension() <= space_dimension());
29922  return this->inner().coefficient(v);
29923}
29924
29925template <typename T>
29926inline bool
29927Expression_Hide_Last<T>::is_zero() const {
29928  return this->inner().all_zeroes(0, space_dimension() + 1);
29929}
29930
29931template <typename T>
29932inline bool
29933Expression_Hide_Last<T>::all_homogeneous_terms_are_zero() const {
29934  return this->inner().all_zeroes(1, space_dimension() + 1);
29935}
29936
29937template <typename T>
29938template <typename Expression>
29939inline bool
29940Expression_Hide_Last<T>
29941::is_equal_to(const Expression& y) const {
29942  const dimension_type x_dim = space_dimension();
29943  const dimension_type y_dim = y.space_dimension();
29944  if (x_dim != y_dim) {
29945    return false;
29946  }
29947  return is_equal_to(y, 0, x_dim + 1);
29948}
29949
29950template <typename T>
29951inline bool
29952Expression_Hide_Last<T>::all_zeroes(const Variables_Set& vars) const {
29953  PPL_ASSERT(vars.space_dimension() <= space_dimension());
29954  return this->inner().all_zeroes(vars);
29955}
29956
29957template <typename T>
29958inline Coefficient_traits::const_reference
29959Expression_Hide_Last<T>::get(dimension_type i) const {
29960  PPL_ASSERT(i <= space_dimension());
29961  return this->inner().get(i);
29962}
29963
29964template <typename T>
29965inline Coefficient_traits::const_reference
29966Expression_Hide_Last<T>::get(Variable v) const {
29967  PPL_ASSERT(v.space_dimension() <= space_dimension());
29968  return this->inner().get(v);
29969}
29970
29971template <typename T>
29972inline bool
29973Expression_Hide_Last<T>::all_zeroes(dimension_type start,
29974                                    dimension_type end) const {
29975  PPL_ASSERT(end <= space_dimension() + 1);
29976  return this->inner().all_zeroes(start, end);
29977}
29978
29979template <typename T>
29980inline dimension_type
29981Expression_Hide_Last<T>::num_zeroes(dimension_type start,
29982                                    dimension_type end) const {
29983  PPL_ASSERT(end <= space_dimension() + 1);
29984  return this->inner().num_zeroes(start, end);
29985}
29986
29987template <typename T>
29988inline Coefficient
29989Expression_Hide_Last<T>::gcd(dimension_type start,
29990                             dimension_type end) const {
29991  PPL_ASSERT(end <= space_dimension() + 1);
29992  return this->inner().gcd(start, end);
29993}
29994
29995template <typename T>
29996inline dimension_type
29997Expression_Hide_Last<T>::last_nonzero() const {
29998  return this->inner().last_nonzero(0, space_dimension() + 1);
29999}
30000
30001template <typename T>
30002inline dimension_type
30003Expression_Hide_Last<T>::last_nonzero(dimension_type first,
30004                                      dimension_type last) const {
30005  PPL_ASSERT(last <= space_dimension() + 1);
30006  return this->inner().last_nonzero(first, last);
30007}
30008
30009template <typename T>
30010inline dimension_type
30011Expression_Hide_Last<T>::first_nonzero(dimension_type first,
30012                                       dimension_type last) const {
30013  PPL_ASSERT(last <= space_dimension() + 1);
30014  return this->inner().first_nonzero(first, last);
30015}
30016
30017template <typename T>
30018inline bool
30019Expression_Hide_Last<T>
30020::all_zeroes_except(const Variables_Set& vars,
30021                    dimension_type start, dimension_type end) const {
30022  PPL_ASSERT(end <= space_dimension() + 1);
30023  return this->inner().all_zeroes_except(vars, start, end);
30024}
30025
30026template <typename T>
30027inline void
30028Expression_Hide_Last<T>
30029::has_a_free_dimension_helper(std::set<dimension_type>& x) const {
30030  if (x.empty()) {
30031    return;
30032  }
30033  PPL_ASSERT(*(--x.end()) <= space_dimension());
30034  this->inner().has_a_free_dimension_helper(x);
30035}
30036
30037template <typename T>
30038template <typename Expression>
30039inline bool
30040Expression_Hide_Last<T>
30041::is_equal_to(const Expression& y,
30042              dimension_type start, dimension_type end) const {
30043  PPL_ASSERT(end <= space_dimension() + 1);
30044  PPL_ASSERT(end <= y.space_dimension() + 1);
30045  return this->inner().is_equal_to(y, start, end);
30046}
30047
30048template <typename T>
30049template <typename Expression>
30050inline bool
30051Expression_Hide_Last<T>
30052::is_equal_to(const Expression& y,
30053              Coefficient_traits::const_reference c1,
30054              Coefficient_traits::const_reference c2,
30055              dimension_type start, dimension_type end) const {
30056  PPL_ASSERT(end <= space_dimension() + 1);
30057  PPL_ASSERT(end <= y.space_dimension() + 1);
30058  return this->inner().is_equal_to(y, c1, c2, start, end);
30059}
30060
30061template <typename T>
30062inline void
30063Expression_Hide_Last<T>::get_row(Dense_Row& r) const {
30064  this->inner().get_row(r);
30065  if (hide_last_) {
30066    PPL_ASSERT(r.size() != 0);
30067    r.resize(r.size() - 1);
30068  }
30069}
30070
30071template <typename T>
30072inline void
30073Expression_Hide_Last<T>::get_row(Sparse_Row& r) const {
30074  this->inner().get_row(r);
30075  if (hide_last_) {
30076    PPL_ASSERT(r.size() != 0);
30077    r.resize(r.size() - 1);
30078  }
30079}
30080
30081template <typename T>
30082template <typename Expression>
30083inline bool
30084Expression_Hide_Last<T>
30085::have_a_common_variable(const Expression& y,
30086                         Variable first, Variable last) const {
30087  PPL_ASSERT(last.space_dimension() <= space_dimension() + 1);
30088  PPL_ASSERT(last.space_dimension() <= y.space_dimension() + 1);
30089  return this->inner().have_a_common_variable(y, first, last);
30090}
30091
30092} // namespace Parma_Polyhedra_Library
30093
30094/* Automatically generated from PPL source file ../src/Expression_Hide_Last_defs.hh line 164. */
30095
30096/* Automatically generated from PPL source file ../src/Constraint_defs.hh line 40. */
30097
30098#include <iosfwd>
30099
30100namespace Parma_Polyhedra_Library {
30101
30102//! Returns the constraint \p e1 \< \p e2.
30103/*! \relates Constraint */
30104Constraint
30105operator<(const Linear_Expression& e1, const Linear_Expression& e2);
30106
30107//! Returns the constraint \p v1 \< \p v2.
30108/*! \relates Constraint */
30109Constraint
30110operator<(Variable v1, Variable v2);
30111
30112//! Returns the constraint \p e \< \p n.
30113/*! \relates Constraint */
30114Constraint
30115operator<(const Linear_Expression& e, Coefficient_traits::const_reference n);
30116
30117//! Returns the constraint \p n \< \p e.
30118/*! \relates Constraint */
30119Constraint
30120operator<(Coefficient_traits::const_reference n, const Linear_Expression& e);
30121
30122//! Returns the constraint \p e1 \> \p e2.
30123/*! \relates Constraint */
30124Constraint
30125operator>(const Linear_Expression& e1, const Linear_Expression& e2);
30126
30127//! Returns the constraint \p v1 \> \p v2.
30128/*! \relates Constraint */
30129Constraint
30130operator>(Variable v1, Variable v2);
30131
30132//! Returns the constraint \p e \> \p n.
30133/*! \relates Constraint */
30134Constraint
30135operator>(const Linear_Expression& e, Coefficient_traits::const_reference n);
30136
30137//! Returns the constraint \p n \> \p e.
30138/*! \relates Constraint */
30139Constraint
30140operator>(Coefficient_traits::const_reference n, const Linear_Expression& e);
30141
30142//! Returns the constraint \p e1 = \p e2.
30143/*! \relates Constraint */
30144Constraint
30145operator==(const Linear_Expression& e1, const Linear_Expression& e2);
30146
30147//! Returns the constraint \p v1 = \p v2.
30148/*! \relates Constraint */
30149Constraint
30150operator==(Variable v1, Variable v2);
30151
30152//! Returns the constraint \p e = \p n.
30153/*! \relates Constraint */
30154Constraint
30155operator==(const Linear_Expression& e, Coefficient_traits::const_reference n);
30156
30157//! Returns the constraint \p n = \p e.
30158/*! \relates Constraint */
30159Constraint
30160operator==(Coefficient_traits::const_reference n, const Linear_Expression& e);
30161
30162//! Returns the constraint \p e1 \<= \p e2.
30163/*! \relates Constraint */
30164Constraint
30165operator<=(const Linear_Expression& e1, const Linear_Expression& e2);
30166
30167//! Returns the constraint \p v1 \<= \p v2.
30168/*! \relates Constraint */
30169Constraint
30170operator<=(Variable v1, Variable v2);
30171
30172//! Returns the constraint \p e \<= \p n.
30173/*! \relates Constraint */
30174Constraint
30175operator<=(const Linear_Expression& e, Coefficient_traits::const_reference n);
30176
30177//! Returns the constraint \p n \<= \p e.
30178/*! \relates Constraint */
30179Constraint
30180operator<=(Coefficient_traits::const_reference n, const Linear_Expression& e);
30181
30182//! Returns the constraint \p e1 \>= \p e2.
30183/*! \relates Constraint */
30184Constraint
30185operator>=(const Linear_Expression& e1, const Linear_Expression& e2);
30186
30187//! Returns the constraint \p v1 \>= \p v2.
30188/*! \relates Constraint */
30189Constraint
30190operator>=(Variable v1, Variable v2);
30191
30192//! Returns the constraint \p e \>= \p n.
30193/*! \relates Constraint */
30194Constraint
30195operator>=(const Linear_Expression& e, Coefficient_traits::const_reference n);
30196
30197//! Returns the constraint \p n \>= \p e.
30198/*! \relates Constraint */
30199Constraint
30200operator>=(Coefficient_traits::const_reference n, const Linear_Expression& e);
30201
30202#ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
30203//! The basic comparison function.
30204/*! \relates Constraint
30205  \return
30206  The returned absolute value can be \f$0\f$, \f$1\f$ or \f$2\f$.
30207
30208  \param x
30209  A row of coefficients;
30210
30211  \param y
30212  Another row.
30213
30214  Compares \p x and \p y, where \p x and \p y may be of different size,
30215  in which case the "missing" coefficients are assumed to be zero.
30216  The comparison is such that:
30217  -# equalities are smaller than inequalities;
30218  -# lines are smaller than points and rays;
30219  -# the ordering is lexicographic;
30220  -# the positions compared are, in decreasing order of significance,
30221     1, 2, ..., \p size(), 0;
30222  -# the result is negative, zero, or positive if x is smaller than,
30223     equal to, or greater than y, respectively;
30224  -# when \p x and \p y are different, the absolute value of the
30225     result is 1 if the difference is due to the coefficient in
30226     position 0; it is 2 otherwise.
30227
30228  When \p x and \p y represent the hyper-planes associated
30229  to two equality or inequality constraints, the coefficient
30230  at 0 is the known term.
30231  In this case, the return value can be characterized as follows:
30232  - -2, if \p x is smaller than \p y and they are \e not parallel;
30233  - -1, if \p x is smaller than \p y and they \e are parallel;
30234  -  0, if \p x and y are equal;
30235  - +1, if \p y is smaller than \p x and they \e are parallel;
30236  - +2, if \p y is smaller than \p x and they are \e not parallel.
30237*/
30238#endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
30239int compare(const Constraint& x, const Constraint& y);
30240
30241}
30242
30243//! A linear equality or inequality.
30244/*! \ingroup PPL_CXX_interface
30245  An object of the class Constraint is either:
30246  - an equality: \f$\sum_{i=0}^{n-1} a_i x_i + b = 0\f$;
30247  - a non-strict inequality: \f$\sum_{i=0}^{n-1} a_i x_i + b \geq 0\f$; or
30248  - a strict inequality: \f$\sum_{i=0}^{n-1} a_i x_i + b > 0\f$;
30249
30250  where \f$n\f$ is the dimension of the space,
30251  \f$a_i\f$ is the integer coefficient of variable \f$x_i\f$
30252  and \f$b\f$ is the integer inhomogeneous term.
30253
30254  \par How to build a constraint
30255  Constraints are typically built by applying a relation symbol
30256  to a pair of linear expressions.
30257  Available relation symbols are equality (<CODE>==</CODE>),
30258  non-strict inequalities (<CODE>\>=</CODE> and <CODE>\<=</CODE>) and
30259  strict inequalities (<CODE>\<</CODE> and <CODE>\></CODE>).
30260  The space dimension of a constraint is defined as the maximum
30261  space dimension of the arguments of its constructor.
30262
30263  \par
30264  In the following examples it is assumed that variables
30265  <CODE>x</CODE>, <CODE>y</CODE> and <CODE>z</CODE>
30266  are defined as follows:
30267  \code
30268  Variable x(0);
30269  Variable y(1);
30270  Variable z(2);
30271  \endcode
30272
30273  \par Example 1
30274  The following code builds the equality constraint
30275  \f$3x + 5y - z = 0\f$, having space dimension \f$3\f$:
30276  \code
30277  Constraint eq_c(3*x + 5*y - z == 0);
30278  \endcode
30279  The following code builds the (non-strict) inequality constraint
30280  \f$4x \geq 2y - 13\f$, having space dimension \f$2\f$:
30281  \code
30282  Constraint ineq_c(4*x >= 2*y - 13);
30283  \endcode
30284  The corresponding strict inequality constraint
30285  \f$4x > 2y - 13\f$ is obtained as follows:
30286  \code
30287  Constraint strict_ineq_c(4*x > 2*y - 13);
30288  \endcode
30289  An unsatisfiable constraint on the zero-dimension space \f$\Rset^0\f$
30290  can be specified as follows:
30291  \code
30292  Constraint false_c = Constraint::zero_dim_false();
30293  \endcode
30294  Equivalent, but more involved ways are the following:
30295  \code
30296  Constraint false_c1(Linear_Expression::zero() == 1);
30297  Constraint false_c2(Linear_Expression::zero() >= 1);
30298  Constraint false_c3(Linear_Expression::zero() > 0);
30299  \endcode
30300  In contrast, the following code defines an unsatisfiable constraint
30301  having space dimension \f$3\f$:
30302  \code
30303  Constraint false_c(0*z == 1);
30304  \endcode
30305
30306  \par How to inspect a constraint
30307  Several methods are provided to examine a constraint and extract
30308  all the encoded information: its space dimension, its type
30309  (equality, non-strict inequality, strict inequality) and
30310  the value of its integer coefficients.
30311
30312  \par Example 2
30313  The following code shows how it is possible to access each single
30314  coefficient of a constraint. Given an inequality constraint
30315  (in this case \f$x - 5y + 3z \leq 4\f$), we construct a new constraint
30316  corresponding to its complement (thus, in this case we want to obtain
30317  the strict inequality constraint \f$x - 5y + 3z > 4\f$).
30318  \code
30319  Constraint c1(x - 5*y + 3*z <= 4);
30320  cout << "Constraint c1: " << c1 << endl;
30321  if (c1.is_equality())
30322    cout << "Constraint c1 is not an inequality." << endl;
30323  else {
30324    Linear_Expression e;
30325    for (dimension_type i = c1.space_dimension(); i-- > 0; )
30326      e += c1.coefficient(Variable(i)) * Variable(i);
30327    e += c1.inhomogeneous_term();
30328    Constraint c2 = c1.is_strict_inequality() ? (e <= 0) : (e < 0);
30329    cout << "Complement c2: " << c2 << endl;
30330  }
30331  \endcode
30332  The actual output is the following:
30333  \code
30334  Constraint c1: -A + 5*B - 3*C >= -4
30335  Complement c2: A - 5*B + 3*C > 4
30336  \endcode
30337  Note that, in general, the particular output obtained can be
30338  syntactically different from the (semantically equivalent)
30339  constraint considered.
30340*/
30341class Parma_Polyhedra_Library::Constraint {
30342public:
30343
30344  //! The constraint type.
30345  enum Type {
30346    /*! The constraint is an equality. */
30347    EQUALITY,
30348    /*! The constraint is a non-strict inequality. */
30349    NONSTRICT_INEQUALITY,
30350    /*! The constraint is a strict inequality. */
30351    STRICT_INEQUALITY
30352  };
30353
30354  //! The representation used for new Constraints.
30355  /*!
30356    \note The copy constructor and the copy constructor with specified size
30357          use the representation of the original object, so that it is
30358          indistinguishable from the original object.
30359  */
30360  static const Representation default_representation = SPARSE;
30361
30362  //! Constructs the \f$0<=0\f$ constraint.
30363  explicit Constraint(Representation r = default_representation);
30364
30365  //! Ordinary copy constructor.
30366  /*!
30367    \note The new Constraint will have the same representation as `c',
30368          not default_representation, so that they are indistinguishable.
30369  */
30370  Constraint(const Constraint& c);
30371
30372  //! Copy constructor with given size.
30373  /*!
30374    \note The new Constraint will have the same representation as `c',
30375          not default_representation, so that they are indistinguishable.
30376  */
30377  Constraint(const Constraint& c, dimension_type space_dim);
30378
30379  //! Copy constructor with given representation.
30380  Constraint(const Constraint& c, Representation r);
30381
30382  //! Copy constructor with given size and representation.
30383  Constraint(const Constraint& c, dimension_type space_dim,
30384             Representation r);
30385
30386  //! Copy-constructs from equality congruence \p cg.
30387  /*!
30388    \exception std::invalid_argument
30389    Thrown if \p cg is a proper congruence.
30390  */
30391  explicit Constraint(const Congruence& cg,
30392                      Representation r = default_representation);
30393
30394  //! Destructor.
30395  ~Constraint();
30396
30397  //! Returns the current representation of *this.
30398  Representation representation() const;
30399
30400  //! Converts *this to the specified representation.
30401  void set_representation(Representation r);
30402
30403  //! Assignment operator.
30404  Constraint& operator=(const Constraint& c);
30405
30406  //! Returns the maximum space dimension a Constraint can handle.
30407  static dimension_type max_space_dimension();
30408
30409  //! Returns the dimension of the vector space enclosing \p *this.
30410  dimension_type space_dimension() const;
30411
30412  //! Sets the dimension of the vector space enclosing \p *this to
30413  //! \p space_dim .
30414  void set_space_dimension(dimension_type space_dim);
30415
30416  //! Swaps the coefficients of the variables \p v1 and \p v2 .
30417  void swap_space_dimensions(Variable v1, Variable v2);
30418
30419  //! Removes all the specified dimensions from the constraint.
30420  /*!
30421    The space dimension of the variable with the highest space
30422    dimension in \p vars must be at most the space dimension
30423    of \p this.
30424
30425    Always returns \p true. The return value is needed for compatibility with
30426    the Generator class.
30427  */
30428  bool remove_space_dimensions(const Variables_Set& vars);
30429
30430  //! Permutes the space dimensions of the constraint.
30431  /*
30432    \param cycle
30433    A vector representing a cycle of the permutation according to which the
30434    space dimensions must be rearranged.
30435
30436    The \p cycle vector represents a cycle of a permutation of space
30437    dimensions.
30438    For example, the permutation
30439    \f$ \{ x_1 \mapsto x_2, x_2 \mapsto x_3, x_3 \mapsto x_1 \}\f$ can be
30440    represented by the vector containing \f$ x_1, x_2, x_3 \f$.
30441  */
30442  void permute_space_dimensions(const std::vector<Variable>& cycle);
30443
30444  //! Shift by \p n positions the coefficients of variables, starting from
30445  //! the coefficient of \p v. This increases the space dimension by \p n.
30446  void shift_space_dimensions(Variable v, dimension_type n);
30447
30448  //! Returns the constraint type of \p *this.
30449  Type type() const;
30450
30451  /*! \brief
30452    Returns <CODE>true</CODE> if and only if
30453    \p *this is an equality constraint.
30454  */
30455  bool is_equality() const;
30456
30457  /*! \brief
30458    Returns <CODE>true</CODE> if and only if
30459    \p *this is an inequality constraint (either strict or non-strict).
30460  */
30461  bool is_inequality() const;
30462
30463  /*! \brief
30464    Returns <CODE>true</CODE> if and only if
30465    \p *this is a non-strict inequality constraint.
30466  */
30467  bool is_nonstrict_inequality() const;
30468
30469  /*! \brief
30470    Returns <CODE>true</CODE> if and only if
30471    \p *this is a strict inequality constraint.
30472  */
30473  bool is_strict_inequality() const;
30474
30475  //! Returns the coefficient of \p v in \p *this.
30476  /*!
30477    \exception std::invalid_argument thrown if the index of \p v
30478    is greater than or equal to the space dimension of \p *this.
30479  */
30480  Coefficient_traits::const_reference coefficient(Variable v) const;
30481
30482  //! Returns the inhomogeneous term of \p *this.
30483  Coefficient_traits::const_reference inhomogeneous_term() const;
30484
30485  //! Initializes the class.
30486  static void initialize();
30487
30488  //! Finalizes the class.
30489  static void finalize();
30490
30491  //! The unsatisfiable (zero-dimension space) constraint \f$0 = 1\f$.
30492  static const Constraint& zero_dim_false();
30493
30494  /*! \brief
30495    The true (zero-dimension space) constraint \f$0 \leq 1\f$,
30496    also known as <EM>positivity constraint</EM>.
30497  */
30498  static const Constraint& zero_dim_positivity();
30499
30500  /*! \brief
30501    Returns a lower bound to the total size in bytes of the memory
30502    occupied by \p *this.
30503  */
30504  memory_size_type total_memory_in_bytes() const;
30505
30506  //! Returns the size in bytes of the memory managed by \p *this.
30507  memory_size_type external_memory_in_bytes() const;
30508
30509  /*! \brief
30510    Returns <CODE>true</CODE> if and only if
30511    \p *this is a tautology (i.e., an always true constraint).
30512
30513    A tautology can have either one of the following forms:
30514    - an equality: \f$\sum_{i=0}^{n-1} 0 x_i + 0 = 0\f$; or
30515    - a non-strict inequality: \f$\sum_{i=0}^{n-1} 0 x_i + b \geq 0\f$,
30516      where \f$b \geq 0\f$; or
30517    - a strict inequality: \f$\sum_{i=0}^{n-1} 0 x_i + b > 0\f$,
30518      where \f$b > 0\f$.
30519  */
30520  bool is_tautological() const;
30521
30522  /*! \brief
30523    Returns <CODE>true</CODE> if and only if
30524    \p *this is inconsistent (i.e., an always false constraint).
30525
30526    An inconsistent constraint can have either one of the following forms:
30527    - an equality: \f$\sum_{i=0}^{n-1} 0 x_i + b = 0\f$,
30528      where \f$b \neq 0\f$; or
30529    - a non-strict inequality: \f$\sum_{i=0}^{n-1} 0 x_i + b \geq 0\f$,
30530      where \f$b < 0\f$; or
30531    - a strict inequality: \f$\sum_{i=0}^{n-1} 0 x_i + b > 0\f$,
30532      where \f$b \leq 0\f$.
30533  */
30534  bool is_inconsistent() const;
30535
30536  /*! \brief
30537    Returns <CODE>true</CODE> if and only if \p *this and \p y
30538    are equivalent constraints.
30539
30540    Constraints having different space dimensions are not equivalent.
30541    Note that constraints having different types may nonetheless be
30542    equivalent, if they both are tautologies or inconsistent.
30543  */
30544  bool is_equivalent_to(const Constraint& y) const;
30545
30546  //! Returns <CODE>true</CODE> if \p *this is identical to \p y.
30547  /*!
30548    This is faster than is_equivalent_to(), but it may return `false' even
30549    for equivalent constraints.
30550  */
30551  bool is_equal_to(const Constraint& y) const;
30552
30553  //! Checks if all the invariants are satisfied.
30554  bool OK() const;
30555
30556  PPL_OUTPUT_DECLARATIONS
30557
30558  /*! \brief
30559    Loads from \p s an ASCII representation (as produced by
30560    ascii_dump(std::ostream&) const) and sets \p *this accordingly.
30561    Returns <CODE>true</CODE> if successful, <CODE>false</CODE> otherwise.
30562  */
30563  bool ascii_load(std::istream& s);
30564
30565  //! Swaps \p *this with \p y.
30566  void m_swap(Constraint& y);
30567
30568  //! Returns the zero-dimension space constraint \f$\epsilon \geq 0\f$.
30569  static const Constraint& epsilon_geq_zero();
30570
30571  /*! \brief
30572    The zero-dimension space constraint \f$\epsilon \leq 1\f$
30573    (used to implement NNC polyhedra).
30574  */
30575  static const Constraint& epsilon_leq_one();
30576
30577  //! The type of the (adapted) internal expression.
30578  typedef Expression_Hide_Last<Linear_Expression> expr_type;
30579  //! Partial read access to the (adapted) internal expression.
30580  expr_type expression() const;
30581
30582private:
30583
30584  //! The possible kinds of Constraint objects.
30585  enum Kind {
30586    LINE_OR_EQUALITY = 0,
30587    RAY_OR_POINT_OR_INEQUALITY = 1
30588  };
30589
30590  Linear_Expression expr;
30591
30592  Kind kind_;
30593
30594  Topology topology_;
30595
30596  /*! \brief
30597    Holds (between class initialization and finalization) a pointer to
30598    the unsatisfiable (zero-dimension space) constraint \f$0 = 1\f$.
30599  */
30600  static const Constraint* zero_dim_false_p;
30601
30602  /*! \brief
30603    Holds (between class initialization and finalization) a pointer to
30604    the true (zero-dimension space) constraint \f$0 \leq 1\f$, also
30605    known as <EM>positivity constraint</EM>.
30606  */
30607  static const Constraint* zero_dim_positivity_p;
30608
30609  /*! \brief
30610    Holds (between class initialization and finalization) a pointer to
30611    the zero-dimension space constraint \f$\epsilon \geq 0\f$.
30612  */
30613  static const Constraint* epsilon_geq_zero_p;
30614
30615  /*! \brief
30616    Holds (between class initialization and finalization) a pointer to
30617    the zero-dimension space constraint \f$\epsilon \leq 1\f$
30618    (used to implement NNC polyhedra).
30619  */
30620  static const Constraint* epsilon_leq_one_p;
30621
30622  //! Constructs the \f$0<0\f$ constraint.
30623  Constraint(dimension_type space_dim, Kind kind, Topology topology,
30624             Representation r = default_representation);
30625
30626  /*! \brief
30627    Builds a constraint of kind \p kind and topology \p topology,
30628    stealing the coefficients from \p e.
30629
30630    \note The new Constraint will have the same representation as `e'.
30631  */
30632  Constraint(Linear_Expression& e, Kind kind, Topology topology);
30633
30634  /*! \brief
30635    Builds a constraint of type \p type and topology \p topology,
30636    stealing the coefficients from \p e.
30637
30638    \note The new Constraint will have the same representation as `e'.
30639  */
30640  Constraint(Linear_Expression& e, Type type, Topology topology);
30641
30642  /*! \brief
30643    Returns <CODE>true</CODE> if and only if \p *this row
30644    represents a line or an equality.
30645  */
30646  bool is_line_or_equality() const;
30647
30648  /*! \brief
30649    Returns <CODE>true</CODE> if and only if \p *this row
30650    represents a ray, a point or an inequality.
30651  */
30652  bool is_ray_or_point_or_inequality() const;
30653
30654  //! Sets to \p LINE_OR_EQUALITY the kind of \p *this row.
30655  void set_is_line_or_equality();
30656
30657  //! Sets to \p RAY_OR_POINT_OR_INEQUALITY the kind of \p *this row.
30658  void set_is_ray_or_point_or_inequality();
30659
30660  //! \name Flags inspection methods
30661  //@{
30662  //! Returns the topological kind of \p *this.
30663  Topology topology() const;
30664
30665  /*! \brief
30666    Returns <CODE>true</CODE> if and only if the topology
30667    of \p *this row is not necessarily closed.
30668  */
30669  bool is_not_necessarily_closed() const;
30670
30671  /*! \brief
30672    Returns <CODE>true</CODE> if and only if the topology
30673    of \p *this row is necessarily closed.
30674  */
30675  bool is_necessarily_closed() const;
30676  //@} // Flags inspection methods
30677
30678  //! \name Flags coercion methods
30679  //@{
30680
30681  // TODO: Consider setting the epsilon dimension in this method.
30682  //! Sets to \p x the topological kind of \p *this row.
30683  void set_topology(Topology x);
30684
30685  //! Sets to \p NECESSARILY_CLOSED the topological kind of \p *this row.
30686  void set_necessarily_closed();
30687
30688  //! Sets to \p NOT_NECESSARILY_CLOSED the topological kind of \p *this row.
30689  void set_not_necessarily_closed();
30690  //@} // Flags coercion methods
30691
30692  //! Sets the dimension of the vector space enclosing \p *this to
30693  //! \p space_dim .
30694  //! Sets the space dimension of the rows in the system to \p space_dim .
30695  /*!
30696    This method is for internal use, it does *not* assert OK() at the end,
30697    so it can be used for invalid objects.
30698  */
30699  void set_space_dimension_no_ok(dimension_type space_dim);
30700
30701  /*! \brief
30702    Throws a <CODE>std::invalid_argument</CODE> exception containing
30703    error message \p message.
30704  */
30705  void
30706  throw_invalid_argument(const char* method, const char* message) const;
30707
30708  /*! \brief
30709    Throws a <CODE>std::invalid_argument</CODE> exception
30710    containing the appropriate error message.
30711  */
30712  void
30713  throw_dimension_incompatible(const char* method,
30714                               const char* name_var,
30715                               Variable v) const;
30716
30717  //! Returns the epsilon coefficient. The constraint must be NNC.
30718  Coefficient_traits::const_reference epsilon_coefficient() const;
30719
30720  //! Sets the epsilon coefficient to \p n. The constraint must be NNC.
30721  void set_epsilon_coefficient(Coefficient_traits::const_reference n);
30722
30723  //! Marks the epsilon dimension as a standard dimension.
30724  /*!
30725    The row topology is changed to <CODE>NOT_NECESSARILY_CLOSED</CODE>, and
30726    the number of space dimensions is increased by 1.
30727  */
30728  void mark_as_necessarily_closed();
30729
30730  //! Marks the last dimension as the epsilon dimension.
30731  /*!
30732    The row topology is changed to <CODE>NECESSARILY_CLOSED</CODE>, and
30733    the number of space dimensions is decreased by 1.
30734  */
30735  void mark_as_not_necessarily_closed();
30736
30737  //! Sets the constraint type to <CODE>EQUALITY</CODE>.
30738  void set_is_equality();
30739
30740  //! Sets the constraint to be an inequality.
30741  /*!
30742    Whether the constraint type will become <CODE>NONSTRICT_INEQUALITY</CODE>
30743    or <CODE>STRICT_INEQUALITY</CODE> depends on the topology and the value
30744    of the low-level coefficients of the constraint.
30745  */
30746  void set_is_inequality();
30747
30748  //! Linearly combines \p *this with \p y so that i-th coefficient is 0.
30749  /*!
30750    \param y
30751    The Constraint that will be combined with \p *this object;
30752
30753    \param i
30754    The index of the coefficient that has to become \f$0\f$.
30755
30756    Computes a linear combination of \p *this and \p y having
30757    the i-th coefficient equal to \f$0\f$. Then it assigns
30758    the resulting Constraint to \p *this and normalizes it.
30759  */
30760  void linear_combine(const Constraint& y, dimension_type i);
30761
30762  /*! \brief
30763    Normalizes the sign of the coefficients so that the first non-zero
30764    (homogeneous) coefficient of a line-or-equality is positive.
30765  */
30766  void sign_normalize();
30767
30768  /*! \brief
30769    Strong normalization: ensures that different Constraint objects
30770    represent different hyperplanes or hyperspaces.
30771
30772    Applies both Constraint::normalize() and Constraint::sign_normalize().
30773  */
30774  void strong_normalize();
30775
30776  /*! \brief
30777    Returns <CODE>true</CODE> if and only if the coefficients are
30778    strongly normalized.
30779  */
30780  bool check_strong_normalized() const;
30781
30782  /*! \brief
30783    Builds a new copy of the zero-dimension space constraint
30784    \f$\epsilon \geq 0\f$ (used to implement NNC polyhedra).
30785  */
30786  static Constraint construct_epsilon_geq_zero();
30787
30788  friend int
30789  compare(const Constraint& x, const Constraint& y);
30790
30791  friend class Linear_System<Constraint>;
30792  friend class Constraint_System;
30793  friend class Polyhedron;
30794  friend class Scalar_Products;
30795  friend class Topology_Adjusted_Scalar_Product_Sign;
30796  friend class Termination_Helpers;
30797  friend class Grid;
30798  template <typename T>
30799  friend class Octagonal_Shape;
30800
30801  friend Constraint
30802  operator<(const Linear_Expression& e1, const Linear_Expression& e2);
30803
30804  friend Constraint
30805  operator<(Variable v1, Variable v2);
30806
30807  friend Constraint
30808  operator<(const Linear_Expression& e, Coefficient_traits::const_reference n);
30809
30810  friend Constraint
30811  operator<(Coefficient_traits::const_reference n, const Linear_Expression& e);
30812
30813  friend Constraint
30814  operator>(const Linear_Expression& e1, const Linear_Expression& e2);
30815
30816  friend Constraint
30817  operator>(Variable v1, Variable v2);
30818
30819  friend Constraint
30820  operator>(const Linear_Expression& e, Coefficient_traits::const_reference n);
30821
30822  friend Constraint
30823  operator>(Coefficient_traits::const_reference n, const Linear_Expression& e);
30824
30825  friend Constraint
30826  operator==(const Linear_Expression& e1, const Linear_Expression& e2);
30827
30828  friend Constraint
30829  operator==(Variable v1, Variable v2);
30830
30831  friend Constraint
30832  operator==(const Linear_Expression& e, Coefficient_traits::const_reference n);
30833
30834  friend Constraint
30835  operator==(Coefficient_traits::const_reference n, const Linear_Expression& e);
30836
30837  friend Constraint
30838  operator<=(const Linear_Expression& e1, const Linear_Expression& e2);
30839
30840  friend Constraint
30841  operator<=(Variable v1, Variable v2);
30842
30843  friend Constraint
30844  operator<=(const Linear_Expression& e, Coefficient_traits::const_reference n);
30845
30846  friend Constraint
30847  operator<=(Coefficient_traits::const_reference n, const Linear_Expression& e);
30848
30849  friend Constraint
30850  operator>=(const Linear_Expression& e1, const Linear_Expression& e2);
30851
30852  friend Constraint
30853  operator>=(Variable v1, Variable v2);
30854
30855  friend Constraint
30856  operator>=(const Linear_Expression& e, Coefficient_traits::const_reference n);
30857
30858  friend Constraint
30859  operator>=(Coefficient_traits::const_reference n, const Linear_Expression& e);
30860};
30861
30862namespace Parma_Polyhedra_Library {
30863
30864namespace IO_Operators {
30865
30866//! Output operator.
30867/*! \relates Parma_Polyhedra_Library::Constraint */
30868std::ostream& operator<<(std::ostream& s, const Constraint& c);
30869
30870//! Output operator.
30871/*! \relates Parma_Polyhedra_Library::Constraint */
30872std::ostream& operator<<(std::ostream& s, const Constraint::Type& t);
30873
30874} // namespace IO_Operators
30875
30876//! Returns <CODE>true</CODE> if and only if \p x is equivalent to \p y.
30877/*! \relates Constraint */
30878bool
30879operator==(const Constraint& x, const Constraint& y);
30880
30881//! Returns <CODE>true</CODE> if and only if \p x is not equivalent to \p y.
30882/*! \relates Constraint */
30883bool
30884operator!=(const Constraint& x, const Constraint& y);
30885
30886/*! \relates Constraint */
30887void swap(Constraint& x, Constraint& y);
30888
30889} // namespace Parma_Polyhedra_Library
30890
30891/* Automatically generated from PPL source file ../src/Constraint_inlines.hh line 1. */
30892/* Constraint class implementation: inline functions.
30893*/
30894
30895
30896/* Automatically generated from PPL source file ../src/Constraint_inlines.hh line 28. */
30897
30898namespace Parma_Polyhedra_Library {
30899
30900inline bool
30901Constraint::is_necessarily_closed() const {
30902  return (topology_ == NECESSARILY_CLOSED);
30903}
30904
30905inline bool
30906Constraint::is_not_necessarily_closed() const {
30907  return !is_necessarily_closed();
30908}
30909
30910inline Constraint::expr_type
30911Constraint::expression() const {
30912  return expr_type(expr, is_not_necessarily_closed());
30913}
30914
30915inline dimension_type
30916Constraint::space_dimension() const {
30917  return expression().space_dimension();
30918}
30919
30920inline void
30921Constraint::shift_space_dimensions(Variable v, dimension_type n) {
30922  expr.shift_space_dimensions(v, n);
30923}
30924
30925inline bool
30926Constraint::is_line_or_equality() const {
30927  return (kind_ == LINE_OR_EQUALITY);
30928}
30929
30930inline bool
30931Constraint::is_ray_or_point_or_inequality() const {
30932  return (kind_ == RAY_OR_POINT_OR_INEQUALITY);
30933}
30934
30935inline Topology
30936Constraint::topology() const {
30937  return topology_;
30938}
30939
30940inline void
30941Constraint::set_is_line_or_equality() {
30942  kind_ = LINE_OR_EQUALITY;
30943}
30944
30945inline void
30946Constraint::set_is_ray_or_point_or_inequality() {
30947  kind_ = RAY_OR_POINT_OR_INEQUALITY;
30948}
30949
30950inline void
30951Constraint::set_topology(Topology x) {
30952  if (topology() == x) {
30953    return;
30954  }
30955  if (topology() == NECESSARILY_CLOSED) {
30956    // Add a column for the epsilon dimension.
30957    expr.set_space_dimension(expr.space_dimension() + 1);
30958  }
30959  else {
30960    PPL_ASSERT(expr.space_dimension() != 0);
30961    expr.set_space_dimension(expr.space_dimension() - 1);
30962  }
30963  topology_ = x;
30964}
30965
30966inline void
30967Constraint::mark_as_necessarily_closed() {
30968  PPL_ASSERT(is_not_necessarily_closed());
30969  topology_ = NECESSARILY_CLOSED;
30970}
30971
30972inline void
30973Constraint::mark_as_not_necessarily_closed() {
30974  PPL_ASSERT(is_necessarily_closed());
30975  topology_ = NOT_NECESSARILY_CLOSED;
30976}
30977
30978inline void
30979Constraint::set_necessarily_closed() {
30980  set_topology(NECESSARILY_CLOSED);
30981}
30982
30983inline void
30984Constraint::set_not_necessarily_closed() {
30985  set_topology(NOT_NECESSARILY_CLOSED);
30986}
30987
30988inline
30989Constraint::Constraint(Representation r)
30990  : expr(r),
30991    kind_(RAY_OR_POINT_OR_INEQUALITY),
30992    topology_(NECESSARILY_CLOSED) {
30993  PPL_ASSERT(OK());
30994}
30995
30996inline
30997Constraint::Constraint(dimension_type space_dim, Kind kind, Topology topology,
30998                       Representation r)
30999  : expr(r),
31000    kind_(kind),
31001    topology_(topology) {
31002  expr.set_space_dimension(space_dim + 1);
31003  PPL_ASSERT(space_dimension() == space_dim);
31004  PPL_ASSERT(OK());
31005}
31006
31007inline
31008Constraint::Constraint(Linear_Expression& e, Kind kind, Topology topology)
31009  : kind_(kind),
31010    topology_(topology) {
31011  PPL_ASSERT(kind != RAY_OR_POINT_OR_INEQUALITY || topology == NOT_NECESSARILY_CLOSED);
31012  swap(expr, e);
31013  if (topology == NOT_NECESSARILY_CLOSED) {
31014    // Add the epsilon dimension.
31015    expr.set_space_dimension(expr.space_dimension() + 1);
31016  }
31017  strong_normalize();
31018  PPL_ASSERT(OK());
31019}
31020
31021inline
31022Constraint::Constraint(Linear_Expression& e, Type type, Topology topology)
31023  : topology_(topology) {
31024  PPL_ASSERT(type != STRICT_INEQUALITY || topology == NOT_NECESSARILY_CLOSED);
31025  swap(expr, e);
31026  if (topology == NOT_NECESSARILY_CLOSED) {
31027    expr.set_space_dimension(expr.space_dimension() + 1);
31028  }
31029  if (type == EQUALITY) {
31030    kind_ = LINE_OR_EQUALITY;
31031  }
31032  else {
31033    kind_ = RAY_OR_POINT_OR_INEQUALITY;
31034  }
31035  strong_normalize();
31036  PPL_ASSERT(OK());
31037}
31038
31039inline
31040Constraint::Constraint(const Constraint& c)
31041  : expr(c.expr),
31042    kind_(c.kind_),
31043    topology_(c.topology_) {
31044  // NOTE: This does not call PPL_ASSERT(OK()) because this is called by OK().
31045}
31046
31047inline
31048Constraint::Constraint(const Constraint& c, Representation r)
31049  : expr(c.expr, r),
31050    kind_(c.kind_),
31051    topology_(c.topology_) {
31052  PPL_ASSERT(OK());
31053}
31054
31055inline
31056Constraint::Constraint(const Constraint& c, const dimension_type space_dim)
31057  : expr(c.expr, c.is_necessarily_closed() ? space_dim : (space_dim + 1)),
31058    kind_(c.kind_), topology_(c.topology_) {
31059  PPL_ASSERT(space_dimension() == space_dim);
31060  PPL_ASSERT(OK());
31061}
31062
31063inline
31064Constraint::Constraint(const Constraint& c, const dimension_type space_dim,
31065                       Representation r)
31066  : expr(c.expr, c.is_necessarily_closed() ? space_dim : (space_dim + 1), r),
31067    kind_(c.kind_), topology_(c.topology_) {
31068  PPL_ASSERT(space_dimension() == space_dim);
31069  PPL_ASSERT(OK());
31070}
31071
31072inline
31073Constraint::~Constraint() {
31074}
31075
31076inline Constraint&
31077Constraint::operator=(const Constraint& c) {
31078  Constraint tmp = c;
31079  swap(*this, tmp);
31080
31081  return *this;
31082}
31083
31084inline Representation
31085Constraint::representation() const {
31086  return expr.representation();
31087}
31088
31089inline void
31090Constraint::set_representation(Representation r) {
31091  expr.set_representation(r);
31092}
31093
31094inline dimension_type
31095Constraint::max_space_dimension() {
31096  return Linear_Expression::max_space_dimension();
31097}
31098
31099inline void
31100Constraint::set_space_dimension_no_ok(dimension_type space_dim) {
31101  const dimension_type old_expr_space_dim = expr.space_dimension();
31102  if (topology() == NECESSARILY_CLOSED) {
31103    expr.set_space_dimension(space_dim);
31104  }
31105  else {
31106    const dimension_type old_space_dim = space_dimension();
31107    if (space_dim > old_space_dim) {
31108      expr.set_space_dimension(space_dim + 1);
31109      expr.swap_space_dimensions(Variable(space_dim), Variable(old_space_dim));
31110    }
31111    else {
31112      expr.swap_space_dimensions(Variable(space_dim), Variable(old_space_dim));
31113      expr.set_space_dimension(space_dim + 1);
31114    }
31115  }
31116  PPL_ASSERT(space_dimension() == space_dim);
31117  if (expr.space_dimension() < old_expr_space_dim) {
31118    strong_normalize();
31119  }
31120}
31121
31122inline void
31123Constraint::set_space_dimension(dimension_type space_dim) {
31124  set_space_dimension_no_ok(space_dim);
31125  PPL_ASSERT(OK());
31126}
31127
31128inline bool
31129Constraint::remove_space_dimensions(const Variables_Set& vars) {
31130  expr.remove_space_dimensions(vars);
31131  return true;
31132}
31133
31134inline bool
31135Constraint::is_equality() const {
31136  return is_line_or_equality();
31137}
31138
31139inline bool
31140Constraint::is_inequality() const {
31141  return is_ray_or_point_or_inequality();
31142}
31143
31144inline Constraint::Type
31145Constraint::type() const {
31146  if (is_equality()) {
31147    return EQUALITY;
31148  }
31149  if (is_necessarily_closed()) {
31150    return NONSTRICT_INEQUALITY;
31151  }
31152  if (epsilon_coefficient() < 0) {
31153    return STRICT_INEQUALITY;
31154  }
31155  else {
31156    return NONSTRICT_INEQUALITY;
31157  }
31158}
31159
31160inline bool
31161Constraint::is_nonstrict_inequality() const {
31162  return type() == NONSTRICT_INEQUALITY;
31163}
31164
31165inline bool
31166Constraint::is_strict_inequality() const {
31167  return type() == STRICT_INEQUALITY;
31168}
31169
31170inline void
31171Constraint::set_is_equality() {
31172  set_is_line_or_equality();
31173}
31174
31175inline void
31176Constraint::set_is_inequality() {
31177  set_is_ray_or_point_or_inequality();
31178}
31179
31180inline Coefficient_traits::const_reference
31181Constraint::coefficient(const Variable v) const {
31182  if (v.space_dimension() > space_dimension()) {
31183    throw_dimension_incompatible("coefficient(v)", "v", v);
31184  }
31185  return expr.coefficient(v);
31186}
31187
31188inline Coefficient_traits::const_reference
31189Constraint::inhomogeneous_term() const {
31190  return expr.inhomogeneous_term();
31191}
31192
31193inline memory_size_type
31194Constraint::external_memory_in_bytes() const {
31195  return expr.external_memory_in_bytes();
31196}
31197
31198inline memory_size_type
31199Constraint::total_memory_in_bytes() const {
31200  return sizeof(*this) + external_memory_in_bytes();
31201}
31202
31203inline void
31204Constraint::strong_normalize() {
31205  expr.normalize();
31206  sign_normalize();
31207}
31208
31209/*! \relates Constraint */
31210inline bool
31211operator==(const Constraint& x, const Constraint& y) {
31212  return x.is_equivalent_to(y);
31213}
31214
31215/*! \relates Constraint */
31216inline bool
31217operator!=(const Constraint& x, const Constraint& y) {
31218  return !x.is_equivalent_to(y);
31219}
31220
31221/*! \relates Constraint */
31222inline Constraint
31223operator==(const Linear_Expression& e1, const Linear_Expression& e2) {
31224  Linear_Expression diff(e1,
31225                         std::max(e1.space_dimension(), e2.space_dimension()),
31226                         Constraint::default_representation);
31227  diff -= e2;
31228  return Constraint(diff, Constraint::EQUALITY, NECESSARILY_CLOSED);
31229}
31230
31231/*! \relates Constraint */
31232inline Constraint
31233operator==(Variable v1, Variable v2) {
31234  if (v1.space_dimension() > v2.space_dimension()) {
31235    swap(v1, v2);
31236  }
31237  PPL_ASSERT(v1.space_dimension() <= v2.space_dimension());
31238
31239  Linear_Expression diff(v1, Constraint::default_representation);
31240  diff -= v2;
31241  return Constraint(diff, Constraint::EQUALITY, NECESSARILY_CLOSED);
31242}
31243
31244/*! \relates Constraint */
31245inline Constraint
31246operator>=(const Linear_Expression& e1, const Linear_Expression& e2) {
31247  Linear_Expression diff(e1,
31248                         std::max(e1.space_dimension(), e2.space_dimension()),
31249                         Constraint::default_representation);
31250  diff -= e2;
31251  return Constraint(diff, Constraint::NONSTRICT_INEQUALITY, NECESSARILY_CLOSED);
31252}
31253
31254/*! \relates Constraint */
31255inline Constraint
31256operator>=(const Variable v1, const Variable v2) {
31257  Linear_Expression diff(Constraint::default_representation);
31258  diff.set_space_dimension(std::max(v1.space_dimension(),
31259                                    v2.space_dimension()));
31260  diff += v1;
31261  diff -= v2;
31262  return Constraint(diff, Constraint::NONSTRICT_INEQUALITY, NECESSARILY_CLOSED);
31263}
31264
31265/*! \relates Constraint */
31266inline Constraint
31267operator>(const Linear_Expression& e1, const Linear_Expression& e2) {
31268  Linear_Expression diff(e1, Constraint::default_representation);
31269  diff -= e2;
31270  Constraint c(diff, Constraint::STRICT_INEQUALITY, NOT_NECESSARILY_CLOSED);
31271
31272  // NOTE: this also enforces normalization.
31273  c.set_epsilon_coefficient(-1);
31274  PPL_ASSERT(c.OK());
31275
31276  return c;
31277}
31278
31279/*! \relates Constraint */
31280inline Constraint
31281operator>(const Variable v1, const Variable v2) {
31282  Linear_Expression diff(Constraint::default_representation);
31283  diff.set_space_dimension(std::max(v1.space_dimension(),
31284                                    v2.space_dimension()));
31285  diff += v1;
31286  diff -= v2;
31287  Constraint c(diff, Constraint::STRICT_INEQUALITY, NOT_NECESSARILY_CLOSED);
31288
31289  c.set_epsilon_coefficient(-1);
31290  PPL_ASSERT(c.OK());
31291
31292  return c;
31293}
31294
31295/*! \relates Constraint */
31296inline Constraint
31297operator==(Coefficient_traits::const_reference n, const Linear_Expression& e) {
31298  Linear_Expression diff(e, Constraint::default_representation);
31299  neg_assign(diff);
31300  diff += n;
31301  return Constraint(diff, Constraint::EQUALITY, NECESSARILY_CLOSED);
31302}
31303
31304/*! \relates Constraint */
31305inline Constraint
31306operator>=(Coefficient_traits::const_reference n, const Linear_Expression& e) {
31307  Linear_Expression diff(e, Constraint::default_representation);
31308  neg_assign(diff);
31309  diff += n;
31310  return Constraint(diff, Constraint::NONSTRICT_INEQUALITY, NECESSARILY_CLOSED);
31311}
31312
31313/*! \relates Constraint */
31314inline Constraint
31315operator>(Coefficient_traits::const_reference n, const Linear_Expression& e) {
31316  Linear_Expression diff(e, Constraint::default_representation);
31317  neg_assign(diff);
31318  diff += n;
31319  Constraint c(diff, Constraint::STRICT_INEQUALITY, NOT_NECESSARILY_CLOSED);
31320
31321  // NOTE: this also enforces normalization.
31322  c.set_epsilon_coefficient(-1);
31323  PPL_ASSERT(c.OK());
31324
31325  return c;
31326}
31327
31328/*! \relates Constraint */
31329inline Constraint
31330operator==(const Linear_Expression& e, Coefficient_traits::const_reference n) {
31331  Linear_Expression diff(e, Constraint::default_representation);
31332  diff -= n;
31333  return Constraint(diff, Constraint::EQUALITY, NECESSARILY_CLOSED);
31334}
31335
31336/*! \relates Constraint */
31337inline Constraint
31338operator>=(const Linear_Expression& e, Coefficient_traits::const_reference n) {
31339  Linear_Expression diff(e, Constraint::default_representation);
31340  diff -= n;
31341  return Constraint(diff, Constraint::NONSTRICT_INEQUALITY, NECESSARILY_CLOSED);
31342}
31343
31344/*! \relates Constraint */
31345inline Constraint
31346operator>(const Linear_Expression& e, Coefficient_traits::const_reference n) {
31347  Linear_Expression diff(e, Constraint::default_representation);
31348  diff -= n;
31349  Constraint c(diff, Constraint::STRICT_INEQUALITY, NOT_NECESSARILY_CLOSED);
31350
31351  // NOTE: this also enforces normalization.
31352  c.set_epsilon_coefficient(-1);
31353  PPL_ASSERT(c.OK());
31354
31355  return c;
31356}
31357
31358/*! \relates Constraint */
31359inline Constraint
31360operator<=(const Linear_Expression& e1, const Linear_Expression& e2) {
31361  return e2 >= e1;
31362}
31363
31364/*! \relates Constraint */
31365inline Constraint
31366operator<=(const Variable v1, const Variable v2) {
31367  return v2 >= v1;
31368}
31369
31370/*! \relates Constraint */
31371inline Constraint
31372operator<=(Coefficient_traits::const_reference n, const Linear_Expression& e) {
31373  return e >= n;
31374}
31375
31376/*! \relates Constraint */
31377inline Constraint
31378operator<=(const Linear_Expression& e, Coefficient_traits::const_reference n) {
31379  return n >= e;
31380}
31381
31382/*! \relates Constraint */
31383inline Constraint
31384operator<(const Linear_Expression& e1, const Linear_Expression& e2) {
31385  return e2 > e1;
31386}
31387
31388/*! \relates Constraint */
31389inline Constraint
31390operator<(const Variable v1, const Variable v2) {
31391  return v2 > v1;
31392}
31393
31394/*! \relates Constraint */
31395inline Constraint
31396operator<(Coefficient_traits::const_reference n, const Linear_Expression& e) {
31397  return e > n;
31398}
31399
31400/*! \relates Constraint */
31401inline Constraint
31402operator<(const Linear_Expression& e, Coefficient_traits::const_reference n) {
31403  return n > e;
31404}
31405
31406inline const Constraint&
31407Constraint::zero_dim_false() {
31408  PPL_ASSERT(zero_dim_false_p != 0);
31409  return *zero_dim_false_p;
31410}
31411
31412inline const Constraint&
31413Constraint::zero_dim_positivity() {
31414  PPL_ASSERT(zero_dim_positivity_p != 0);
31415  return *zero_dim_positivity_p;
31416}
31417
31418inline const Constraint&
31419Constraint::epsilon_geq_zero() {
31420  PPL_ASSERT(epsilon_geq_zero_p != 0);
31421  return *epsilon_geq_zero_p;
31422}
31423
31424inline const Constraint&
31425Constraint::epsilon_leq_one() {
31426  PPL_ASSERT(epsilon_leq_one_p != 0);
31427  return *epsilon_leq_one_p;
31428}
31429
31430inline void
31431Constraint::m_swap(Constraint& y) {
31432  using std::swap;
31433  swap(expr, y.expr);
31434  swap(kind_, y.kind_);
31435  swap(topology_, y.topology_);
31436}
31437
31438inline Coefficient_traits::const_reference
31439Constraint::epsilon_coefficient() const {
31440  PPL_ASSERT(is_not_necessarily_closed());
31441  return expr.coefficient(Variable(expr.space_dimension() - 1));
31442}
31443
31444inline void
31445Constraint::set_epsilon_coefficient(Coefficient_traits::const_reference n) {
31446  PPL_ASSERT(is_not_necessarily_closed());
31447  expr.set_coefficient(Variable(expr.space_dimension() - 1), n);
31448}
31449
31450/*! \relates Constraint */
31451inline void
31452swap(Constraint& x, Constraint& y) {
31453  x.m_swap(y);
31454}
31455
31456} // namespace Parma_Polyhedra_Library
31457
31458/* Automatically generated from PPL source file ../src/Constraint_defs.hh line 835. */
31459
31460/* Automatically generated from PPL source file ../src/Generator_defs.hh line 1. */
31461/* Generator class declaration.
31462*/
31463
31464
31465/* Automatically generated from PPL source file ../src/Generator_System_types.hh line 1. */
31466
31467
31468namespace Parma_Polyhedra_Library {
31469
31470class Generator_System;
31471class Generator_System_const_iterator;
31472
31473} // namespace Parma_Polyhedra_Library
31474
31475/* Automatically generated from PPL source file ../src/Grid_Generator_System_types.hh line 1. */
31476
31477
31478namespace Parma_Polyhedra_Library {
31479
31480class Grid_Generator_System;
31481
31482}
31483
31484/* Automatically generated from PPL source file ../src/Generator_defs.hh line 38. */
31485
31486/* Automatically generated from PPL source file ../src/distances_defs.hh line 1. */
31487/* Class declarations for several distances.
31488*/
31489
31490
31491/* Automatically generated from PPL source file ../src/distances_types.hh line 1. */
31492
31493
31494namespace Parma_Polyhedra_Library {
31495
31496template <typename Temp>
31497struct Rectilinear_Distance_Specialization;
31498
31499template <typename Temp>
31500struct Euclidean_Distance_Specialization;
31501
31502template <typename Temp>
31503struct L_Infinity_Distance_Specialization;
31504
31505} // namespace Parma_Polyhedra_Library
31506
31507/* Automatically generated from PPL source file ../src/distances_defs.hh line 29. */
31508
31509template <typename Temp>
31510struct Parma_Polyhedra_Library::Rectilinear_Distance_Specialization {
31511  static void combine(Temp& running, const Temp& current, Rounding_Dir dir);
31512
31513  static void finalize(Temp&, Rounding_Dir);
31514};
31515
31516template <typename Temp>
31517struct Parma_Polyhedra_Library::Euclidean_Distance_Specialization {
31518  static void combine(Temp& running, Temp& current, Rounding_Dir dir);
31519
31520  static void finalize(Temp& running, Rounding_Dir dir);
31521};
31522
31523
31524template <typename Temp>
31525struct Parma_Polyhedra_Library::L_Infinity_Distance_Specialization {
31526  static void combine(Temp& running, const Temp& current, Rounding_Dir);
31527
31528  static void finalize(Temp&, Rounding_Dir);
31529};
31530
31531/* Automatically generated from PPL source file ../src/distances_inlines.hh line 1. */
31532/* Inline functions implementing distances.
31533*/
31534
31535
31536/* Automatically generated from PPL source file ../src/distances_inlines.hh line 28. */
31537
31538namespace Parma_Polyhedra_Library {
31539
31540// A struct to work around the lack of partial specialization
31541// of function templates in C++.
31542template <typename To, typename From>
31543struct maybe_assign_struct {
31544  static inline Result
31545  function(const To*& top, To& tmp, const From& from, Rounding_Dir dir) {
31546    // When `To' and `From' are different types, we make the conversion
31547    // and use `tmp'.
31548    top = &tmp;
31549    return assign_r(tmp, from, dir);
31550  }
31551};
31552
31553template <typename Type>
31554struct maybe_assign_struct<Type, Type> {
31555  static inline Result
31556  function(const Type*& top, Type&, const Type& from, Rounding_Dir) {
31557    // When the types are the same, conversion is unnecessary.
31558    top = &from;
31559    return V_EQ;
31560  }
31561};
31562
31563#ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
31564/*! \brief
31565  Assigns to \p top a pointer to a location that holds the
31566  conversion, according to \p dir, of \p from to type \p To.  When
31567  necessary, and only when necessary, the variable \p tmp is used to
31568  hold the result of conversion.
31569*/
31570#endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
31571template <typename To, typename From>
31572inline Result
31573maybe_assign(const To*& top, To& tmp, const From& from, Rounding_Dir dir) {
31574  return maybe_assign_struct<To, From>::function(top, tmp, from, dir);
31575}
31576
31577template <typename Temp>
31578inline void
31579Rectilinear_Distance_Specialization<Temp>::combine(Temp& running,
31580                                                   const Temp& current,
31581                                                   Rounding_Dir dir) {
31582  add_assign_r(running, running, current, dir);
31583}
31584
31585template <typename Temp>
31586inline void
31587Rectilinear_Distance_Specialization<Temp>::finalize(Temp&, Rounding_Dir) {
31588}
31589
31590template <typename Temp>
31591inline void
31592Euclidean_Distance_Specialization<Temp>::combine(Temp& running,
31593                                                 Temp& current,
31594                                                 Rounding_Dir dir) {
31595  mul_assign_r(current, current, current, dir);
31596  add_assign_r(running, running, current, dir);
31597}
31598
31599template <typename Temp>
31600inline void
31601Euclidean_Distance_Specialization<Temp>::finalize(Temp& running,
31602                                                  Rounding_Dir dir) {
31603  sqrt_assign_r(running, running, dir);
31604}
31605
31606template <typename Temp>
31607inline void
31608L_Infinity_Distance_Specialization<Temp>::combine(Temp& running,
31609                                                  const Temp& current,
31610                                                  Rounding_Dir) {
31611  if (current > running) {
31612    running = current;
31613  }
31614}
31615
31616template <typename Temp>
31617inline void
31618L_Infinity_Distance_Specialization<Temp>::finalize(Temp&, Rounding_Dir) {
31619}
31620
31621} // namespace Parma_Polyhedra_Library
31622
31623/* Automatically generated from PPL source file ../src/distances_defs.hh line 53. */
31624
31625/* Automatically generated from PPL source file ../src/Expression_Hide_Inhomo_defs.hh line 1. */
31626/* Expression_Hide_Inhomo class declaration.
31627*/
31628
31629
31630/* Automatically generated from PPL source file ../src/Expression_Hide_Inhomo_defs.hh line 28. */
31631
31632/* Automatically generated from PPL source file ../src/Expression_Hide_Inhomo_defs.hh line 32. */
31633
31634#ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
31635/*! \brief
31636  An adapter for Linear_Expression that hides the inhomogeneous term.
31637
31638  The methods of this class always pretend that the value of the
31639  inhomogeneous term is zero.
31640*/
31641#endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
31642template <typename T>
31643class Parma_Polyhedra_Library::Expression_Hide_Inhomo
31644  : public Expression_Adapter<T> {
31645  typedef Expression_Adapter<T> base_type;
31646public:
31647  //! The type of this object.
31648  typedef Expression_Hide_Inhomo<T> const_reference;
31649  //! The type obtained by one-level unwrapping.
31650  typedef typename base_type::inner_type inner_type;
31651  //! The raw, completely unwrapped type.
31652  typedef typename base_type::raw_type raw_type;
31653
31654  //! Constructor.
31655  explicit Expression_Hide_Inhomo(const raw_type& expr);
31656
31657public:
31658  //! The type of const iterators on coefficients.
31659  typedef typename base_type::const_iterator const_iterator;
31660
31661  //! Returns the constant zero.
31662  Coefficient_traits::const_reference inhomogeneous_term() const;
31663
31664  //! Returns <CODE>true</CODE> if and only if \p *this is zero.
31665  bool is_zero() const;
31666
31667  /*! \brief Returns \p true if \p *this is equal to \p y.
31668
31669    Note that <CODE>(*this == y)</CODE> has a completely different meaning.
31670  */
31671  template <typename Expression>
31672  bool is_equal_to(const Expression& y) const;
31673
31674  //! Returns the i-th coefficient.
31675  Coefficient_traits::const_reference get(dimension_type i) const;
31676
31677  //! Returns the coefficient of v.
31678  Coefficient_traits::const_reference get(Variable v) const;
31679
31680  /*! \brief
31681    Returns <CODE>true</CODE> if the coefficient of each variable in
31682    \p vars is zero.
31683  */
31684  bool all_zeroes(const Variables_Set& vars) const;
31685
31686  /*! \brief
31687    Returns <CODE>true</CODE> if (*this)[i] is zero,
31688    for each i in [start, end).
31689  */
31690  bool all_zeroes(dimension_type start, dimension_type end) const;
31691
31692  /*! \brief
31693    Returns the number of zero coefficient in [start, end).
31694  */
31695  dimension_type num_zeroes(dimension_type start, dimension_type end) const;
31696
31697  /*! \brief
31698    Returns the gcd of the nonzero coefficients in [start,end). If all the
31699    coefficients in this range are zero, returns zero.
31700  */
31701  Coefficient gcd(dimension_type start, dimension_type end) const;
31702
31703  //! Returns the index of the last nonzero element, or zero if there are no
31704  //! nonzero elements.
31705  dimension_type last_nonzero() const;
31706
31707  //! Returns the index of the last nonzero element in [first,last), or last
31708  //! if there are no nonzero elements.
31709  dimension_type last_nonzero(dimension_type first, dimension_type last) const;
31710
31711  //! Returns the index of the first nonzero element, or \p last if there
31712  //! are no nonzero elements, considering only elements in [first,last).
31713  dimension_type first_nonzero(dimension_type first, dimension_type last) const;
31714
31715  /*! \brief
31716    Returns <CODE>true</CODE> if all coefficients in [start,end),
31717    except those corresponding to variables in \p vars, are zero.
31718  */
31719  bool all_zeroes_except(const Variables_Set& vars,
31720                         dimension_type start, dimension_type end) const;
31721
31722  //! Removes from set \p x all the indexes of nonzero elements in \p *this.
31723  void has_a_free_dimension_helper(std::set<dimension_type>& x) const;
31724
31725  //! Returns \c true if <CODE>(*this)[i]</CODE> is equal to <CODE>y[i]</CODE>,
31726  //! for each i in [start,end).
31727  template <typename Expression>
31728  bool is_equal_to(const Expression& y,
31729                   dimension_type start, dimension_type end) const;
31730
31731  //! Returns \c true if <CODE>(*this)[i]*c1</CODE> is equal to
31732  //! <CODE>y[i]*c2</CODE>, for each i in [start,end).
31733  template <typename Expression>
31734  bool is_equal_to(const Expression& y,
31735                   Coefficient_traits::const_reference c1,
31736                   Coefficient_traits::const_reference c2,
31737                   dimension_type start, dimension_type end) const;
31738
31739  //! Sets \p r to a copy of the row as adapted by \p *this.
31740  void get_row(Dense_Row& r) const;
31741
31742  //! Sets \p r to a copy of the row as adapted by \p *this.
31743  void get_row(Sparse_Row& r) const;
31744};
31745
31746/* Automatically generated from PPL source file ../src/Expression_Hide_Inhomo_inlines.hh line 1. */
31747/* Expression_Hide_Inhomo class implementation: inline functions.
31748*/
31749
31750
31751/* Automatically generated from PPL source file ../src/Expression_Hide_Inhomo_inlines.hh line 28. */
31752
31753namespace Parma_Polyhedra_Library {
31754
31755template <typename T>
31756Expression_Hide_Inhomo<T>::Expression_Hide_Inhomo(const raw_type& expr)
31757  : base_type(expr) {
31758}
31759
31760template <typename T>
31761inline Coefficient_traits::const_reference
31762Expression_Hide_Inhomo<T>::inhomogeneous_term() const {
31763  // Pretend it is zero.
31764  return Coefficient_zero();
31765}
31766
31767template <typename T>
31768inline bool
31769Expression_Hide_Inhomo<T>::is_zero() const {
31770  // Don't check the inhomogeneous_term (i.e., pretend it is zero).
31771  return this->inner().all_homogeneous_terms_are_zero();
31772}
31773
31774template <typename T>
31775template <typename Expression>
31776inline bool
31777Expression_Hide_Inhomo<T>
31778::is_equal_to(const Expression& y) const {
31779  const dimension_type x_dim = this->space_dimension();
31780  const dimension_type y_dim = y.space_dimension();
31781  if (x_dim != y_dim) {
31782    return false;
31783  }
31784  if (y.inhomogeneous_term() != 0) {
31785    return false;
31786  }
31787  // Note that the inhomogeneous term is not compared.
31788  return this->inner().is_equal_to(y, 1, x_dim + 1);
31789}
31790
31791template <typename T>
31792inline Coefficient_traits::const_reference
31793Expression_Hide_Inhomo<T>::get(dimension_type i) const {
31794  if (i == 0) {
31795    return Coefficient_zero();
31796  }
31797  else {
31798    return this->inner().get(i);
31799  }
31800}
31801
31802template <typename T>
31803inline Coefficient_traits::const_reference
31804Expression_Hide_Inhomo<T>::get(Variable v) const {
31805  return this->inner().get(v);
31806}
31807
31808template <typename T>
31809inline bool
31810Expression_Hide_Inhomo<T>
31811::all_zeroes(const Variables_Set& vars) const {
31812  return this->inner().all_zeroes(vars);
31813}
31814
31815template <typename T>
31816inline bool
31817Expression_Hide_Inhomo<T>::all_zeroes(dimension_type start,
31818                                      dimension_type end) const {
31819  if (start == end) {
31820    return true;
31821  }
31822  if (start == 0) {
31823    ++start;
31824  }
31825  return this->inner().all_zeroes(start, end);
31826}
31827
31828template <typename T>
31829inline dimension_type
31830Expression_Hide_Inhomo<T>::num_zeroes(dimension_type start,
31831                                      dimension_type end) const {
31832  if (start == end) {
31833    return 0;
31834  }
31835  dimension_type nz = 0;
31836  if (start == 0) {
31837    ++start;
31838    ++nz;
31839  }
31840  nz += this->inner().num_zeroes(start, end);
31841  return nz;
31842}
31843
31844template <typename T>
31845inline Coefficient
31846Expression_Hide_Inhomo<T>::gcd(dimension_type start,
31847                               dimension_type end) const {
31848  if (start == end) {
31849    return Coefficient_zero();
31850  }
31851  if (start == 0) {
31852    ++start;
31853  }
31854  return this->inner().gcd(start, end);
31855}
31856
31857template <typename T>
31858inline dimension_type
31859Expression_Hide_Inhomo<T>::last_nonzero() const {
31860  return this->inner().last_nonzero();
31861}
31862
31863template <typename T>
31864inline dimension_type
31865Expression_Hide_Inhomo<T>::last_nonzero(dimension_type first,
31866                                        dimension_type last) const {
31867  if (first == last) {
31868    return last;
31869  }
31870  if (first == 0) {
31871    ++first;
31872  }
31873  return this->inner().last_nonzero(first, last);
31874}
31875
31876template <typename T>
31877inline dimension_type
31878Expression_Hide_Inhomo<T>::first_nonzero(dimension_type first,
31879                                         dimension_type last) const {
31880  if (first == last) {
31881    return last;
31882  }
31883  if (first == 0) {
31884    ++first;
31885  }
31886  return this->inner().first_nonzero(first, last);
31887}
31888
31889template <typename T>
31890inline bool
31891Expression_Hide_Inhomo<T>
31892::all_zeroes_except(const Variables_Set& vars,
31893                    dimension_type start, dimension_type end) const {
31894  if (start == end) {
31895    return true;
31896  }
31897  if (start == 0) {
31898    ++start;
31899  }
31900  return this->inner().all_zeroes_except(vars, start, end);
31901}
31902
31903template <typename T>
31904inline void
31905Expression_Hide_Inhomo<T>
31906::has_a_free_dimension_helper(std::set<dimension_type>& y) const {
31907  bool had_0 = (y.count(0) == 1);
31908  this->inner().has_a_free_dimension_helper(y);
31909  if (had_0) {
31910    y.insert(0);
31911  }
31912}
31913
31914template <typename T>
31915template <typename Expression>
31916inline bool
31917Expression_Hide_Inhomo<T>
31918::is_equal_to(const Expression& y,
31919              dimension_type start, dimension_type end) const {
31920  if (start == end) {
31921    return true;
31922  }
31923  if (start == 0) {
31924    ++start;
31925  }
31926  return this->inner().is_equal_to(y, start, end);
31927}
31928
31929template <typename T>
31930template <typename Expression>
31931inline bool
31932Expression_Hide_Inhomo<T>
31933::is_equal_to(const Expression& y,
31934              Coefficient_traits::const_reference c1,
31935              Coefficient_traits::const_reference c2,
31936              dimension_type start, dimension_type end) const {
31937  if (start == end) {
31938    return true;
31939  }
31940  if (start == 0) {
31941    ++start;
31942  }
31943  return this->inner().is_equal_to(y, c1, c2, start, end);
31944}
31945
31946template <typename T>
31947inline void
31948Expression_Hide_Inhomo<T>::get_row(Dense_Row& r) const {
31949  this->inner().get_row(r);
31950  r.reset(0);
31951}
31952
31953template <typename T>
31954inline void
31955Expression_Hide_Inhomo<T>::get_row(Sparse_Row& r) const {
31956  this->inner().get_row(r);
31957  r.reset(0);
31958}
31959
31960} // namespace Parma_Polyhedra_Library
31961
31962/* Automatically generated from PPL source file ../src/Expression_Hide_Inhomo_defs.hh line 146. */
31963
31964/* Automatically generated from PPL source file ../src/Generator_defs.hh line 46. */
31965
31966#include <iosfwd>
31967
31968namespace Parma_Polyhedra_Library {
31969
31970// Put them in the namespace here to declare them friend later.
31971
31972#ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
31973//! The basic comparison function.
31974/*! \relates Generator
31975  \return
31976  The returned absolute value can be \f$0\f$, \f$1\f$ or \f$2\f$.
31977
31978  \param x
31979  A row of coefficients;
31980
31981  \param y
31982  Another row.
31983
31984  Compares \p x and \p y, where \p x and \p y may be of different size,
31985  in which case the "missing" coefficients are assumed to be zero.
31986  The comparison is such that:
31987  -# equalities are smaller than inequalities;
31988  -# lines are smaller than points and rays;
31989  -# the ordering is lexicographic;
31990  -# the positions compared are, in decreasing order of significance,
31991     1, 2, ..., \p size(), 0;
31992  -# the result is negative, zero, or positive if x is smaller than,
31993     equal to, or greater than y, respectively;
31994  -# when \p x and \p y are different, the absolute value of the
31995     result is 1 if the difference is due to the coefficient in
31996     position 0; it is 2 otherwise.
31997
31998  When \p x and \p y represent the hyper-planes associated
31999  to two equality or inequality constraints, the coefficient
32000  at 0 is the known term.
32001  In this case, the return value can be characterized as follows:
32002  - -2, if \p x is smaller than \p y and they are \e not parallel;
32003  - -1, if \p x is smaller than \p y and they \e are parallel;
32004  -  0, if \p x and y are equal;
32005  - +1, if \p y is smaller than \p x and they \e are parallel;
32006  - +2, if \p y is smaller than \p x and they are \e not parallel.
32007*/
32008#endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
32009int compare(const Generator& x, const Generator& y);
32010
32011namespace IO_Operators {
32012
32013//! Output operator.
32014/*! \relates Parma_Polyhedra_Library::Generator */
32015std::ostream& operator<<(std::ostream& s, const Generator& g);
32016
32017} // namespace IO_Operators
32018
32019//! Swaps \p x with \p y.
32020/*! \relates Generator */
32021void swap(Generator& x, Generator& y);
32022
32023} // namespace Parma_Polyhedra_Library
32024
32025
32026//! A line, ray, point or closure point.
32027/*! \ingroup PPL_CXX_interface
32028  An object of the class Generator is one of the following:
32029
32030  - a line \f$\vect{l} = (a_0, \ldots, a_{n-1})^\transpose\f$;
32031
32032  - a ray \f$\vect{r} = (a_0, \ldots, a_{n-1})^\transpose\f$;
32033
32034  - a point
32035    \f$\vect{p} = (\frac{a_0}{d}, \ldots, \frac{a_{n-1}}{d})^\transpose\f$;
32036
32037  - a closure point
32038    \f$\vect{c} = (\frac{a_0}{d}, \ldots, \frac{a_{n-1}}{d})^\transpose\f$;
32039
32040  where \f$n\f$ is the dimension of the space
32041  and, for points and closure points, \f$d > 0\f$ is the divisor.
32042
32043  \par A note on terminology.
32044  As observed in Section \ref representation, there are cases when,
32045  in order to represent a polyhedron \f$\cP\f$ using the generator system
32046  \f$\cG = (L, R, P, C)\f$, we need to include in the finite set
32047  \f$P\f$ even points of \f$\cP\f$ that are <EM>not</EM> vertices
32048  of \f$\cP\f$.
32049  This situation is even more frequent when working with NNC polyhedra
32050  and it is the reason why we prefer to use the word `point'
32051  where other libraries use the word `vertex'.
32052
32053  \par How to build a generator.
32054  Each type of generator is built by applying the corresponding
32055  function (<CODE>line</CODE>, <CODE>ray</CODE>, <CODE>point</CODE>
32056  or <CODE>closure_point</CODE>) to a linear expression,
32057  representing a direction in the space;
32058  the space dimension of the generator is defined as the space dimension
32059  of the corresponding linear expression.
32060  Linear expressions used to define a generator should be homogeneous
32061  (any constant term will be simply ignored).
32062  When defining points and closure points, an optional Coefficient argument
32063  can be used as a common <EM>divisor</EM> for all the coefficients
32064  occurring in the provided linear expression;
32065  the default value for this argument is 1.
32066
32067  \par
32068  In all the following examples it is assumed that variables
32069  <CODE>x</CODE>, <CODE>y</CODE> and <CODE>z</CODE>
32070  are defined as follows:
32071  \code
32072  Variable x(0);
32073  Variable y(1);
32074  Variable z(2);
32075  \endcode
32076
32077  \par Example 1
32078  The following code builds a line with direction \f$x-y-z\f$
32079  and having space dimension \f$3\f$:
32080  \code
32081  Generator l = line(x - y - z);
32082  \endcode
32083  As mentioned above, the constant term of the linear expression
32084  is not relevant. Thus, the following code has the same effect:
32085  \code
32086  Generator l = line(x - y - z + 15);
32087  \endcode
32088  By definition, the origin of the space is not a line, so that
32089  the following code throws an exception:
32090  \code
32091  Generator l = line(0*x);
32092  \endcode
32093
32094  \par Example 2
32095  The following code builds a ray with the same direction as the
32096  line in Example 1:
32097  \code
32098  Generator r = ray(x - y - z);
32099  \endcode
32100  As is the case for lines, when specifying a ray the constant term
32101  of the linear expression is not relevant; also, an exception is thrown
32102  when trying to build a ray from the origin of the space.
32103
32104  \par Example 3
32105  The following code builds the point
32106  \f$\vect{p} = (1, 0, 2)^\transpose \in \Rset^3\f$:
32107  \code
32108  Generator p = point(1*x + 0*y + 2*z);
32109  \endcode
32110  The same effect can be obtained by using the following code:
32111  \code
32112  Generator p = point(x + 2*z);
32113  \endcode
32114  Similarly, the origin \f$\vect{0} \in \Rset^3\f$ can be defined
32115  using either one of the following lines of code:
32116  \code
32117  Generator origin3 = point(0*x + 0*y + 0*z);
32118  Generator origin3_alt = point(0*z);
32119  \endcode
32120  Note however that the following code would have defined
32121  a different point, namely \f$\vect{0} \in \Rset^2\f$:
32122  \code
32123  Generator origin2 = point(0*y);
32124  \endcode
32125  The following two lines of code both define the only point
32126  having space dimension zero, namely \f$\vect{0} \in \Rset^0\f$.
32127  In the second case we exploit the fact that the first argument
32128  of the function <CODE>point</CODE> is optional.
32129  \code
32130  Generator origin0 = Generator::zero_dim_point();
32131  Generator origin0_alt = point();
32132  \endcode
32133
32134  \par Example 4
32135  The point \f$\vect{p}\f$ specified in Example 3 above
32136  can also be obtained with the following code,
32137  where we provide a non-default value for the second argument
32138  of the function <CODE>point</CODE> (the divisor):
32139  \code
32140  Generator p = point(2*x + 0*y + 4*z, 2);
32141  \endcode
32142  Obviously, the divisor can be usefully exploited to specify
32143  points having some non-integer (but rational) coordinates.
32144  For instance, the point
32145  \f$\vect{q} = (-1.5, 3.2, 2.1)^\transpose \in \Rset^3\f$
32146  can be specified by the following code:
32147  \code
32148  Generator q = point(-15*x + 32*y + 21*z, 10);
32149  \endcode
32150  If a zero divisor is provided, an exception is thrown.
32151
32152  \par Example 5
32153  Closure points are specified in the same way we defined points,
32154  but invoking their specific constructor function.
32155  For instance, the closure point
32156  \f$\vect{c} = (1, 0, 2)^\transpose \in \Rset^3\f$ is defined by
32157  \code
32158  Generator c = closure_point(1*x + 0*y + 2*z);
32159  \endcode
32160  For the particular case of the (only) closure point
32161  having space dimension zero, we can use any of the following:
32162  \code
32163  Generator closure_origin0 = Generator::zero_dim_closure_point();
32164  Generator closure_origin0_alt = closure_point();
32165  \endcode
32166
32167  \par How to inspect a generator
32168  Several methods are provided to examine a generator and extract
32169  all the encoded information: its space dimension, its type and
32170  the value of its integer coefficients.
32171
32172  \par Example 6
32173  The following code shows how it is possible to access each single
32174  coefficient of a generator.
32175  If <CODE>g1</CODE> is a point having coordinates
32176  \f$(a_0, \ldots, a_{n-1})^\transpose\f$,
32177  we construct the closure point <CODE>g2</CODE> having coordinates
32178  \f$(a_0, 2 a_1, \ldots, (i+1)a_i, \ldots, n a_{n-1})^\transpose\f$.
32179  \code
32180  if (g1.is_point()) {
32181    cout << "Point g1: " << g1 << endl;
32182    Linear_Expression e;
32183    for (dimension_type i = g1.space_dimension(); i-- > 0; )
32184      e += (i + 1) * g1.coefficient(Variable(i)) * Variable(i);
32185    Generator g2 = closure_point(e, g1.divisor());
32186    cout << "Closure point g2: " << g2 << endl;
32187  }
32188  else
32189    cout << "Generator g1 is not a point." << endl;
32190  \endcode
32191  Therefore, for the point
32192  \code
32193  Generator g1 = point(2*x - y + 3*z, 2);
32194  \endcode
32195  we would obtain the following output:
32196  \code
32197  Point g1: p((2*A - B + 3*C)/2)
32198  Closure point g2: cp((2*A - 2*B + 9*C)/2)
32199  \endcode
32200  When working with (closure) points, be careful not to confuse
32201  the notion of <EM>coefficient</EM> with the notion of <EM>coordinate</EM>:
32202  these are equivalent only when the divisor of the (closure) point is 1.
32203*/
32204class Parma_Polyhedra_Library::Generator {
32205public:
32206
32207  //! The representation used for new Generators.
32208  /*!
32209    \note The copy constructor and the copy constructor with specified size
32210          use the representation of the original object, so that it is
32211          indistinguishable from the original object.
32212  */
32213  static const Representation default_representation = SPARSE;
32214
32215  //! Returns the line of direction \p e.
32216  /*!
32217    \exception std::invalid_argument
32218    Thrown if the homogeneous part of \p e represents the origin of
32219    the vector space.
32220  */
32221  static Generator line(const Linear_Expression& e,
32222                        Representation r = default_representation);
32223
32224  //! Returns the ray of direction \p e.
32225  /*!
32226    \exception std::invalid_argument
32227    Thrown if the homogeneous part of \p e represents the origin of
32228    the vector space.
32229  */
32230  static Generator ray(const Linear_Expression& e,
32231                       Representation r = default_representation);
32232
32233  //! Returns the point at \p e / \p d.
32234  /*!
32235    Both \p e and \p d are optional arguments, with default values
32236    Linear_Expression::zero() and Coefficient_one(), respectively.
32237
32238    \exception std::invalid_argument
32239    Thrown if \p d is zero.
32240  */
32241  static Generator point(const Linear_Expression& e
32242                         = Linear_Expression::zero(),
32243                         Coefficient_traits::const_reference d
32244                         = Coefficient_one(),
32245                         Representation r = default_representation);
32246
32247  //! Returns the origin.
32248  static Generator point(Representation r);
32249
32250  //! Returns the point at \p e.
32251  static Generator point(const Linear_Expression& e,
32252                         Representation r);
32253
32254  //! Constructs the point at the origin.
32255  explicit Generator(Representation r = default_representation);
32256
32257  //! Returns the closure point at \p e / \p d.
32258  /*!
32259    Both \p e and \p d are optional arguments, with default values
32260    Linear_Expression::zero() and Coefficient_one(), respectively.
32261
32262    \exception std::invalid_argument
32263    Thrown if \p d is zero.
32264  */
32265  static Generator
32266  closure_point(const Linear_Expression& e = Linear_Expression::zero(),
32267                Coefficient_traits::const_reference d = Coefficient_one(),
32268                Representation r = default_representation);
32269
32270  //! Returns the closure point at the origin.
32271  static Generator
32272  closure_point(Representation r);
32273
32274  //! Returns the closure point at \p e.
32275  static Generator
32276  closure_point(const Linear_Expression& e, Representation r);
32277
32278  //! Ordinary copy constructor.
32279  //! The representation of the new Generator will be the same as g.
32280  Generator(const Generator& g);
32281
32282  //! Copy constructor with given representation.
32283  Generator(const Generator& g, Representation r);
32284
32285  //! Copy constructor with given space dimension.
32286  //! The representation of the new Generator will be the same as g.
32287  Generator(const Generator& g, dimension_type space_dim);
32288
32289  //! Copy constructor with given representation and space dimension.
32290  Generator(const Generator& g, dimension_type space_dim, Representation r);
32291
32292  //! Destructor.
32293  ~Generator();
32294
32295  //! Assignment operator.
32296  Generator& operator=(const Generator& g);
32297
32298  //! Returns the current representation of *this.
32299  Representation representation() const;
32300
32301  //! Converts *this to the specified representation.
32302  void set_representation(Representation r);
32303
32304  //! Returns the maximum space dimension a Generator can handle.
32305  static dimension_type max_space_dimension();
32306
32307  //! Returns the dimension of the vector space enclosing \p *this.
32308  dimension_type space_dimension() const;
32309
32310  //! Sets the dimension of the vector space enclosing \p *this to
32311  //! \p space_dim .
32312  void set_space_dimension(dimension_type space_dim);
32313
32314  //! Swaps the coefficients of the variables \p v1 and \p v2 .
32315  void swap_space_dimensions(Variable v1, Variable v2);
32316
32317  //! Removes all the specified dimensions from the generator.
32318  /*!
32319    The space dimension of the variable with the highest space
32320    dimension in \p vars must be at most the space dimension
32321    of \p this.
32322
32323    If all dimensions with nonzero coefficients are removed from a ray or a
32324    line, it is changed into a point and this method returns \p false .
32325    Otherwise, it returns \p true .
32326  */
32327  bool remove_space_dimensions(const Variables_Set& vars);
32328
32329  //! Permutes the space dimensions of the generator.
32330  /*!
32331    \param cycle
32332    A vector representing a cycle of the permutation according to which the
32333    space dimensions must be rearranged.
32334
32335    The \p cycle vector represents a cycle of a permutation of space
32336    dimensions.
32337    For example, the permutation
32338    \f$ \{ x_1 \mapsto x_2, x_2 \mapsto x_3, x_3 \mapsto x_1 \}\f$ can be
32339    represented by the vector containing \f$ x_1, x_2, x_3 \f$.
32340  */
32341  void permute_space_dimensions(const std::vector<Variable>& cycle);
32342
32343  //! Shift by \p n positions the coefficients of variables, starting from
32344  //! the coefficient of \p v. This increases the space dimension by \p n.
32345  void shift_space_dimensions(Variable v, dimension_type n);
32346
32347  //! The generator type.
32348  enum Type {
32349    /*! The generator is a line. */
32350    LINE,
32351    /*! The generator is a ray. */
32352    RAY,
32353    /*! The generator is a point. */
32354    POINT,
32355    /*! The generator is a closure point. */
32356    CLOSURE_POINT
32357  };
32358
32359  //! Returns the generator type of \p *this.
32360  Type type() const;
32361
32362  //! Returns <CODE>true</CODE> if and only if \p *this is a line.
32363  bool is_line() const;
32364
32365  //! Returns <CODE>true</CODE> if and only if \p *this is a ray.
32366  bool is_ray() const;
32367
32368#ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
32369  //! Returns <CODE>true</CODE> if and only if \p *this is a line or a ray.
32370#endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
32371  bool is_line_or_ray() const;
32372
32373  //! Returns <CODE>true</CODE> if and only if \p *this is a point.
32374  bool is_point() const;
32375
32376  //! Returns <CODE>true</CODE> if and only if \p *this is a closure point.
32377  bool is_closure_point() const;
32378
32379  //! Returns the coefficient of \p v in \p *this.
32380  /*!
32381    \exception std::invalid_argument
32382    Thrown if the index of \p v is greater than or equal to the
32383    space dimension of \p *this.
32384  */
32385  Coefficient_traits::const_reference coefficient(Variable v) const;
32386
32387  //! If \p *this is either a point or a closure point, returns its divisor.
32388  /*!
32389    \exception std::invalid_argument
32390    Thrown if \p *this is neither a point nor a closure point.
32391  */
32392  Coefficient_traits::const_reference divisor() const;
32393
32394  //! Initializes the class.
32395  static void initialize();
32396
32397  //! Finalizes the class.
32398  static void finalize();
32399
32400  //! Returns the origin of the zero-dimensional space \f$\Rset^0\f$.
32401  static const Generator& zero_dim_point();
32402
32403  /*! \brief
32404    Returns, as a closure point,
32405    the origin of the zero-dimensional space \f$\Rset^0\f$.
32406  */
32407  static const Generator& zero_dim_closure_point();
32408
32409  /*! \brief
32410    Returns a lower bound to the total size in bytes of the memory
32411    occupied by \p *this.
32412  */
32413  memory_size_type total_memory_in_bytes() const;
32414
32415  //! Returns the size in bytes of the memory managed by \p *this.
32416  memory_size_type external_memory_in_bytes() const;
32417
32418  /*! \brief
32419    Returns <CODE>true</CODE> if and only if \p *this and \p y
32420    are equivalent generators.
32421
32422    Generators having different space dimensions are not equivalent.
32423  */
32424  bool is_equivalent_to(const Generator& y) const;
32425
32426  //! Returns <CODE>true</CODE> if \p *this is identical to \p y.
32427  /*!
32428    This is faster than is_equivalent_to(), but it may return `false' even
32429    for equivalent generators.
32430  */
32431  bool is_equal_to(const Generator& y) const;
32432
32433  //! Checks if all the invariants are satisfied.
32434  bool OK() const;
32435
32436  PPL_OUTPUT_DECLARATIONS
32437
32438  /*! \brief
32439    Loads from \p s an ASCII representation (as produced by
32440    ascii_dump(std::ostream&) const) and sets \p *this accordingly.
32441    Returns <CODE>true</CODE> if successful, <CODE>false</CODE> otherwise.
32442  */
32443  bool ascii_load(std::istream& s);
32444
32445  //! Swaps \p *this with \p y.
32446  void m_swap(Generator& y);
32447
32448  //! The type of the (adapted) internal expression.
32449  typedef Expression_Hide_Last<Expression_Hide_Inhomo<Linear_Expression> >
32450  expr_type;
32451  //! Partial read access to the (adapted) internal expression.
32452  expr_type expression() const;
32453
32454private:
32455  //! The possible kinds of Generator objects.
32456  enum Kind {
32457    LINE_OR_EQUALITY = 0,
32458    RAY_OR_POINT_OR_INEQUALITY = 1
32459  };
32460
32461  //! The linear expression encoding \p *this.
32462  Linear_Expression expr;
32463
32464  //! The kind of \p *this.
32465  Kind kind_;
32466
32467  //! The topology of \p *this.
32468  Topology topology_;
32469
32470  /*! \brief
32471    Holds (between class initialization and finalization) a pointer to
32472    the origin of the zero-dimensional space \f$\Rset^0\f$.
32473  */
32474  static const Generator* zero_dim_point_p;
32475
32476  /*! \brief
32477    Holds (between class initialization and finalization) a pointer to
32478    the origin of the zero-dimensional space \f$\Rset^0\f$, as a closure point.
32479  */
32480  static const Generator* zero_dim_closure_point_p;
32481
32482  /*! \brief
32483    Builds a generator of type \p type and topology \p topology,
32484    stealing the coefficients from \p e.
32485
32486    If the topology is NNC, the last dimension of \p e is used as the epsilon
32487    coefficient.
32488  */
32489  Generator(Linear_Expression& e, Type type, Topology topology);
32490
32491  Generator(Linear_Expression& e, Kind kind, Topology topology);
32492
32493  Generator(dimension_type space_dim, Kind kind, Topology topology,
32494            Representation r = default_representation);
32495
32496  /*! \brief
32497    Returns <CODE>true</CODE> if and only if \p *this row
32498    represents a line or an equality.
32499  */
32500  bool is_line_or_equality() const;
32501
32502  /*! \brief
32503    Returns <CODE>true</CODE> if and only if \p *this row
32504    represents a ray, a point or an inequality.
32505  */
32506  bool is_ray_or_point_or_inequality() const;
32507
32508  //! Sets to \p LINE_OR_EQUALITY the kind of \p *this row.
32509  void set_is_line_or_equality();
32510
32511  //! Sets to \p RAY_OR_POINT_OR_INEQUALITY the kind of \p *this row.
32512  void set_is_ray_or_point_or_inequality();
32513
32514  //! \name Flags inspection methods
32515  //@{
32516  //! Returns the topological kind of \p *this.
32517  Topology topology() const;
32518
32519  /*! \brief
32520    Returns <CODE>true</CODE> if and only if the topology
32521    of \p *this row is not necessarily closed.
32522  */
32523  bool is_not_necessarily_closed() const;
32524
32525  /*! \brief
32526    Returns <CODE>true</CODE> if and only if the topology
32527    of \p *this row is necessarily closed.
32528  */
32529  bool is_necessarily_closed() const;
32530  //@} // Flags inspection methods
32531
32532  //! \name Flags coercion methods
32533  //@{
32534
32535  //! Sets to \p x the topological kind of \p *this row.
32536  void set_topology(Topology x);
32537
32538  //! Sets to \p NECESSARILY_CLOSED the topological kind of \p *this row.
32539  void set_necessarily_closed();
32540
32541  //! Sets to \p NOT_NECESSARILY_CLOSED the topological kind of \p *this row.
32542  void set_not_necessarily_closed();
32543  //@} // Flags coercion methods
32544
32545  //! Marks the epsilon dimension as a standard dimension.
32546  /*!
32547    The row topology is changed to <CODE>NECESSARILY_CLOSED</CODE>, and
32548    the number of space dimensions is increased by 1.
32549  */
32550  void mark_as_necessarily_closed();
32551
32552  //! Marks the last dimension as the epsilon dimension.
32553  /*!
32554    The row topology is changed to <CODE>NOT_NECESSARILY_CLOSED</CODE>, and
32555    the number of space dimensions is decreased by 1.
32556  */
32557  void mark_as_not_necessarily_closed();
32558
32559  //! Linearly combines \p *this with \p y so that i-th coefficient is 0.
32560  /*!
32561    \param y
32562    The Generator that will be combined with \p *this object;
32563
32564    \param i
32565    The index of the coefficient that has to become \f$0\f$.
32566
32567    Computes a linear combination of \p *this and \p y having
32568    the i-th coefficient equal to \f$0\f$. Then it assigns
32569    the resulting Generator to \p *this and normalizes it.
32570  */
32571  void linear_combine(const Generator& y, dimension_type i);
32572
32573  //! Sets the dimension of the vector space enclosing \p *this to
32574  //! \p space_dim .
32575  //! Sets the space dimension of the rows in the system to \p space_dim .
32576  /*!
32577    This method is for internal use, it does *not* assert OK() at the end,
32578    so it can be used for invalid objects.
32579  */
32580  void set_space_dimension_no_ok(dimension_type space_dim);
32581
32582  /*! \brief
32583    Throw a <CODE>std::invalid_argument</CODE> exception
32584    containing the appropriate error message.
32585  */
32586  void
32587  throw_dimension_incompatible(const char* method,
32588                               const char* v_name,
32589                               Variable v) const;
32590
32591  /*! \brief
32592    Throw a <CODE>std::invalid_argument</CODE> exception
32593    containing the appropriate error message.
32594  */
32595  void
32596  throw_invalid_argument(const char* method, const char* reason) const;
32597
32598  //! Returns <CODE>true</CODE> if and only if \p *this is not a line.
32599  bool is_ray_or_point() const;
32600
32601  //! Sets the Generator kind to <CODE>LINE_OR_EQUALITY</CODE>.
32602  void set_is_line();
32603
32604  //! Sets the Generator kind to <CODE>RAY_OR_POINT_OR_INEQUALITY</CODE>.
32605  void set_is_ray_or_point();
32606
32607  /*! \brief
32608    Returns <CODE>true</CODE> if and only if the closure point
32609    \p *this has the same \e coordinates of the point \p p.
32610
32611    It is \e assumed that \p *this is a closure point, \p p is a point
32612    and both topologies and space dimensions agree.
32613  */
32614  bool is_matching_closure_point(const Generator& p) const;
32615
32616  //! Returns the epsilon coefficient. The generator must be NNC.
32617  Coefficient_traits::const_reference epsilon_coefficient() const;
32618
32619  //! Sets the epsilon coefficient to \p n. The generator must be NNC.
32620  void set_epsilon_coefficient(Coefficient_traits::const_reference n);
32621
32622  /*! \brief
32623    Normalizes the sign of the coefficients so that the first non-zero
32624    (homogeneous) coefficient of a line-or-equality is positive.
32625  */
32626  void sign_normalize();
32627
32628  /*! \brief
32629    Strong normalization: ensures that different Generator objects
32630    represent different hyperplanes or hyperspaces.
32631
32632    Applies both Generator::normalize() and Generator::sign_normalize().
32633  */
32634  void strong_normalize();
32635
32636  /*! \brief
32637    Returns <CODE>true</CODE> if and only if the coefficients are
32638    strongly normalized.
32639  */
32640  bool check_strong_normalized() const;
32641
32642  /*! \brief
32643    A print function, with fancy, more human-friendly output.
32644
32645    This is used by operator<<().
32646  */
32647  void fancy_print(std::ostream& s) const;
32648
32649  friend class Expression_Adapter<Generator>;
32650  friend class Linear_System<Generator>;
32651  friend class Parma_Polyhedra_Library::Scalar_Products;
32652  friend class Parma_Polyhedra_Library::Topology_Adjusted_Scalar_Product_Sign;
32653  friend class Parma_Polyhedra_Library::Topology_Adjusted_Scalar_Product_Assign;
32654  friend class Parma_Polyhedra_Library::Generator_System;
32655  friend class Parma_Polyhedra_Library::Generator_System_const_iterator;
32656  // FIXME: the following friend declaration should be avoided.
32657  friend class Parma_Polyhedra_Library::Polyhedron;
32658  // This is for access to Linear_Expression in `insert'.
32659  friend class Parma_Polyhedra_Library::Grid_Generator_System;
32660  friend class Parma_Polyhedra_Library::MIP_Problem;
32661  friend class Parma_Polyhedra_Library::Grid;
32662
32663  friend std::ostream&
32664  Parma_Polyhedra_Library::IO_Operators::operator<<(std::ostream& s,
32665                                                    const Generator& g);
32666
32667  friend int
32668  compare(const Generator& x, const Generator& y);
32669};
32670
32671
32672namespace Parma_Polyhedra_Library {
32673
32674//! Shorthand for Generator::line(const Linear_Expression& e, Representation r).
32675/*! \relates Generator */
32676Generator line(const Linear_Expression& e,
32677               Representation r = Generator::default_representation);
32678
32679//! Shorthand for Generator::ray(const Linear_Expression& e, Representation r).
32680/*! \relates Generator */
32681Generator ray(const Linear_Expression& e,
32682              Representation r = Generator::default_representation);
32683
32684/*! \brief
32685  Shorthand for
32686  Generator::point(const Linear_Expression& e, Coefficient_traits::const_reference d, Representation r).
32687
32688  \relates Generator
32689*/
32690Generator
32691point(const Linear_Expression& e = Linear_Expression::zero(),
32692      Coefficient_traits::const_reference d = Coefficient_one(),
32693      Representation r = Generator::default_representation);
32694
32695//! Shorthand for Generator::point(Representation r).
32696/*! \relates Generator */
32697Generator
32698point(Representation r);
32699
32700/*! \brief
32701  Shorthand for
32702  Generator::point(const Linear_Expression& e, Representation r).
32703
32704  \relates Generator
32705*/
32706Generator
32707point(const Linear_Expression& e, Representation r);
32708
32709/*! \brief
32710  Shorthand for
32711  Generator::closure_point(const Linear_Expression& e, Coefficient_traits::const_reference d, Representation r).
32712
32713  \relates Generator
32714*/
32715Generator
32716closure_point(const Linear_Expression& e = Linear_Expression::zero(),
32717              Coefficient_traits::const_reference d = Coefficient_one(),
32718              Representation r = Generator::default_representation);
32719
32720//! Shorthand for Generator::closure_point(Representation r).
32721/*! \relates Generator */
32722Generator
32723closure_point(Representation r);
32724
32725/*! \brief
32726  Shorthand for
32727  Generator::closure_point(const Linear_Expression& e, Representation r).
32728
32729  \relates Generator
32730*/
32731Generator
32732closure_point(const Linear_Expression& e, Representation r);
32733
32734//! Returns <CODE>true</CODE> if and only if \p x is equivalent to \p y.
32735/*! \relates Generator */
32736bool operator==(const Generator& x, const Generator& y);
32737
32738//! Returns <CODE>true</CODE> if and only if \p x is not equivalent to \p y.
32739/*! \relates Generator */
32740bool operator!=(const Generator& x, const Generator& y);
32741
32742//! Computes the rectilinear (or Manhattan) distance between \p x and \p y.
32743/*! \relates Generator
32744  If the rectilinear distance between \p x and \p y is defined,
32745  stores an approximation of it into \p r and returns <CODE>true</CODE>;
32746  returns <CODE>false</CODE> otherwise.
32747
32748  The direction of the approximation is specified by \p dir.
32749
32750  All computations are performed using variables of type
32751  <CODE>Checked_Number\<To, Extended_Number_Policy\></CODE>.
32752
32753  \note
32754  Distances are \e only defined between generators that are points and/or
32755  closure points; for rays or lines, \c false is returned.
32756*/
32757template <typename To>
32758bool rectilinear_distance_assign(Checked_Number<To, Extended_Number_Policy>& r,
32759                                 const Generator& x,
32760                                 const Generator& y,
32761                                 Rounding_Dir dir);
32762
32763//! Computes the rectilinear (or Manhattan) distance between \p x and \p y.
32764/*! \relates Generator
32765  If the rectilinear distance between \p x and \p y is defined,
32766  stores an approximation of it into \p r and returns <CODE>true</CODE>;
32767  returns <CODE>false</CODE> otherwise.
32768
32769  The direction of the approximation is specified by \p dir.
32770
32771  All computations are performed using variables of type
32772  <CODE>Checked_Number\<Temp, Extended_Number_Policy\></CODE>.
32773
32774  \note
32775  Distances are \e only defined between generators that are points and/or
32776  closure points; for rays or lines, \c false is returned.
32777*/
32778template <typename Temp, typename To>
32779bool rectilinear_distance_assign(Checked_Number<To, Extended_Number_Policy>& r,
32780                                 const Generator& x,
32781                                 const Generator& y,
32782                                 Rounding_Dir dir);
32783
32784//! Computes the rectilinear (or Manhattan) distance between \p x and \p y.
32785/*! \relates Generator
32786  If the rectilinear distance between \p x and \p y is defined,
32787  stores an approximation of it into \p r and returns <CODE>true</CODE>;
32788  returns <CODE>false</CODE> otherwise.
32789
32790  The direction of the approximation is specified by \p dir.
32791
32792  All computations are performed using the temporary variables
32793  \p tmp0, \p tmp1 and \p tmp2.
32794
32795  \note
32796  Distances are \e only defined between generators that are points and/or
32797  closure points; for rays or lines, \c false is returned.
32798*/
32799template <typename Temp, typename To>
32800bool rectilinear_distance_assign(Checked_Number<To, Extended_Number_Policy>& r,
32801                                 const Generator& x,
32802                                 const Generator& y,
32803                                 Rounding_Dir dir,
32804                                 Temp& tmp0,
32805                                 Temp& tmp1,
32806                                 Temp& tmp2);
32807
32808//! Computes the euclidean distance between \p x and \p y.
32809/*! \relates Generator
32810  If the euclidean distance between \p x and \p y is defined,
32811  stores an approximation of it into \p r and returns <CODE>true</CODE>;
32812  returns <CODE>false</CODE> otherwise.
32813
32814  The direction of the approximation is specified by \p dir.
32815
32816  All computations are performed using variables of type
32817  <CODE>Checked_Number\<To, Extended_Number_Policy\></CODE>.
32818
32819  \note
32820  Distances are \e only defined between generators that are points and/or
32821  closure points; for rays or lines, \c false is returned.
32822*/
32823template <typename To>
32824bool euclidean_distance_assign(Checked_Number<To, Extended_Number_Policy>& r,
32825                               const Generator& x,
32826                               const Generator& y,
32827                               Rounding_Dir dir);
32828
32829//! Computes the euclidean distance between \p x and \p y.
32830/*! \relates Generator
32831  If the euclidean distance between \p x and \p y is defined,
32832  stores an approximation of it into \p r and returns <CODE>true</CODE>;
32833  returns <CODE>false</CODE> otherwise.
32834
32835  The direction of the approximation is specified by \p dir.
32836
32837  All computations are performed using variables of type
32838  <CODE>Checked_Number\<Temp, Extended_Number_Policy\></CODE>.
32839
32840  \note
32841  Distances are \e only defined between generators that are points and/or
32842  closure points; for rays or lines, \c false is returned.
32843*/
32844template <typename Temp, typename To>
32845bool rectilinear_distance_assign(Checked_Number<To, Extended_Number_Policy>& r,
32846                                 const Generator& x,
32847                                 const Generator& y,
32848                                 Rounding_Dir dir);
32849
32850//! Computes the euclidean distance between \p x and \p y.
32851/*! \relates Generator
32852  If the euclidean distance between \p x and \p y is defined,
32853  stores an approximation of it into \p r and returns <CODE>true</CODE>;
32854  returns <CODE>false</CODE> otherwise.
32855
32856  The direction of the approximation is specified by \p dir.
32857
32858  All computations are performed using the temporary variables
32859  \p tmp0, \p tmp1 and \p tmp2.
32860
32861  \note
32862  Distances are \e only defined between generators that are points and/or
32863  closure points; for rays or lines, \c false is returned.
32864*/
32865template <typename Temp, typename To>
32866bool euclidean_distance_assign(Checked_Number<To, Extended_Number_Policy>& r,
32867                               const Generator& x,
32868                               const Generator& y,
32869                               Rounding_Dir dir,
32870                               Temp& tmp0,
32871                               Temp& tmp1,
32872                               Temp& tmp2);
32873
32874//! Computes the \f$L_\infty\f$ distance between \p x and \p y.
32875/*! \relates Generator
32876  If the \f$L_\infty\f$ distance between \p x and \p y is defined,
32877  stores an approximation of it into \p r and returns <CODE>true</CODE>;
32878  returns <CODE>false</CODE> otherwise.
32879
32880  The direction of the approximation is specified by \p dir.
32881
32882  All computations are performed using variables of type
32883  <CODE>Checked_Number\<To, Extended_Number_Policy\></CODE>.
32884
32885  \note
32886  Distances are \e only defined between generators that are points and/or
32887  closure points; for rays or lines, \c false is returned.
32888*/
32889template <typename To>
32890bool l_infinity_distance_assign(Checked_Number<To, Extended_Number_Policy>& r,
32891                                const Generator& x,
32892                                const Generator& y,
32893                                Rounding_Dir dir);
32894
32895//! Computes the \f$L_\infty\f$ distance between \p x and \p y.
32896/*! \relates Generator
32897  If the \f$L_\infty\f$ distance between \p x and \p y is defined,
32898  stores an approximation of it into \p r and returns <CODE>true</CODE>;
32899  returns <CODE>false</CODE> otherwise.
32900
32901  The direction of the approximation is specified by \p dir.
32902
32903  All computations are performed using variables of type
32904  <CODE>Checked_Number\<Temp, Extended_Number_Policy\></CODE>.
32905
32906  \note
32907  Distances are \e only defined between generators that are points and/or
32908  closure points; for rays or lines, \c false is returned.
32909*/
32910template <typename Temp, typename To>
32911bool l_infinity_distance_assign(Checked_Number<To, Extended_Number_Policy>& r,
32912                                const Generator& x,
32913                                const Generator& y,
32914                                Rounding_Dir dir);
32915
32916//! Computes the \f$L_\infty\f$ distance between \p x and \p y.
32917/*! \relates Generator
32918  If the \f$L_\infty\f$ distance between \p x and \p y is defined,
32919  stores an approximation of it into \p r and returns <CODE>true</CODE>;
32920  returns <CODE>false</CODE> otherwise.
32921
32922  The direction of the approximation is specified by \p dir.
32923
32924  All computations are performed using the temporary variables
32925  \p tmp0, \p tmp1 and \p tmp2.
32926
32927  \note
32928  Distances are \e only defined between generators that are points and/or
32929  closure points; for rays or lines, \c false is returned.
32930*/
32931template <typename Temp, typename To>
32932bool l_infinity_distance_assign(Checked_Number<To, Extended_Number_Policy>& r,
32933                                const Generator& x,
32934                                const Generator& y,
32935                                Rounding_Dir dir,
32936                                Temp& tmp0,
32937                                Temp& tmp1,
32938                                Temp& tmp2);
32939
32940namespace IO_Operators {
32941
32942//! Output operator.
32943/*! \relates Parma_Polyhedra_Library::Generator */
32944std::ostream& operator<<(std::ostream& s, const Generator::Type& t);
32945
32946} // namespace IO_Operators
32947
32948} // namespace Parma_Polyhedra_Library
32949
32950/* Automatically generated from PPL source file ../src/Generator_inlines.hh line 1. */
32951/* Generator class implementation: inline functions.
32952*/
32953
32954
32955namespace Parma_Polyhedra_Library {
32956
32957inline bool
32958Generator::is_necessarily_closed() const {
32959  return (topology() == NECESSARILY_CLOSED);
32960}
32961
32962inline bool
32963Generator::is_not_necessarily_closed() const {
32964  return (topology() == NOT_NECESSARILY_CLOSED);
32965}
32966
32967inline Generator::expr_type
32968Generator::expression() const {
32969  return expr_type(expr, is_not_necessarily_closed());
32970}
32971
32972inline dimension_type
32973Generator::space_dimension() const {
32974  return expression().space_dimension();
32975}
32976
32977inline bool
32978Generator::is_line_or_equality() const {
32979  return (kind_ == LINE_OR_EQUALITY);
32980}
32981
32982inline bool
32983Generator::is_ray_or_point_or_inequality() const {
32984  return (kind_ == RAY_OR_POINT_OR_INEQUALITY);
32985}
32986
32987inline Topology
32988Generator::topology() const {
32989  return topology_;
32990}
32991
32992inline void
32993Generator::set_is_line_or_equality() {
32994  kind_ = LINE_OR_EQUALITY;
32995}
32996
32997inline void
32998Generator::set_is_ray_or_point_or_inequality() {
32999  kind_ = RAY_OR_POINT_OR_INEQUALITY;
33000}
33001
33002inline void
33003Generator::set_topology(Topology x) {
33004  if (topology() == x) {
33005    return;
33006  }
33007  if (topology() == NECESSARILY_CLOSED) {
33008    // Add a column for the epsilon dimension.
33009    expr.set_space_dimension(expr.space_dimension() + 1);
33010  }
33011  else {
33012    PPL_ASSERT(expr.space_dimension() > 0);
33013    expr.set_space_dimension(expr.space_dimension() - 1);
33014  }
33015  topology_ = x;
33016}
33017
33018inline void
33019Generator::mark_as_necessarily_closed() {
33020  PPL_ASSERT(is_not_necessarily_closed());
33021  topology_ = NECESSARILY_CLOSED;
33022}
33023
33024inline void
33025Generator::mark_as_not_necessarily_closed() {
33026  PPL_ASSERT(is_necessarily_closed());
33027  topology_ = NOT_NECESSARILY_CLOSED;
33028}
33029
33030inline void
33031Generator::set_necessarily_closed() {
33032  set_topology(NECESSARILY_CLOSED);
33033}
33034
33035inline void
33036Generator::set_not_necessarily_closed() {
33037  set_topology(NOT_NECESSARILY_CLOSED);
33038}
33039
33040inline
33041Generator::Generator(Representation r)
33042  : expr(r),
33043    kind_(RAY_OR_POINT_OR_INEQUALITY),
33044    topology_(NECESSARILY_CLOSED) {
33045  expr.set_inhomogeneous_term(Coefficient_one());
33046  PPL_ASSERT(space_dimension() == 0);
33047  PPL_ASSERT(OK());
33048}
33049
33050inline
33051Generator::Generator(dimension_type space_dim, Kind kind, Topology topology,
33052                     Representation r)
33053  : expr(r),
33054    kind_(kind),
33055    topology_(topology) {
33056  if (is_necessarily_closed()) {
33057    expr.set_space_dimension(space_dim);
33058  }
33059  else {
33060    expr.set_space_dimension(space_dim + 1);
33061  }
33062  PPL_ASSERT(space_dimension() == space_dim);
33063  PPL_ASSERT(OK());
33064}
33065
33066inline
33067Generator::Generator(Linear_Expression& e, Type type, Topology topology)
33068  : topology_(topology) {
33069  PPL_ASSERT(type != CLOSURE_POINT || topology == NOT_NECESSARILY_CLOSED);
33070  swap(expr, e);
33071  if (topology == NOT_NECESSARILY_CLOSED) {
33072    expr.set_space_dimension(expr.space_dimension() + 1);
33073  }
33074  if (type == LINE) {
33075    kind_ = LINE_OR_EQUALITY;
33076  }
33077  else {
33078    kind_ = RAY_OR_POINT_OR_INEQUALITY;
33079  }
33080  strong_normalize();
33081}
33082
33083inline
33084Generator::Generator(Linear_Expression& e, Kind kind, Topology topology)
33085  : kind_(kind),
33086    topology_(topology) {
33087  swap(expr, e);
33088  if (topology == NOT_NECESSARILY_CLOSED) {
33089    expr.set_space_dimension(expr.space_dimension() + 1);
33090  }
33091  strong_normalize();
33092}
33093
33094inline
33095Generator::Generator(const Generator& g)
33096  : expr(g.expr),
33097    kind_(g.kind_),
33098    topology_(g.topology_) {
33099}
33100
33101inline
33102Generator::Generator(const Generator& g, Representation r)
33103  : expr(g.expr, r),
33104    kind_(g.kind_),
33105    topology_(g.topology_) {
33106  // This does not assert OK() because it's called by OK().
33107  PPL_ASSERT(OK());
33108}
33109
33110inline
33111Generator::Generator(const Generator& g, dimension_type space_dim)
33112  : expr(g.expr, g.is_necessarily_closed() ? space_dim : (space_dim + 1)),
33113    kind_(g.kind_),
33114    topology_(g.topology_) {
33115  PPL_ASSERT(OK());
33116  PPL_ASSERT(space_dimension() == space_dim);
33117}
33118
33119inline
33120Generator::Generator(const Generator& g, dimension_type space_dim,
33121                     Representation r)
33122  : expr(g.expr, g.is_necessarily_closed() ? space_dim : (space_dim + 1), r),
33123    kind_(g.kind_),
33124    topology_(g.topology_) {
33125  PPL_ASSERT(OK());
33126  PPL_ASSERT(space_dimension() == space_dim);
33127}
33128
33129inline
33130Generator::~Generator() {
33131}
33132
33133inline Generator&
33134Generator::operator=(const Generator& g) {
33135  Generator tmp = g;
33136  swap(*this, tmp);
33137
33138  return *this;
33139}
33140
33141inline Representation
33142Generator::representation() const {
33143  return expr.representation();
33144}
33145
33146inline void
33147Generator::set_representation(Representation r) {
33148  expr.set_representation(r);
33149}
33150
33151inline dimension_type
33152Generator::max_space_dimension() {
33153  return Linear_Expression::max_space_dimension();
33154}
33155
33156inline void
33157Generator::set_space_dimension_no_ok(dimension_type space_dim) {
33158  const dimension_type old_expr_space_dim = expr.space_dimension();
33159  if (topology() == NECESSARILY_CLOSED) {
33160    expr.set_space_dimension(space_dim);
33161  }
33162  else {
33163    const dimension_type old_space_dim = space_dimension();
33164    if (space_dim > old_space_dim) {
33165      expr.set_space_dimension(space_dim + 1);
33166      expr.swap_space_dimensions(Variable(space_dim), Variable(old_space_dim));
33167    }
33168    else {
33169      expr.swap_space_dimensions(Variable(space_dim), Variable(old_space_dim));
33170      expr.set_space_dimension(space_dim + 1);
33171    }
33172  }
33173  PPL_ASSERT(space_dimension() == space_dim);
33174  if (expr.space_dimension() < old_expr_space_dim) {
33175    strong_normalize();
33176  }
33177}
33178
33179inline void
33180Generator::set_space_dimension(dimension_type space_dim) {
33181  set_space_dimension_no_ok(space_dim);
33182  PPL_ASSERT(OK());
33183}
33184
33185inline void
33186Generator::shift_space_dimensions(Variable v, dimension_type n) {
33187  expr.shift_space_dimensions(v, n);
33188}
33189
33190inline bool
33191Generator::is_line() const {
33192  return is_line_or_equality();
33193}
33194
33195inline bool
33196Generator::is_ray_or_point() const {
33197  return is_ray_or_point_or_inequality();
33198}
33199
33200inline bool
33201Generator::is_line_or_ray() const {
33202  return expr.inhomogeneous_term() == 0;
33203}
33204
33205inline bool
33206Generator::is_ray() const {
33207  return is_ray_or_point() && is_line_or_ray();
33208}
33209
33210inline Generator::Type
33211Generator::type() const {
33212  if (is_line()) {
33213    return LINE;
33214  }
33215  if (is_line_or_ray()) {
33216    return RAY;
33217  }
33218  if (is_necessarily_closed()) {
33219    return POINT;
33220  }
33221  else {
33222    // Checking the value of the epsilon coefficient.
33223    if (epsilon_coefficient() == 0) {
33224      return CLOSURE_POINT;
33225    }
33226    else {
33227      return POINT;
33228    }
33229  }
33230}
33231
33232inline bool
33233Generator::is_point() const {
33234  return type() == POINT;
33235}
33236
33237inline bool
33238Generator::is_closure_point() const {
33239  return type() == CLOSURE_POINT;
33240}
33241
33242inline void
33243Generator::set_is_line() {
33244  set_is_line_or_equality();
33245}
33246
33247inline void
33248Generator::set_is_ray_or_point() {
33249  set_is_ray_or_point_or_inequality();
33250}
33251
33252inline Coefficient_traits::const_reference
33253Generator::coefficient(const Variable v) const {
33254  if (v.space_dimension() > space_dimension()) {
33255    throw_dimension_incompatible("coefficient(v)", "v", v);
33256  }
33257  return expr.coefficient(v);
33258}
33259
33260inline Coefficient_traits::const_reference
33261Generator::divisor() const {
33262  Coefficient_traits::const_reference d = expr.inhomogeneous_term();
33263  if (!is_ray_or_point() || d == 0) {
33264    throw_invalid_argument("divisor()",
33265                           "*this is neither a point nor a closure point");
33266  }
33267  return d;
33268}
33269
33270inline Coefficient_traits::const_reference
33271Generator::epsilon_coefficient() const {
33272  PPL_ASSERT(is_not_necessarily_closed());
33273  return expr.coefficient(Variable(expr.space_dimension() - 1));
33274}
33275
33276
33277inline void
33278Generator::set_epsilon_coefficient(Coefficient_traits::const_reference n) {
33279  PPL_ASSERT(is_not_necessarily_closed());
33280  expr.set_coefficient(Variable(expr.space_dimension() - 1), n);
33281}
33282
33283
33284inline memory_size_type
33285Generator::external_memory_in_bytes() const {
33286  return expr.external_memory_in_bytes();
33287}
33288
33289inline memory_size_type
33290Generator::total_memory_in_bytes() const {
33291  return sizeof(*this) + external_memory_in_bytes();
33292}
33293
33294inline void
33295Generator::strong_normalize() {
33296  expr.normalize();
33297  sign_normalize();
33298}
33299
33300inline const Generator&
33301Generator::zero_dim_point() {
33302  PPL_ASSERT(zero_dim_point_p != 0);
33303  return *zero_dim_point_p;
33304}
33305
33306inline const Generator&
33307Generator::zero_dim_closure_point() {
33308  PPL_ASSERT(zero_dim_closure_point_p != 0);
33309  return *zero_dim_closure_point_p;
33310}
33311
33312/*! \relates Generator */
33313inline Generator
33314line(const Linear_Expression& e, Representation r) {
33315  return Generator::line(e, r);
33316}
33317
33318/*! \relates Generator */
33319inline Generator
33320ray(const Linear_Expression& e, Representation r) {
33321  return Generator::ray(e, r);
33322}
33323
33324/*! \relates Generator */
33325inline Generator
33326point(const Linear_Expression& e, Coefficient_traits::const_reference d,
33327      Representation r) {
33328  return Generator::point(e, d, r);
33329}
33330
33331/*! \relates Generator */
33332inline Generator
33333point(Representation r) {
33334  return Generator::point(r);
33335}
33336
33337/*! \relates Generator */
33338inline Generator
33339point(const Linear_Expression& e, Representation r) {
33340  return Generator::point(e, r);
33341}
33342
33343/*! \relates Generator */
33344inline Generator
33345closure_point(const Linear_Expression& e,
33346              Coefficient_traits::const_reference d,
33347              Representation r) {
33348  return Generator::closure_point(e, d, r);
33349}
33350
33351/*! \relates Generator */
33352inline Generator
33353closure_point(Representation r) {
33354  return Generator::closure_point(r);
33355}
33356
33357/*! \relates Generator */
33358inline Generator
33359closure_point(const Linear_Expression& e,
33360              Representation r) {
33361  return Generator::closure_point(e, r);
33362}
33363
33364/*! \relates Generator */
33365inline bool
33366operator==(const Generator& x, const Generator& y) {
33367  return x.is_equivalent_to(y);
33368}
33369
33370/*! \relates Generator */
33371inline bool
33372operator!=(const Generator& x, const Generator& y) {
33373  return !x.is_equivalent_to(y);
33374}
33375
33376inline void
33377Generator::ascii_dump(std::ostream& s) const {
33378
33379  expr.ascii_dump(s);
33380
33381  s << " ";
33382
33383  switch (type()) {
33384  case Generator::LINE:
33385    s << "L ";
33386    break;
33387  case Generator::RAY:
33388    s << "R ";
33389    break;
33390  case Generator::POINT:
33391    s << "P ";
33392    break;
33393  case Generator::CLOSURE_POINT:
33394    s << "C ";
33395    break;
33396  }
33397  if (is_necessarily_closed()) {
33398    s << "(C)";
33399  }
33400  else {
33401    s << "(NNC)";
33402  }
33403  s << "\n";
33404}
33405
33406inline bool
33407Generator::ascii_load(std::istream& s) {
33408  std::string str;
33409
33410  expr.ascii_load(s);
33411
33412  if (!(s >> str)) {
33413    return false;
33414  }
33415  if (str == "L") {
33416    set_is_line();
33417  }
33418  else if (str == "R" || str == "P" || str == "C") {
33419    set_is_ray_or_point();
33420  }
33421  else {
33422    return false;
33423  }
33424
33425  std::string str2;
33426
33427  if (!(s >> str2)) {
33428    return false;
33429  }
33430  if (str2 == "(C)") {
33431    if (is_not_necessarily_closed()) {
33432      // TODO: Avoid using the mark_as_*() methods if possible.
33433      mark_as_necessarily_closed();
33434    }
33435  }
33436  else {
33437    if (str2 == "(NNC)") {
33438      if (is_necessarily_closed()) {
33439        // TODO: Avoid using the mark_as_*() methods if possible.
33440        mark_as_not_necessarily_closed();
33441      }
33442    }
33443    else {
33444      return false;
33445    }
33446  }
33447
33448  // Checking for equality of actual and declared types.
33449  switch (type()) {
33450  case Generator::LINE:
33451    if (str != "L") {
33452      return false;
33453    }
33454    break;
33455  case Generator::RAY:
33456    if (str != "R") {
33457      return false;
33458    }
33459    break;
33460  case Generator::POINT:
33461    if (str != "P") {
33462      return false;
33463    }
33464    break;
33465  case Generator::CLOSURE_POINT:
33466    if (str != "C") {
33467      return false;
33468    }
33469    break;
33470  }
33471
33472  return true;
33473}
33474
33475inline void
33476Generator::m_swap(Generator& y) {
33477  using std::swap;
33478  swap(expr, y.expr);
33479  swap(kind_, y.kind_);
33480  swap(topology_, y.topology_);
33481}
33482
33483#ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
33484/*! \relates Generator */
33485#endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
33486template <typename Specialization, typename Temp, typename To>
33487inline bool
33488l_m_distance_assign(Checked_Number<To, Extended_Number_Policy>& r,
33489                    const Generator& x,
33490                    const Generator& y,
33491                    const Rounding_Dir dir,
33492                    Temp& tmp0,
33493                    Temp& tmp1,
33494                    Temp& tmp2) {
33495  // Generator kind compatibility check: we only compute distances
33496  // between (closure) points.
33497  if (x.is_line_or_ray() || y.is_line_or_ray()) {
33498    return false;
33499  }
33500  const dimension_type x_space_dim = x.space_dimension();
33501  // Dimension-compatibility check.
33502  if (x_space_dim != y.space_dimension()) {
33503    return false;
33504  }
33505
33506  // All zero-dim generators have distance zero.
33507  if (x_space_dim == 0) {
33508    assign_r(r, 0, ROUND_NOT_NEEDED);
33509    return true;
33510  }
33511
33512  PPL_DIRTY_TEMP(mpq_class, x_coord);
33513  PPL_DIRTY_TEMP(mpq_class, y_coord);
33514  PPL_DIRTY_TEMP(mpq_class, x_div);
33515  PPL_DIRTY_TEMP(mpq_class, y_div);
33516  assign_r(x_div, x.divisor(), ROUND_NOT_NEEDED);
33517  assign_r(y_div, y.divisor(), ROUND_NOT_NEEDED);
33518
33519  assign_r(tmp0, 0, ROUND_NOT_NEEDED);
33520  // TODO: This loop can be optimized more, if needed.
33521  for (dimension_type i = x_space_dim; i-- > 0; ) {
33522    assign_r(x_coord, x.coefficient(Variable(i)), ROUND_NOT_NEEDED);
33523    div_assign_r(x_coord, x_coord, x_div, ROUND_NOT_NEEDED);
33524    assign_r(y_coord, y.coefficient(Variable(i)), ROUND_NOT_NEEDED);
33525    div_assign_r(y_coord, y_coord, y_div, ROUND_NOT_NEEDED);
33526    const Temp* tmp1p;
33527    const Temp* tmp2p;
33528
33529    if (x_coord > y_coord) {
33530      maybe_assign(tmp1p, tmp1, x_coord, dir);
33531      maybe_assign(tmp2p, tmp2, y_coord, inverse(dir));
33532    }
33533    else {
33534      maybe_assign(tmp1p, tmp1, y_coord, dir);
33535      maybe_assign(tmp2p, tmp2, x_coord, inverse(dir));
33536    }
33537    sub_assign_r(tmp1, *tmp1p, *tmp2p, dir);
33538    PPL_ASSERT(sgn(tmp1) >= 0);
33539    Specialization::combine(tmp0, tmp1, dir);
33540  }
33541  Specialization::finalize(tmp0, dir);
33542  assign_r(r, tmp0, dir);
33543  return true;
33544}
33545
33546/*! \relates Generator */
33547template <typename Temp, typename To>
33548inline bool
33549rectilinear_distance_assign(Checked_Number<To, Extended_Number_Policy>& r,
33550                            const Generator& x,
33551                            const Generator& y,
33552                            const Rounding_Dir dir,
33553                            Temp& tmp0,
33554                            Temp& tmp1,
33555                            Temp& tmp2) {
33556  return l_m_distance_assign<Rectilinear_Distance_Specialization<Temp> >
33557    (r, x, y, dir, tmp0, tmp1, tmp2);
33558}
33559
33560/*! \relates Generator */
33561template <typename Temp, typename To>
33562inline bool
33563rectilinear_distance_assign(Checked_Number<To, Extended_Number_Policy>& r,
33564                            const Generator& x,
33565                            const Generator& y,
33566                            const Rounding_Dir dir) {
33567  typedef Checked_Number<Temp, Extended_Number_Policy> Checked_Temp;
33568  PPL_DIRTY_TEMP(Checked_Temp, tmp0);
33569  PPL_DIRTY_TEMP(Checked_Temp, tmp1);
33570  PPL_DIRTY_TEMP(Checked_Temp, tmp2);
33571  return rectilinear_distance_assign(r, x, y, dir, tmp0, tmp1, tmp2);
33572}
33573
33574/*! \relates Generator */
33575template <typename To>
33576inline bool
33577rectilinear_distance_assign(Checked_Number<To, Extended_Number_Policy>& r,
33578                            const Generator& x,
33579                            const Generator& y,
33580                            const Rounding_Dir dir) {
33581  return rectilinear_distance_assign<To, To>(r, x, y, dir);
33582}
33583
33584/*! \relates Generator */
33585template <typename Temp, typename To>
33586inline bool
33587euclidean_distance_assign(Checked_Number<To, Extended_Number_Policy>& r,
33588                          const Generator& x,
33589                          const Generator& y,
33590                          const Rounding_Dir dir,
33591                          Temp& tmp0,
33592                          Temp& tmp1,
33593                          Temp& tmp2) {
33594  return l_m_distance_assign<Euclidean_Distance_Specialization<Temp> >
33595    (r, x, y, dir, tmp0, tmp1, tmp2);
33596}
33597
33598/*! \relates Generator */
33599template <typename Temp, typename To>
33600inline bool
33601euclidean_distance_assign(Checked_Number<To, Extended_Number_Policy>& r,
33602                          const Generator& x,
33603                          const Generator& y,
33604                          const Rounding_Dir dir) {
33605  typedef Checked_Number<Temp, Extended_Number_Policy> Checked_Temp;
33606  PPL_DIRTY_TEMP(Checked_Temp, tmp0);
33607  PPL_DIRTY_TEMP(Checked_Temp, tmp1);
33608  PPL_DIRTY_TEMP(Checked_Temp, tmp2);
33609  return euclidean_distance_assign(r, x, y, dir, tmp0, tmp1, tmp2);
33610}
33611
33612/*! \relates Generator */
33613template <typename To>
33614inline bool
33615euclidean_distance_assign(Checked_Number<To, Extended_Number_Policy>& r,
33616                          const Generator& x,
33617                          const Generator& y,
33618                          const Rounding_Dir dir) {
33619  return euclidean_distance_assign<To, To>(r, x, y, dir);
33620}
33621
33622/*! \relates Generator */
33623template <typename Temp, typename To>
33624inline bool
33625l_infinity_distance_assign(Checked_Number<To, Extended_Number_Policy>& r,
33626                           const Generator& x,
33627                           const Generator& y,
33628                           const Rounding_Dir dir,
33629                           Temp& tmp0,
33630                           Temp& tmp1,
33631                           Temp& tmp2) {
33632  return l_m_distance_assign<L_Infinity_Distance_Specialization<Temp> >
33633    (r, x, y, dir, tmp0, tmp1, tmp2);
33634}
33635
33636/*! \relates Generator */
33637template <typename Temp, typename To>
33638inline bool
33639l_infinity_distance_assign(Checked_Number<To, Extended_Number_Policy>& r,
33640                           const Generator& x,
33641                           const Generator& y,
33642                           const Rounding_Dir dir) {
33643  typedef Checked_Number<Temp, Extended_Number_Policy> Checked_Temp;
33644  PPL_DIRTY_TEMP(Checked_Temp, tmp0);
33645  PPL_DIRTY_TEMP(Checked_Temp, tmp1);
33646  PPL_DIRTY_TEMP(Checked_Temp, tmp2);
33647  return l_infinity_distance_assign(r, x, y, dir, tmp0, tmp1, tmp2);
33648}
33649
33650/*! \relates Generator */
33651template <typename To>
33652inline bool
33653l_infinity_distance_assign(Checked_Number<To, Extended_Number_Policy>& r,
33654                           const Generator& x,
33655                           const Generator& y,
33656                           const Rounding_Dir dir) {
33657  return l_infinity_distance_assign<To, To>(r, x, y, dir);
33658}
33659
33660/*! \relates Generator */
33661inline void
33662swap(Generator& x, Generator& y) {
33663  x.m_swap(y);
33664}
33665
33666} // namespace Parma_Polyhedra_Library
33667
33668/* Automatically generated from PPL source file ../src/Generator_defs.hh line 1032. */
33669
33670/* Automatically generated from PPL source file ../src/Grid_Generator_defs.hh line 1. */
33671/* Grid_Generator class declaration.
33672*/
33673
33674
33675/* Automatically generated from PPL source file ../src/Grid_Generator_defs.hh line 29. */
33676
33677/* Automatically generated from PPL source file ../src/Grid_Generator_defs.hh line 33. */
33678
33679/* Automatically generated from PPL source file ../src/Grid_Generator_defs.hh line 39. */
33680
33681/* Automatically generated from PPL source file ../src/Grid_Generator_defs.hh line 41. */
33682#include <iosfwd>
33683
33684namespace Parma_Polyhedra_Library {
33685
33686// Put these in the namespace here to declare them friend later.
33687
33688#ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
33689//! The basic comparison function.
33690/*! \relates Grid_Generator
33691  \return
33692  The returned absolute value can be \f$0\f$, \f$1\f$ or \f$2\f$.
33693
33694  \param x
33695  A row of coefficients;
33696
33697  \param y
33698  Another row.
33699
33700  Compares \p x and \p y, where \p x and \p y may be of different size,
33701  in which case the "missing" coefficients are assumed to be zero.
33702  The comparison is such that:
33703  -# equalities are smaller than inequalities;
33704  -# lines are smaller than points and rays;
33705  -# the ordering is lexicographic;
33706  -# the positions compared are, in decreasing order of significance,
33707     1, 2, ..., \p size(), 0;
33708  -# the result is negative, zero, or positive if x is smaller than,
33709     equal to, or greater than y, respectively;
33710  -# when \p x and \p y are different, the absolute value of the
33711     result is 1 if the difference is due to the coefficient in
33712     position 0; it is 2 otherwise.
33713
33714  When \p x and \p y represent the hyper-planes associated
33715  to two equality or inequality constraints, the coefficient
33716  at 0 is the known term.
33717  In this case, the return value can be characterized as follows:
33718  - -2, if \p x is smaller than \p y and they are \e not parallel;
33719  - -1, if \p x is smaller than \p y and they \e are parallel;
33720  -  0, if \p x and y are equal;
33721  - +1, if \p y is smaller than \p x and they \e are parallel;
33722  - +2, if \p y is smaller than \p x and they are \e not parallel.
33723*/
33724#endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
33725int compare(const Grid_Generator& x, const Grid_Generator& y);
33726
33727namespace IO_Operators {
33728
33729//! Output operator.
33730/*! \relates Parma_Polyhedra_Library::Grid_Generator */
33731std::ostream& operator<<(std::ostream& s, const Grid_Generator& g);
33732
33733} // namespace IO_Operators
33734
33735//! Swaps \p x with \p y.
33736/*! \relates Grid_Generator */
33737void swap(Grid_Generator& x, Grid_Generator& y);
33738
33739} // namespace Parma_Polyhedra_Library
33740
33741//! A grid line, parameter or grid point.
33742/*! \ingroup PPL_CXX_interface
33743  An object of the class Grid_Generator is one of the following:
33744
33745  - a grid_line \f$\vect{l} = (a_0, \ldots, a_{n-1})^\transpose\f$;
33746
33747  - a parameter
33748    \f$\vect{q} = (\frac{a_0}{d}, \ldots, \frac{a_{n-1}}{d})^\transpose\f$;
33749
33750  - a grid_point
33751    \f$\vect{p} = (\frac{a_0}{d}, \ldots, \frac{a_{n-1}}{d})^\transpose\f$;
33752
33753  where \f$n\f$ is the dimension of the space
33754  and, for grid_points and parameters, \f$d > 0\f$ is the divisor.
33755
33756  \par How to build a grid generator.
33757  Each type of generator is built by applying the corresponding
33758  function (<CODE>grid_line</CODE>, <CODE>parameter</CODE>
33759  or <CODE>grid_point</CODE>) to a linear expression;
33760  the space dimension of the generator is defined as the space dimension
33761  of the corresponding linear expression.
33762  Linear expressions used to define a generator should be homogeneous
33763  (any constant term will be simply ignored).
33764  When defining grid points and parameters, an optional Coefficient argument
33765  can be used as a common <EM>divisor</EM> for all the coefficients
33766  occurring in the provided linear expression;
33767  the default value for this argument is 1.
33768
33769  \par
33770  In all the following examples it is assumed that variables
33771  <CODE>x</CODE>, <CODE>y</CODE> and <CODE>z</CODE>
33772  are defined as follows:
33773  \code
33774  Variable x(0);
33775  Variable y(1);
33776  Variable z(2);
33777  \endcode
33778
33779  \par Example 1
33780  The following code builds a grid line with direction \f$x-y-z\f$
33781  and having space dimension \f$3\f$:
33782  \code
33783  Grid_Generator l = grid_line(x - y - z);
33784  \endcode
33785  By definition, the origin of the space is not a line, so that
33786  the following code throws an exception:
33787  \code
33788  Grid_Generator l = grid_line(0*x);
33789  \endcode
33790
33791  \par Example 2
33792  The following code builds the parameter as the vector
33793  \f$\vect{p} = (1, -1, -1)^\transpose \in \Rset^3\f$
33794  which has the same direction as the line in Example 1:
33795  \code
33796  Grid_Generator q = parameter(x - y - z);
33797  \endcode
33798  Note that, unlike lines, for parameters, the length as well
33799  as the direction of the vector represented by the code is significant.
33800  Thus \p q is \e not the same as the parameter \p q1 defined by
33801  \code
33802  Grid_Generator q1 = parameter(2x - 2y - 2z);
33803  \endcode
33804  By definition, the origin of the space is not a parameter, so that
33805  the following code throws an exception:
33806  \code
33807  Grid_Generator q = parameter(0*x);
33808  \endcode
33809
33810  \par Example 3
33811  The following code builds the grid point
33812  \f$\vect{p} = (1, 0, 2)^\transpose \in \Rset^3\f$:
33813  \code
33814  Grid_Generator p = grid_point(1*x + 0*y + 2*z);
33815  \endcode
33816  The same effect can be obtained by using the following code:
33817  \code
33818  Grid_Generator p = grid_point(x + 2*z);
33819  \endcode
33820  Similarly, the origin \f$\vect{0} \in \Rset^3\f$ can be defined
33821  using either one of the following lines of code:
33822  \code
33823  Grid_Generator origin3 = grid_point(0*x + 0*y + 0*z);
33824  Grid_Generator origin3_alt = grid_point(0*z);
33825  \endcode
33826  Note however that the following code would have defined
33827  a different point, namely \f$\vect{0} \in \Rset^2\f$:
33828  \code
33829  Grid_Generator origin2 = grid_point(0*y);
33830  \endcode
33831  The following two lines of code both define the only grid point
33832  having space dimension zero, namely \f$\vect{0} \in \Rset^0\f$.
33833  In the second case we exploit the fact that the first argument
33834  of the function <CODE>point</CODE> is optional.
33835  \code
33836  Grid_Generator origin0 = Generator::zero_dim_point();
33837  Grid_Generator origin0_alt = grid_point();
33838  \endcode
33839
33840  \par Example 4
33841  The grid point \f$\vect{p}\f$ specified in Example 3 above
33842  can also be obtained with the following code,
33843  where we provide a non-default value for the second argument
33844  of the function <CODE>grid_point</CODE> (the divisor):
33845  \code
33846  Grid_Generator p = grid_point(2*x + 0*y + 4*z, 2);
33847  \endcode
33848  Obviously, the divisor can be used to specify
33849  points having some non-integer (but rational) coordinates.
33850  For instance, the grid point
33851  \f$\vect{p1} = (-1.5, 3.2, 2.1)^\transpose \in \Rset^3\f$
33852  can be specified by the following code:
33853  \code
33854  Grid_Generator p1 = grid_point(-15*x + 32*y + 21*z, 10);
33855  \endcode
33856  If a zero divisor is provided, an exception is thrown.
33857
33858  \par Example 5
33859  Parameters, like grid points can have a divisor.
33860  For instance, the parameter
33861  \f$\vect{q} = (1, 0, 2)^\transpose \in \Rset^3\f$ can be defined:
33862  \code
33863  Grid_Generator q = parameter(2*x + 0*y + 4*z, 2);
33864  \endcode
33865  Also, the divisor can be used to specify
33866  parameters having some non-integer (but rational) coordinates.
33867  For instance, the parameter
33868  \f$\vect{q} = (-1.5, 3.2, 2.1)^\transpose \in \Rset^3\f$
33869  can be defined:
33870  \code
33871  Grid_Generator q = parameter(-15*x + 32*y + 21*z, 10);
33872  \endcode
33873  If a zero divisor is provided, an exception is thrown.
33874
33875  \par How to inspect a grid generator
33876  Several methods are provided to examine a grid generator and extract
33877  all the encoded information: its space dimension, its type and
33878  the value of its integer coefficients and the value of the denominator.
33879
33880  \par Example 6
33881  The following code shows how it is possible to access each single
33882  coefficient of a grid generator.
33883  If <CODE>g1</CODE> is a grid point having coordinates
33884  \f$(a_0, \ldots, a_{n-1})^\transpose\f$,
33885  we construct the parameter <CODE>g2</CODE> having coordinates
33886  \f$(a_0, 2 a_1, \ldots, (i+1)a_i, \ldots, n a_{n-1})^\transpose\f$.
33887  \code
33888  if (g1.is_point()) {
33889    cout << "Grid point g1: " << g1 << endl;
33890    Linear_Expression e;
33891    for (dimension_type i = g1.space_dimension(); i-- > 0; )
33892      e += (i + 1) * g1.coefficient(Variable(i)) * Variable(i);
33893    Grid_Generator g2 = parameter(e, g1.divisor());
33894    cout << "Parameter g2: " << g2 << endl;
33895  }
33896  else
33897    cout << "Grid generator g1 is not a grid point." << endl;
33898  \endcode
33899  Therefore, for the grid point
33900  \code
33901  Grid_Generator g1 = grid_point(2*x - y + 3*z, 2);
33902  \endcode
33903  we would obtain the following output:
33904  \code
33905  Grid point g1: p((2*A - B + 3*C)/2)
33906  Parameter g2: parameter((2*A - 2*B + 9*C)/2)
33907  \endcode
33908  When working with grid points and parameters, be careful not to confuse
33909  the notion of <EM>coefficient</EM> with the notion of <EM>coordinate</EM>:
33910  these are equivalent only when the divisor is 1.
33911*/
33912class Parma_Polyhedra_Library::Grid_Generator {
33913public:
33914
33915  //! The possible kinds of Grid_Generator objects.
33916  enum Kind {
33917    LINE_OR_EQUALITY = 0,
33918    RAY_OR_POINT_OR_INEQUALITY = 1
33919  };
33920
33921  //! The representation used for new Grid_Generators.
33922  /*!
33923    \note The copy constructor and the copy constructor with specified size
33924          use the representation of the original object, so that it is
33925          indistinguishable from the original object.
33926  */
33927  static const Representation default_representation = SPARSE;
33928
33929  //! Returns the line of direction \p e.
33930  /*!
33931    \exception std::invalid_argument
33932    Thrown if the homogeneous part of \p e represents the origin of
33933    the vector space.
33934  */
33935  static Grid_Generator grid_line(const Linear_Expression& e,
33936                                  Representation r = default_representation);
33937
33938  //! Returns the parameter of direction \p e and size \p e/d, with the same
33939  //! representation as e.
33940  /*!
33941    Both \p e and \p d are optional arguments, with default values
33942    Linear_Expression::zero() and Coefficient_one(), respectively.
33943
33944    \exception std::invalid_argument
33945    Thrown if \p d is zero.
33946  */
33947  static Grid_Generator parameter(const Linear_Expression& e
33948                                  = Linear_Expression::zero(),
33949                                  Coefficient_traits::const_reference d
33950                                  = Coefficient_one(),
33951                                  Representation r = default_representation);
33952
33953  // TODO: Improve the documentation of this method.
33954  //! Returns the parameter of direction and size \p Linear_Expression::zero() .
33955  static Grid_Generator parameter(Representation r);
33956
33957  //! Returns the parameter of direction and size \p e .
33958  static Grid_Generator parameter(const Linear_Expression& e,
33959                                  Representation r);
33960
33961  //! Returns the point at \p e / \p d.
33962  /*!
33963    Both \p e and \p d are optional arguments, with default values
33964    Linear_Expression::zero() and Coefficient_one(), respectively.
33965
33966    \exception std::invalid_argument
33967    Thrown if \p d is zero.
33968  */
33969  static Grid_Generator grid_point(const Linear_Expression& e
33970                                   = Linear_Expression::zero(),
33971                                   Coefficient_traits::const_reference d
33972                                   = Coefficient_one(),
33973                                   Representation r = default_representation);
33974
33975  //! Returns the point at \p e .
33976  static Grid_Generator grid_point(Representation r);
33977
33978  //! Returns the point at \p e .
33979  static Grid_Generator grid_point(const Linear_Expression& e,
33980                                   Representation r);
33981
33982  //! Returns the origin of the zero-dimensional space \f$\Rset^0\f$.
33983  explicit Grid_Generator(Representation r = default_representation);
33984
33985  //! Ordinary copy constructor.
33986  //! The new Grid_Generator will have the same representation as g.
33987  Grid_Generator(const Grid_Generator& g);
33988
33989  //! Copy constructor with specified representation.
33990  Grid_Generator(const Grid_Generator& g, Representation r);
33991
33992  //! Copy constructor with specified space dimension.
33993  //! The new Grid_Generator will have the same representation as g.
33994  Grid_Generator(const Grid_Generator& g, dimension_type space_dim);
33995
33996  //! Copy constructor with specified space dimension and representation.
33997  Grid_Generator(const Grid_Generator& g, dimension_type space_dim,
33998                 Representation r);
33999
34000  //! Destructor.
34001  ~Grid_Generator();
34002
34003  //! Assignment operator.
34004  Grid_Generator& operator=(const Grid_Generator& g);
34005
34006  //! Returns the current representation of *this.
34007  Representation representation() const;
34008
34009  //! Converts *this to the specified representation.
34010  void set_representation(Representation r);
34011
34012  //! Returns the maximum space dimension a Grid_Generator can handle.
34013  static dimension_type max_space_dimension();
34014
34015  //! Returns the dimension of the vector space enclosing \p *this.
34016  dimension_type space_dimension() const;
34017
34018  //! Sets the dimension of the vector space enclosing \p *this to
34019  //! \p space_dim .
34020  void set_space_dimension(dimension_type space_dim);
34021
34022  //! Swaps the coefficients of the variables \p v1 and \p v2 .
34023  void swap_space_dimensions(Variable v1, Variable v2);
34024
34025  //! Removes all the specified dimensions from the grid generator.
34026  /*!
34027    The space dimension of the variable with the highest space
34028    dimension in \p vars must be at most the space dimension
34029    of \p this.
34030
34031    Always returns \p true. The return value is needed for compatibility with
34032    the Generator class.
34033  */
34034  bool remove_space_dimensions(const Variables_Set& vars);
34035
34036  //! Permutes the space dimensions of the grid generator.
34037  /*
34038    \param cycle
34039    A vector representing a cycle of the permutation according to which the
34040    space dimensions must be rearranged.
34041
34042    The \p cycle vector represents a cycle of a permutation of space
34043    dimensions.
34044    For example, the permutation
34045    \f$ \{ x_1 \mapsto x_2, x_2 \mapsto x_3, x_3 \mapsto x_1 \}\f$ can be
34046    represented by the vector containing \f$ x_1, x_2, x_3 \f$.
34047  */
34048  void permute_space_dimensions(const std::vector<Variable>& cycle);
34049
34050  //! Shift by \p n positions the coefficients of variables, starting from
34051  //! the coefficient of \p v. This increases the space dimension by \p n.
34052  void shift_space_dimensions(Variable v, dimension_type n);
34053
34054  //! The generator type.
34055  enum Type {
34056    /*! The generator is a grid line. */
34057    LINE,
34058    /*! The generator is a parameter. */
34059    PARAMETER,
34060    /*! The generator is a grid point. */
34061    POINT
34062  };
34063
34064  //! Returns the generator type of \p *this.
34065  Type type() const;
34066
34067  //! Returns <CODE>true</CODE> if and only if \p *this is a line.
34068  bool is_line() const;
34069
34070  //! Returns <CODE>true</CODE> if and only if \p *this is a parameter.
34071  bool is_parameter() const;
34072
34073  /*! \brief
34074    Returns <CODE>true</CODE> if and only if \p *this is a line or
34075    a parameter.
34076  */
34077  bool is_line_or_parameter() const;
34078
34079  //! Returns <CODE>true</CODE> if and only if \p *this is a point.
34080  bool is_point() const;
34081
34082  /*! \brief
34083    Returns <CODE>true</CODE> if and only if \p *this row represents a
34084    parameter or a point.
34085  */
34086  bool is_parameter_or_point() const;
34087
34088  //! Returns the coefficient of \p v in \p *this.
34089  /*!
34090    \exception std::invalid_argument
34091    Thrown if the index of \p v is greater than or equal to the
34092    space dimension of \p *this.
34093  */
34094  Coefficient_traits::const_reference coefficient(Variable v) const;
34095
34096  //! Returns the divisor of \p *this.
34097  /*!
34098    \exception std::invalid_argument
34099    Thrown if \p *this is a line.
34100  */
34101  Coefficient_traits::const_reference divisor() const;
34102
34103  //! Initializes the class.
34104  static void initialize();
34105
34106  //! Finalizes the class.
34107  static void finalize();
34108
34109  //! Returns the origin of the zero-dimensional space \f$\Rset^0\f$.
34110  static const Grid_Generator& zero_dim_point();
34111
34112  /*! \brief
34113    Returns a lower bound to the total size in bytes of the memory
34114    occupied by \p *this.
34115  */
34116  memory_size_type total_memory_in_bytes() const;
34117
34118  //! Returns the size in bytes of the memory managed by \p *this.
34119  memory_size_type external_memory_in_bytes() const;
34120
34121  /*! \brief
34122    Returns <CODE>true</CODE> if and only if \p *this and \p y are
34123    equivalent generators.
34124
34125    Generators having different space dimensions are not equivalent.
34126  */
34127  bool is_equivalent_to(const Grid_Generator& y) const;
34128
34129  //! Returns <CODE>true</CODE> if \p *this is identical to \p y.
34130  /*!
34131    This is faster than is_equivalent_to(), but it may return `false' even
34132    for equivalent generators.
34133  */
34134  bool is_equal_to(const Grid_Generator& y) const;
34135
34136  /*! \brief
34137    Returns <CODE>true</CODE> if and only if all the homogeneous terms
34138    of \p *this are \f$0\f$.
34139  */
34140  bool all_homogeneous_terms_are_zero() const;
34141
34142  //! Checks if all the invariants are satisfied.
34143  bool OK() const;
34144
34145  PPL_OUTPUT_DECLARATIONS
34146
34147  /*! \brief
34148    Loads from \p s an ASCII representation (as produced by
34149    ascii_dump(std::ostream&) const) and sets \p *this accordingly.
34150    Returns <CODE>true</CODE> if successful, <CODE>false</CODE> otherwise.
34151  */
34152  bool ascii_load(std::istream& s);
34153
34154  //! Swaps \p *this with \p y.
34155  void m_swap(Grid_Generator& y);
34156
34157  /*! \brief
34158    Scales \p *this to be represented with a divisor of \p d (if
34159    \*this is a parameter or point). Does nothing at all on lines.
34160
34161    It is assumed that \p d is a multiple of the current divisor
34162    and different from zero. The behavior is undefined if the assumption
34163    does not hold.
34164  */
34165  void scale_to_divisor(Coefficient_traits::const_reference d);
34166
34167  //! Sets the divisor of \p *this to \p d.
34168  /*!
34169    \exception std::invalid_argument
34170    Thrown if \p *this is a line.
34171  */
34172  void set_divisor(Coefficient_traits::const_reference d);
34173
34174  //! The type of the (adapted) internal expression.
34175  typedef Expression_Hide_Last<Expression_Hide_Inhomo<Linear_Expression> >
34176  expr_type;
34177  //! Partial read access to the (adapted) internal expression.
34178  expr_type expression() const;
34179
34180private:
34181  Linear_Expression expr;
34182
34183  Kind kind_;
34184
34185  /*! \brief
34186    Holds (between class initialization and finalization) a pointer to
34187    the origin of the zero-dimensional space \f$\Rset^0\f$.
34188  */
34189  static const Grid_Generator* zero_dim_point_p;
34190
34191  //! Constructs a Grid_Generator with the specified space dimension, kind
34192  //! and topology.
34193  Grid_Generator(dimension_type space_dim, Kind kind, Topology topology,
34194                 Representation r = default_representation);
34195
34196  // TODO: Avoid reducing the space dimension.
34197  /*! \brief
34198    Constructs a grid generator of type \p t from linear expression \p e,
34199    stealing the underlying data structures from \p e.
34200
34201    The last column in \p e becomes the parameter divisor column of
34202    the new Grid_Generator.
34203
34204    \note The new Grid_Generator will have the same representation as `e'.
34205  */
34206  Grid_Generator(Linear_Expression& e, Type t);
34207
34208  //! Sets the dimension of the vector space enclosing \p *this to
34209  //! \p space_dim .
34210  //! Sets the space dimension of the rows in the system to \p space_dim .
34211  /*!
34212    This method is for internal use, it does *not* assert OK() at the end,
34213    so it can be used for invalid objects.
34214  */
34215  void set_space_dimension_no_ok(dimension_type space_dim);
34216
34217  /*! \brief
34218    Returns <CODE>true</CODE> if \p *this is equal to \p gg in
34219    dimension \p dim.
34220  */
34221  bool is_equal_at_dimension(dimension_type dim,
34222                             const Grid_Generator& gg) const;
34223
34224  /*! \brief
34225    A print function, with fancy, more human-friendly output.
34226
34227    This is used by operator<<().
34228  */
34229  void fancy_print(std::ostream& s) const;
34230
34231  //! Converts the Grid_Generator into a parameter.
34232  void set_is_parameter();
34233
34234  //! Sets the Grid_Generator kind to <CODE>LINE_OR_EQUALITY</CODE>.
34235  void set_is_line();
34236
34237  //! Sets the Grid_Generator kind to <CODE>RAY_OR_POINT_OR_INEQUALITY</CODE>.
34238  void set_is_parameter_or_point();
34239
34240  //! \name Flags inspection methods
34241  //@{
34242  //! Returns the topological kind of \p *this.
34243  Topology topology() const;
34244
34245  /*! \brief
34246    Returns <CODE>true</CODE> if and only if the topology
34247    of \p *this row is not necessarily closed.
34248  */
34249  bool is_not_necessarily_closed() const;
34250
34251  /*! \brief
34252    Returns <CODE>true</CODE> if and only if the topology
34253    of \p *this row is necessarily closed.
34254  */
34255  bool is_necessarily_closed() const;
34256
34257  /*! \brief
34258    Returns <CODE>true</CODE> if and only if \p *this row
34259    represents a line or an equality.
34260  */
34261  bool is_line_or_equality() const;
34262
34263  /*! \brief
34264    Returns <CODE>true</CODE> if and only if \p *this row
34265    represents a ray, a point or an inequality.
34266  */
34267  bool is_ray_or_point_or_inequality() const;
34268  //@} // Flags inspection methods
34269
34270  //! \name Flags coercion methods
34271  //@{
34272
34273  //! Sets to \p x the topological kind of \p *this row.
34274  void set_topology(Topology x);
34275
34276  //! Sets to \p NECESSARILY_CLOSED the topological kind of \p *this row.
34277  void set_necessarily_closed();
34278
34279  //! Sets to \p NOT_NECESSARILY_CLOSED the topological kind of \p *this row.
34280  void set_not_necessarily_closed();
34281
34282  //! Sets to \p LINE_OR_EQUALITY the kind of \p *this row.
34283  void set_is_line_or_equality();
34284
34285  //! Sets to \p RAY_OR_POINT_OR_INEQUALITY the kind of \p *this row.
34286  void set_is_ray_or_point_or_inequality();
34287  //@} // Flags coercion methods
34288
34289  /*! \brief
34290    Normalizes the sign of the coefficients so that the first non-zero
34291    (homogeneous) coefficient of a line-or-equality is positive.
34292  */
34293  void sign_normalize();
34294
34295  /*! \brief
34296    Strong normalization: ensures that different Grid_Generator objects
34297    represent different hyperplanes or hyperspaces.
34298
34299    Applies both Grid_Generator::normalize() and Grid_Generator::sign_normalize().
34300  */
34301  void strong_normalize();
34302
34303  /*! \brief
34304    Returns <CODE>true</CODE> if and only if the coefficients are
34305    strongly normalized.
34306  */
34307  bool check_strong_normalized() const;
34308
34309  //! Linearly combines \p *this with \p y so that i-th coefficient is 0.
34310  /*!
34311    \param y
34312    The Grid_Generator that will be combined with \p *this object;
34313
34314    \param i
34315    The index of the coefficient that has to become \f$0\f$.
34316
34317    Computes a linear combination of \p *this and \p y having
34318    the i-th coefficient equal to \f$0\f$. Then it assigns
34319    the resulting Grid_Generator to \p *this and normalizes it.
34320  */
34321  void linear_combine(const Grid_Generator& y, dimension_type i);
34322
34323  /*! \brief
34324    Throw a <CODE>std::invalid_argument</CODE> exception containing
34325    the appropriate error message.
34326  */
34327  void
34328  throw_dimension_incompatible(const char* method,
34329                               const char* name_var,
34330                               const Variable v) const;
34331
34332  /*! \brief
34333    Throw a <CODE>std::invalid_argument</CODE> exception containing
34334    the appropriate error message.
34335  */
34336  void
34337  throw_invalid_argument(const char* method, const char* reason) const;
34338
34339  friend std::ostream&
34340  IO_Operators::operator<<(std::ostream& s, const Grid_Generator& g);
34341
34342  friend int
34343  compare(const Grid_Generator& x, const Grid_Generator& y);
34344
34345  friend class Expression_Adapter<Grid_Generator>;
34346  friend class Grid_Generator_System;
34347  friend class Grid;
34348  friend class Linear_System<Grid_Generator>;
34349  friend class Scalar_Products;
34350  friend class Topology_Adjusted_Scalar_Product_Sign;
34351};
34352
34353
34354namespace Parma_Polyhedra_Library {
34355
34356/*! \brief
34357  Shorthand for
34358  Grid_Generator::grid_line(const Linear_Expression& e, Representation r).
34359
34360  \relates Grid_Generator
34361*/
34362Grid_Generator
34363grid_line(const Linear_Expression& e,
34364          Representation r = Grid_Generator::default_representation);
34365
34366/*! \brief
34367  Shorthand for
34368  Grid_Generator::parameter(const Linear_Expression& e, Coefficient_traits::const_reference d, Representation r).
34369
34370  \relates Grid_Generator
34371*/
34372Grid_Generator
34373parameter(const Linear_Expression& e = Linear_Expression::zero(),
34374          Coefficient_traits::const_reference d = Coefficient_one(),
34375          Representation r = Grid_Generator::default_representation);
34376
34377//! Shorthand for Grid_Generator::parameter(Representation r).
34378/*! \relates Grid_Generator */
34379Grid_Generator
34380parameter(Representation r);
34381
34382/*! \brief
34383  Shorthand for
34384  Grid_Generator::parameter(const Linear_Expression& e, Representation r).
34385
34386  \relates Grid_Generator
34387*/
34388Grid_Generator
34389parameter(const Linear_Expression& e, Representation r);
34390
34391/*! \brief
34392  Shorthand for
34393  Grid_Generator::grid_point(const Linear_Expression& e, Coefficient_traits::const_reference d, Representation r).
34394
34395  \relates Grid_Generator
34396*/
34397Grid_Generator
34398grid_point(const Linear_Expression& e = Linear_Expression::zero(),
34399           Coefficient_traits::const_reference d = Coefficient_one(),
34400           Representation r = Grid_Generator::default_representation);
34401
34402//! Shorthand for Grid_Generator::grid_point(Representation r).
34403/*! \relates Grid_Generator */
34404Grid_Generator
34405grid_point(Representation r);
34406
34407/*! \brief
34408  Shorthand for
34409  Grid_Generator::grid_point(const Linear_Expression& e, Representation r).
34410
34411  \relates Grid_Generator
34412*/
34413Grid_Generator
34414grid_point(const Linear_Expression& e, Representation r);
34415
34416//! Returns <CODE>true</CODE> if and only if \p x is equivalent to \p y.
34417/*! \relates Grid_Generator */
34418bool operator==(const Grid_Generator& x, const Grid_Generator& y);
34419
34420//! Returns <CODE>true</CODE> if and only if \p x is not equivalent to \p y.
34421/*! \relates Grid_Generator */
34422bool operator!=(const Grid_Generator& x, const Grid_Generator& y);
34423
34424
34425namespace IO_Operators {
34426
34427//! Output operator.
34428/*! \relates Parma_Polyhedra_Library::Grid_Generator */
34429std::ostream& operator<<(std::ostream& s, const Grid_Generator::Type& t);
34430
34431} // namespace IO_Operators
34432
34433} // namespace Parma_Polyhedra_Library
34434
34435/* Automatically generated from PPL source file ../src/Grid_Generator_inlines.hh line 1. */
34436/* Grid Generator class implementation: inline functions.
34437*/
34438
34439
34440namespace Parma_Polyhedra_Library {
34441
34442inline bool
34443Grid_Generator::is_necessarily_closed() const {
34444  return true;
34445}
34446
34447inline bool
34448Grid_Generator::is_not_necessarily_closed() const {
34449  return false;
34450}
34451
34452inline bool
34453Grid_Generator::is_line_or_equality() const {
34454  return (kind_ == LINE_OR_EQUALITY);
34455}
34456
34457inline bool
34458Grid_Generator::is_ray_or_point_or_inequality() const {
34459  return (kind_ == RAY_OR_POINT_OR_INEQUALITY);
34460}
34461
34462inline Topology
34463Grid_Generator::topology() const {
34464  return NECESSARILY_CLOSED;
34465}
34466
34467inline void
34468Grid_Generator::set_is_line_or_equality() {
34469  kind_ = LINE_OR_EQUALITY;
34470}
34471
34472inline void
34473Grid_Generator::set_is_ray_or_point_or_inequality() {
34474  kind_ = RAY_OR_POINT_OR_INEQUALITY;
34475}
34476
34477inline void
34478Grid_Generator::set_topology(Topology x) {
34479  PPL_USED(x);
34480  PPL_ASSERT(x == NECESSARILY_CLOSED);
34481}
34482
34483inline void
34484Grid_Generator::set_necessarily_closed() {
34485  set_topology(NECESSARILY_CLOSED);
34486}
34487
34488inline void
34489Grid_Generator::set_not_necessarily_closed() {
34490  set_topology(NOT_NECESSARILY_CLOSED);
34491}
34492
34493inline
34494Grid_Generator::Grid_Generator(Linear_Expression& e, Type type) {
34495  swap(expr, e);
34496  if (type == LINE) {
34497    kind_ = LINE_OR_EQUALITY;
34498  }
34499  else {
34500    kind_ = RAY_OR_POINT_OR_INEQUALITY;
34501  }
34502  PPL_ASSERT(OK());
34503}
34504
34505inline
34506Grid_Generator::Grid_Generator(Representation r)
34507  : expr(Coefficient_one(), r),
34508    kind_(RAY_OR_POINT_OR_INEQUALITY) {
34509  expr.set_space_dimension(1);
34510  PPL_ASSERT(OK());
34511}
34512
34513inline
34514Grid_Generator::Grid_Generator(const Grid_Generator& g)
34515  : expr(g.expr),
34516    kind_(g.kind_) {
34517}
34518
34519inline
34520Grid_Generator::Grid_Generator(const Grid_Generator& g, Representation r)
34521  : expr(g.expr, r),
34522    kind_(g.kind_) {
34523}
34524
34525inline
34526Grid_Generator::Grid_Generator(dimension_type space_dim, Kind kind,
34527                               Topology topology, Representation r)
34528  : expr(r),
34529    kind_(kind) {
34530  PPL_USED(topology);
34531  PPL_ASSERT(topology == NECESSARILY_CLOSED);
34532  expr.set_space_dimension(space_dim + 1);
34533  PPL_ASSERT(space_dimension() == space_dim);
34534}
34535
34536inline
34537Grid_Generator::Grid_Generator(const Grid_Generator& g,
34538                               dimension_type space_dim)
34539  : expr(g.expr, space_dim + 1),
34540    kind_(g.kind_) {
34541  PPL_ASSERT(OK());
34542  PPL_ASSERT(space_dimension() == space_dim);
34543}
34544
34545inline
34546Grid_Generator::Grid_Generator(const Grid_Generator& g,
34547                               dimension_type space_dim, Representation r)
34548  : expr(g.expr, space_dim + 1, r),
34549    kind_(g.kind_) {
34550  PPL_ASSERT(OK());
34551  PPL_ASSERT(space_dimension() == space_dim);
34552}
34553
34554inline
34555Grid_Generator::~Grid_Generator() {
34556}
34557
34558inline Grid_Generator::expr_type
34559Grid_Generator::expression() const {
34560  return expr_type(expr, true);
34561}
34562
34563inline Representation
34564Grid_Generator::representation() const {
34565  return expr.representation();
34566}
34567
34568inline void
34569Grid_Generator::set_representation(Representation r) {
34570  expr.set_representation(r);
34571}
34572
34573inline dimension_type
34574Grid_Generator::max_space_dimension() {
34575  return Linear_Expression::max_space_dimension() - 1;
34576}
34577
34578inline dimension_type
34579Grid_Generator::space_dimension() const {
34580  return expression().space_dimension();
34581}
34582
34583inline void
34584Grid_Generator::set_space_dimension(dimension_type space_dim) {
34585  const dimension_type old_space_dim = space_dimension();
34586  if (space_dim > old_space_dim) {
34587    expr.set_space_dimension(space_dim + 1);
34588    expr.swap_space_dimensions(Variable(space_dim), Variable(old_space_dim));
34589  }
34590  else {
34591    expr.swap_space_dimensions(Variable(space_dim), Variable(old_space_dim));
34592    expr.set_space_dimension(space_dim + 1);
34593  }
34594  PPL_ASSERT(space_dimension() == space_dim);
34595}
34596
34597inline void
34598Grid_Generator::set_space_dimension_no_ok(dimension_type space_dim) {
34599  set_space_dimension(space_dim);
34600}
34601
34602inline void
34603Grid_Generator::shift_space_dimensions(Variable v, dimension_type n) {
34604  expr.shift_space_dimensions(v, n);
34605}
34606
34607inline Grid_Generator::Type
34608Grid_Generator::type() const {
34609  if (is_line()) {
34610    return LINE;
34611  }
34612  return is_point() ? POINT : PARAMETER;
34613}
34614
34615inline bool
34616Grid_Generator::is_line() const {
34617  return is_line_or_equality();
34618}
34619
34620inline bool
34621Grid_Generator::is_parameter() const {
34622  return is_parameter_or_point() && is_line_or_parameter();
34623}
34624
34625inline bool
34626Grid_Generator::is_line_or_parameter() const {
34627  return expr.inhomogeneous_term() == 0;
34628}
34629
34630inline bool
34631Grid_Generator::is_point() const {
34632  return !is_line_or_parameter();
34633}
34634
34635inline bool
34636Grid_Generator::is_parameter_or_point() const {
34637  return is_ray_or_point_or_inequality();
34638}
34639
34640inline void
34641Grid_Generator::set_divisor(Coefficient_traits::const_reference d) {
34642  PPL_ASSERT(!is_line());
34643  if (is_line_or_parameter()) {
34644    expr.set_coefficient(Variable(space_dimension()), d);
34645  }
34646  else {
34647    expr.set_inhomogeneous_term(d);
34648  }
34649}
34650
34651inline Coefficient_traits::const_reference
34652Grid_Generator::divisor() const {
34653  if (is_line()) {
34654    throw_invalid_argument("divisor()", "*this is a line");
34655  }
34656  if (is_line_or_parameter()) {
34657    return expr.coefficient(Variable(space_dimension()));
34658  }
34659  else {
34660    return expr.inhomogeneous_term();
34661  }
34662}
34663
34664inline bool
34665Grid_Generator::is_equal_at_dimension(dimension_type dim,
34666                                      const Grid_Generator& y) const {
34667  const Grid_Generator& x = *this;
34668  return x.expr.get(dim) * y.divisor() == y.expr.get(dim) * x.divisor();
34669}
34670
34671inline void
34672Grid_Generator::set_is_line() {
34673  set_is_line_or_equality();
34674}
34675
34676inline void
34677Grid_Generator::set_is_parameter_or_point() {
34678  set_is_ray_or_point_or_inequality();
34679}
34680
34681inline Grid_Generator&
34682Grid_Generator::operator=(const Grid_Generator& g) {
34683  Grid_Generator tmp = g;
34684  swap(*this, tmp);
34685
34686  return *this;
34687}
34688
34689inline Coefficient_traits::const_reference
34690Grid_Generator::coefficient(const Variable v) const {
34691  if (v.space_dimension() > space_dimension()) {
34692    throw_dimension_incompatible("coefficient(v)", "v", v);
34693  }
34694  return expr.coefficient(v);
34695}
34696
34697inline memory_size_type
34698Grid_Generator::total_memory_in_bytes() const {
34699  return sizeof(*this) + external_memory_in_bytes();
34700}
34701
34702inline memory_size_type
34703Grid_Generator::external_memory_in_bytes() const {
34704  return expr.external_memory_in_bytes();
34705}
34706
34707inline const Grid_Generator&
34708Grid_Generator::zero_dim_point() {
34709  PPL_ASSERT(zero_dim_point_p != 0);
34710  return *zero_dim_point_p;
34711}
34712
34713inline void
34714Grid_Generator::strong_normalize() {
34715  PPL_ASSERT(!is_parameter());
34716  expr.normalize();
34717  sign_normalize();
34718}
34719
34720inline void
34721Grid_Generator::m_swap(Grid_Generator& y) {
34722  using std::swap;
34723  swap(expr, y.expr);
34724  swap(kind_, y.kind_);
34725}
34726
34727/*! \relates Grid_Generator */
34728inline bool
34729operator==(const Grid_Generator& x, const Grid_Generator& y) {
34730  return x.is_equivalent_to(y);
34731}
34732
34733/*! \relates Grid_Generator */
34734inline bool
34735operator!=(const Grid_Generator& x, const Grid_Generator& y) {
34736  return !(x == y);
34737}
34738
34739/*! \relates Grid_Generator */
34740inline Grid_Generator
34741grid_line(const Linear_Expression& e, Representation r) {
34742  return Grid_Generator::grid_line(e, r);
34743}
34744
34745/*! \relates Grid_Generator */
34746inline Grid_Generator
34747parameter(const Linear_Expression& e,
34748          Coefficient_traits::const_reference d, Representation r) {
34749  return Grid_Generator::parameter(e, d, r);
34750}
34751
34752/*! \relates Grid_Generator */
34753inline Grid_Generator
34754parameter(Representation r) {
34755  return Grid_Generator::parameter(r);
34756}
34757
34758/*! \relates Grid_Generator */
34759inline Grid_Generator
34760parameter(const Linear_Expression& e, Representation r) {
34761  return Grid_Generator::parameter(e, r);
34762}
34763
34764/*! \relates Grid_Generator */
34765inline Grid_Generator
34766grid_point(const Linear_Expression& e,
34767           Coefficient_traits::const_reference d, Representation r) {
34768  return Grid_Generator::grid_point(e, d, r);
34769}
34770
34771/*! \relates Grid_Generator */
34772inline Grid_Generator
34773grid_point(Representation r) {
34774  return Grid_Generator::grid_point(r);
34775}
34776
34777/*! \relates Grid_Generator */
34778inline Grid_Generator
34779grid_point(const Linear_Expression& e, Representation r) {
34780  return Grid_Generator::grid_point(e, r);
34781}
34782
34783/*! \relates Grid_Generator */
34784inline void
34785swap(Grid_Generator& x, Grid_Generator& y) {
34786  x.m_swap(y);
34787}
34788
34789} // namespace Parma_Polyhedra_Library
34790
34791/* Automatically generated from PPL source file ../src/Grid_Generator_defs.hh line 795. */
34792
34793/* Automatically generated from PPL source file ../src/Congruence_defs.hh line 1. */
34794/* Congruence class declaration.
34795*/
34796
34797
34798/* Automatically generated from PPL source file ../src/Congruence_defs.hh line 28. */
34799
34800/* Automatically generated from PPL source file ../src/Congruence_defs.hh line 31. */
34801
34802/* Automatically generated from PPL source file ../src/Congruence_defs.hh line 37. */
34803
34804#include <iosfwd>
34805#include <vector>
34806
34807// These are declared here because they are friend of Congruence.
34808namespace Parma_Polyhedra_Library {
34809
34810//! Returns <CODE>true</CODE> if and only if \p x and \p y are equivalent.
34811/*! \relates Congruence */
34812bool
34813operator==(const Congruence& x, const Congruence& y);
34814
34815//! Returns <CODE>false</CODE> if and only if \p x and \p y are equivalent.
34816/*! \relates Congruence */
34817bool
34818operator!=(const Congruence& x, const Congruence& y);
34819
34820} // namespace Parma_Polyhedra_Library
34821
34822
34823//! A linear congruence.
34824/*! \ingroup PPL_CXX_interface
34825  An object of the class Congruence is a congruence:
34826  - \f$\cg = \sum_{i=0}^{n-1} a_i x_i + b = 0 \pmod m\f$
34827
34828  where \f$n\f$ is the dimension of the space,
34829  \f$a_i\f$ is the integer coefficient of variable \f$x_i\f$,
34830  \f$b\f$ is the integer inhomogeneous term and \f$m\f$ is the integer modulus;
34831  if \f$m = 0\f$, then \f$\cg\f$ represents the equality congruence
34832  \f$\sum_{i=0}^{n-1} a_i x_i + b = 0\f$
34833  and, if \f$m \neq 0\f$, then the congruence \f$\cg\f$ is
34834  said to be a proper congruence.
34835
34836  \par How to build a congruence
34837  Congruences \f$\pmod{1}\f$ are typically built by
34838  applying the congruence symbol `<CODE>\%=</CODE>'
34839  to a pair of linear expressions.
34840  Congruences with modulus \p m
34841  are typically constructed by building a congruence \f$\pmod{1}\f$
34842  using the given pair of linear expressions
34843  and then adding the modulus \p m
34844  using the modulus symbol is `<CODE>/</CODE>'.
34845
34846  The space dimension of a congruence is defined as the maximum
34847  space dimension of the arguments of its constructor.
34848
34849  \par
34850  In the following examples it is assumed that variables
34851  <CODE>x</CODE>, <CODE>y</CODE> and <CODE>z</CODE>
34852  are defined as follows:
34853  \code
34854  Variable x(0);
34855  Variable y(1);
34856  Variable z(2);
34857  \endcode
34858
34859  \par Example 1
34860  The following code builds the equality congruence
34861  \f$3x + 5y - z = 0\f$, having space dimension \f$3\f$:
34862  \code
34863  Congruence eq_cg((3*x + 5*y - z %= 0) / 0);
34864  \endcode
34865  The following code builds the congruence
34866  \f$4x = 2y - 13 \pmod{1}\f$, having space dimension \f$2\f$:
34867  \code
34868  Congruence mod1_cg(4*x %= 2*y - 13);
34869  \endcode
34870  The following code builds the congruence
34871  \f$4x = 2y - 13 \pmod{2}\f$, having space dimension \f$2\f$:
34872  \code
34873  Congruence mod2_cg((4*x %= 2*y - 13) / 2);
34874  \endcode
34875  An unsatisfiable congruence on the zero-dimension space \f$\Rset^0\f$
34876  can be specified as follows:
34877  \code
34878  Congruence false_cg = Congruence::zero_dim_false();
34879  \endcode
34880  Equivalent, but more involved ways are the following:
34881  \code
34882  Congruence false_cg1((Linear_Expression::zero() %= 1) / 0);
34883  Congruence false_cg2((Linear_Expression::zero() %= 1) / 2);
34884  \endcode
34885  In contrast, the following code defines an unsatisfiable congruence
34886  having space dimension \f$3\f$:
34887  \code
34888  Congruence false_cg3((0*z %= 1) / 0);
34889  \endcode
34890
34891  \par How to inspect a congruence
34892  Several methods are provided to examine a congruence and extract
34893  all the encoded information: its space dimension, its modulus
34894  and the value of its integer coefficients.
34895
34896  \par Example 2
34897  The following code shows how it is possible to access the modulus
34898  as well as each of the coefficients.
34899  Given a congruence with linear expression \p e and modulus \p m
34900  (in this case \f$x - 5y + 3z = 4 \pmod{5}\f$), we construct a new
34901  congruence with the same modulus \p m but where the linear
34902  expression is \f$2 e\f$ (\f$2x - 10y + 6z = 8 \pmod{5}\f$).
34903  \code
34904  Congruence cg1((x - 5*y + 3*z %= 4) / 5);
34905  cout << "Congruence cg1: " << cg1 << endl;
34906  const Coefficient& m = cg1.modulus();
34907  if (m == 0)
34908    cout << "Congruence cg1 is an equality." << endl;
34909  else {
34910    Linear_Expression e;
34911    for (dimension_type i = cg1.space_dimension(); i-- > 0; )
34912      e += 2 * cg1.coefficient(Variable(i)) * Variable(i);
34913      e += 2 * cg1.inhomogeneous_term();
34914    Congruence cg2((e %= 0) / m);
34915    cout << "Congruence cg2: " << cg2 << endl;
34916  }
34917  \endcode
34918  The actual output could be the following:
34919  \code
34920  Congruence cg1: A - 5*B + 3*C %= 4 / 5
34921  Congruence cg2: 2*A - 10*B + 6*C %= 8 / 5
34922  \endcode
34923  Note that, in general, the particular output obtained can be
34924  syntactically different from the (semantically equivalent)
34925  congruence considered.
34926*/
34927class Parma_Polyhedra_Library::Congruence {
34928public:
34929
34930  //! The representation used for new Congruences.
34931  /*!
34932    \note The copy constructor and the copy constructor with specified size
34933          use the representation of the original object, so that it is
34934          indistinguishable from the original object.
34935  */
34936  static const Representation default_representation = SPARSE;
34937
34938  //! Constructs the 0 = 0 congruence with space dimension \p 0 .
34939  explicit Congruence(Representation r = default_representation);
34940
34941  //! Ordinary copy constructor.
34942  /*!
34943    \note The new Congruence will have the same representation as `cg',
34944          not default_representation, so that they are indistinguishable.
34945  */
34946  Congruence(const Congruence& cg);
34947
34948  //! Copy constructor with specified representation.
34949  Congruence(const Congruence& cg, Representation r);
34950
34951  //! Copy-constructs (modulo 0) from equality constraint \p c.
34952  /*!
34953    \exception std::invalid_argument
34954    Thrown if \p c is an inequality.
34955  */
34956  explicit Congruence(const Constraint& c,
34957                      Representation r = default_representation);
34958
34959  //! Destructor.
34960  ~Congruence();
34961
34962  //! Assignment operator.
34963  Congruence& operator=(const Congruence& y);
34964
34965  //! Returns the current representation of *this.
34966  Representation representation() const;
34967
34968  //! Converts *this to the specified representation.
34969  void set_representation(Representation r);
34970
34971  //! Returns the maximum space dimension a Congruence can handle.
34972  static dimension_type max_space_dimension();
34973
34974  //! Returns the dimension of the vector space enclosing \p *this.
34975  dimension_type space_dimension() const;
34976
34977  void permute_space_dimensions(const std::vector<Variable>& cycles);
34978
34979  //! The type of the (adapted) internal expression.
34980  typedef Expression_Adapter_Transparent<Linear_Expression> expr_type;
34981  //! Partial read access to the (adapted) internal expression.
34982  expr_type expression() const;
34983
34984  //! Returns the coefficient of \p v in \p *this.
34985  /*!
34986    \exception std::invalid_argument thrown if the index of \p v
34987    is greater than or equal to the space dimension of \p *this.
34988  */
34989  Coefficient_traits::const_reference coefficient(Variable v) const;
34990
34991  //! Returns the inhomogeneous term of \p *this.
34992  Coefficient_traits::const_reference inhomogeneous_term() const;
34993
34994  //! Returns a const reference to the modulus of \p *this.
34995  Coefficient_traits::const_reference modulus() const;
34996
34997  //! Sets the modulus of \p *this to \p m .
34998  //! If \p m is 0, the congruence becomes an equality.
34999  void set_modulus(Coefficient_traits::const_reference m);
35000
35001  //! Multiplies all the coefficients, including the modulus, by \p factor .
35002  void scale(Coefficient_traits::const_reference factor);
35003
35004  // TODO: Document this.
35005  void affine_preimage(Variable v,
35006                       const Linear_Expression& expr,
35007                       Coefficient_traits::const_reference denominator);
35008
35009  //! Multiplies \p k into the modulus of \p *this.
35010  /*!
35011    If called with \p *this representing the congruence \f$ e_1 = e_2
35012    \pmod{m}\f$, then it returns with *this representing
35013    the congruence \f$ e_1 = e_2 \pmod{mk}\f$.
35014  */
35015  Congruence&
35016  operator/=(Coefficient_traits::const_reference k);
35017
35018  /*! \brief
35019    Returns <CODE>true</CODE> if and only if \p *this is a tautology
35020    (i.e., an always true congruence).
35021
35022    A tautological congruence has one the following two forms:
35023    - an equality: \f$\sum_{i=0}^{n-1} 0 x_i + 0 == 0\f$; or
35024    - a proper congruence: \f$\sum_{i=0}^{n-1} 0 x_i + b \%= 0 / m\f$,
35025      where \f$b = 0 \pmod{m}\f$.
35026  */
35027  bool is_tautological() const;
35028
35029  /*! \brief
35030    Returns <CODE>true</CODE> if and only if
35031    \p *this is inconsistent (i.e., an always false congruence).
35032
35033    An inconsistent congruence has one of the following two forms:
35034    - an equality: \f$\sum_{i=0}^{n-1} 0 x_i + b == 0\f$
35035      where \f$b \neq 0\f$; or
35036    - a proper congruence: \f$\sum_{i=0}^{n-1} 0 x_i + b \%= 0 / m\f$,
35037      where \f$b \neq 0 \pmod{m}\f$.
35038  */
35039  bool is_inconsistent() const;
35040
35041  //! Returns <CODE>true</CODE> if the modulus is greater than zero.
35042  /*!
35043    A congruence with a modulus of 0 is a linear equality.
35044  */
35045  bool is_proper_congruence() const;
35046
35047  //! Returns <CODE>true</CODE> if \p *this is an equality.
35048  /*!
35049    A modulus of zero denotes a linear equality.
35050  */
35051  bool is_equality() const;
35052
35053  //! Initializes the class.
35054  static void initialize();
35055
35056  //! Finalizes the class.
35057  static void finalize();
35058
35059  /*! \brief
35060    Returns a reference to the true (zero-dimension space) congruence
35061    \f$0 = 1 \pmod{1}\f$, also known as the <EM>integrality
35062    congruence</EM>.
35063  */
35064  static const Congruence& zero_dim_integrality();
35065
35066  /*! \brief
35067    Returns a reference to the false (zero-dimension space) congruence
35068    \f$0 = 1 \pmod{0}\f$.
35069  */
35070  static const Congruence& zero_dim_false();
35071
35072  //! Returns the congruence \f$e1 = e2 \pmod{1}\f$.
35073  static Congruence
35074  create(const Linear_Expression& e1, const Linear_Expression& e2,
35075         Representation r = default_representation);
35076
35077  //! Returns the congruence \f$e = n \pmod{1}\f$.
35078  static Congruence
35079  create(const Linear_Expression& e, Coefficient_traits::const_reference n,
35080         Representation r = default_representation);
35081
35082  //! Returns the congruence \f$n = e \pmod{1}\f$.
35083  static Congruence
35084  create(Coefficient_traits::const_reference n, const Linear_Expression& e,
35085         Representation r = default_representation);
35086
35087  /*! \brief
35088    Returns a lower bound to the total size in bytes of the memory
35089    occupied by \p *this.
35090  */
35091  memory_size_type total_memory_in_bytes() const;
35092
35093  //! Returns the size in bytes of the memory managed by \p *this.
35094  memory_size_type external_memory_in_bytes() const;
35095
35096  //! Checks if all the invariants are satisfied.
35097  bool OK() const;
35098
35099  PPL_OUTPUT_DECLARATIONS
35100
35101  /*! \brief
35102    Loads from \p s an ASCII representation of the internal
35103    representation of \p *this.
35104  */
35105  bool ascii_load(std::istream& s);
35106
35107  //! Swaps \p *this with \p y.
35108  void m_swap(Congruence& y);
35109
35110  //! Copy-constructs with the specified space dimension.
35111  /*!
35112    \note The new Congruence will have the same representation as `cg',
35113          not default_representation, for consistency with the copy
35114          constructor.
35115  */
35116  Congruence(const Congruence& cg, dimension_type new_space_dimension);
35117
35118  //! Copy-constructs with the specified space dimension and representation.
35119  Congruence(const Congruence& cg, dimension_type new_space_dimension,
35120             Representation r);
35121
35122  //! Copy-constructs from a constraint, with the specified space dimension
35123  //! and (optional) representation.
35124  Congruence(const Constraint& cg, dimension_type new_space_dimension,
35125             Representation r = default_representation);
35126
35127  //! Constructs from Linear_Expression \p le, using modulus \p m.
35128  /*!
35129    Builds a congruence with modulus \p m, stealing the coefficients
35130    from \p le.
35131
35132    \note The new Congruence will have the same representation as `le'.
35133
35134    \param le
35135    The Linear_Expression holding the coefficients.
35136
35137    \param m
35138    The modulus for the congruence, which must be zero or greater.
35139  */
35140  Congruence(Linear_Expression& le,
35141             Coefficient_traits::const_reference m, Recycle_Input);
35142
35143  //! Swaps the coefficients of the variables \p v1 and \p v2 .
35144  void swap_space_dimensions(Variable v1, Variable v2);
35145
35146  //! Sets the space dimension by \p n , adding or removing coefficients as
35147  //! needed.
35148  void set_space_dimension(dimension_type n);
35149
35150  //! Shift by \p n positions the coefficients of variables, starting from
35151  //! the coefficient of \p v. This increases the space dimension by \p n.
35152  void shift_space_dimensions(Variable v, dimension_type n);
35153
35154  //! Normalizes the signs.
35155  /*!
35156    The signs of the coefficients and the inhomogeneous term are
35157    normalized, leaving the first non-zero homogeneous coefficient
35158    positive.
35159  */
35160  void sign_normalize();
35161
35162  //! Normalizes signs and the inhomogeneous term.
35163  /*!
35164    Applies sign_normalize, then reduces the inhomogeneous term to the
35165    smallest possible positive number.
35166  */
35167  void normalize();
35168
35169  //! Calls normalize, then divides out common factors.
35170  /*!
35171    Strongly normalized Congruences have equivalent semantics if and
35172    only if they have the same syntax (as output by operator<<).
35173  */
35174  void strong_normalize();
35175
35176private:
35177  /*! \brief
35178    Holds (between class initialization and finalization) a pointer to
35179    the false (zero-dimension space) congruence \f$0 = 1 \pmod{0}\f$.
35180  */
35181  static const Congruence* zero_dim_false_p;
35182
35183  /*! \brief
35184    Holds (between class initialization and finalization) a pointer to
35185    the true (zero-dimension space) congruence \f$0 = 1 \pmod{1}\f$,
35186    also known as the <EM>integrality congruence</EM>.
35187  */
35188  static const Congruence* zero_dim_integrality_p;
35189
35190  Linear_Expression expr;
35191
35192  Coefficient modulus_;
35193
35194  /*! \brief
35195    Returns <CODE>true</CODE> if \p *this is equal to \p cg in
35196    dimension \p v.
35197  */
35198  bool is_equal_at_dimension(Variable v,
35199                             const Congruence& cg) const;
35200
35201  /*! \brief
35202    Throws a <CODE>std::invalid_argument</CODE> exception containing
35203    error message \p message.
35204  */
35205  void
35206  throw_invalid_argument(const char* method, const char* message) const;
35207
35208  /*! \brief
35209    Throws a <CODE>std::invalid_argument</CODE> exception containing
35210    the appropriate error message.
35211  */
35212  void
35213  throw_dimension_incompatible(const char* method,
35214                               const char* v_name,
35215                               Variable v) const;
35216
35217  friend bool
35218  operator==(const Congruence& x, const Congruence& y);
35219
35220  friend bool
35221  operator!=(const Congruence& x, const Congruence& y);
35222
35223  friend class Scalar_Products;
35224  friend class Grid;
35225};
35226
35227namespace Parma_Polyhedra_Library {
35228
35229namespace IO_Operators {
35230
35231//! Output operators.
35232
35233/*! \relates Parma_Polyhedra_Library::Congruence */
35234std::ostream&
35235operator<<(std::ostream& s, const Congruence& c);
35236
35237} // namespace IO_Operators
35238
35239//! Returns the congruence \f$e1 = e2 \pmod{1}\f$.
35240/*! \relates Congruence */
35241Congruence
35242operator%=(const Linear_Expression& e1, const Linear_Expression& e2);
35243
35244//! Returns the congruence \f$e = n \pmod{1}\f$.
35245/*! \relates Congruence */
35246Congruence
35247operator%=(const Linear_Expression& e, Coefficient_traits::const_reference n);
35248
35249//! Returns a copy of \p cg, multiplying \p k into the copy's modulus.
35250/*!
35251    If \p cg represents the congruence \f$ e_1 = e_2
35252    \pmod{m}\f$, then the result represents the
35253    congruence \f$ e_1 = e_2 \pmod{mk}\f$.
35254  \relates Congruence
35255*/
35256Congruence
35257operator/(const Congruence& cg, Coefficient_traits::const_reference k);
35258
35259//! Creates a congruence from \p c, with \p m as the modulus.
35260/*! \relates Congruence */
35261Congruence
35262operator/(const Constraint& c, Coefficient_traits::const_reference m);
35263
35264/*! \relates Congruence */
35265void
35266swap(Congruence& x, Congruence& y);
35267
35268} // namespace Parma_Polyhedra_Library
35269
35270/* Automatically generated from PPL source file ../src/Congruence_inlines.hh line 1. */
35271/* Congruence class implementation: inline functions.
35272*/
35273
35274
35275#include <sstream>
35276
35277namespace Parma_Polyhedra_Library {
35278
35279inline
35280Congruence::Congruence(Representation r)
35281  : expr(r) {
35282  PPL_ASSERT(OK());
35283}
35284
35285inline
35286Congruence::Congruence(const Congruence& cg)
35287  : expr(cg.expr), modulus_(cg.modulus_) {
35288}
35289
35290inline
35291Congruence::Congruence(const Congruence& cg, Representation r)
35292  : expr(cg.expr, r), modulus_(cg.modulus_) {
35293}
35294
35295inline
35296Congruence::Congruence(const Congruence& cg,
35297                       dimension_type new_space_dimension)
35298  : expr(cg.expr, new_space_dimension), modulus_(cg.modulus_) {
35299  PPL_ASSERT(OK());
35300}
35301
35302inline
35303Congruence::Congruence(const Congruence& cg,
35304                       dimension_type new_space_dimension,
35305                       Representation r)
35306  : expr(cg.expr, new_space_dimension, r), modulus_(cg.modulus_) {
35307  PPL_ASSERT(OK());
35308}
35309
35310inline Representation
35311Congruence::representation() const {
35312  return expr.representation();
35313}
35314
35315inline void
35316Congruence::set_representation(Representation r) {
35317  expr.set_representation(r);
35318}
35319
35320inline Congruence::expr_type
35321Congruence::expression() const {
35322  return expr_type(expr);
35323}
35324
35325inline void
35326Congruence::set_space_dimension(dimension_type n) {
35327  expr.set_space_dimension(n);
35328  PPL_ASSERT(OK());
35329}
35330
35331inline void
35332Congruence::shift_space_dimensions(Variable v, dimension_type n) {
35333  expr.shift_space_dimensions(v, n);
35334}
35335
35336inline
35337Congruence::~Congruence() {
35338}
35339
35340inline
35341Congruence::Congruence(Linear_Expression& le,
35342                       Coefficient_traits::const_reference m,
35343                       Recycle_Input)
35344  : modulus_(m) {
35345  PPL_ASSERT(m >= 0);
35346  swap(expr, le);
35347
35348  PPL_ASSERT(OK());
35349}
35350
35351inline Congruence
35352Congruence::create(const Linear_Expression& e,
35353                   Coefficient_traits::const_reference n,
35354                   Representation r) {
35355  Linear_Expression diff(e, r);
35356  diff -= n;
35357  const Congruence cg(diff, 1, Recycle_Input());
35358  return cg;
35359}
35360
35361inline Congruence
35362Congruence::create(Coefficient_traits::const_reference n,
35363                   const Linear_Expression& e,
35364                   Representation r) {
35365  Linear_Expression diff(e, r);
35366  diff -= n;
35367  const Congruence cg(diff, 1, Recycle_Input());
35368  return cg;
35369}
35370
35371/*! \relates Parma_Polyhedra_Library::Congruence */
35372inline Congruence
35373operator%=(const Linear_Expression& e1, const Linear_Expression& e2) {
35374  return Congruence::create(e1, e2);
35375}
35376
35377/*! \relates Parma_Polyhedra_Library::Congruence */
35378inline Congruence
35379operator%=(const Linear_Expression& e, Coefficient_traits::const_reference n) {
35380  return Congruence::create(e, n);
35381}
35382
35383/*! \relates Parma_Polyhedra_Library::Congruence */
35384inline Congruence
35385operator/(const Congruence& cg, Coefficient_traits::const_reference k) {
35386  Congruence ret = cg;
35387  ret /= k;
35388  return ret;
35389}
35390
35391inline const Congruence&
35392Congruence::zero_dim_integrality() {
35393  return *zero_dim_integrality_p;
35394}
35395
35396inline const Congruence&
35397Congruence::zero_dim_false() {
35398  return *zero_dim_false_p;
35399}
35400
35401inline Congruence&
35402Congruence::operator=(const Congruence& y) {
35403  Congruence tmp = y;
35404  swap(*this, tmp);
35405  return *this;
35406}
35407
35408/*! \relates Congruence */
35409inline Congruence
35410operator/(const Constraint& c, Coefficient_traits::const_reference m) {
35411  Congruence ret(c);
35412  ret /= m;
35413  return ret;
35414}
35415
35416inline Congruence&
35417Congruence::operator/=(Coefficient_traits::const_reference k) {
35418  if (k >= 0) {
35419    modulus_ *= k;
35420  }
35421  else {
35422    modulus_ *= -k;
35423  }
35424  return *this;
35425}
35426
35427/*! \relates Congruence */
35428inline bool
35429operator==(const Congruence& x, const Congruence& y) {
35430  if (x.space_dimension() != y.space_dimension()) {
35431    return false;
35432  }
35433  Congruence x_temp(x);
35434  Congruence y_temp(y);
35435  x_temp.strong_normalize();
35436  y_temp.strong_normalize();
35437  return x_temp.expr.is_equal_to(y_temp.expr)
35438    && x_temp.modulus() == y_temp.modulus();
35439}
35440
35441/*! \relates Congruence */
35442inline bool
35443operator!=(const Congruence& x, const Congruence& y) {
35444  return !(x == y);
35445}
35446
35447inline dimension_type
35448Congruence::max_space_dimension() {
35449  return Linear_Expression::max_space_dimension();
35450}
35451
35452inline dimension_type
35453Congruence::space_dimension() const {
35454  return expr.space_dimension();
35455}
35456
35457inline Coefficient_traits::const_reference
35458Congruence::coefficient(const Variable v) const {
35459  if (v.space_dimension() > space_dimension()) {
35460    throw_dimension_incompatible("coefficient(v)", "v", v);
35461  }
35462  return expr.coefficient(v);
35463}
35464
35465inline void
35466Congruence::permute_space_dimensions(const std::vector<Variable>& cycles) {
35467  expr.permute_space_dimensions(cycles);
35468}
35469
35470inline Coefficient_traits::const_reference
35471Congruence::inhomogeneous_term() const {
35472  return expr.inhomogeneous_term();
35473}
35474
35475inline Coefficient_traits::const_reference
35476Congruence::modulus() const {
35477  return modulus_;
35478}
35479
35480inline void
35481Congruence::set_modulus(Coefficient_traits::const_reference m) {
35482  modulus_ = m;
35483  PPL_ASSERT(OK());
35484}
35485
35486inline bool
35487Congruence::is_proper_congruence() const {
35488  return modulus() > 0;
35489}
35490
35491inline bool
35492Congruence::is_equality() const {
35493  return modulus() == 0;
35494}
35495
35496inline bool
35497Congruence::is_equal_at_dimension(Variable v,
35498                                  const Congruence& cg) const {
35499  return coefficient(v) * cg.modulus() == cg.coefficient(v) * modulus();
35500}
35501
35502inline memory_size_type
35503Congruence::external_memory_in_bytes() const {
35504  return expr.external_memory_in_bytes()
35505         + Parma_Polyhedra_Library::external_memory_in_bytes(modulus_);
35506}
35507
35508inline memory_size_type
35509Congruence::total_memory_in_bytes() const {
35510  return external_memory_in_bytes() + sizeof(*this);
35511}
35512
35513inline void
35514Congruence::m_swap(Congruence& y) {
35515  using std::swap;
35516  swap(expr, y.expr);
35517  swap(modulus_, y.modulus_);
35518}
35519
35520inline void
35521Congruence::swap_space_dimensions(Variable v1, Variable v2) {
35522  expr.swap_space_dimensions(v1, v2);
35523}
35524
35525/*! \relates Congruence */
35526inline void
35527swap(Congruence& x, Congruence& y) {
35528  x.m_swap(y);
35529}
35530
35531} // namespace Parma_Polyhedra_Library
35532
35533/* Automatically generated from PPL source file ../src/Congruence_defs.hh line 505. */
35534
35535/* Automatically generated from PPL source file ../src/Linear_Expression_Impl_templates.hh line 34. */
35536#include <stdexcept>
35537#include <iostream>
35538
35539namespace Parma_Polyhedra_Library {
35540
35541template <typename Row>
35542Linear_Expression_Impl<Row>
35543::Linear_Expression_Impl(const Linear_Expression_Impl& e) {
35544  construct(e);
35545}
35546
35547template <typename Row>
35548template <typename Row2>
35549Linear_Expression_Impl<Row>
35550::Linear_Expression_Impl(const Linear_Expression_Impl<Row2>& e) {
35551  construct(e);
35552}
35553
35554template <typename Row>
35555Linear_Expression_Impl<Row>
35556::Linear_Expression_Impl(const Linear_Expression_Interface& e) {
35557  typedef const Linear_Expression_Impl<Dense_Row>* Dense_Ptr;
35558  typedef const Linear_Expression_Impl<Sparse_Row>* Sparse_Ptr;
35559  if (const Dense_Ptr p = dynamic_cast<Dense_Ptr>(&e)) {
35560    construct(*p);
35561  }
35562  else if (const Sparse_Ptr p = dynamic_cast<Sparse_Ptr>(&e)) {
35563    construct(*p);
35564  }
35565  else {
35566    // Add implementations for other derived classes here.
35567    PPL_UNREACHABLE;
35568  }
35569}
35570
35571template <typename Row>
35572Linear_Expression_Impl<Row>
35573::Linear_Expression_Impl(const Linear_Expression_Interface& e,
35574                         dimension_type space_dim) {
35575  typedef const Linear_Expression_Impl<Dense_Row>* Dense_Ptr;
35576  typedef const Linear_Expression_Impl<Sparse_Row>* Sparse_Ptr;
35577  if (const Dense_Ptr p = dynamic_cast<Dense_Ptr>(&e)) {
35578    construct(*p, space_dim);
35579  }
35580  else if (const Sparse_Ptr p = dynamic_cast<Sparse_Ptr>(&e)) {
35581    construct(*p, space_dim);
35582  }
35583  else {
35584    // Add implementations for other derived classes here.
35585    PPL_UNREACHABLE;
35586  }
35587}
35588
35589template <typename Row>
35590template <typename Row2>
35591void
35592Linear_Expression_Impl<Row>
35593::linear_combine(const Linear_Expression_Impl<Row2>& y, Variable i) {
35594  PPL_ASSERT(space_dimension() == y.space_dimension());
35595  PPL_ASSERT(i.space_dimension() <= space_dimension());
35596  linear_combine(y, i.space_dimension());
35597}
35598
35599template <typename Row>
35600template <typename Row2>
35601void
35602Linear_Expression_Impl<Row>
35603::linear_combine(const Linear_Expression_Impl<Row2>& y, dimension_type i) {
35604  const Linear_Expression_Impl& x = *this;
35605  PPL_ASSERT(i < x.space_dimension() + 1);
35606  PPL_ASSERT(x.space_dimension() == y.space_dimension());
35607  Coefficient_traits::const_reference x_i = x.row.get(i);
35608  Coefficient_traits::const_reference y_i = y.row.get(i);
35609  PPL_ASSERT(x_i != 0);
35610  PPL_ASSERT(y_i != 0);
35611  PPL_DIRTY_TEMP_COEFFICIENT(normalized_x_v);
35612  PPL_DIRTY_TEMP_COEFFICIENT(normalized_y_v);
35613  normalize2(x_i, y_i, normalized_x_v, normalized_y_v);
35614  neg_assign(normalized_x_v);
35615  linear_combine(y, normalized_y_v, normalized_x_v);
35616  // We cannot use x_i here because it may have been invalidated by
35617  // linear_combine().
35618  assert(x.row.get(i) == 0);
35619  PPL_ASSERT(OK());
35620}
35621
35622template <typename Row>
35623template <typename Row2>
35624void
35625Linear_Expression_Impl<Row>
35626::linear_combine(const Linear_Expression_Impl<Row2>& y,
35627                 Coefficient_traits::const_reference c1,
35628                 Coefficient_traits::const_reference c2) {
35629  PPL_ASSERT(c1 != 0);
35630  PPL_ASSERT(c2 != 0);
35631  if (space_dimension() < y.space_dimension()) {
35632    set_space_dimension(y.space_dimension());
35633  }
35634  linear_combine(y, c1, c2, 0, y.space_dimension() + 1);
35635  PPL_ASSERT(OK());
35636}
35637
35638template <typename Row>
35639template <typename Row2>
35640void
35641Linear_Expression_Impl<Row>
35642::linear_combine_lax(const Linear_Expression_Impl<Row2>& y,
35643                     Coefficient_traits::const_reference c1,
35644                     Coefficient_traits::const_reference c2) {
35645  if (space_dimension() < y.space_dimension()) {
35646    set_space_dimension(y.space_dimension());
35647  }
35648  linear_combine_lax(y, c1, c2, 0, y.space_dimension() + 1);
35649  PPL_ASSERT(OK());
35650}
35651
35652template <typename Row>
35653template <typename Row2>
35654int
35655Linear_Expression_Impl<Row>
35656::compare(const Linear_Expression_Impl<Row2>& y) const {
35657  const Linear_Expression_Impl& x = *this;
35658  // Compare all the coefficients of the row starting from position 1.
35659  // NOTE: x and y may be of different size.
35660  typename Row::const_iterator i = x.row.lower_bound(1);
35661  typename Row::const_iterator i_end = x.row.end();
35662  typename Row2::const_iterator j = y.row.lower_bound(1);
35663  typename Row2::const_iterator j_end = y.row.end();
35664  while (i != i_end && j != j_end) {
35665    if (i.index() < j.index()) {
35666      const int s = sgn(*i);
35667      if (s != 0) {
35668        return 2*s;
35669      }
35670      ++i;
35671      continue;
35672    }
35673    if (i.index() > j.index()) {
35674      const int s = sgn(*j);
35675      if (s != 0) {
35676        return -2*s;
35677      }
35678      ++j;
35679      continue;
35680    }
35681    PPL_ASSERT(i.index() == j.index());
35682    const int s = cmp(*i, *j);
35683    if (s < 0) {
35684      return -2;
35685    }
35686    if (s > 0) {
35687      return 2;
35688    }
35689    PPL_ASSERT(s == 0);
35690    ++i;
35691    ++j;
35692  }
35693  for ( ; i != i_end; ++i) {
35694    const int s = sgn(*i);
35695    if (s != 0) {
35696      return 2*s;
35697    }
35698  }
35699  for ( ; j != j_end; ++j) {
35700    const int s = sgn(*j);
35701    if (s != 0) {
35702      return -2*s;
35703    }
35704  }
35705
35706  // If all the coefficients in `x' equal all the coefficients in `y'
35707  // (starting from position 1) we compare coefficients in position 0,
35708  // i.e., inhomogeneous terms.
35709  const int comp = cmp(x.row.get(0), y.row.get(0));
35710  if (comp > 0) {
35711    return 1;
35712  }
35713  if (comp < 0) {
35714    return -1;
35715  }
35716  PPL_ASSERT(comp == 0);
35717
35718  // `x' and `y' are equal.
35719  return 0;
35720}
35721
35722template <typename Row>
35723Linear_Expression_Impl<Row>::Linear_Expression_Impl(const Variable v) {
35724  if (v.space_dimension() > max_space_dimension()) {
35725    throw std::length_error("Linear_Expression_Impl::"
35726                            "Linear_Expression_Impl(v):\n"
35727                            "v exceeds the maximum allowed "
35728                            "space dimension.");
35729  }
35730  set_space_dimension(v.space_dimension());
35731  (*this) += v;
35732  PPL_ASSERT(OK());
35733}
35734
35735template <typename Row>
35736template <typename Row2>
35737bool
35738Linear_Expression_Impl<Row>
35739::is_equal_to(const Linear_Expression_Impl<Row2>& x) const {
35740  return row == x.row;
35741}
35742
35743template <typename Row>
35744void
35745Linear_Expression_Impl<Row>::get_row(Dense_Row& r) const {
35746  r = this->row;
35747}
35748
35749template <typename Row>
35750void
35751Linear_Expression_Impl<Row>::get_row(Sparse_Row& r) const {
35752  r = this->row;
35753}
35754
35755template <typename Row>
35756void
35757Linear_Expression_Impl<Row>
35758::permute_space_dimensions(const std::vector<Variable>& cycle) {
35759  const dimension_type n = cycle.size();
35760  if (n < 2) {
35761    return;
35762  }
35763
35764  if (n == 2) {
35765    row.swap_coefficients(cycle[0].space_dimension(),
35766                          cycle[1].space_dimension());
35767  }
35768  else {
35769    PPL_DIRTY_TEMP_COEFFICIENT(tmp);
35770    tmp = row.get(cycle.back().space_dimension());
35771    for (dimension_type i = n - 1; i-- > 0; ) {
35772      row.swap_coefficients(cycle[i + 1].space_dimension(),
35773                            cycle[i].space_dimension());
35774    }
35775    if (tmp == 0) {
35776      row.reset(cycle[0].space_dimension());
35777    }
35778    else {
35779      using std::swap;
35780      swap(tmp, row[cycle[0].space_dimension()]);
35781    }
35782  }
35783  PPL_ASSERT(OK());
35784}
35785
35786template <typename Row>
35787template <typename Row2>
35788Linear_Expression_Impl<Row>&
35789Linear_Expression_Impl<Row>::operator+=(const Linear_Expression_Impl<Row2>& e) {
35790  linear_combine(e, Coefficient_one(), Coefficient_one());
35791  return *this;
35792}
35793
35794/*! \relates Parma_Polyhedra_Library::Linear_Expression_Impl */
35795template <typename Row>
35796Linear_Expression_Impl<Row>&
35797Linear_Expression_Impl<Row>::operator+=(const Variable v) {
35798  const dimension_type v_space_dim = v.space_dimension();
35799  if (v_space_dim > Linear_Expression_Impl<Row>::max_space_dimension()) {
35800    throw std::length_error("Linear_Expression_Impl& "
35801                            "operator+=(e, v):\n"
35802                            "v exceeds the maximum allowed space dimension.");
35803  }
35804  if (space_dimension() < v_space_dim) {
35805    set_space_dimension(v_space_dim);
35806  }
35807  typename Row::iterator itr = row.insert(v_space_dim);
35808  ++(*itr);
35809  if (*itr == 0) {
35810    row.reset(itr);
35811  }
35812  PPL_ASSERT(OK());
35813  return *this;
35814}
35815
35816/*! \relates Parma_Polyhedra_Library::Linear_Expression_Impl */
35817template <typename Row>
35818template <typename Row2>
35819Linear_Expression_Impl<Row>&
35820Linear_Expression_Impl<Row>::operator-=(const Linear_Expression_Impl<Row2>& e2) {
35821  linear_combine(e2, Coefficient_one(), -1);
35822  return *this;
35823}
35824
35825/*! \relates Parma_Polyhedra_Library::Linear_Expression_Impl */
35826template <typename Row>
35827Linear_Expression_Impl<Row>&
35828Linear_Expression_Impl<Row>::operator-=(const Variable v) {
35829  const dimension_type v_space_dim = v.space_dimension();
35830  if (v_space_dim > Linear_Expression_Impl<Row>::max_space_dimension()) {
35831    throw std::length_error("Linear_Expression_Impl& "
35832                            "operator-=(e, v):\n"
35833                            "v exceeds the maximum allowed space dimension.");
35834  }
35835  if (space_dimension() < v_space_dim) {
35836    set_space_dimension(v_space_dim);
35837  }
35838  typename Row::iterator itr = row.insert(v_space_dim);
35839  --(*itr);
35840  if (*itr == 0) {
35841    row.reset(itr);
35842  }
35843  PPL_ASSERT(OK());
35844  return *this;
35845}
35846
35847/*! \relates Parma_Polyhedra_Library::Linear_Expression_Impl */
35848template <typename Row>
35849Linear_Expression_Impl<Row>&
35850Linear_Expression_Impl<Row>::operator*=(Coefficient_traits::const_reference n) {
35851  if (n == 0) {
35852    row.clear();
35853    PPL_ASSERT(OK());
35854    return *this;
35855  }
35856  for (typename Row::iterator i = row.begin(),
35857         i_end = row.end(); i != i_end; ++i) {
35858    (*i) *= n;
35859  }
35860  PPL_ASSERT(OK());
35861  return *this;
35862}
35863
35864/*! \relates Parma_Polyhedra_Library::Linear_Expression_Impl */
35865template <typename Row>
35866Linear_Expression_Impl<Row>&
35867Linear_Expression_Impl<Row>::operator/=(Coefficient_traits::const_reference n) {
35868  typename Row::iterator i = row.begin();
35869  const typename Row::iterator& i_end = row.end();
35870  while (i != i_end) {
35871    (*i) /= n;
35872    if (*i == 0) {
35873      i = row.reset(i);
35874    }
35875    else {
35876      ++i;
35877    }
35878  }
35879  PPL_ASSERT(OK());
35880  return *this;
35881}
35882
35883/*! \relates Parma_Polyhedra_Library::Linear_Expression_Impl */
35884template <typename Row>
35885void
35886Linear_Expression_Impl<Row>::negate() {
35887  for (typename Row::iterator i = row.begin(),
35888         i_end = row.end(); i != i_end; ++i) {
35889    neg_assign(*i);
35890  }
35891  PPL_ASSERT(OK());
35892}
35893
35894/*! \relates Parma_Polyhedra_Library::Linear_Expression_Impl */
35895template <typename Row>
35896Linear_Expression_Impl<Row>&
35897Linear_Expression_Impl<Row>::add_mul_assign(Coefficient_traits::const_reference n,
35898                                            const Variable v) {
35899  const dimension_type v_space_dim = v.space_dimension();
35900  if (v_space_dim > Linear_Expression_Impl<Row>::max_space_dimension()) {
35901    throw std::length_error("Linear_Expression_Impl& "
35902                            "add_mul_assign(e, n, v):\n"
35903                            "v exceeds the maximum allowed space dimension.");
35904  }
35905  if (space_dimension() < v_space_dim) {
35906    set_space_dimension(v_space_dim);
35907  }
35908  if (n == 0) {
35909    return *this;
35910  }
35911  typename Row::iterator itr = row.insert(v_space_dim);
35912  (*itr) += n;
35913  if (*itr == 0) {
35914    row.reset(itr);
35915  }
35916  PPL_ASSERT(OK());
35917  return *this;
35918}
35919
35920/*! \relates Parma_Polyhedra_Library::Linear_Expression_Impl */
35921template <typename Row>
35922Linear_Expression_Impl<Row>&
35923Linear_Expression_Impl<Row>
35924::sub_mul_assign(Coefficient_traits::const_reference n,
35925                 const Variable v) {
35926  const dimension_type v_space_dim = v.space_dimension();
35927  if (v_space_dim > Linear_Expression_Impl<Row>::max_space_dimension()) {
35928    throw std::length_error("Linear_Expression_Impl& "
35929                            "sub_mul_assign(e, n, v):\n"
35930                            "v exceeds the maximum allowed space dimension.");
35931  }
35932  if (space_dimension() < v_space_dim) {
35933    set_space_dimension(v_space_dim);
35934  }
35935  if (n == 0) {
35936    return *this;
35937  }
35938  typename Row::iterator itr = row.insert(v_space_dim);
35939  (*itr) -= n;
35940  if (*itr == 0) {
35941    row.reset(itr);
35942  }
35943  PPL_ASSERT(OK());
35944  return *this;
35945}
35946
35947template <typename Row>
35948template <typename Row2>
35949void
35950Linear_Expression_Impl<Row>
35951::add_mul_assign(Coefficient_traits::const_reference factor,
35952                 const Linear_Expression_Impl<Row2>& y) {
35953  if (factor != 0) {
35954    linear_combine(y, Coefficient_one(), factor);
35955  }
35956}
35957
35958template <typename Row>
35959template <typename Row2>
35960void
35961Linear_Expression_Impl<Row>
35962::sub_mul_assign(Coefficient_traits::const_reference factor,
35963                 const Linear_Expression_Impl<Row2>& y) {
35964  if (factor != 0) {
35965    linear_combine(y, Coefficient_one(), -factor);
35966  }
35967}
35968
35969template <typename Row>
35970void
35971Linear_Expression_Impl<Row>::print(std::ostream& s) const {
35972  PPL_DIRTY_TEMP_COEFFICIENT(ev);
35973  bool first = true;
35974  for (typename Row::const_iterator i = row.lower_bound(1), i_end = row.end();
35975       i != i_end; ++i) {
35976    ev = *i;
35977    if (ev == 0) {
35978      continue;
35979    }
35980    if (!first) {
35981      if (ev > 0) {
35982        s << " + ";
35983      }
35984      else {
35985        s << " - ";
35986        neg_assign(ev);
35987      }
35988    }
35989    else {
35990      first = false;
35991    }
35992    if (ev == -1) {
35993      s << "-";
35994    }
35995    else if (ev != 1) {
35996      s << ev << "*";
35997    }
35998    IO_Operators::operator<<(s, Variable(i.index() - 1));
35999  }
36000  // Inhomogeneous term.
36001  PPL_DIRTY_TEMP_COEFFICIENT(it);
36002  it = row[0];
36003  if (it != 0) {
36004    if (!first) {
36005      if (it > 0) {
36006        s << " + ";
36007      }
36008      else {
36009        s << " - ";
36010        neg_assign(it);
36011      }
36012    }
36013    else {
36014      first = false;
36015    }
36016    s << it;
36017  }
36018
36019  if (first) {
36020    // The null linear expression.
36021    s << Coefficient_zero();
36022  }
36023}
36024
36025template <typename Row>
36026Coefficient_traits::const_reference
36027Linear_Expression_Impl<Row>::get(dimension_type i) const {
36028  return row.get(i);
36029}
36030
36031template <typename Row>
36032void
36033Linear_Expression_Impl<Row>
36034::set(dimension_type i, Coefficient_traits::const_reference n) {
36035  if (n == 0) {
36036    row.reset(i);
36037  }
36038  else {
36039    row.insert(i, n);
36040  }
36041  PPL_ASSERT(OK());
36042}
36043
36044template <typename Row>
36045void
36046Linear_Expression_Impl<Row>
36047::exact_div_assign(Coefficient_traits::const_reference c,
36048                   dimension_type start, dimension_type end) {
36049  // NOTE: Since all coefficients in [start,end) are multiple of c,
36050  // each of the resulting coefficients will be nonzero iff the initial
36051  // coefficient was.
36052  for (typename Row::iterator i = row.lower_bound(start),
36053         i_end = row.lower_bound(end); i != i_end; ++i) {
36054    Parma_Polyhedra_Library::exact_div_assign(*i, *i, c);
36055  }
36056  PPL_ASSERT(OK());
36057}
36058
36059template <typename Row>
36060void
36061Linear_Expression_Impl<Row>
36062::mul_assign(Coefficient_traits::const_reference c,
36063                   dimension_type start, dimension_type end) {
36064  if (c == 0) {
36065    typename Row::iterator i = row.lower_bound(start);
36066    const typename Row::iterator& i_end = row.end();
36067    while (i != i_end && i.index() < end) {
36068      i = row.reset(i);
36069    }
36070  }
36071  else {
36072    for (typename Row::iterator
36073      i = row.lower_bound(start), i_end = row.lower_bound(end);
36074      i != i_end; ++i) {
36075      (*i) *= c;
36076    }
36077  }
36078  PPL_ASSERT(OK());
36079}
36080
36081template <typename Row>
36082template <typename Row2>
36083void
36084Linear_Expression_Impl<Row>
36085::linear_combine(const Linear_Expression_Impl<Row2>& y,
36086                 Coefficient_traits::const_reference c1,
36087                 Coefficient_traits::const_reference c2,
36088                 dimension_type start, dimension_type end) {
36089  Parma_Polyhedra_Library::linear_combine(row, y.row, c1, c2, start, end);
36090  PPL_ASSERT(OK());
36091}
36092
36093template <typename Row>
36094template <typename Row2>
36095void
36096Linear_Expression_Impl<Row>
36097::linear_combine_lax(const Linear_Expression_Impl<Row2>& y,
36098                     Coefficient_traits::const_reference c1,
36099                     Coefficient_traits::const_reference c2,
36100                     dimension_type start, dimension_type end) {
36101  PPL_ASSERT(start <= end);
36102  PPL_ASSERT(end <= row.size());
36103  PPL_ASSERT(end <= y.row.size());
36104  if (c1 == 0) {
36105    if (c2 == 0) {
36106      PPL_ASSERT(c1 == 0);
36107      PPL_ASSERT(c2 == 0);
36108      typename Row::iterator i = row.lower_bound(start);
36109      const typename Row::iterator& i_end = row.end();
36110      while (i != i_end && i.index() < end) {
36111        i = row.reset(i);
36112      }
36113    }
36114    else {
36115      PPL_ASSERT(c1 == 0);
36116      PPL_ASSERT(c2 != 0);
36117
36118      typename Row::iterator i = row.lower_bound(start);
36119      const typename Row::iterator& i_end = row.end();
36120      typename Row2::const_iterator j = y.row.lower_bound(start);
36121      typename Row2::const_iterator j_last = y.row.lower_bound(end);
36122
36123      while (i != i_end && i.index() < end && j != j_last) {
36124        if (i.index() < j.index()) {
36125          i = row.reset(i);
36126          continue;
36127        }
36128        if (i.index() > j.index()) {
36129          i = row.insert(i, j.index(), *j);
36130          (*i) *= c2;
36131          ++i;
36132          ++j;
36133          continue;
36134        }
36135        PPL_ASSERT(i.index() == j.index());
36136        (*i) = (*j);
36137        (*i) *= c2;
36138        ++i;
36139        ++j;
36140      }
36141      while (i != i_end && i.index() < end) {
36142        i = row.reset(i);
36143      }
36144      while (j != j_last) {
36145        i = row.insert(i, j.index(), *j);
36146        (*i) *= c2;
36147        // No need to increment i here.
36148        ++j;
36149      }
36150    }
36151  }
36152  else {
36153    if (c2 == 0) {
36154      PPL_ASSERT(c1 != 0);
36155      PPL_ASSERT(c2 == 0);
36156      for (typename Row::iterator i = row.lower_bound(start),
36157             i_end = row.lower_bound(end); i != i_end; ++i) {
36158        (*i) *= c1;
36159      }
36160    }
36161    else {
36162      PPL_ASSERT(c1 != 0);
36163      PPL_ASSERT(c2 != 0);
36164      Parma_Polyhedra_Library::linear_combine(row, y.row, c1, c2, start, end);
36165    }
36166  }
36167  PPL_ASSERT(OK());
36168}
36169
36170template <typename Row>
36171void
36172Linear_Expression_Impl<Row>::sign_normalize() {
36173  typename Row::iterator i = row.lower_bound(1);
36174  typename Row::iterator i_end = row.end();
36175
36176  for ( ; i != i_end; ++i) {
36177    if (*i != 0) {
36178      break;
36179    }
36180  }
36181
36182  if (i != i_end && *i < 0) {
36183    for ( ; i != i_end; ++i) {
36184      neg_assign(*i);
36185    }
36186    // Negate the first coefficient, too.
36187    typename Row::iterator first = row.begin();
36188    if (first != row.end() && first.index() == 0) {
36189      neg_assign(*first);
36190    }
36191  }
36192  PPL_ASSERT(OK());
36193}
36194
36195template <typename Row>
36196void
36197Linear_Expression_Impl<Row>::negate(dimension_type first, dimension_type last) {
36198  PPL_ASSERT(first <= last);
36199  PPL_ASSERT(last <= row.size());
36200  typename Row::iterator i = row.lower_bound(first);
36201  typename Row::iterator i_end = row.lower_bound(last);
36202  for ( ; i != i_end; ++i) {
36203    neg_assign(*i);
36204  }
36205  PPL_ASSERT(OK());
36206}
36207
36208template <typename Row>
36209template <typename Row2>
36210void
36211Linear_Expression_Impl<Row>::construct(const Linear_Expression_Impl<Row2>& e) {
36212  row = e.row;
36213  PPL_ASSERT(OK());
36214}
36215
36216template <typename Row>
36217template <typename Row2>
36218void
36219Linear_Expression_Impl<Row>::construct(const Linear_Expression_Impl<Row2>& e,
36220                                       dimension_type space_dim) {
36221  Row x(e.row, space_dim + 1, space_dim + 1);
36222  swap(row, x);
36223  PPL_ASSERT(OK());
36224}
36225
36226template <typename Row>
36227template <typename Row2>
36228void
36229Linear_Expression_Impl<Row>
36230::scalar_product_assign(Coefficient& result,
36231                        const Linear_Expression_Impl<Row2>& y,
36232                        dimension_type start, dimension_type end) const {
36233  const Linear_Expression_Impl<Row>& x = *this;
36234  PPL_ASSERT(start <= end);
36235  PPL_ASSERT(end <= x.row.size());
36236  PPL_ASSERT(end <= y.row.size());
36237  result = 0;
36238  typename Row ::const_iterator x_i = x.row.lower_bound(start);
36239  typename Row ::const_iterator x_end = x.row.lower_bound(end);
36240  typename Row2::const_iterator y_i = y.row.lower_bound(start);
36241  typename Row2::const_iterator y_end = y.row.lower_bound(end);
36242  while (x_i != x_end && y_i != y_end) {
36243    if (x_i.index() == y_i.index()) {
36244      Parma_Polyhedra_Library::add_mul_assign(result, *x_i, *y_i);
36245      ++x_i;
36246      ++y_i;
36247    }
36248    else {
36249      if (x_i.index() < y_i.index()) {
36250        PPL_ASSERT(y.row.get(x_i.index()) == 0);
36251        // (*x_i) * 0 == 0, nothing to do.
36252        ++x_i;
36253      }
36254      else {
36255        PPL_ASSERT(x.row.get(y_i.index()) == 0);
36256        // 0 * (*y_i) == 0, nothing to do.
36257        ++y_i;
36258      }
36259    }
36260  }
36261  // In the remaining positions (if any) at most one row is nonzero, so
36262  // there's nothing left to do.
36263}
36264
36265template <typename Row>
36266template <typename Row2>
36267int
36268Linear_Expression_Impl<Row>
36269::scalar_product_sign(const Linear_Expression_Impl<Row2>& y,
36270                      dimension_type start, dimension_type end) const {
36271  PPL_DIRTY_TEMP_COEFFICIENT(result);
36272  scalar_product_assign(result, y, start, end);
36273  return sgn(result);
36274}
36275
36276template <typename Row>
36277template <typename Row2>
36278bool
36279Linear_Expression_Impl<Row>
36280::is_equal_to(const Linear_Expression_Impl<Row2>& y,
36281              dimension_type start, dimension_type end) const {
36282  const Linear_Expression_Impl<Row>& x = *this;
36283  PPL_ASSERT(start <= end);
36284  PPL_ASSERT(end <= x.row.size());
36285  PPL_ASSERT(end <= y.row.size());
36286
36287  typename Row::const_iterator i = x.row.lower_bound(start);
36288  typename Row::const_iterator i_end = x.row.lower_bound(end);
36289  typename Row2::const_iterator j = y.row.lower_bound(start);
36290  typename Row2::const_iterator j_end = y.row.lower_bound(end);
36291  while (i != i_end && j != j_end) {
36292    if (i.index() == j.index()) {
36293      if (*i != *j) {
36294        return false;
36295      }
36296      ++i;
36297      ++j;
36298    }
36299    else {
36300      if (i.index() < j.index()) {
36301        if (*i != 0) {
36302          return false;
36303        }
36304        ++i;
36305      }
36306      else {
36307        PPL_ASSERT(i.index() > j.index());
36308        if (*j != 0) {
36309          return false;
36310        }
36311        ++j;
36312      }
36313    }
36314  }
36315  for ( ; i != i_end; ++i) {
36316    if (*i != 0) {
36317      return false;
36318    }
36319  }
36320  for ( ; j != j_end; ++j) {
36321    if (*j != 0) {
36322      return false;
36323    }
36324  }
36325  return true;
36326}
36327
36328template <typename Row>
36329template <typename Row2>
36330bool
36331Linear_Expression_Impl<Row>
36332::is_equal_to(const Linear_Expression_Impl<Row2>& y,
36333              Coefficient_traits::const_reference c1,
36334              Coefficient_traits::const_reference c2,
36335              dimension_type start, dimension_type end) const {
36336  const Linear_Expression_Impl<Row>& x = *this;
36337  PPL_ASSERT(start <= end);
36338  PPL_ASSERT(end <= x.row.size());
36339  PPL_ASSERT(end <= y.row.size());
36340
36341  // Deal with trivial cases.
36342  if (c1 == 0) {
36343    if (c2 == 0) {
36344      return true;
36345    }
36346    else {
36347      return y.all_zeroes(start, end);
36348    }
36349  }
36350  if (c2 == 0) {
36351    return x.all_zeroes(start, end);
36352  }
36353
36354  PPL_ASSERT(c1 != 0);
36355  PPL_ASSERT(c2 != 0);
36356  typename Row::const_iterator i = x.row.lower_bound(start);
36357  typename Row::const_iterator i_end = x.row.lower_bound(end);
36358  typename Row2::const_iterator j = y.row.lower_bound(start);
36359  typename Row2::const_iterator j_end = y.row.lower_bound(end);
36360  while (i != i_end && j != j_end) {
36361    if (i.index() == j.index()) {
36362      if ((*i) * c1 != (*j) * c2) {
36363        return false;
36364      }
36365      ++i;
36366      ++j;
36367    }
36368    else {
36369      if (i.index() < j.index()) {
36370        if (*i != 0) {
36371          return false;
36372        }
36373        ++i;
36374      }
36375      else {
36376        PPL_ASSERT(i.index() > j.index());
36377        if (*j != 0) {
36378          return false;
36379        }
36380        ++j;
36381      }
36382    }
36383  }
36384  for ( ; i != i_end; ++i) {
36385    if (*i != 0) {
36386      return false;
36387    }
36388  }
36389  for ( ; j != j_end; ++j) {
36390    if (*j != 0) {
36391      return false;
36392    }
36393  }
36394  return true;
36395}
36396
36397template <typename Row>
36398void
36399Linear_Expression_Impl<Row>
36400::linear_combine(const Linear_Expression_Interface& y, Variable v) {
36401  typedef const Linear_Expression_Impl<Dense_Row>* Dense_Ptr;
36402  typedef const Linear_Expression_Impl<Sparse_Row>* Sparse_Ptr;
36403  if (const Dense_Ptr p = dynamic_cast<Dense_Ptr>(&y)) {
36404    linear_combine(*p, v);
36405  }
36406  else if (const Sparse_Ptr p = dynamic_cast<Sparse_Ptr>(&y)) {
36407    linear_combine(*p, v);
36408  }
36409  else {
36410    // Add implementations for new derived classes here.
36411    PPL_UNREACHABLE;
36412  }
36413}
36414
36415template <typename Row>
36416void
36417Linear_Expression_Impl<Row>
36418::linear_combine(const Linear_Expression_Interface& y,
36419                 Coefficient_traits::const_reference c1,
36420                 Coefficient_traits::const_reference c2) {
36421  typedef const Linear_Expression_Impl<Dense_Row>* Dense_Ptr;
36422  typedef const Linear_Expression_Impl<Sparse_Row>* Sparse_Ptr;
36423  if (const Dense_Ptr p = dynamic_cast<Dense_Ptr>(&y)) {
36424    linear_combine(*p, c1, c2);
36425  }
36426  else if (const Sparse_Ptr p = dynamic_cast<Sparse_Ptr>(&y)) {
36427    linear_combine(*p, c1, c2);
36428  }
36429  else {
36430    // Add implementations for new derived classes here.
36431    PPL_UNREACHABLE;
36432  }
36433}
36434
36435template <typename Row>
36436void
36437Linear_Expression_Impl<Row>
36438::linear_combine_lax(const Linear_Expression_Interface& y,
36439                     Coefficient_traits::const_reference c1,
36440                     Coefficient_traits::const_reference c2) {
36441  typedef const Linear_Expression_Impl<Dense_Row>* Dense_Ptr;
36442  typedef const Linear_Expression_Impl<Sparse_Row>* Sparse_Ptr;
36443  if (const Dense_Ptr p = dynamic_cast<Dense_Ptr>(&y)) {
36444    linear_combine_lax(*p, c1, c2);
36445  }
36446  else if (const Sparse_Ptr p = dynamic_cast<Sparse_Ptr>(&y)) {
36447    linear_combine_lax(*p, c1, c2);
36448  }
36449  else {
36450    // Add implementations for new derived classes here.
36451    PPL_UNREACHABLE;
36452  }
36453}
36454
36455template <typename Row>
36456bool
36457Linear_Expression_Impl<Row>
36458::is_equal_to(const Linear_Expression_Interface& y) const {
36459  typedef const Linear_Expression_Impl<Dense_Row>* Dense_Ptr;
36460  typedef const Linear_Expression_Impl<Sparse_Row>* Sparse_Ptr;
36461  if (const Dense_Ptr p = dynamic_cast<Dense_Ptr>(&y)) {
36462    return is_equal_to(*p);
36463  }
36464  else if (const Sparse_Ptr p = dynamic_cast<Sparse_Ptr>(&y)) {
36465    return is_equal_to(*p);
36466  }
36467  else {
36468    // Add implementations for new derived classes here.
36469    PPL_UNREACHABLE;
36470    return false;
36471  }
36472}
36473
36474template <typename Row>
36475Linear_Expression_Impl<Row>&
36476Linear_Expression_Impl<Row>
36477::operator+=(const Linear_Expression_Interface& y) {
36478  typedef const Linear_Expression_Impl<Dense_Row>* Dense_Ptr;
36479  typedef const Linear_Expression_Impl<Sparse_Row>* Sparse_Ptr;
36480  if (const Dense_Ptr p = dynamic_cast<Dense_Ptr>(&y)) {
36481    return operator+=(*p);
36482  }
36483  else if (const Sparse_Ptr p = dynamic_cast<Sparse_Ptr>(&y)) {
36484    return operator+=(*p);
36485  }
36486  else {
36487    // Add implementations for new derived classes here.
36488    PPL_UNREACHABLE;
36489    return *this;
36490  }
36491}
36492
36493template <typename Row>
36494Linear_Expression_Impl<Row>&
36495Linear_Expression_Impl<Row>
36496::operator-=(const Linear_Expression_Interface& y) {
36497  typedef const Linear_Expression_Impl<Dense_Row>* Dense_Ptr;
36498  typedef const Linear_Expression_Impl<Sparse_Row>* Sparse_Ptr;
36499  if (const Dense_Ptr p = dynamic_cast<Dense_Ptr>(&y)) {
36500    return operator-=(*p);
36501  }
36502  else if (const Sparse_Ptr p = dynamic_cast<Sparse_Ptr>(&y)) {
36503    return operator-=(*p);
36504  }
36505  else {
36506    // Add implementations for new derived classes here.
36507    PPL_UNREACHABLE;
36508    return *this;
36509  }
36510}
36511
36512template <typename Row>
36513void
36514Linear_Expression_Impl<Row>
36515::add_mul_assign(Coefficient_traits::const_reference factor,
36516                 const Linear_Expression_Interface& y) {
36517  typedef const Linear_Expression_Impl<Dense_Row>* Dense_Ptr;
36518  typedef const Linear_Expression_Impl<Sparse_Row>* Sparse_Ptr;
36519  if (const Dense_Ptr p = dynamic_cast<Dense_Ptr>(&y)) {
36520    add_mul_assign(factor, *p);
36521  }
36522  else if (const Sparse_Ptr p = dynamic_cast<Sparse_Ptr>(&y)) {
36523    add_mul_assign(factor, *p);
36524  }
36525  else {
36526    // Add implementations for new derived classes here.
36527    PPL_UNREACHABLE;
36528  }
36529}
36530
36531template <typename Row>
36532void
36533Linear_Expression_Impl<Row>
36534::sub_mul_assign(Coefficient_traits::const_reference factor,
36535                 const Linear_Expression_Interface& y) {
36536  typedef const Linear_Expression_Impl<Dense_Row>* Dense_Ptr;
36537  typedef const Linear_Expression_Impl<Sparse_Row>* Sparse_Ptr;
36538  if (const Dense_Ptr p = dynamic_cast<Dense_Ptr>(&y)) {
36539    sub_mul_assign(factor, *p);
36540  }
36541  else if (const Sparse_Ptr p = dynamic_cast<Sparse_Ptr>(&y)) {
36542    sub_mul_assign(factor, *p);
36543  }
36544  else {
36545    // Add implementations for new derived classes here.
36546    PPL_UNREACHABLE;
36547  }
36548}
36549
36550template <typename Row>
36551void
36552Linear_Expression_Impl<Row>
36553::linear_combine(const Linear_Expression_Interface& y, dimension_type i) {
36554  typedef const Linear_Expression_Impl<Dense_Row>* Dense_Ptr;
36555  typedef const Linear_Expression_Impl<Sparse_Row>* Sparse_Ptr;
36556  if (const Dense_Ptr p = dynamic_cast<Dense_Ptr>(&y)) {
36557    linear_combine(*p, i);
36558  }
36559  else if (const Sparse_Ptr p = dynamic_cast<Sparse_Ptr>(&y)) {
36560    linear_combine(*p, i);
36561  }
36562  else {
36563    // Add implementations for new derived classes here.
36564    PPL_UNREACHABLE;
36565  }
36566}
36567
36568template <typename Row>
36569void
36570Linear_Expression_Impl<Row>
36571::linear_combine(const Linear_Expression_Interface& y,
36572                 Coefficient_traits::const_reference c1,
36573                 Coefficient_traits::const_reference c2,
36574                 dimension_type start, dimension_type end) {
36575  typedef const Linear_Expression_Impl<Dense_Row>* Dense_Ptr;
36576  typedef const Linear_Expression_Impl<Sparse_Row>* Sparse_Ptr;
36577  if (const Dense_Ptr p = dynamic_cast<Dense_Ptr>(&y)) {
36578    linear_combine(*p, c1, c2, start, end);
36579  }
36580  else if (const Sparse_Ptr p = dynamic_cast<Sparse_Ptr>(&y)) {
36581    linear_combine(*p, c1, c2, start, end);
36582  }
36583  else {
36584    // Add implementations for new derived classes here.
36585    PPL_UNREACHABLE;
36586  }
36587}
36588
36589template <typename Row>
36590void
36591Linear_Expression_Impl<Row>
36592::linear_combine_lax(const Linear_Expression_Interface& y,
36593                     Coefficient_traits::const_reference c1,
36594                     Coefficient_traits::const_reference c2,
36595                     dimension_type start, dimension_type end) {
36596  typedef const Linear_Expression_Impl<Dense_Row>* Dense_Ptr;
36597  typedef const Linear_Expression_Impl<Sparse_Row>* Sparse_Ptr;
36598  if (const Dense_Ptr p = dynamic_cast<Dense_Ptr>(&y)) {
36599    linear_combine_lax(*p, c1, c2, start, end);
36600  }
36601  else if (const Sparse_Ptr p = dynamic_cast<Sparse_Ptr>(&y)) {
36602    linear_combine_lax(*p, c1, c2, start, end);
36603  }
36604  else {
36605    // Add implementations for new derived classes here.
36606    PPL_UNREACHABLE;
36607  }
36608}
36609
36610template <typename Row>
36611int
36612Linear_Expression_Impl<Row>
36613::compare(const Linear_Expression_Interface& y) const {
36614  typedef const Linear_Expression_Impl<Dense_Row>* Dense_Ptr;
36615  typedef const Linear_Expression_Impl<Sparse_Row>* Sparse_Ptr;
36616  if (const Dense_Ptr p = dynamic_cast<Dense_Ptr>(&y)) {
36617    return compare(*p);
36618  }
36619  else if (const Sparse_Ptr p = dynamic_cast<Sparse_Ptr>(&y)) {
36620    return compare(*p);
36621  }
36622  else {
36623    // Add implementations for new derived classes here.
36624    PPL_UNREACHABLE;
36625    return 0;
36626  }
36627}
36628
36629
36630template <typename Row>
36631void
36632Linear_Expression_Impl<Row>::construct(const Linear_Expression_Interface& y) {
36633  typedef const Linear_Expression_Impl<Dense_Row>* Dense_Ptr;
36634  typedef const Linear_Expression_Impl<Sparse_Row>* Sparse_Ptr;
36635  if (const Dense_Ptr p = dynamic_cast<Dense_Ptr>(&y)) {
36636    return construct(*p);
36637  }
36638  else if (const Sparse_Ptr p = dynamic_cast<Sparse_Ptr>(&y)) {
36639    return construct(*p);
36640  }
36641  else {
36642    // Add implementations for new derived classes here.
36643    PPL_UNREACHABLE;
36644  }
36645}
36646
36647template <typename Row>
36648void
36649Linear_Expression_Impl<Row>::construct(const Linear_Expression_Interface& y,
36650                                       dimension_type space_dim) {
36651  typedef const Linear_Expression_Impl<Dense_Row>* Dense_Ptr;
36652  typedef const Linear_Expression_Impl<Sparse_Row>* Sparse_Ptr;
36653  if (const Dense_Ptr p = dynamic_cast<Dense_Ptr>(&y)) {
36654    return construct(*p, space_dim);
36655  }
36656  else if (const Sparse_Ptr p = dynamic_cast<Sparse_Ptr>(&y)) {
36657    return construct(*p, space_dim);
36658  }
36659  else {
36660    // Add implementations for new derived classes here.
36661    PPL_UNREACHABLE;
36662  }
36663}
36664
36665template <typename Row>
36666void
36667Linear_Expression_Impl<Row>
36668::scalar_product_assign(Coefficient& result,
36669                        const Linear_Expression_Interface& y,
36670                        dimension_type start, dimension_type end) const {
36671  typedef const Linear_Expression_Impl<Dense_Row>* Dense_Ptr;
36672  typedef const Linear_Expression_Impl<Sparse_Row>* Sparse_Ptr;
36673  if (const Dense_Ptr p = dynamic_cast<Dense_Ptr>(&y)) {
36674    scalar_product_assign(result, *p, start, end);
36675  }
36676  else if (const Sparse_Ptr p = dynamic_cast<Sparse_Ptr>(&y)) {
36677    scalar_product_assign(result, *p, start, end);
36678  }
36679  else {
36680    // Add implementations for new derived classes here.
36681    PPL_UNREACHABLE;
36682  }
36683}
36684
36685template <typename Row>
36686int
36687Linear_Expression_Impl<Row>
36688::scalar_product_sign(const Linear_Expression_Interface& y,
36689                      dimension_type start, dimension_type end) const {
36690  typedef const Linear_Expression_Impl<Dense_Row>* Dense_Ptr;
36691  typedef const Linear_Expression_Impl<Sparse_Row>* Sparse_Ptr;
36692  if (const Dense_Ptr p = dynamic_cast<Dense_Ptr>(&y)) {
36693    return scalar_product_sign(*p, start, end);
36694  }
36695  else if (const Sparse_Ptr p = dynamic_cast<Sparse_Ptr>(&y)) {
36696    return scalar_product_sign(*p, start, end);
36697  }
36698  else {
36699    // Add implementations for new derived classes here.
36700    PPL_UNREACHABLE;
36701    return 0;
36702  }
36703}
36704
36705template <typename Row>
36706bool
36707Linear_Expression_Impl<Row>
36708::is_equal_to(const Linear_Expression_Interface& y,
36709              dimension_type start, dimension_type end) const {
36710  typedef const Linear_Expression_Impl<Dense_Row>* Dense_Ptr;
36711  typedef const Linear_Expression_Impl<Sparse_Row>* Sparse_Ptr;
36712  if (const Dense_Ptr p = dynamic_cast<Dense_Ptr>(&y)) {
36713    return is_equal_to(*p, start, end);
36714  }
36715  else if (const Sparse_Ptr p = dynamic_cast<Sparse_Ptr>(&y)) {
36716    return is_equal_to(*p, start, end);
36717  }
36718  else {
36719    // Add implementations for new derived classes here.
36720    PPL_UNREACHABLE;
36721    return false;
36722  }
36723}
36724
36725template <typename Row>
36726bool
36727Linear_Expression_Impl<Row>
36728::is_equal_to(const Linear_Expression_Interface& y,
36729              Coefficient_traits::const_reference c1,
36730              Coefficient_traits::const_reference c2,
36731              dimension_type start, dimension_type end) const {
36732  typedef const Linear_Expression_Impl<Dense_Row>* Dense_Ptr;
36733  typedef const Linear_Expression_Impl<Sparse_Row>* Sparse_Ptr;
36734  if (const Dense_Ptr p = dynamic_cast<Dense_Ptr>(&y)) {
36735    return is_equal_to(*p, c1, c2, start, end);
36736  }
36737  else if (const Sparse_Ptr p = dynamic_cast<Sparse_Ptr>(&y)) {
36738    return is_equal_to(*p, c1, c2, start, end);
36739  }
36740  else {
36741    // Add implementations for new derived classes here.
36742    PPL_UNREACHABLE;
36743    return false;
36744  }
36745}
36746
36747template <typename Row>
36748bool
36749Linear_Expression_Impl<Row>
36750::have_a_common_variable(const Linear_Expression_Interface& y,
36751                         Variable first, Variable last) const {
36752  typedef const Linear_Expression_Impl<Dense_Row>* Dense_Ptr;
36753  typedef const Linear_Expression_Impl<Sparse_Row>* Sparse_Ptr;
36754  if (const Dense_Ptr p = dynamic_cast<Dense_Ptr>(&y)) {
36755    return have_a_common_variable(*p, first, last);
36756  }
36757  else if (const Sparse_Ptr p = dynamic_cast<Sparse_Ptr>(&y)) {
36758    return have_a_common_variable(*p, first, last);
36759  }
36760  else {
36761    // Add implementations for new derived classes here.
36762    PPL_UNREACHABLE;
36763    return false;
36764  }
36765}
36766
36767template <typename Row>
36768Linear_Expression_Interface::const_iterator_interface*
36769Linear_Expression_Impl<Row>::begin() const {
36770  return new const_iterator(row, 1);
36771}
36772
36773template <typename Row>
36774Linear_Expression_Interface::const_iterator_interface*
36775Linear_Expression_Impl<Row>::end() const {
36776  return new const_iterator(row, row.size());
36777}
36778
36779template <typename Row>
36780Linear_Expression_Interface::const_iterator_interface*
36781Linear_Expression_Impl<Row>::lower_bound(Variable v) const {
36782  return new const_iterator(row, v.space_dimension());
36783}
36784
36785template <typename Row>
36786Linear_Expression_Impl<Row>::const_iterator
36787::const_iterator(const Row& r, dimension_type i)
36788  : row(&r), itr(r.lower_bound(i)) {
36789  skip_zeroes_forward();
36790}
36791
36792template <typename Row>
36793Linear_Expression_Interface::const_iterator_interface*
36794Linear_Expression_Impl<Row>::const_iterator
36795::clone() const {
36796  return new const_iterator(*this);
36797}
36798
36799template <typename Row>
36800void
36801Linear_Expression_Impl<Row>::const_iterator
36802::operator++() {
36803  ++itr;
36804  skip_zeroes_forward();
36805}
36806
36807template <typename Row>
36808void
36809Linear_Expression_Impl<Row>::const_iterator
36810::operator--() {
36811  --itr;
36812  skip_zeroes_backward();
36813}
36814
36815template <typename Row>
36816typename Linear_Expression_Impl<Row>::const_iterator::reference
36817Linear_Expression_Impl<Row>::const_iterator
36818::operator*() const {
36819  return *itr;
36820}
36821
36822template <typename Row>
36823Variable
36824Linear_Expression_Impl<Row>::const_iterator
36825::variable() const {
36826  const dimension_type i = itr.index();
36827  PPL_ASSERT(i != 0);
36828  return Variable(i - 1);
36829}
36830
36831template <typename Row>
36832bool
36833Linear_Expression_Impl<Row>::const_iterator
36834::operator==(const const_iterator_interface& x) const {
36835  const const_iterator* const p = dynamic_cast<const const_iterator*>(&x);
36836  // Comparing iterators belonging to different rows is forbidden.
36837  PPL_ASSERT(p != 0);
36838  PPL_ASSERT(row == p->row);
36839  return itr == p->itr;
36840}
36841
36842template <typename Row>
36843void
36844Linear_Expression_Impl<Row>::ascii_dump(std::ostream& s) const {
36845  s << "size " << (space_dimension() + 1) << " ";
36846  for (dimension_type i = 0; i < row.size(); ++i) {
36847    s << row.get(i);
36848    if (i != row.size() - 1) {
36849      s << ' ';
36850    }
36851  }
36852}
36853
36854template <typename Row>
36855bool
36856Linear_Expression_Impl<Row>::ascii_load(std::istream& s) {
36857  std::string str;
36858
36859  if (!(s >> str)) {
36860    return false;
36861  }
36862  if (str != "size") {
36863    return false;
36864  }
36865
36866  dimension_type new_size;
36867  if (!(s >> new_size)) {
36868    return false;
36869  }
36870
36871  row.resize(0);
36872  row.resize(new_size);
36873
36874  PPL_DIRTY_TEMP_COEFFICIENT(c);
36875
36876  for (dimension_type j = 0; j < new_size; ++j) {
36877    if (!(s >> c)) {
36878      return false;
36879    }
36880    if (c != 0) {
36881      row.insert(j, c);
36882    }
36883  }
36884
36885  PPL_ASSERT(OK());
36886  return true;
36887}
36888
36889template <typename Row>
36890bool
36891Linear_Expression_Impl<Row>::OK() const {
36892  return row.OK();
36893}
36894
36895} // namespace Parma_Polyhedra_Library
36896
36897/* Automatically generated from PPL source file ../src/Linear_Expression_Impl_defs.hh line 905. */
36898
36899/* Automatically generated from PPL source file ../src/Linear_Form_templates.hh line 1. */
36900/* Linear_Form class implementation: non-inline template functions.
36901*/
36902
36903
36904/* Automatically generated from PPL source file ../src/Box_defs.hh line 1. */
36905/* Box class declaration.
36906*/
36907
36908
36909/* Automatically generated from PPL source file ../src/Poly_Con_Relation_types.hh line 1. */
36910
36911
36912namespace Parma_Polyhedra_Library {
36913
36914class Poly_Con_Relation;
36915
36916} // namespace Parma_Polyhedra_Library
36917
36918/* Automatically generated from PPL source file ../src/Poly_Gen_Relation_types.hh line 1. */
36919
36920
36921namespace Parma_Polyhedra_Library {
36922
36923class Poly_Gen_Relation;
36924
36925} // namespace Parma_Polyhedra_Library
36926
36927/* Automatically generated from PPL source file ../src/Partially_Reduced_Product_types.hh line 1. */
36928
36929
36930namespace Parma_Polyhedra_Library {
36931
36932template <typename D1, typename D2>
36933class Smash_Reduction;
36934
36935template <typename D1, typename D2>
36936class Constraints_Reduction;
36937
36938template <typename D1, typename D2>
36939class Congruences_Reduction;
36940
36941template <typename D1, typename D2>
36942class Shape_Preserving_Reduction;
36943
36944template <typename D1, typename D2>
36945class No_Reduction;
36946
36947template <typename D1, typename D2, typename R>
36948class Partially_Reduced_Product;
36949
36950} // namespace Parma_Polyhedra_Library
36951
36952/* Automatically generated from PPL source file ../src/Box_defs.hh line 50. */
36953#include <vector>
36954#include <iosfwd>
36955
36956namespace Parma_Polyhedra_Library {
36957
36958struct Interval_Base;
36959
36960//! Swaps \p x with \p y.
36961/*! \relates Box */
36962template <typename ITV>
36963void swap(Box<ITV>& x, Box<ITV>& y);
36964
36965//! Returns <CODE>true</CODE> if and only if \p x and \p y are the same box.
36966/*! \relates Box
36967  Note that \p x and \p y may be dimension-incompatible boxes:
36968  in this case, the value <CODE>false</CODE> is returned.
36969*/
36970template <typename ITV>
36971bool operator==(const Box<ITV>& x, const Box<ITV>& y);
36972
36973//! Returns <CODE>true</CODE> if and only if \p x and \p y are not the same box.
36974/*! \relates Box
36975  Note that \p x and \p y may be dimension-incompatible boxes:
36976  in this case, the value <CODE>true</CODE> is returned.
36977*/
36978template <typename ITV>
36979bool operator!=(const Box<ITV>& x, const Box<ITV>& y);
36980
36981namespace IO_Operators {
36982
36983//! Output operator.
36984/*! \relates Parma_Polyhedra_Library::Box */
36985template <typename ITV>
36986std::ostream& operator<<(std::ostream& s, const Box<ITV>& box);
36987
36988} // namespace IO_Operators
36989
36990//! Computes the rectilinear (or Manhattan) distance between \p x and \p y.
36991/*! \relates Box
36992  If the rectilinear distance between \p x and \p y is defined,
36993  stores an approximation of it into \p r and returns <CODE>true</CODE>;
36994  returns <CODE>false</CODE> otherwise.
36995
36996  The direction of the approximation is specified by \p dir.
36997
36998  All computations are performed using variables of type
36999  <CODE>Checked_Number\<To, Extended_Number_Policy\></CODE>.
37000*/
37001template <typename To, typename ITV>
37002bool
37003rectilinear_distance_assign(Checked_Number<To, Extended_Number_Policy>& r,
37004                            const Box<ITV>& x,
37005                            const Box<ITV>& y,
37006                            Rounding_Dir dir);
37007
37008//! Computes the rectilinear (or Manhattan) distance between \p x and \p y.
37009/*! \relates Box
37010  If the rectilinear distance between \p x and \p y is defined,
37011  stores an approximation of it into \p r and returns <CODE>true</CODE>;
37012  returns <CODE>false</CODE> otherwise.
37013
37014  The direction of the approximation is specified by \p dir.
37015
37016  All computations are performed using variables of type
37017  <CODE>Checked_Number\<Temp, Extended_Number_Policy\></CODE>.
37018*/
37019template <typename Temp, typename To, typename ITV>
37020bool
37021rectilinear_distance_assign(Checked_Number<To, Extended_Number_Policy>& r,
37022                            const Box<ITV>& x,
37023                            const Box<ITV>& y,
37024                            Rounding_Dir dir);
37025
37026//! Computes the rectilinear (or Manhattan) distance between \p x and \p y.
37027/*! \relates Box
37028  If the rectilinear distance between \p x and \p y is defined,
37029  stores an approximation of it into \p r and returns <CODE>true</CODE>;
37030  returns <CODE>false</CODE> otherwise.
37031
37032  The direction of the approximation is specified by \p dir.
37033
37034  All computations are performed using the temporary variables
37035  \p tmp0, \p tmp1 and \p tmp2.
37036*/
37037template <typename Temp, typename To, typename ITV>
37038bool
37039rectilinear_distance_assign(Checked_Number<To, Extended_Number_Policy>& r,
37040                            const Box<ITV>& x,
37041                            const Box<ITV>& y,
37042                            Rounding_Dir dir,
37043                            Temp& tmp0,
37044                            Temp& tmp1,
37045                            Temp& tmp2);
37046
37047//! Computes the euclidean distance between \p x and \p y.
37048/*! \relates Box
37049  If the euclidean distance between \p x and \p y is defined,
37050  stores an approximation of it into \p r and returns <CODE>true</CODE>;
37051  returns <CODE>false</CODE> otherwise.
37052
37053  The direction of the approximation is specified by \p dir.
37054
37055  All computations are performed using variables of type
37056  <CODE>Checked_Number\<To, Extended_Number_Policy\></CODE>.
37057*/
37058template <typename To, typename ITV>
37059bool
37060euclidean_distance_assign(Checked_Number<To, Extended_Number_Policy>& r,
37061                          const Box<ITV>& x,
37062                          const Box<ITV>& y,
37063                          Rounding_Dir dir);
37064
37065//! Computes the euclidean distance between \p x and \p y.
37066/*! \relates Box
37067  If the euclidean distance between \p x and \p y is defined,
37068  stores an approximation of it into \p r and returns <CODE>true</CODE>;
37069  returns <CODE>false</CODE> otherwise.
37070
37071  The direction of the approximation is specified by \p dir.
37072
37073  All computations are performed using variables of type
37074  <CODE>Checked_Number\<Temp, Extended_Number_Policy\></CODE>.
37075*/
37076template <typename Temp, typename To, typename ITV>
37077bool
37078euclidean_distance_assign(Checked_Number<To, Extended_Number_Policy>& r,
37079                          const Box<ITV>& x,
37080                          const Box<ITV>& y,
37081                          Rounding_Dir dir);
37082
37083//! Computes the euclidean distance between \p x and \p y.
37084/*! \relates Box
37085  If the euclidean distance between \p x and \p y is defined,
37086  stores an approximation of it into \p r and returns <CODE>true</CODE>;
37087  returns <CODE>false</CODE> otherwise.
37088
37089  The direction of the approximation is specified by \p dir.
37090
37091  All computations are performed using the temporary variables
37092  \p tmp0, \p tmp1 and \p tmp2.
37093*/
37094template <typename Temp, typename To, typename ITV>
37095bool
37096euclidean_distance_assign(Checked_Number<To, Extended_Number_Policy>& r,
37097                          const Box<ITV>& x,
37098                          const Box<ITV>& y,
37099                          Rounding_Dir dir,
37100                          Temp& tmp0,
37101                          Temp& tmp1,
37102                          Temp& tmp2);
37103
37104//! Computes the \f$L_\infty\f$ distance between \p x and \p y.
37105/*! \relates Box
37106  If the \f$L_\infty\f$ distance between \p x and \p y is defined,
37107  stores an approximation of it into \p r and returns <CODE>true</CODE>;
37108  returns <CODE>false</CODE> otherwise.
37109
37110  The direction of the approximation is specified by \p dir.
37111
37112  All computations are performed using variables of type
37113  <CODE>Checked_Number\<To, Extended_Number_Policy\></CODE>.
37114*/
37115template <typename To, typename ITV>
37116bool
37117l_infinity_distance_assign(Checked_Number<To, Extended_Number_Policy>& r,
37118                           const Box<ITV>& x,
37119                           const Box<ITV>& y,
37120                           Rounding_Dir dir);
37121
37122//! Computes the \f$L_\infty\f$ distance between \p x and \p y.
37123/*! \relates Box
37124  If the \f$L_\infty\f$ distance between \p x and \p y is defined,
37125  stores an approximation of it into \p r and returns <CODE>true</CODE>;
37126  returns <CODE>false</CODE> otherwise.
37127
37128  The direction of the approximation is specified by \p dir.
37129
37130  All computations are performed using variables of type
37131  <CODE>Checked_Number\<Temp, Extended_Number_Policy\></CODE>.
37132*/
37133template <typename Temp, typename To, typename ITV>
37134bool
37135l_infinity_distance_assign(Checked_Number<To, Extended_Number_Policy>& r,
37136                           const Box<ITV>& x,
37137                           const Box<ITV>& y,
37138                           Rounding_Dir dir);
37139
37140//! Computes the \f$L_\infty\f$ distance between \p x and \p y.
37141/*! \relates Box
37142  If the \f$L_\infty\f$ distance between \p x and \p y is defined,
37143  stores an approximation of it into \p r and returns <CODE>true</CODE>;
37144  returns <CODE>false</CODE> otherwise.
37145
37146  The direction of the approximation is specified by \p dir.
37147
37148  All computations are performed using the temporary variables
37149  \p tmp0, \p tmp1 and \p tmp2.
37150*/
37151template <typename Temp, typename To, typename ITV>
37152bool
37153l_infinity_distance_assign(Checked_Number<To, Extended_Number_Policy>& r,
37154                           const Box<ITV>& x,
37155                           const Box<ITV>& y,
37156                           Rounding_Dir dir,
37157                           Temp& tmp0,
37158                           Temp& tmp1,
37159                           Temp& tmp2);
37160
37161#ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
37162/*! \relates Box
37163  Helper function for computing distances.
37164*/
37165#endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
37166template <typename Specialization,
37167          typename Temp, typename To, typename ITV>
37168bool
37169l_m_distance_assign(Checked_Number<To, Extended_Number_Policy>& r,
37170                    const Box<ITV>& x, const Box<ITV>& y,
37171                    Rounding_Dir dir,
37172                    Temp& tmp0, Temp& tmp1, Temp& tmp2);
37173
37174} // namespace Parma_Polyhedra_Library
37175
37176//! A not necessarily closed, iso-oriented hyperrectangle.
37177/*! \ingroup PPL_CXX_interface
37178  A Box object represents the smash product of \f$n\f$
37179  not necessarily closed and possibly unbounded intervals
37180  represented by objects of class \p ITV,
37181  where \f$n\f$ is the space dimension of the box.
37182
37183  An <EM>interval constraint</EM> (resp., <EM>interval congruence</EM>)
37184  is a syntactic constraint (resp., congruence) that only mentions
37185  a single space dimension.
37186
37187  The Box domain <EM>optimally supports</EM>:
37188    - tautological and inconsistent constraints and congruences;
37189    - the interval constraints that are optimally supported by
37190      the template argument class \c ITV;
37191    - the interval congruences that are optimally supported by
37192      the template argument class \c ITV.
37193
37194  Depending on the method, using a constraint or congruence that is not
37195  optimally supported by the domain will either raise an exception or
37196  result in a (possibly non-optimal) upward approximation.
37197
37198  The user interface for the Box domain is meant to be as similar
37199  as possible to the one developed for the polyhedron class C_Polyhedron.
37200*/
37201template <typename ITV>
37202class Parma_Polyhedra_Library::Box {
37203public:
37204  //! The type of intervals used to implement the box.
37205  typedef ITV interval_type;
37206
37207  //! Returns the maximum space dimension that a Box can handle.
37208  static dimension_type max_space_dimension();
37209
37210  /*! \brief
37211    Returns false indicating that this domain does not recycle constraints
37212  */
37213  static bool can_recycle_constraint_systems();
37214
37215  /*! \brief
37216    Returns false indicating that this domain does not recycle congruences
37217  */
37218  static bool can_recycle_congruence_systems();
37219
37220  //! \name Constructors, Assignment, Swap and Destructor
37221  //@{
37222
37223  //! Builds a universe or empty box of the specified space dimension.
37224  /*!
37225    \param num_dimensions
37226    The number of dimensions of the vector space enclosing the box;
37227
37228    \param kind
37229    Specifies whether the universe or the empty box has to be built.
37230  */
37231  explicit Box(dimension_type num_dimensions = 0,
37232               Degenerate_Element kind = UNIVERSE);
37233
37234  //! Ordinary copy constructor.
37235  /*!
37236    The complexity argument is ignored.
37237  */
37238  Box(const Box& y,
37239      Complexity_Class complexity = ANY_COMPLEXITY);
37240
37241  //! Builds a conservative, upward approximation of \p y.
37242  /*!
37243    The complexity argument is ignored.
37244  */
37245  template <typename Other_ITV>
37246  explicit Box(const Box<Other_ITV>& y,
37247               Complexity_Class complexity = ANY_COMPLEXITY);
37248
37249  //! Builds a box from the system of constraints \p cs.
37250  /*!
37251    The box inherits the space dimension of \p cs.
37252
37253    \param cs
37254    A system of constraints: constraints that are not
37255    \ref intervals "interval constraints"
37256    are ignored (even though they may have contributed
37257    to the space dimension).
37258  */
37259  explicit Box(const Constraint_System& cs);
37260
37261  //! Builds a box recycling a system of constraints \p cs.
37262  /*!
37263    The box inherits the space dimension of \p cs.
37264
37265    \param cs
37266    A system of constraints: constraints that are not
37267    \ref intervals "interval constraints"
37268    are ignored (even though they may have contributed
37269    to the space dimension).
37270
37271    \param dummy
37272    A dummy tag to syntactically differentiate this one
37273    from the other constructors.
37274  */
37275  Box(const Constraint_System& cs, Recycle_Input dummy);
37276
37277  //! Builds a box from the system of generators \p gs.
37278  /*!
37279    Builds the smallest box containing the polyhedron defined by \p gs.
37280    The box inherits the space dimension of \p gs.
37281
37282    \exception std::invalid_argument
37283    Thrown if the system of generators is not empty but has no points.
37284  */
37285  explicit Box(const Generator_System& gs);
37286
37287  //! Builds a box recycling the system of generators \p gs.
37288  /*!
37289    Builds the smallest box containing the polyhedron defined by \p gs.
37290    The box inherits the space dimension of \p gs.
37291
37292    \param gs
37293    The generator system describing the polyhedron to be approximated.
37294
37295    \param dummy
37296    A dummy tag to syntactically differentiate this one
37297    from the other constructors.
37298
37299    \exception std::invalid_argument
37300    Thrown if the system of generators is not empty but has no points.
37301  */
37302  Box(const Generator_System& gs, Recycle_Input dummy);
37303
37304  /*!
37305    Builds the smallest box containing the grid defined by a
37306    system of congruences \p cgs.
37307    The box inherits the space dimension of \p cgs.
37308
37309    \param cgs
37310    A system of congruences: congruences that are not
37311    non-relational equality constraints are ignored
37312    (though they may have contributed to the space dimension).
37313  */
37314  explicit Box(const Congruence_System& cgs);
37315
37316  /*!
37317    Builds the smallest box containing the grid defined by a
37318    system of congruences \p cgs, recycling \p cgs.
37319    The box inherits the space dimension of \p cgs.
37320
37321    \param cgs
37322    A system of congruences: congruences that are not
37323    non-relational equality constraints are ignored
37324    (though they will contribute to the space dimension).
37325
37326    \param dummy
37327    A dummy tag to syntactically differentiate this one
37328    from the other constructors.
37329  */
37330  Box(const Congruence_System& cgs, Recycle_Input dummy);
37331
37332  //! Builds a box containing the BDS \p bds.
37333  /*!
37334    Builds the smallest box containing \p bds using a polynomial algorithm.
37335    The \p complexity argument is ignored.
37336  */
37337  template <typename T>
37338  explicit Box(const BD_Shape<T>& bds,
37339               Complexity_Class complexity = POLYNOMIAL_COMPLEXITY);
37340
37341  //! Builds a box containing the octagonal shape \p oct.
37342  /*!
37343    Builds the smallest box containing \p oct using a polynomial algorithm.
37344    The \p complexity argument is ignored.
37345  */
37346  template <typename T>
37347  explicit Box(const Octagonal_Shape<T>& oct,
37348               Complexity_Class complexity = POLYNOMIAL_COMPLEXITY);
37349
37350  //! Builds a box containing the polyhedron \p ph.
37351  /*!
37352    Builds a box containing \p ph using algorithms whose complexity
37353    does not exceed the one specified by \p complexity.  If
37354    \p complexity is \p ANY_COMPLEXITY, then the built box is the
37355    smallest one containing \p ph.
37356  */
37357  explicit Box(const Polyhedron& ph,
37358               Complexity_Class complexity = ANY_COMPLEXITY);
37359
37360  //! Builds a box containing the grid \p gr.
37361  /*!
37362    Builds the smallest box containing \p gr using a polynomial algorithm.
37363    The \p complexity argument is ignored.
37364  */
37365  explicit Box(const Grid& gr,
37366               Complexity_Class complexity = POLYNOMIAL_COMPLEXITY);
37367
37368  //! Builds a box containing the partially reduced product \p dp.
37369  /*!
37370    Builds a box containing \p ph using algorithms whose complexity
37371    does not exceed the one specified by \p complexity.
37372  */
37373  template <typename D1, typename D2, typename R>
37374  explicit Box(const Partially_Reduced_Product<D1, D2, R>& dp,
37375               Complexity_Class complexity = ANY_COMPLEXITY);
37376
37377  /*! \brief
37378    The assignment operator
37379    (\p *this and \p y can be dimension-incompatible).
37380  */
37381  Box& operator=(const Box& y);
37382
37383  /*! \brief
37384    Swaps \p *this with \p y
37385    (\p *this and \p y can be dimension-incompatible).
37386  */
37387  void m_swap(Box& y);
37388
37389  //@} Constructors, Assignment, Swap and Destructor
37390
37391  //! \name Member Functions that Do Not Modify the Box
37392  //@{
37393
37394  //! Returns the dimension of the vector space enclosing \p *this.
37395  dimension_type space_dimension() const;
37396
37397  /*! \brief
37398    Returns \f$0\f$, if \p *this is empty; otherwise, returns the
37399    \ref Affine_Independence_and_Affine_Dimension "affine dimension"
37400    of \p *this.
37401  */
37402  dimension_type affine_dimension() const;
37403
37404  //! Returns <CODE>true</CODE> if and only if \p *this is an empty box.
37405  bool is_empty() const;
37406
37407  //! Returns <CODE>true</CODE> if and only if \p *this is a universe box.
37408  bool is_universe() const;
37409
37410  /*! \brief
37411    Returns <CODE>true</CODE> if and only if \p *this
37412    is a topologically closed subset of the vector space.
37413  */
37414  bool is_topologically_closed() const;
37415
37416  //! Returns <CODE>true</CODE> if and only if \p *this is discrete.
37417  bool is_discrete() const;
37418
37419  //! Returns <CODE>true</CODE> if and only if \p *this is a bounded box.
37420  bool is_bounded() const;
37421
37422  /*! \brief
37423    Returns <CODE>true</CODE> if and only if \p *this
37424    contains at least one integer point.
37425  */
37426  bool contains_integer_point() const;
37427
37428  /*! \brief
37429    Returns <CODE>true</CODE> if and only if \p var is constrained in
37430    \p *this.
37431
37432    \exception std::invalid_argument
37433    Thrown if \p var is not a space dimension of \p *this.
37434  */
37435  bool constrains(Variable var) const;
37436
37437  //! Returns the relations holding between \p *this and the constraint \p c.
37438  /*!
37439    \exception std::invalid_argument
37440    Thrown if \p *this and constraint \p c are dimension-incompatible.
37441  */
37442  Poly_Con_Relation relation_with(const Constraint& c) const;
37443
37444  //! Returns the relations holding between \p *this and the congruence \p cg.
37445  /*!
37446    \exception std::invalid_argument
37447    Thrown if \p *this and constraint \p cg are dimension-incompatible.
37448  */
37449  Poly_Con_Relation relation_with(const Congruence& cg) const;
37450
37451  //! Returns the relations holding between \p *this and the generator \p g.
37452  /*!
37453    \exception std::invalid_argument
37454    Thrown if \p *this and generator \p g are dimension-incompatible.
37455  */
37456  Poly_Gen_Relation relation_with(const Generator& g) const;
37457
37458  /*! \brief
37459    Returns <CODE>true</CODE> if and only if \p expr is
37460    bounded from above in \p *this.
37461
37462    \exception std::invalid_argument
37463    Thrown if \p expr and \p *this are dimension-incompatible.
37464  */
37465  bool bounds_from_above(const Linear_Expression& expr) const;
37466
37467  /*! \brief
37468    Returns <CODE>true</CODE> if and only if \p expr is
37469    bounded from below in \p *this.
37470
37471    \exception std::invalid_argument
37472    Thrown if \p expr and \p *this are dimension-incompatible.
37473  */
37474  bool bounds_from_below(const Linear_Expression& expr) const;
37475
37476  /*! \brief
37477    Returns <CODE>true</CODE> if and only if \p *this is not empty
37478    and \p expr is bounded from above in \p *this, in which case
37479    the supremum value is computed.
37480
37481    \param expr
37482    The linear expression to be maximized subject to \p *this;
37483
37484    \param sup_n
37485    The numerator of the supremum value;
37486
37487    \param sup_d
37488    The denominator of the supremum value;
37489
37490    \param maximum
37491    <CODE>true</CODE> if and only if the supremum is also the maximum value.
37492
37493    \exception std::invalid_argument
37494    Thrown if \p expr and \p *this are dimension-incompatible.
37495
37496    If \p *this is empty or \p expr is not bounded from above,
37497    <CODE>false</CODE> is returned and \p sup_n, \p sup_d
37498    and \p maximum are left untouched.
37499  */
37500  bool maximize(const Linear_Expression& expr,
37501                Coefficient& sup_n, Coefficient& sup_d, bool& maximum) const;
37502
37503  /*! \brief
37504    Returns <CODE>true</CODE> if and only if \p *this is not empty
37505    and \p expr is bounded from above in \p *this, in which case
37506    the supremum value and a point where \p expr reaches it are computed.
37507
37508    \param expr
37509    The linear expression to be maximized subject to \p *this;
37510
37511    \param sup_n
37512    The numerator of the supremum value;
37513
37514    \param sup_d
37515    The denominator of the supremum value;
37516
37517    \param maximum
37518    <CODE>true</CODE> if and only if the supremum is also the maximum value;
37519
37520    \param g
37521    When maximization succeeds, will be assigned the point or
37522    closure point where \p expr reaches its supremum value.
37523
37524    \exception std::invalid_argument
37525    Thrown if \p expr and \p *this are dimension-incompatible.
37526
37527    If \p *this is empty or \p expr is not bounded from above,
37528    <CODE>false</CODE> is returned and \p sup_n, \p sup_d, \p maximum
37529    and \p g are left untouched.
37530  */
37531  bool maximize(const Linear_Expression& expr,
37532                Coefficient& sup_n, Coefficient& sup_d, bool& maximum,
37533                Generator& g) const;
37534
37535  /*! \brief
37536    Returns <CODE>true</CODE> if and only if \p *this is not empty
37537    and \p expr is bounded from below in \p *this, in which case
37538    the infimum value is computed.
37539
37540    \param expr
37541    The linear expression to be minimized subject to \p *this;
37542
37543    \param inf_n
37544    The numerator of the infimum value;
37545
37546    \param inf_d
37547    The denominator of the infimum value;
37548
37549    \param minimum
37550    <CODE>true</CODE> if and only if the infimum is also the minimum value.
37551
37552    \exception std::invalid_argument
37553    Thrown if \p expr and \p *this are dimension-incompatible.
37554
37555    If \p *this is empty or \p expr is not bounded from below,
37556    <CODE>false</CODE> is returned and \p inf_n, \p inf_d
37557    and \p minimum are left untouched.
37558  */
37559  bool minimize(const Linear_Expression& expr,
37560                Coefficient& inf_n, Coefficient& inf_d, bool& minimum) const;
37561
37562  /*! \brief
37563    Returns <CODE>true</CODE> if and only if \p *this is not empty
37564    and \p expr is bounded from below in \p *this, in which case
37565    the infimum value and a point where \p expr reaches it are computed.
37566
37567    \param expr
37568    The linear expression to be minimized subject to \p *this;
37569
37570    \param inf_n
37571    The numerator of the infimum value;
37572
37573    \param inf_d
37574    The denominator of the infimum value;
37575
37576    \param minimum
37577    <CODE>true</CODE> if and only if the infimum is also the minimum value;
37578
37579    \param g
37580    When minimization succeeds, will be assigned a point or
37581    closure point where \p expr reaches its infimum value.
37582
37583    \exception std::invalid_argument
37584    Thrown if \p expr and \p *this are dimension-incompatible.
37585
37586    If \p *this is empty or \p expr is not bounded from below,
37587    <CODE>false</CODE> is returned and \p inf_n, \p inf_d, \p minimum
37588    and \p g are left untouched.
37589  */
37590  bool minimize(const Linear_Expression& expr,
37591                Coefficient& inf_n, Coefficient& inf_d, bool& minimum,
37592                Generator& g) const;
37593
37594  /*! \brief
37595    Returns <CODE>true</CODE> if and only if there exist a
37596    unique value \p val such that \p *this
37597    saturates the equality <CODE>expr = val</CODE>.
37598
37599    \param expr
37600    The linear expression for which the frequency is needed;
37601
37602    \param freq_n
37603    If <CODE>true</CODE> is returned, the value is set to \f$0\f$;
37604    Present for interface compatibility with class Grid, where
37605    the \ref Grid_Frequency "frequency" can have a non-zero value;
37606
37607    \param freq_d
37608    If <CODE>true</CODE> is returned, the value is set to \f$1\f$;
37609
37610    \param val_n
37611    The numerator of \p val;
37612
37613    \param val_d
37614    The denominator of \p val;
37615
37616    \exception std::invalid_argument
37617    Thrown if \p expr and \p *this are dimension-incompatible.
37618
37619    If <CODE>false</CODE> is returned, then \p freq_n, \p freq_d,
37620    \p val_n and \p val_d are left untouched.
37621  */
37622  bool frequency(const Linear_Expression& expr,
37623                 Coefficient& freq_n, Coefficient& freq_d,
37624                 Coefficient& val_n, Coefficient& val_d) const;
37625
37626  /*! \brief
37627    Returns <CODE>true</CODE> if and only if \p *this contains \p y.
37628
37629    \exception std::invalid_argument
37630    Thrown if \p x and \p y are dimension-incompatible.
37631  */
37632  bool contains(const Box& y) const;
37633
37634  /*! \brief
37635    Returns <CODE>true</CODE> if and only if \p *this strictly contains \p y.
37636
37637    \exception std::invalid_argument
37638    Thrown if \p x and \p y are dimension-incompatible.
37639  */
37640  bool strictly_contains(const Box& y) const;
37641
37642  /*! \brief
37643    Returns <CODE>true</CODE> if and only if \p *this and \p y are disjoint.
37644
37645    \exception std::invalid_argument
37646    Thrown if \p x and \p y are dimension-incompatible.
37647  */
37648  bool is_disjoint_from(const Box& y) const;
37649
37650  /*! \brief
37651    Returns <CODE>true</CODE> if and only if \p *this satisfies
37652    all its invariants.
37653  */
37654  bool OK() const;
37655
37656  //@} Member Functions that Do Not Modify the Box
37657
37658  //! \name Space-Dimension Preserving Member Functions that May Modify the Box
37659  //@{
37660
37661  /*! \brief
37662    Adds a copy of constraint \p c to the system of constraints
37663    defining \p *this.
37664
37665    \param c
37666    The constraint to be added.
37667
37668    \exception std::invalid_argument
37669    Thrown if \p *this and constraint \p c are dimension-incompatible,
37670    or \p c is not optimally supported by the Box domain.
37671  */
37672  void add_constraint(const Constraint& c);
37673
37674  /*! \brief
37675    Adds the constraints in \p cs to the system of constraints
37676    defining \p *this.
37677
37678    \param  cs
37679    The constraints to be added.
37680
37681    \exception std::invalid_argument
37682    Thrown if \p *this and \p cs are dimension-incompatible,
37683    or \p cs contains a constraint which is not optimally supported
37684    by the box domain.
37685  */
37686  void add_constraints(const Constraint_System& cs);
37687
37688  /*! \brief
37689    Adds the constraints in \p cs to the system of constraints
37690    defining \p *this.
37691
37692    \param  cs
37693    The constraints to be added. They may be recycled.
37694
37695    \exception std::invalid_argument
37696    Thrown if \p *this and \p cs are dimension-incompatible,
37697    or \p cs contains a constraint which is not optimally supported
37698    by the box domain.
37699
37700    \warning
37701    The only assumption that can be made on \p cs upon successful or
37702    exceptional return is that it can be safely destroyed.
37703  */
37704  void add_recycled_constraints(Constraint_System& cs);
37705
37706  /*! \brief
37707    Adds to \p *this a constraint equivalent to the congruence \p cg.
37708
37709    \param cg
37710    The congruence to be added.
37711
37712    \exception std::invalid_argument
37713    Thrown if \p *this and congruence \p cg are dimension-incompatible,
37714    or \p cg is not optimally supported by the box domain.
37715  */
37716  void add_congruence(const Congruence& cg);
37717
37718  /*! \brief
37719    Adds to \p *this constraints equivalent to the congruences in \p cgs.
37720
37721    \param cgs
37722    The congruences to be added.
37723
37724    \exception std::invalid_argument
37725    Thrown if \p *this and \p cgs are dimension-incompatible,
37726    or \p cgs contains a congruence which is not optimally supported
37727    by the box domain.
37728  */
37729  void add_congruences(const Congruence_System& cgs);
37730
37731  /*! \brief
37732    Adds to \p *this constraints equivalent to the congruences in \p cgs.
37733
37734    \param cgs
37735    The congruence system to be added to \p *this.  The congruences in
37736    \p cgs may be recycled.
37737
37738    \exception std::invalid_argument
37739    Thrown if \p *this and \p cgs are dimension-incompatible,
37740    or \p cgs contains a congruence which is not optimally supported
37741    by the box domain.
37742
37743    \warning
37744    The only assumption that can be made on \p cgs upon successful or
37745    exceptional return is that it can be safely destroyed.
37746  */
37747  void add_recycled_congruences(Congruence_System& cgs);
37748
37749  /*! \brief
37750    Use the constraint \p c to refine \p *this.
37751
37752    \param c
37753    The constraint to be used for refinement.
37754
37755    \exception std::invalid_argument
37756    Thrown if \p *this and \p c are dimension-incompatible.
37757  */
37758  void refine_with_constraint(const Constraint& c);
37759
37760  /*! \brief
37761    Use the constraints in \p cs to refine \p *this.
37762
37763    \param  cs
37764    The constraints to be used for refinement.
37765    To avoid termination problems, each constraint in \p cs
37766    will be used for a single refinement step.
37767
37768    \exception std::invalid_argument
37769    Thrown if \p *this and \p cs are dimension-incompatible.
37770
37771    \note
37772    The user is warned that the accuracy of this refinement operator
37773    depends on the order of evaluation of the constraints in \p cs,
37774    which is in general unpredictable. If a fine control on such an
37775    order is needed, the user should consider calling the method
37776    <code>refine_with_constraint(const Constraint& c)</code> inside
37777    an appropriate looping construct.
37778  */
37779  void refine_with_constraints(const Constraint_System& cs);
37780
37781  /*! \brief
37782    Use the congruence \p cg to refine \p *this.
37783
37784    \param cg
37785    The congruence to be used for refinement.
37786
37787    \exception std::invalid_argument
37788    Thrown if \p *this and \p cg are dimension-incompatible.
37789  */
37790  void refine_with_congruence(const Congruence& cg);
37791
37792  /*! \brief
37793    Use the congruences in \p cgs to refine \p *this.
37794
37795    \param  cgs
37796    The congruences to be used for refinement.
37797
37798    \exception std::invalid_argument
37799    Thrown if \p *this and \p cgs are dimension-incompatible.
37800  */
37801  void refine_with_congruences(const Congruence_System& cgs);
37802
37803  /*! \brief
37804    Use the constraint \p c for constraint propagation on \p *this.
37805
37806    \param c
37807    The constraint to be used for constraint propagation.
37808
37809    \exception std::invalid_argument
37810    Thrown if \p *this and \p c are dimension-incompatible.
37811  */
37812  void propagate_constraint(const Constraint& c);
37813
37814  /*! \brief
37815    Use the constraints in \p cs for constraint propagation on \p *this.
37816
37817    \param cs
37818    The constraints to be used for constraint propagation.
37819
37820    \param max_iterations
37821    The maximum number of propagation steps for each constraint in
37822    \p cs.  If zero (the default), the number of propagation steps
37823    will be unbounded, possibly resulting in an infinite loop.
37824
37825    \exception std::invalid_argument
37826    Thrown if \p *this and \p cs are dimension-incompatible.
37827
37828    \warning
37829    This method may lead to non-termination if \p max_iterations is 0.
37830  */
37831  void propagate_constraints(const Constraint_System& cs,
37832                             dimension_type max_iterations = 0);
37833
37834  /*! \brief
37835    Computes the \ref Cylindrification "cylindrification" of \p *this with
37836    respect to space dimension \p var, assigning the result to \p *this.
37837
37838    \param var
37839    The space dimension that will be unconstrained.
37840
37841    \exception std::invalid_argument
37842    Thrown if \p var is not a space dimension of \p *this.
37843  */
37844  void unconstrain(Variable var);
37845
37846  /*! \brief
37847    Computes the \ref Cylindrification "cylindrification" of \p *this with
37848    respect to the set of space dimensions \p vars,
37849    assigning the result to \p *this.
37850
37851    \param vars
37852    The set of space dimension that will be unconstrained.
37853
37854    \exception std::invalid_argument
37855    Thrown if \p *this is dimension-incompatible with one of the
37856    Variable objects contained in \p vars.
37857  */
37858  void unconstrain(const Variables_Set& vars);
37859
37860  //! Assigns to \p *this the intersection of \p *this and \p y.
37861  /*!
37862    \exception std::invalid_argument
37863    Thrown if \p *this and \p y are dimension-incompatible.
37864  */
37865  void intersection_assign(const Box& y);
37866
37867  /*! \brief
37868    Assigns to \p *this the smallest box containing the union
37869    of \p *this and \p y.
37870
37871    \exception std::invalid_argument
37872    Thrown if \p *this and \p y are dimension-incompatible.
37873  */
37874  void upper_bound_assign(const Box& y);
37875
37876  /*! \brief
37877    If the upper bound of \p *this and \p y is exact, it is assigned
37878    to \p *this and <CODE>true</CODE> is returned,
37879    otherwise <CODE>false</CODE> is returned.
37880
37881    \exception std::invalid_argument
37882    Thrown if \p *this and \p y are dimension-incompatible.
37883  */
37884  bool upper_bound_assign_if_exact(const Box& y);
37885
37886  /*! \brief
37887    Assigns to \p *this the difference of \p *this and \p y.
37888
37889    \exception std::invalid_argument
37890    Thrown if \p *this and \p y are dimension-incompatible.
37891  */
37892  void difference_assign(const Box& y);
37893
37894  /*! \brief
37895    Assigns to \p *this a \ref Meet_Preserving_Simplification
37896    "meet-preserving simplification" of \p *this with respect to \p y.
37897    If \c false is returned, then the intersection is empty.
37898
37899    \exception std::invalid_argument
37900    Thrown if \p *this and \p y are dimension-incompatible.
37901  */
37902  bool simplify_using_context_assign(const Box& y);
37903
37904  /*! \brief
37905    Assigns to \p *this the
37906    \ref Single_Update_Affine_Functions "affine image"
37907    of \p *this under the function mapping variable \p var to the
37908    affine expression specified by \p expr and \p denominator.
37909
37910    \param var
37911    The variable to which the affine expression is assigned;
37912
37913    \param expr
37914    The numerator of the affine expression;
37915
37916    \param denominator
37917    The denominator of the affine expression (optional argument with
37918    default value 1).
37919
37920    \exception std::invalid_argument
37921    Thrown if \p denominator is zero or if \p expr and \p *this are
37922    dimension-incompatible or if \p var is not a space dimension of
37923    \p *this.
37924  */
37925  void affine_image(Variable var,
37926                    const Linear_Expression& expr,
37927                    Coefficient_traits::const_reference denominator
37928                      = Coefficient_one());
37929
37930  // FIXME: To be completed.
37931  /*! \brief
37932    Assigns to \p *this the \ref affine_form_relation "affine form image"
37933    of \p *this under the function mapping variable \p var into the
37934    affine expression(s) specified by \p lf.
37935
37936    \param var
37937    The variable to which the affine expression is assigned.
37938
37939    \param lf
37940    The linear form on intervals with floating point boundaries that
37941    defines the affine expression(s). ALL of its coefficients MUST be bounded.
37942
37943    \exception std::invalid_argument
37944    Thrown if \p lf and \p *this are dimension-incompatible or if \p var
37945    is not a dimension of \p *this.
37946
37947    This function is used in abstract interpretation to model an assignment
37948    of a value that is correctly overapproximated by \p lf to the
37949    floating point variable represented by \p var.
37950  */
37951  void affine_form_image(Variable var,
37952                         const Linear_Form<ITV>& lf);
37953
37954  /*! \brief
37955    Assigns to \p *this the
37956    \ref Single_Update_Affine_Functions "affine preimage"
37957    of \p *this under the function mapping variable \p var to the
37958    affine expression specified by \p expr and \p denominator.
37959
37960    \param var
37961    The variable to which the affine expression is substituted;
37962
37963    \param expr
37964    The numerator of the affine expression;
37965
37966    \param denominator
37967    The denominator of the affine expression (optional argument with
37968    default value 1).
37969
37970    \exception std::invalid_argument
37971    Thrown if \p denominator is zero or if \p expr and \p *this are
37972    dimension-incompatible or if \p var is not a space dimension of \p *this.
37973  */
37974  void affine_preimage(Variable var,
37975                       const Linear_Expression& expr,
37976                       Coefficient_traits::const_reference denominator
37977                         = Coefficient_one());
37978
37979  /*! \brief
37980    Assigns to \p *this the image of \p *this with respect to the
37981    \ref Generalized_Affine_Relations "generalized affine relation"
37982    \f$\mathrm{var}' \relsym \frac{\mathrm{expr}}{\mathrm{denominator}}\f$,
37983    where \f$\mathord{\relsym}\f$ is the relation symbol encoded
37984    by \p relsym.
37985
37986    \param var
37987    The left hand side variable of the generalized affine relation;
37988
37989    \param relsym
37990    The relation symbol;
37991
37992    \param expr
37993    The numerator of the right hand side affine expression;
37994
37995    \param denominator
37996    The denominator of the right hand side affine expression (optional
37997    argument with default value 1).
37998
37999    \exception std::invalid_argument
38000    Thrown if \p denominator is zero or if \p expr and \p *this are
38001    dimension-incompatible or if \p var is not a space dimension of \p *this.
38002  */
38003  void generalized_affine_image(Variable var,
38004                                Relation_Symbol relsym,
38005                                const Linear_Expression& expr,
38006                                Coefficient_traits::const_reference denominator
38007                                  = Coefficient_one());
38008
38009  /*! \brief
38010    Assigns to \p *this the preimage of \p *this with respect to the
38011    \ref Generalized_Affine_Relations "generalized affine relation"
38012    \f$\mathrm{var}' \relsym \frac{\mathrm{expr}}{\mathrm{denominator}}\f$,
38013    where \f$\mathord{\relsym}\f$ is the relation symbol encoded
38014    by \p relsym.
38015
38016    \param var
38017    The left hand side variable of the generalized affine relation;
38018
38019    \param relsym
38020    The relation symbol;
38021
38022    \param expr
38023    The numerator of the right hand side affine expression;
38024
38025    \param denominator
38026    The denominator of the right hand side affine expression (optional
38027    argument with default value 1).
38028
38029    \exception std::invalid_argument
38030    Thrown if \p denominator is zero or if \p expr and \p *this are
38031    dimension-incompatible or if \p var is not a space dimension of \p *this.
38032  */
38033  void
38034  generalized_affine_preimage(Variable var,
38035                              Relation_Symbol relsym,
38036                              const Linear_Expression& expr,
38037                              Coefficient_traits::const_reference denominator
38038                              = Coefficient_one());
38039
38040  /*! \brief
38041    Assigns to \p *this the image of \p *this with respect to the
38042    \ref Generalized_Affine_Relations "generalized affine relation"
38043    \f$\mathrm{lhs}' \relsym \mathrm{rhs}\f$, where
38044    \f$\mathord{\relsym}\f$ is the relation symbol encoded by \p relsym.
38045
38046    \param lhs
38047    The left hand side affine expression;
38048
38049    \param relsym
38050    The relation symbol;
38051
38052    \param rhs
38053    The right hand side affine expression.
38054
38055    \exception std::invalid_argument
38056    Thrown if \p *this is dimension-incompatible with \p lhs or \p rhs.
38057  */
38058  void generalized_affine_image(const Linear_Expression& lhs,
38059                                Relation_Symbol relsym,
38060                                const Linear_Expression& rhs);
38061
38062  /*! \brief
38063    Assigns to \p *this the preimage of \p *this with respect to the
38064    \ref Generalized_Affine_Relations "generalized affine relation"
38065    \f$\mathrm{lhs}' \relsym \mathrm{rhs}\f$, where
38066    \f$\mathord{\relsym}\f$ is the relation symbol encoded by \p relsym.
38067
38068    \param lhs
38069    The left hand side affine expression;
38070
38071    \param relsym
38072    The relation symbol;
38073
38074    \param rhs
38075    The right hand side affine expression.
38076
38077    \exception std::invalid_argument
38078    Thrown if \p *this is dimension-incompatible with \p lhs or \p rhs.
38079  */
38080  void generalized_affine_preimage(const Linear_Expression& lhs,
38081                                   Relation_Symbol relsym,
38082                                   const Linear_Expression& rhs);
38083
38084  /*! \brief
38085    Assigns to \p *this the image of \p *this with respect to the
38086    \ref Single_Update_Bounded_Affine_Relations "bounded affine relation"
38087    \f$\frac{\mathrm{lb\_expr}}{\mathrm{denominator}}
38088         \leq \mathrm{var}'
38089           \leq \frac{\mathrm{ub\_expr}}{\mathrm{denominator}}\f$.
38090
38091    \param var
38092    The variable updated by the affine relation;
38093
38094    \param lb_expr
38095    The numerator of the lower bounding affine expression;
38096
38097    \param ub_expr
38098    The numerator of the upper bounding affine expression;
38099
38100    \param denominator
38101    The (common) denominator for the lower and upper bounding
38102    affine expressions (optional argument with default value 1).
38103
38104    \exception std::invalid_argument
38105    Thrown if \p denominator is zero or if \p lb_expr (resp., \p ub_expr)
38106    and \p *this are dimension-incompatible or if \p var is not a space
38107    dimension of \p *this.
38108  */
38109  void bounded_affine_image(Variable var,
38110                            const Linear_Expression& lb_expr,
38111                            const Linear_Expression& ub_expr,
38112                            Coefficient_traits::const_reference denominator
38113                            = Coefficient_one());
38114
38115  /*! \brief
38116    Assigns to \p *this the preimage of \p *this with respect to the
38117    \ref Single_Update_Bounded_Affine_Relations "bounded affine relation"
38118    \f$\frac{\mathrm{lb\_expr}}{\mathrm{denominator}}
38119         \leq \mathrm{var}'
38120           \leq \frac{\mathrm{ub\_expr}}{\mathrm{denominator}}\f$.
38121
38122    \param var
38123    The variable updated by the affine relation;
38124
38125    \param lb_expr
38126    The numerator of the lower bounding affine expression;
38127
38128    \param ub_expr
38129    The numerator of the upper bounding affine expression;
38130
38131    \param denominator
38132    The (common) denominator for the lower and upper bounding
38133    affine expressions (optional argument with default value 1).
38134
38135    \exception std::invalid_argument
38136    Thrown if \p denominator is zero or if \p lb_expr (resp., \p ub_expr)
38137    and \p *this are dimension-incompatible or if \p var is not a space
38138    dimension of \p *this.
38139  */
38140  void bounded_affine_preimage(Variable var,
38141                               const Linear_Expression& lb_expr,
38142                               const Linear_Expression& ub_expr,
38143                               Coefficient_traits::const_reference denominator
38144                               = Coefficient_one());
38145
38146  /*! \brief
38147    Assigns to \p *this the result of computing the
38148    \ref Time_Elapse_Operator "time-elapse" between \p *this and \p y.
38149
38150    \exception std::invalid_argument
38151    Thrown if \p *this and \p y are dimension-incompatible.
38152  */
38153  void time_elapse_assign(const Box& y);
38154
38155  //! Assigns to \p *this its topological closure.
38156  void topological_closure_assign();
38157
38158  /*! \brief
38159    \ref Wrapping_Operator "Wraps" the specified dimensions of the
38160    vector space.
38161
38162    \param vars
38163    The set of Variable objects corresponding to the space dimensions
38164    to be wrapped.
38165
38166    \param w
38167    The width of the bounded integer type corresponding to
38168    all the dimensions to be wrapped.
38169
38170    \param r
38171    The representation of the bounded integer type corresponding to
38172    all the dimensions to be wrapped.
38173
38174    \param o
38175    The overflow behavior of the bounded integer type corresponding to
38176    all the dimensions to be wrapped.
38177
38178    \param cs_p
38179    Possibly null pointer to a constraint system.  When non-null,
38180    the pointed-to constraint system is assumed to represent the
38181    conditional or looping construct guard with respect to which
38182    wrapping is performed.  Since wrapping requires the computation
38183    of upper bounds and due to non-distributivity of constraint
38184    refinement over upper bounds, passing a constraint system in this
38185    way can be more precise than refining the result of the wrapping
38186    operation with the constraints in <CODE>*cs_p</CODE>.
38187
38188    \param complexity_threshold
38189    A precision parameter which is ignored for the Box domain.
38190
38191    \param wrap_individually
38192    A precision parameter which is ignored for the Box domain.
38193
38194    \exception std::invalid_argument
38195    Thrown if \p *this is dimension-incompatible with one of the
38196    Variable objects contained in \p vars or with <CODE>*cs_p</CODE>.
38197  */
38198  void wrap_assign(const Variables_Set& vars,
38199                   Bounded_Integer_Type_Width w,
38200                   Bounded_Integer_Type_Representation r,
38201                   Bounded_Integer_Type_Overflow o,
38202                   const Constraint_System* cs_p = 0,
38203                   unsigned complexity_threshold = 16,
38204                   bool wrap_individually = true);
38205
38206  /*! \brief
38207    Possibly tightens \p *this by dropping some points with non-integer
38208    coordinates.
38209
38210    \param complexity
38211    The maximal complexity of any algorithms used.
38212
38213    \note
38214    Currently there is no optimality guarantee, not even if
38215    \p complexity is <CODE>ANY_COMPLEXITY</CODE>.
38216  */
38217  void drop_some_non_integer_points(Complexity_Class complexity
38218                                    = ANY_COMPLEXITY);
38219
38220  /*! \brief
38221    Possibly tightens \p *this by dropping some points with non-integer
38222    coordinates for the space dimensions corresponding to \p vars.
38223
38224    \param vars
38225    Points with non-integer coordinates for these variables/space-dimensions
38226    can be discarded.
38227
38228    \param complexity
38229    The maximal complexity of any algorithms used.
38230
38231    \note
38232    Currently there is no optimality guarantee, not even if
38233    \p complexity is <CODE>ANY_COMPLEXITY</CODE>.
38234  */
38235  void drop_some_non_integer_points(const Variables_Set& vars,
38236                                    Complexity_Class complexity
38237                                    = ANY_COMPLEXITY);
38238
38239  /*! \brief
38240    Assigns to \p *this the result of computing the
38241    \ref CC76_extrapolation "CC76-widening" between \p *this and \p y.
38242
38243    \param y
38244    A box that <EM>must</EM> be contained in \p *this.
38245
38246    \param tp
38247    An optional pointer to an unsigned variable storing the number of
38248    available tokens (to be used when applying the
38249    \ref Widening_with_Tokens "widening with tokens" delay technique).
38250
38251    \exception std::invalid_argument
38252    Thrown if \p *this and \p y are dimension-incompatible.
38253  */
38254  template <typename T>
38255  typename Enable_If<Is_Same<T, Box>::value
38256                     && Is_Same_Or_Derived<Interval_Base, ITV>::value,
38257                     void>::type
38258  CC76_widening_assign(const T& y, unsigned* tp = 0);
38259
38260  /*! \brief
38261    Assigns to \p *this the result of computing the
38262    \ref CC76_extrapolation "CC76-widening" between \p *this and \p y.
38263
38264    \param y
38265    A box that <EM>must</EM> be contained in \p *this.
38266
38267    \param first
38268    An iterator that points to the first stop-point.
38269
38270    \param last
38271    An iterator that points one past the last stop-point.
38272
38273    \exception std::invalid_argument
38274    Thrown if \p *this and \p y are dimension-incompatible.
38275  */
38276  template <typename T, typename Iterator>
38277  typename Enable_If<Is_Same<T, Box>::value
38278                     && Is_Same_Or_Derived<Interval_Base, ITV>::value,
38279                     void>::type
38280  CC76_widening_assign(const T& y,
38281                       Iterator first, Iterator last);
38282
38283  //! Same as CC76_widening_assign(y, tp).
38284  void widening_assign(const Box& y, unsigned* tp = 0);
38285
38286  /*! \brief
38287    Improves the result of the \ref CC76_extrapolation "CC76-extrapolation"
38288    computation by also enforcing those constraints in \p cs that are
38289    satisfied by all the points of \p *this.
38290
38291    \param y
38292    A box that <EM>must</EM> be contained in \p *this.
38293
38294    \param cs
38295    The system of constraints used to improve the widened box.
38296
38297    \param tp
38298    An optional pointer to an unsigned variable storing the number of
38299    available tokens (to be used when applying the
38300    \ref Widening_with_Tokens "widening with tokens" delay technique).
38301
38302    \exception std::invalid_argument
38303    Thrown if \p *this, \p y and \p cs are dimension-incompatible or
38304    if \p cs contains a strict inequality.
38305  */
38306  void limited_CC76_extrapolation_assign(const Box& y,
38307                                         const Constraint_System& cs,
38308                                         unsigned* tp = 0);
38309
38310  /*! \brief
38311    Assigns to \p *this the result of restoring in \p y the constraints
38312    of \p *this that were lost by
38313    \ref CC76_extrapolation "CC76-extrapolation" applications.
38314
38315    \param y
38316    A Box that <EM>must</EM> contain \p *this.
38317
38318    \exception std::invalid_argument
38319    Thrown if \p *this and \p y are dimension-incompatible.
38320
38321    \note
38322    As was the case for widening operators, the argument \p y is meant to
38323    denote the value computed in the previous iteration step, whereas
38324    \p *this denotes the value computed in the current iteration step
38325    (in the <EM>decreasing</EM> iteration sequence). Hence, the call
38326    <CODE>x.CC76_narrowing_assign(y)</CODE> will assign to \p x
38327    the result of the computation \f$\mathtt{y} \Delta \mathtt{x}\f$.
38328  */
38329  template <typename T>
38330  typename Enable_If<Is_Same<T, Box>::value
38331                     && Is_Same_Or_Derived<Interval_Base, ITV>::value,
38332                     void>::type
38333  CC76_narrowing_assign(const T& y);
38334
38335  //@} Space-Dimension Preserving Member Functions that May Modify [...]
38336
38337  //! \name Member Functions that May Modify the Dimension of the Vector Space
38338  //@{
38339
38340  //! Adds \p m new dimensions and embeds the old box into the new space.
38341  /*!
38342    \param m
38343    The number of dimensions to add.
38344
38345    The new dimensions will be those having the highest indexes in the new
38346    box, which is defined by a system of interval constraints in which the
38347    variables running through the new dimensions are unconstrained.
38348    For instance, when starting from the box \f$\cB \sseq \Rset^2\f$
38349    and adding a third dimension, the result will be the box
38350    \f[
38351      \bigl\{\,
38352        (x, y, z)^\transpose \in \Rset^3
38353      \bigm|
38354        (x, y)^\transpose \in \cB
38355      \,\bigr\}.
38356    \f]
38357  */
38358  void add_space_dimensions_and_embed(dimension_type m);
38359
38360  /*! \brief
38361    Adds \p m new dimensions to the box and does not embed it in
38362    the new vector space.
38363
38364    \param m
38365    The number of dimensions to add.
38366
38367    The new dimensions will be those having the highest indexes in the
38368    new box, which is defined by a system of bounded differences in
38369    which the variables running through the new dimensions are all
38370    constrained to be equal to 0.
38371    For instance, when starting from the box \f$\cB \sseq \Rset^2\f$
38372    and adding a third dimension, the result will be the box
38373    \f[
38374      \bigl\{\,
38375        (x, y, 0)^\transpose \in \Rset^3
38376      \bigm|
38377        (x, y)^\transpose \in \cB
38378      \,\bigr\}.
38379    \f]
38380  */
38381  void add_space_dimensions_and_project(dimension_type m);
38382
38383  /*! \brief
38384    Seeing a box as a set of tuples (its points),
38385    assigns to \p *this all the tuples that can be obtained by concatenating,
38386    in the order given, a tuple of \p *this with a tuple of \p y.
38387
38388    Let \f$B \sseq \Rset^n\f$ and \f$D \sseq \Rset^m\f$ be the boxes
38389    corresponding, on entry, to \p *this and \p y, respectively.
38390    Upon successful completion, \p *this will represent the box
38391    \f$R \sseq \Rset^{n+m}\f$ such that
38392    \f[
38393      R \defeq
38394          \Bigl\{\,
38395            (x_1, \ldots, x_n, y_1, \ldots, y_m)^\transpose
38396          \Bigm|
38397            (x_1, \ldots, x_n)^\transpose \in B,
38398            (y_1, \ldots, y_m)^\transpose \in D
38399          \,\Bigl\}.
38400    \f]
38401    Another way of seeing it is as follows: first increases the space
38402    dimension of \p *this by adding \p y.space_dimension() new
38403    dimensions; then adds to the system of constraints of \p *this a
38404    renamed-apart version of the constraints of \p y.
38405  */
38406  void concatenate_assign(const Box& y);
38407
38408  //! Removes all the specified dimensions.
38409  /*!
38410    \param vars
38411    The set of Variable objects corresponding to the dimensions to be removed.
38412
38413    \exception std::invalid_argument
38414    Thrown if \p *this is dimension-incompatible with one of the Variable
38415    objects contained in \p vars.
38416  */
38417  void remove_space_dimensions(const Variables_Set& vars);
38418
38419  /*! \brief
38420    Removes the higher dimensions so that the resulting space
38421    will have dimension \p new_dimension.
38422
38423    \exception std::invalid_argument
38424    Thrown if \p new_dimension is greater than the space dimension
38425    of \p *this.
38426  */
38427  void remove_higher_space_dimensions(dimension_type new_dimension);
38428
38429  /*! \brief
38430    Remaps the dimensions of the vector space according to
38431    a \ref Mapping_the_Dimensions_of_the_Vector_Space "partial function".
38432
38433    \param pfunc
38434    The partial function specifying the destiny of each dimension.
38435
38436    The template type parameter Partial_Function must provide
38437    the following methods.
38438    \code
38439      bool has_empty_codomain() const
38440    \endcode
38441    returns <CODE>true</CODE> if and only if the represented partial
38442    function has an empty co-domain (i.e., it is always undefined).
38443    The <CODE>has_empty_codomain()</CODE> method will always be called
38444    before the methods below.  However, if
38445    <CODE>has_empty_codomain()</CODE> returns <CODE>true</CODE>, none
38446    of the functions below will be called.
38447    \code
38448      dimension_type max_in_codomain() const
38449    \endcode
38450    returns the maximum value that belongs to the co-domain
38451    of the partial function.
38452    \code
38453      bool maps(dimension_type i, dimension_type& j) const
38454    \endcode
38455    Let \f$f\f$ be the represented function and \f$k\f$ be the value
38456    of \p i.  If \f$f\f$ is defined in \f$k\f$, then \f$f(k)\f$ is
38457    assigned to \p j and <CODE>true</CODE> is returned.
38458    If \f$f\f$ is undefined in \f$k\f$, then <CODE>false</CODE> is
38459    returned.
38460
38461    The result is undefined if \p pfunc does not encode a partial
38462    function with the properties described in the
38463    \ref Mapping_the_Dimensions_of_the_Vector_Space
38464    "specification of the mapping operator".
38465  */
38466  template <typename Partial_Function>
38467  void map_space_dimensions(const Partial_Function& pfunc);
38468
38469  //! Creates \p m copies of the space dimension corresponding to \p var.
38470  /*!
38471    \param var
38472    The variable corresponding to the space dimension to be replicated;
38473
38474    \param m
38475    The number of replicas to be created.
38476
38477    \exception std::invalid_argument
38478    Thrown if \p var does not correspond to a dimension of the vector space.
38479
38480    \exception std::length_error
38481    Thrown if adding \p m new space dimensions would cause the
38482    vector space to exceed dimension <CODE>max_space_dimension()</CODE>.
38483
38484    If \p *this has space dimension \f$n\f$, with \f$n > 0\f$,
38485    and <CODE>var</CODE> has space dimension \f$k \leq n\f$,
38486    then the \f$k\f$-th space dimension is
38487    \ref expand_space_dimension "expanded" to \p m new space dimensions
38488    \f$n\f$, \f$n+1\f$, \f$\dots\f$, \f$n+m-1\f$.
38489  */
38490  void expand_space_dimension(Variable var, dimension_type m);
38491
38492  //! Folds the space dimensions in \p vars into \p dest.
38493  /*!
38494    \param vars
38495    The set of Variable objects corresponding to the space dimensions
38496    to be folded;
38497
38498    \param dest
38499    The variable corresponding to the space dimension that is the
38500    destination of the folding operation.
38501
38502    \exception std::invalid_argument
38503    Thrown if \p *this is dimension-incompatible with \p dest or with
38504    one of the Variable objects contained in \p vars.
38505    Also thrown if \p dest is contained in \p vars.
38506
38507    If \p *this has space dimension \f$n\f$, with \f$n > 0\f$,
38508    <CODE>dest</CODE> has space dimension \f$k \leq n\f$,
38509    \p vars is a set of variables whose maximum space dimension
38510    is also less than or equal to \f$n\f$, and \p dest is not a member
38511    of \p vars, then the space dimensions corresponding to
38512    variables in \p vars are \ref fold_space_dimensions "folded"
38513    into the \f$k\f$-th space dimension.
38514  */
38515  void fold_space_dimensions(const Variables_Set& vars, Variable dest);
38516
38517  //@} // Member Functions that May Modify the Dimension of the Vector Space
38518
38519  /*! \brief
38520    Returns a reference the interval that bounds \p var.
38521
38522    \exception std::invalid_argument
38523    Thrown if \p var is not a space dimension of \p *this.
38524  */
38525  const ITV& get_interval(Variable var) const;
38526
38527  /*! \brief
38528    Sets to \p i the interval that bounds \p var.
38529
38530    \exception std::invalid_argument
38531    Thrown if \p var is not a space dimension of \p *this.
38532  */
38533  void set_interval(Variable var, const ITV& i);
38534
38535  /*! \brief
38536    If the space dimension of \p var is unbounded below, return
38537    <CODE>false</CODE>. Otherwise return <CODE>true</CODE> and set
38538    \p n, \p d and \p closed accordingly.
38539
38540    \note
38541    It is assumed that <CODE>*this</CODE> is a non-empty box
38542    having space dimension greater than or equal to that of \p var.
38543    An undefined behavior is obtained if this assumption is not met.
38544    \if Include_Implementation_Details
38545    To be more precise, if <CODE>*this</CODE> is an <EM>empty</EM> box
38546    (having space dimension greater than or equal to that of \p var)
38547    such that <CODE>!marked_empty()</CODE> holds, then the method can be
38548    called without incurring in undefined behavior: it will return
38549    <EM>unspecified</EM> boundary values that, if queried systematically
38550    on all space dimensions, will encode the box emptiness.
38551    \endif
38552
38553    Let \f$I\f$ be the interval corresponding to variable \p var
38554    in the non-empty box <CODE>*this</CODE>.
38555    If \f$I\f$ is not bounded from below, simply return <CODE>false</CODE>
38556    (leaving all other parameters unchanged).
38557    Otherwise, set \p n, \p d and \p closed as follows:
38558     - \p n and \p d are assigned the integers \f$n\f$ and \f$d\f$ such
38559       that the fraction \f$n/d\f$ corresponds to the greatest lower bound
38560       of \f$I\f$. The fraction \f$n/d\f$ is in canonical form, meaning
38561       that \f$n\f$ and \f$d\f$ have no common factors, \f$d\f$ is positive,
38562       and if \f$n\f$ is zero then \f$d\f$ is one;
38563     - \p closed is set to <CODE>true</CODE> if and only if the lower
38564       boundary of \f$I\f$ is closed (i.e., it is included in the interval).
38565  */
38566  bool has_lower_bound(Variable var,
38567                       Coefficient& n, Coefficient& d, bool& closed) const;
38568
38569  /*! \brief
38570    If the space dimension of \p var is unbounded above, return
38571    <CODE>false</CODE>. Otherwise return <CODE>true</CODE> and set
38572    \p n, \p d and \p closed accordingly.
38573
38574    \note
38575    It is assumed that <CODE>*this</CODE> is a non-empty box
38576    having space dimension greater than or equal to that of \p var.
38577    An undefined behavior is obtained if this assumption is not met.
38578    \if Include_Implementation_Details
38579    To be more precise, if <CODE>*this</CODE> is an <EM>empty</EM> box
38580    (having space dimension greater than or equal to that of \p var)
38581    such that <CODE>!marked_empty()</CODE> holds, then the method can be
38582    called without incurring in undefined behavior: it will return
38583    <EM>unspecified</EM> boundary values that, if queried systematically
38584    on all space dimensions, will encode the box emptiness.
38585    \endif
38586
38587    Let \f$I\f$ be the interval corresponding to variable \p var
38588    in the non-empty box <CODE>*this</CODE>.
38589    If \f$I\f$ is not bounded from above, simply return <CODE>false</CODE>
38590    (leaving all other parameters unchanged).
38591    Otherwise, set \p n, \p d and \p closed as follows:
38592     - \p n and \p d are assigned the integers \f$n\f$ and \f$d\f$ such
38593       that the fraction \f$n/d\f$ corresponds to the least upper bound
38594       of \f$I\f$. The fraction \f$n/d\f$ is in canonical form, meaning
38595       that \f$n\f$ and \f$d\f$ have no common factors, \f$d\f$ is positive,
38596       and if \f$n\f$ is zero then \f$d\f$ is one;
38597     - \p closed is set to <CODE>true</CODE> if and only if the upper
38598       boundary of \f$I\f$ is closed (i.e., it is included in the interval).
38599  */
38600  bool has_upper_bound(Variable var,
38601                       Coefficient& n, Coefficient& d, bool& closed) const;
38602
38603  //! Returns a system of constraints defining \p *this.
38604  Constraint_System constraints() const;
38605
38606  //! Returns a minimized system of constraints defining \p *this.
38607  Constraint_System minimized_constraints() const;
38608
38609  //! Returns a system of congruences approximating \p *this.
38610  Congruence_System congruences() const;
38611
38612  //! Returns a minimized system of congruences approximating \p *this.
38613  Congruence_System minimized_congruences() const;
38614
38615  //! Returns the total size in bytes of the memory occupied by \p *this.
38616  memory_size_type total_memory_in_bytes() const;
38617
38618  //! Returns the size in bytes of the memory managed by \p *this.
38619  memory_size_type external_memory_in_bytes() const;
38620
38621  /*! \brief
38622    Returns a 32-bit hash code for \p *this.
38623
38624    If <CODE>x</CODE> and <CODE>y</CODE> are such that <CODE>x == y</CODE>,
38625    then <CODE>x.hash_code() == y.hash_code()</CODE>.
38626  */
38627  int32_t hash_code() const;
38628
38629  PPL_OUTPUT_DECLARATIONS
38630
38631#ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
38632  /*! \brief
38633    Loads from \p s an ASCII representation (as produced by
38634    ascii_dump(std::ostream&) const) and sets \p *this accordingly.
38635    Returns <CODE>true</CODE> if successful, <CODE>false</CODE> otherwise.
38636  */
38637#endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
38638  bool ascii_load(std::istream& s);
38639
38640private:
38641  template <typename Other_ITV>
38642  friend class Parma_Polyhedra_Library::Box;
38643
38644  friend bool
38645  operator==<ITV>(const Box<ITV>& x, const Box<ITV>& y);
38646
38647  friend std::ostream&
38648  Parma_Polyhedra_Library
38649  ::IO_Operators::operator<<<>(std::ostream& s, const Box<ITV>& box);
38650
38651  template <typename Specialization, typename Temp, typename To, typename I>
38652  friend bool Parma_Polyhedra_Library
38653  ::l_m_distance_assign(Checked_Number<To, Extended_Number_Policy>& r,
38654                        const Box<I>& x, const Box<I>& y,
38655                        const Rounding_Dir dir,
38656                        Temp& tmp0, Temp& tmp1, Temp& tmp2);
38657
38658  //! The type of sequence used to implement the box.
38659  typedef std::vector<ITV> Sequence;
38660
38661  /*! \brief
38662    The type of intervals used by inner computations when trying to limit
38663    the cumulative effect of approximation errors.
38664  */
38665  typedef ITV Tmp_Interval_Type;
38666
38667  //! A sequence of intervals, one for each dimension of the vector space.
38668  Sequence seq;
38669
38670#define PPL_IN_Box_CLASS
38671/* Automatically generated from PPL source file ../src/Box_Status_idefs.hh line 1. */
38672/* Box<ITV>::Status class declaration.
38673*/
38674
38675
38676#ifndef PPL_IN_Box_CLASS
38677#error "Do not include Box_Status_idefs.hh directly; use Box_defs.hh instead"
38678#endif
38679
38680//! A conjunctive assertion about a Box<ITV> object.
38681/*! \ingroup PPL_CXX_interface
38682  The assertions supported are:
38683  - <EM>empty up-to-date</EM>: the empty flag is meaningful;
38684  - <EM>empty</EM>: the box is the empty set.
38685  - <EM>universe</EM>: the box is universe \f$n\f$-dimensional vector space
38686     \f$\Rset^n\f$.
38687
38688  Not all the conjunctions of these elementary assertions constitute
38689  a legal Status.  In fact:
38690  - <EM>empty up-to-date</EM> and <EM>empty</EM> excludes <EM>universe</EM>.
38691*/
38692class Status;
38693
38694class Status {
38695public:
38696  //! By default Status is the empty set of assertion.
38697  Status();
38698
38699  //! Ordinary copy constructor.
38700  Status(const Status& y);
38701
38702  //! Copy constructor from a box of different type.
38703  template <typename Other_ITV>
38704  Status(const typename Box<Other_ITV>::Status& y);
38705
38706  //! \name Test, remove or add an individual assertion from the conjunction.
38707  //@{
38708  bool test_empty_up_to_date() const;
38709  void reset_empty_up_to_date();
38710  void set_empty_up_to_date();
38711
38712  bool test_empty() const;
38713  void reset_empty();
38714  void set_empty();
38715
38716  bool test_universe() const;
38717  void reset_universe();
38718  void set_universe();
38719  //@}
38720
38721  //! Checks if all the invariants are satisfied.
38722  bool OK() const;
38723
38724  PPL_OUTPUT_DECLARATIONS
38725
38726  /*! \brief
38727    Loads from \p s an ASCII representation (as produced by
38728    ascii_dump(std::ostream&) const) and sets \p *this accordingly.
38729    Returns <CODE>true</CODE> if successful, <CODE>false</CODE> otherwise.
38730  */
38731  bool ascii_load(std::istream& s);
38732
38733private:
38734  //! Status is implemented by means of a finite bitset.
38735  typedef unsigned int flags_t;
38736
38737  //! \name Bit-masks for the individual assertions.
38738  //@{
38739  static const flags_t NONE             = 0U;
38740  static const flags_t EMPTY_UP_TO_DATE = 1U << 0;
38741  static const flags_t EMPTY            = 1U << 1;
38742  static const flags_t UNIVERSE         = 1U << 2;
38743  //@}
38744
38745  //! This holds the current bitset.
38746  flags_t flags;
38747
38748  //! Construct from a bit-mask.
38749  Status(flags_t mask);
38750
38751  //! Check whether <EM>all</EM> bits in \p mask are set.
38752  bool test_all(flags_t mask) const;
38753
38754  //! Check whether <EM>at least one</EM> bit in \p mask is set.
38755  bool test_any(flags_t mask) const;
38756
38757  //! Set the bits in \p mask.
38758  void set(flags_t mask);
38759
38760  //! Reset the bits in \p mask.
38761  void reset(flags_t mask);
38762};
38763
38764/* Automatically generated from PPL source file ../src/Box_defs.hh line 1769. */
38765#undef PPL_IN_Box_CLASS
38766
38767  //! The status flags to keep track of the internal state.
38768  Status status;
38769
38770  /*! \brief
38771    Returns <CODE>true</CODE> if and only if the box is known to be empty.
38772
38773    The return value <CODE>false</CODE> does not necessarily
38774    implies that \p *this is non-empty.
38775  */
38776  bool marked_empty() const;
38777
38778public:
38779  //! Causes the box to become empty, i.e., to represent the empty set.
38780  void set_empty();
38781
38782private:
38783  //! Marks \p *this as definitely not empty.
38784  void set_nonempty();
38785
38786  //! Asserts the validity of the empty flag of \p *this.
38787  void set_empty_up_to_date();
38788
38789  //! Invalidates empty flag of \p *this.
38790  void reset_empty_up_to_date();
38791
38792  /*! \brief
38793    Checks the hard way whether \p *this is an empty box:
38794    returns <CODE>true</CODE> if and only if it is so.
38795  */
38796  bool check_empty() const;
38797
38798   /*! \brief
38799     Returns a reference the interval that bounds
38800     the box on the <CODE>k</CODE>-th space dimension.
38801   */
38802  const ITV& operator[](dimension_type k) const;
38803
38804  /*! \brief
38805    WRITE ME.
38806  */
38807  static I_Result
38808  refine_interval_no_check(ITV& itv,
38809                           Constraint::Type type,
38810                           Coefficient_traits::const_reference numer,
38811                           Coefficient_traits::const_reference denom);
38812
38813  /*! \brief
38814    WRITE ME.
38815  */
38816  void
38817  add_interval_constraint_no_check(dimension_type var_id,
38818                                   Constraint::Type type,
38819                                   Coefficient_traits::const_reference numer,
38820                                   Coefficient_traits::const_reference denom);
38821
38822  /*! \brief
38823    WRITE ME.
38824  */
38825  void add_constraint_no_check(const Constraint& c);
38826
38827  /*! \brief
38828    WRITE ME.
38829  */
38830  void add_constraints_no_check(const Constraint_System& cs);
38831
38832  /*! \brief
38833    WRITE ME.
38834  */
38835  void add_congruence_no_check(const Congruence& cg);
38836
38837  /*! \brief
38838    WRITE ME.
38839  */
38840  void add_congruences_no_check(const Congruence_System& cgs);
38841
38842  /*! \brief
38843    Uses the constraint \p c to refine \p *this.
38844
38845    \param c
38846    The constraint to be used for the refinement.
38847
38848    \warning
38849    If \p c and \p *this are dimension-incompatible,
38850    the behavior is undefined.
38851  */
38852  void refine_no_check(const Constraint& c);
38853
38854  /*! \brief
38855    Uses the constraints in \p cs to refine \p *this.
38856
38857    \param cs
38858    The constraints to be used for the refinement.
38859    To avoid termination problems, each constraint in \p cs
38860    will be used for a single refinement step.
38861
38862    \warning
38863    If \p cs and \p *this are dimension-incompatible,
38864    the behavior is undefined.
38865  */
38866  void refine_no_check(const Constraint_System& cs);
38867
38868  /*! \brief
38869    Uses the congruence \p cg to refine \p *this.
38870
38871    \param cg
38872    The congruence to be added.
38873    Nontrivial proper congruences are ignored.
38874
38875    \warning
38876    If \p cg and \p *this are dimension-incompatible,
38877    the behavior is undefined.
38878  */
38879  void refine_no_check(const Congruence& cg);
38880
38881  /*! \brief
38882    Uses the congruences in \p cgs to refine \p *this.
38883
38884    \param cgs
38885    The congruences to be added.
38886    Nontrivial proper congruences are ignored.
38887
38888    \warning
38889    If \p cgs and \p *this are dimension-incompatible,
38890    the behavior is undefined.
38891  */
38892  void refine_no_check(const Congruence_System& cgs);
38893
38894  /*! \brief
38895    Propagates the constraint \p c to refine \p *this.
38896
38897    \param c
38898    The constraint to be propagated.
38899
38900    \warning
38901    If \p c and \p *this are dimension-incompatible,
38902    the behavior is undefined.
38903
38904    \warning
38905    This method may lead to non-termination.
38906
38907    \if Include_Implementation_Details
38908
38909    For any expression \f$e\f$, we denote by
38910    \f$\left\uparrow e \right\uparrow\f$ (resp., \f$\left\downarrow e
38911    \right\downarrow\f$) the result of any computation that is
38912    guaranteed to yield an upper (resp., lower) approximation of
38913    \f$e\f$.  So there exists \f$\epsilon \in \Rset\f$ with
38914    \f$\epsilon \geq 0\f$ such that
38915    \f$\left\uparrow e \right\uparrow = e + \epsilon\f$.
38916    If \f$\epsilon = 0\f$ we say that the computation of
38917    \f$\left\uparrow e \right\uparrow\f$ is <EM>exact</EM>;
38918    we say it is <EM>inexact</EM> otherwise.
38919    Similarly for \f$\left\downarrow e \right\downarrow\f$.
38920
38921    Consider a constraint of the general form
38922    \f[
38923      z + \sum_{i \in I}{a_ix_i} \relsym 0,
38924    \f]
38925    where \f$z \in \Zset\f$, \f$I\f$ is a set of indices,
38926    \f$a_i \in \Zset\f$ with \f$a_i \neq 0\f$ for each \f$i \in I\f$, and
38927    \f$\mathord{\relsym} \in \{ \mathord{\geq}, \mathord{>}, \mathord{=} \}\f$.
38928    The set \f$I\f$ is subdivided into the disjoint sets \f$P\f$ and \f$N\f$
38929    such that, for each \f$i \in I\f$, \f$a_i > 0\f$ if \f$i \in P\f$ and
38930    \f$a_i < 0\f$ if \f$i \in N\f$.
38931    Suppose that, for each \f$i \in P \union N\f$ a variation interval
38932    \f$\chi_i \sseq \Rset\f$ is known for \f$x_i\f$ and that the infimum
38933    and the supremum of \f$\chi_i\f$ are denoted, respectively,
38934    by \f$\chi_i^\mathrm{l}\f$ and \f$\chi_i^\mathrm{u}\f$, where
38935    \f$\chi_i^\mathrm{l}, \chi_i^\mathrm{u} \in \Rset \union \{ -\infty, +\infty \}\f$.
38936
38937    For each \f$k \in P\f$, we have
38938    \f[
38939      x_k
38940        \relsym
38941          \frac{1}{a_k}
38942            \Biggl(
38943              - z
38944              - \sum_{i \in N}{a_ix_i}
38945              - \sum_{\genfrac{}{}{0pt}{}
38946                              {\scriptstyle i \in P}
38947                              {\scriptstyle i \neq k}}{a_ix_i}
38948            \Biggr).
38949    \f]
38950    Thus, if \f$\chi_i^\mathrm{l} \in \Rset\f$ for each \f$i \in N\f$ and
38951    \f$\chi_i^\mathrm{u} \in \Rset\f$ for each \f$i \in P \setdiff \{ k \}\f$,
38952    we have
38953    \f[
38954      x_k
38955        \geq
38956          \Biggl\downarrow
38957          \frac{1}{a_k}
38958            \Biggl(
38959              - z
38960              - \sum_{i \in N}{a_i\chi_i^\mathrm{l}}
38961              - \sum_{\genfrac{}{}{0pt}{}
38962                              {\scriptstyle i \in P}
38963                              {\scriptstyle i \neq k}}{a_i\chi_i^\mathrm{u}}
38964            \Biggr)
38965          \Biggr\downarrow
38966    \f]
38967    and, if \f$\mathord{\relsym} \in \{ \mathord{=} \}\f$,
38968    \f$\chi_i^\mathrm{u} \in \Rset\f$ for each \f$i \in N\f$ and
38969    \f$\chi_i^\mathrm{l} \in \Rset\f$ for each \f$P \setdiff \{ k \}\f$,
38970    \f[
38971      x_k
38972        \leq
38973          \Biggl\uparrow
38974          \frac{1}{a_k}
38975            \Biggl(
38976              - z
38977              - \sum_{i \in N}{a_i\chi_i^\mathrm{u}}
38978              - \sum_{\genfrac{}{}{0pt}{}
38979                              {\scriptstyle i \in P}
38980                              {\scriptstyle i \neq k}}{a_i\chi_i^\mathrm{l}}
38981            \Biggr)
38982          \Biggl\uparrow.
38983    \f]
38984    In the first inequality, the relation is strict if
38985    \f$\mathord{\relsym} \in \{ \mathord{>} \}\f$, or if
38986    \f$\chi_i^\mathrm{l} \notin \chi_i\f$ for some \f$i \in N\f$, or if
38987    \f$\chi_i^\mathrm{u} \notin \chi_i\f$ for some
38988    \f$i \in P \setdiff \{ k \}\f$, or if the computation is inexact.
38989    In the second inequality, the relation is strict if
38990    \f$\chi_i^\mathrm{u} \notin \chi_i\f$ for some \f$i \in N\f$, or if
38991    \f$\chi_i^\mathrm{l} \notin \chi_i\f$ for some
38992    \f$i \in P \setdiff \{ k \}\f$, or if the computation is inexact.
38993
38994    For each \f$k \in N\f$, we have
38995    \f[
38996      \frac{1}{a_k}
38997        \Biggl(
38998          - z
38999          - \sum_{\genfrac{}{}{0pt}{}
39000                          {\scriptstyle i \in N}
39001                          {\scriptstyle i \neq k}}{a_ix_i}
39002          - \sum_{i \in P}{a_ix_i}
39003        \Biggr)
39004          \relsym
39005            x_k.
39006    \f]
39007    Thus, if
39008    \f$\chi_i^\mathrm{l} \in \Rset\f$
39009    for each \f$i \in N \setdiff \{ k \}\f$ and
39010    \f$\chi_i^\mathrm{u} \in \Rset\f$ for each \f$i \in P\f$,
39011    we have
39012    \f[
39013      \Biggl\uparrow
39014      \frac{1}{a_k}
39015        \Biggl(
39016          - z
39017          - \sum_{\genfrac{}{}{0pt}{}
39018                          {\scriptstyle i \in N}
39019                          {\scriptstyle i \neq k}}{a_i\chi_i^\mathrm{l}}
39020          - \sum_{i \in P}{a_i\chi_i^\mathrm{u}}
39021        \Biggr)
39022      \Biggl\uparrow
39023        \geq
39024          x_k
39025    \f]
39026    and, if \f$\mathord{\relsym} \in \{ \mathord{=} \}\f$,
39027    \f$\chi_i^\mathrm{u} \in \Rset\f$ for each \f$i \in N \setdiff \{ k \}\f$
39028    and \f$\chi_i^\mathrm{l} \in \Rset\f$ for each \f$i \in P\f$,
39029    \f[
39030      \Biggl\downarrow
39031      \frac{1}{a_k}
39032        \Biggl(
39033          - z
39034          - \sum_{\genfrac{}{}{0pt}{}
39035                          {\scriptstyle i \in N}
39036                          {\scriptstyle i \neq k}}{a_i\chi_i^\mathrm{u}}
39037          - \sum_{i \in P}{a_i\chi_i^\mathrm{l}}
39038        \Biggr)
39039      \Biggl\downarrow
39040        \leq
39041          x_k.
39042    \f]
39043    In the first inequality, the relation is strict if
39044    \f$\mathord{\relsym} \in \{ \mathord{>} \}\f$, or if
39045    \f$\chi_i^\mathrm{u} \notin \chi_i\f$ for some \f$i \in P\f$, or if
39046    \f$\chi_i^\mathrm{l} \notin \chi_i\f$ for some
39047    \f$i \in N \setdiff \{ k \}\f$, or if the computation is inexact.
39048    In the second inequality, the relation is strict if
39049    \f$\chi_i^\mathrm{l} \notin \chi_i\f$ for some \f$i \in P\f$, or if
39050    \f$\chi_i^\mathrm{u} \notin \chi_i\f$ for some
39051    \f$i \in N \setdiff \{ k \}\f$, or if the computation is inexact.
39052    \endif
39053  */
39054  void propagate_constraint_no_check(const Constraint& c);
39055
39056  /*! \brief
39057    Propagates the constraints in \p cs to refine \p *this.
39058
39059    \param  cs
39060    The constraints to be propagated.
39061
39062    \param max_iterations
39063    The maximum number of propagation steps for each constraint in \p cs.
39064    If zero, the number of propagation steps will be unbounded, possibly
39065    resulting in an infinite loop.
39066
39067    \warning
39068    If \p cs and \p *this are dimension-incompatible,
39069    the behavior is undefined.
39070
39071    \warning
39072    This method may lead to non-termination if \p max_iterations is 0.
39073  */
39074  void propagate_constraints_no_check(const Constraint_System& cs,
39075                                      dimension_type max_iterations);
39076
39077  //! Checks if and how \p expr is bounded in \p *this.
39078  /*!
39079    Returns <CODE>true</CODE> if and only if \p from_above is
39080    <CODE>true</CODE> and \p expr is bounded from above in \p *this,
39081    or \p from_above is <CODE>false</CODE> and \p expr is bounded
39082    from below in \p *this.
39083
39084    \param expr
39085    The linear expression to test;
39086
39087    \param from_above
39088    <CODE>true</CODE> if and only if the boundedness of interest is
39089    "from above".
39090
39091    \exception std::invalid_argument
39092    Thrown if \p expr and \p *this are dimension-incompatible.
39093  */
39094  bool bounds(const Linear_Expression& expr, bool from_above) const;
39095
39096  //! Maximizes or minimizes \p expr subject to \p *this.
39097  /*!
39098    \param expr
39099    The linear expression to be maximized or minimized subject to \p *this;
39100
39101    \param maximize
39102    <CODE>true</CODE> if maximization is what is wanted;
39103
39104    \param ext_n
39105    The numerator of the extremum value;
39106
39107    \param ext_d
39108    The denominator of the extremum value;
39109
39110    \param included
39111    <CODE>true</CODE> if and only if the extremum of \p expr can
39112    actually be reached in \p *this;
39113
39114    \param g
39115    When maximization or minimization succeeds, will be assigned
39116    a point or closure point where \p expr reaches the
39117    corresponding extremum value.
39118
39119    \exception std::invalid_argument
39120    Thrown if \p expr and \p *this are dimension-incompatible.
39121
39122    If \p *this is empty or \p expr is not bounded in the appropriate
39123    direction, <CODE>false</CODE> is returned and \p ext_n, \p ext_d,
39124    \p included and \p g are left untouched.
39125  */
39126  bool max_min(const Linear_Expression& expr,
39127               bool maximize,
39128               Coefficient& ext_n, Coefficient& ext_d, bool& included,
39129               Generator& g) const;
39130
39131  //! Maximizes or minimizes \p expr subject to \p *this.
39132  /*!
39133    \param expr
39134    The linear expression to be maximized or minimized subject to \p *this;
39135
39136    \param maximize
39137    <CODE>true</CODE> if maximization is what is wanted;
39138
39139    \param ext_n
39140    The numerator of the extremum value;
39141
39142    \param ext_d
39143    The denominator of the extremum value;
39144
39145    \param included
39146    <CODE>true</CODE> if and only if the extremum of \p expr can
39147    actually be reached in \p * this;
39148
39149    \exception std::invalid_argument
39150    Thrown if \p expr and \p *this are dimension-incompatible.
39151
39152    If \p *this is empty or \p expr is not bounded in the appropriate
39153    direction, <CODE>false</CODE> is returned and \p ext_n, \p ext_d,
39154    \p included and \p point are left untouched.
39155  */
39156  bool max_min(const Linear_Expression& expr,
39157               bool maximize,
39158               Coefficient& ext_n, Coefficient& ext_d, bool& included) const;
39159
39160  /*! \brief
39161    Adds to \p limiting_box the interval constraints in \p cs
39162    that are satisfied by \p *this.
39163  */
39164  void get_limiting_box(const Constraint_System& cs,
39165                        Box& limiting_box) const;
39166
39167  //! \name Exception Throwers
39168  //@{
39169  void throw_dimension_incompatible(const char* method,
39170                                    const Box& y) const;
39171
39172  void throw_dimension_incompatible(const char* method,
39173                                    dimension_type required_dim) const;
39174
39175  void throw_dimension_incompatible(const char* method,
39176                                    const Constraint& c) const;
39177
39178  void throw_dimension_incompatible(const char* method,
39179                                    const Congruence& cg) const;
39180
39181  void throw_dimension_incompatible(const char* method,
39182                                    const Constraint_System& cs) const;
39183
39184  void throw_dimension_incompatible(const char* method,
39185                                    const Congruence_System& cgs) const;
39186
39187  void throw_dimension_incompatible(const char* method,
39188                                    const Generator& g) const;
39189
39190  void throw_dimension_incompatible(const char* method,
39191                                    const char* le_name,
39192                                    const Linear_Expression& le) const;
39193
39194  template <typename C>
39195  void throw_dimension_incompatible(const char* method,
39196                                    const char* lf_name,
39197                                    const Linear_Form<C>& lf) const;
39198
39199  static void throw_constraint_incompatible(const char* method);
39200
39201  static void throw_expression_too_complex(const char* method,
39202                                           const Linear_Expression& le);
39203
39204  static void throw_invalid_argument(const char* method, const char* reason);
39205  //@} // Exception Throwers
39206};
39207
39208namespace Parma_Polyhedra_Library {
39209
39210#ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
39211/*! \brief
39212  Returns the relations holding between an interval and
39213  an interval constraint.
39214
39215  \param i
39216  The interval;
39217
39218  \param constraint_type
39219  The constraint type;
39220
39221  \param numer
39222  The numerator of the constraint bound;
39223
39224  \param denom
39225  The denominator of the constraint bound
39226
39227  The interval constraint has the form
39228  <CODE>denom * Variable(0) relsym numer</CODE>
39229  where relsym is  <CODE>==</CODE>,  <CODE>></CODE> or  <CODE>>=</CODE>
39230  depending on the <CODE>constraint_type</CODE>.
39231*/
39232#endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
39233template <typename ITV>
39234Poly_Con_Relation
39235interval_relation(const ITV& i,
39236                  const Constraint::Type constraint_type,
39237                  Coefficient_traits::const_reference numer,
39238                  Coefficient_traits::const_reference denom
39239                  = Coefficient_one());
39240
39241class Box_Helpers {
39242public:
39243  // This is declared here so that Linear_Expression needs to be friend of
39244  // Box_Helpers only, and doesn't need to be friend of this, too.
39245  #ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
39246  //! Decodes the constraint \p c as an interval constraint.
39247  /*! \relates Box
39248    \return
39249    <CODE>true</CODE> if the constraint \p c is an
39250    \ref intervals "interval constraint";
39251    <CODE>false</CODE> otherwise.
39252
39253    \param c
39254    The constraint to be decoded.
39255
39256    \param c_num_vars
39257    If <CODE>true</CODE> is returned, then it will be set to the number
39258    of variables having a non-zero coefficient. The only legal values
39259    will therefore be 0 and 1.
39260
39261    \param c_only_var
39262    If <CODE>true</CODE> is returned and if \p c_num_vars is not set to 0,
39263    then it will be set to the index of the only variable having
39264    a non-zero coefficient in \p c.
39265  */
39266  #endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
39267  static bool extract_interval_constraint(const Constraint& c,
39268                                          dimension_type& c_num_vars,
39269                                          dimension_type& c_only_var);
39270
39271  // This is declared here so that Linear_Expression needs to be friend of
39272  // Box_Helpers only, and doesn't need to be friend of this, too.
39273  static bool extract_interval_congruence(const Congruence& cg,
39274                                          dimension_type& cg_num_vars,
39275                                          dimension_type& cg_only_var);
39276};
39277
39278} // namespace Parma_Polyhedra_Library
39279
39280/* Automatically generated from PPL source file ../src/Box_Status_inlines.hh line 1. */
39281/* Box<ITV>::Status class implementation: inline functions.
39282*/
39283
39284
39285#include <string>
39286
39287namespace Parma_Polyhedra_Library {
39288
39289template <typename ITV>
39290inline
39291Box<ITV>::Status::Status(flags_t mask)
39292  : flags(mask) {
39293}
39294
39295template <typename ITV>
39296inline
39297Box<ITV>::Status::Status(const Status& y)
39298  : flags(y.flags) {
39299}
39300
39301template <typename ITV>
39302template <typename Other_ITV>
39303inline
39304Box<ITV>::Status::Status(const typename Box<Other_ITV>::Status& y)
39305  : flags(y.flags) {
39306}
39307
39308template <typename ITV>
39309inline
39310Box<ITV>::Status::Status()
39311  : flags(NONE) {
39312}
39313
39314template <typename ITV>
39315inline bool
39316Box<ITV>::Status::test_all(flags_t mask) const {
39317  return (flags & mask) == mask;
39318}
39319
39320template <typename ITV>
39321inline bool
39322Box<ITV>::Status::test_any(flags_t mask) const {
39323  return (flags & mask) != 0;
39324}
39325
39326template <typename ITV>
39327inline void
39328Box<ITV>::Status::set(flags_t mask) {
39329  flags |= mask;
39330}
39331
39332template <typename ITV>
39333inline void
39334Box<ITV>::Status::reset(flags_t mask) {
39335  flags &= ~mask;
39336}
39337
39338template <typename ITV>
39339inline bool
39340Box<ITV>::Status::test_empty_up_to_date() const {
39341  return test_any(EMPTY_UP_TO_DATE);
39342}
39343
39344template <typename ITV>
39345inline void
39346Box<ITV>::Status::reset_empty_up_to_date() {
39347  reset(EMPTY_UP_TO_DATE);
39348}
39349
39350template <typename ITV>
39351inline void
39352Box<ITV>::Status::set_empty_up_to_date() {
39353  set(EMPTY_UP_TO_DATE);
39354}
39355
39356template <typename ITV>
39357inline bool
39358Box<ITV>::Status::test_empty() const {
39359  return test_any(EMPTY);
39360}
39361
39362template <typename ITV>
39363inline void
39364Box<ITV>::Status::reset_empty() {
39365  reset(EMPTY);
39366}
39367
39368template <typename ITV>
39369inline void
39370Box<ITV>::Status::set_empty() {
39371  set(EMPTY);
39372}
39373
39374template <typename ITV>
39375inline bool
39376Box<ITV>::Status::test_universe() const {
39377  return test_any(UNIVERSE);
39378}
39379
39380template <typename ITV>
39381inline void
39382Box<ITV>::Status::reset_universe() {
39383  reset(UNIVERSE);
39384}
39385
39386template <typename ITV>
39387inline void
39388Box<ITV>::Status::set_universe() {
39389  set(UNIVERSE);
39390}
39391
39392template <typename ITV>
39393bool
39394Box<ITV>::Status::OK() const {
39395  if (test_empty_up_to_date()
39396      && test_empty()
39397      && test_universe()) {
39398#ifndef NDEBUG
39399    std::cerr
39400      << "The status asserts emptiness and universality at the same time."
39401      << std::endl;
39402#endif
39403    return false;
39404  }
39405
39406  // Any other case is OK.
39407  return true;
39408}
39409
39410
39411namespace Implementation {
39412
39413namespace Boxes {
39414
39415// These are the keywords that indicate the individual assertions.
39416extern const char* empty_up_to_date;
39417extern const char* empty;
39418extern const char* universe;
39419const char yes = '+';
39420const char no = '-';
39421const char separator = ' ';
39422
39423/*! \relates Parma_Polyhedra_Library::Box::Status
39424  Reads a keyword and its associated on/off flag from \p s.
39425  Returns <CODE>true</CODE> if the operation is successful,
39426  returns <CODE>false</CODE> otherwise.
39427  When successful, \p positive is set to <CODE>true</CODE> if the flag
39428  is on; it is set to <CODE>false</CODE> otherwise.
39429*/
39430inline bool
39431get_field(std::istream& s, const char* keyword, bool& positive) {
39432  std::string str;
39433  if (!(s >> str)
39434      || (str[0] != yes && str[0] != no)
39435      || str.substr(1) != keyword) {
39436    return false;
39437  }
39438  positive = (str[0] == yes);
39439  return true;
39440}
39441
39442} // namespace Boxes
39443
39444} // namespace Implementation
39445
39446template <typename ITV>
39447void
39448Box<ITV>::Status::ascii_dump(std::ostream& s) const {
39449  using namespace Implementation::Boxes;
39450  s << (test_empty_up_to_date() ? yes : no) << empty_up_to_date << separator
39451    << (test_empty() ? yes : no) << empty << separator
39452    << (test_universe() ? yes : no) << universe << separator;
39453}
39454
39455PPL_OUTPUT_TEMPLATE_DEFINITIONS_ASCII_ONLY(ITV, Box<ITV>::Status)
39456
39457template <typename ITV>
39458bool
39459Box<ITV>::Status::ascii_load(std::istream& s) {
39460  using namespace Implementation::Boxes;
39461  PPL_UNINITIALIZED(bool, positive);
39462
39463  if (!get_field(s, Implementation::Boxes::empty_up_to_date, positive)) {
39464    return false;
39465  }
39466  if (positive) {
39467    set_empty_up_to_date();
39468  }
39469
39470  if (!get_field(s, Implementation::Boxes::empty, positive)) {
39471    return false;
39472  }
39473  if (positive) {
39474    set_empty();
39475  }
39476  if (!get_field(s, universe, positive)) {
39477    return false;
39478  }
39479  if (positive) {
39480    set_universe();
39481  }
39482  else {
39483    reset_universe();
39484  }
39485
39486  // Check invariants.
39487  PPL_ASSERT(OK());
39488  return true;
39489}
39490
39491} // namespace Parma_Polyhedra_Library
39492
39493/* Automatically generated from PPL source file ../src/Box_inlines.hh line 1. */
39494/* Box class implementation: inline functions.
39495*/
39496
39497
39498/* Automatically generated from PPL source file ../src/Constraint_System_defs.hh line 1. */
39499/* Constraint_System class declaration.
39500*/
39501
39502
39503/* Automatically generated from PPL source file ../src/Constraint_System_defs.hh line 28. */
39504
39505/* Automatically generated from PPL source file ../src/Linear_System_defs.hh line 1. */
39506/* Linear_System class declaration.
39507*/
39508
39509
39510/* Automatically generated from PPL source file ../src/Linear_System_defs.hh line 28. */
39511
39512/* Automatically generated from PPL source file ../src/Swapping_Vector_defs.hh line 1. */
39513/* Swapping_Vector class declaration.
39514*/
39515
39516
39517/* Automatically generated from PPL source file ../src/Swapping_Vector_types.hh line 1. */
39518
39519
39520namespace Parma_Polyhedra_Library {
39521
39522template <typename T>
39523class Swapping_Vector;
39524
39525} // namespace Parma_Polyhedra_Library
39526
39527/* Automatically generated from PPL source file ../src/Swapping_Vector_defs.hh line 29. */
39528#include <vector>
39529
39530namespace Parma_Polyhedra_Library {
39531
39532#ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
39533//! A wrapper for std::vector that calls a swap() method instead of copying
39534//! elements, when possible.
39535#endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
39536template <typename T>
39537class Swapping_Vector {
39538
39539public:
39540  typedef typename std::vector<T>::const_iterator const_iterator;
39541  typedef typename std::vector<T>::iterator iterator;
39542  typedef typename std::vector<T>::size_type size_type;
39543
39544  Swapping_Vector();
39545  explicit Swapping_Vector(dimension_type new_size);
39546  Swapping_Vector(dimension_type new_size, const T& x);
39547
39548  void clear();
39549  void reserve(dimension_type new_capacity);
39550  void resize(dimension_type new_size);
39551  void resize(dimension_type new_size, const T& x);
39552
39553  dimension_type size() const;
39554  dimension_type capacity() const;
39555  bool empty() const;
39556
39557  void m_swap(Swapping_Vector& v);
39558
39559  T& operator[](dimension_type i);
39560  const T& operator[](dimension_type i) const;
39561
39562  T& back();
39563  const T& back() const;
39564
39565  void push_back(const T& x);
39566  void pop_back();
39567
39568  iterator begin();
39569  iterator end();
39570  const_iterator begin() const;
39571  const_iterator end() const;
39572
39573  iterator erase(iterator itr);
39574  iterator erase(iterator first, iterator last);
39575
39576  // This is defined only if T has an external_memory_in_bytes() method.
39577  memory_size_type external_memory_in_bytes() const;
39578
39579  dimension_type max_num_rows();
39580
39581private:
39582  std::vector<T> impl;
39583};
39584
39585#ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
39586/*! \relates Swapping_Vector */
39587#endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
39588template <typename T>
39589void swap(Swapping_Vector<T>& x, Swapping_Vector<T>& y);
39590
39591} // namespace Parma_Polyhedra_Library
39592
39593/* Automatically generated from PPL source file ../src/Swapping_Vector_inlines.hh line 1. */
39594/* Swapping_Vector class implementation: inline functions.
39595*/
39596
39597
39598/* Automatically generated from PPL source file ../src/Swapping_Vector_inlines.hh line 28. */
39599
39600namespace Parma_Polyhedra_Library {
39601
39602template <typename T>
39603inline
39604Swapping_Vector<T>::Swapping_Vector()
39605  : impl() {
39606}
39607
39608template <typename T>
39609inline
39610Swapping_Vector<T>::Swapping_Vector(dimension_type i)
39611  : impl() {
39612  // NOTE: This is not the same as constructing impl as `impl(i)', because
39613  // this implementation calls compute_capacity().
39614  resize(i);
39615}
39616
39617template <typename T>
39618inline
39619Swapping_Vector<T>::Swapping_Vector(dimension_type new_size, const T& x)
39620  : impl() {
39621  resize(new_size, x);
39622}
39623
39624template <typename T>
39625inline void
39626Swapping_Vector<T>::clear() {
39627  impl.clear();
39628}
39629
39630template <typename T>
39631inline void
39632Swapping_Vector<T>::reserve(dimension_type new_capacity) {
39633  if (impl.capacity() < new_capacity) {
39634    // Reallocation will take place.
39635    std::vector<T> new_impl;
39636
39637    new_impl.reserve(compute_capacity(new_capacity, max_num_rows()));
39638    new_impl.resize(impl.size());
39639
39640    using std::swap;
39641
39642    // Steal the old elements.
39643    for (dimension_type i = impl.size(); i-- > 0; ) {
39644      swap(new_impl[i], impl[i]);
39645    }
39646
39647    // Put the new vector into place.
39648    swap(impl, new_impl);
39649  }
39650}
39651
39652template <typename T>
39653inline void
39654Swapping_Vector<T>::resize(dimension_type new_size) {
39655  reserve(new_size);
39656  impl.resize(new_size);
39657}
39658
39659template <typename T>
39660inline void
39661Swapping_Vector<T>::resize(dimension_type new_size, const T& x) {
39662  reserve(new_size);
39663  impl.resize(new_size, x);
39664}
39665
39666template <typename T>
39667inline dimension_type
39668Swapping_Vector<T>::size() const {
39669  return impl.size();
39670}
39671
39672template <typename T>
39673inline dimension_type
39674Swapping_Vector<T>::capacity() const {
39675  return impl.capacity();
39676}
39677
39678template <typename T>
39679inline bool
39680Swapping_Vector<T>::empty() const {
39681  return impl.empty();
39682}
39683
39684template <typename T>
39685inline void
39686Swapping_Vector<T>::m_swap(Swapping_Vector& v) {
39687  using std::swap;
39688  swap(impl, v.impl);
39689}
39690
39691template <typename T>
39692inline T&
39693Swapping_Vector<T>::operator[](dimension_type i) {
39694  return impl[i];
39695}
39696
39697template <typename T>
39698inline const T&
39699Swapping_Vector<T>::operator[](dimension_type i) const {
39700  return impl[i];
39701}
39702
39703template <typename T>
39704inline T&
39705Swapping_Vector<T>::back() {
39706  return impl.back();
39707}
39708
39709template <typename T>
39710inline const T&
39711Swapping_Vector<T>::back() const {
39712  return impl.back();
39713}
39714
39715template <typename T>
39716inline void
39717Swapping_Vector<T>::push_back(const T& x) {
39718  reserve(size() + 1);
39719  impl.push_back(x);
39720}
39721
39722template <typename T>
39723inline void
39724Swapping_Vector<T>::pop_back() {
39725  impl.pop_back();
39726}
39727
39728template <typename T>
39729inline memory_size_type
39730Swapping_Vector<T>::external_memory_in_bytes() const {
39731  // Estimate the size of vector.
39732  memory_size_type n = impl.capacity() * sizeof(T);
39733  for (const_iterator i = begin(), i_end = end(); i != i_end; ++i) {
39734    n += i->external_memory_in_bytes();
39735  }
39736  return n;
39737}
39738
39739template <typename T>
39740inline typename Swapping_Vector<T>::iterator
39741Swapping_Vector<T>::begin() {
39742  return impl.begin();
39743}
39744
39745template <typename T>
39746inline typename Swapping_Vector<T>::iterator
39747Swapping_Vector<T>::end() {
39748  return impl.end();
39749}
39750
39751template <typename T>
39752inline typename Swapping_Vector<T>::const_iterator
39753Swapping_Vector<T>::begin() const {
39754  return impl.begin();
39755}
39756
39757template <typename T>
39758inline typename Swapping_Vector<T>::const_iterator
39759Swapping_Vector<T>::end() const {
39760  return impl.end();
39761}
39762
39763template <typename T>
39764inline typename Swapping_Vector<T>::iterator
39765Swapping_Vector<T>::erase(iterator itr) {
39766  PPL_ASSERT(itr >= begin());
39767  PPL_ASSERT(itr < end());
39768  const dimension_type old_i = itr - begin();
39769  dimension_type i = old_i;
39770  ++i;
39771  while (i != size()) {
39772    swap(impl[i-1], impl[i]);
39773  }
39774  impl.pop_back();
39775  return begin() + old_i;
39776}
39777
39778template <typename T>
39779inline typename Swapping_Vector<T>::iterator
39780Swapping_Vector<T>::erase(iterator first, iterator last) {
39781  PPL_ASSERT(begin() <= first);
39782  PPL_ASSERT(first <= last);
39783  PPL_ASSERT(last <= end());
39784  const iterator old_first = first;
39785  typedef typename std::iterator_traits<iterator>::difference_type diff_t;
39786  const diff_t k = last - first;
39787  const dimension_type n = static_cast<dimension_type>(end() - last);
39788  using std::swap;
39789  for (dimension_type i = 0; i < n; ++i, ++first) {
39790    swap(*first, *(first + k));
39791  }
39792  impl.erase(end() - k, end());
39793  return old_first;
39794}
39795
39796template <typename T>
39797inline dimension_type
39798Swapping_Vector<T>::max_num_rows() {
39799  return impl.max_size();
39800}
39801
39802template <typename T>
39803inline void
39804swap(Swapping_Vector<T>& vec1, Swapping_Vector<T>& vec2) {
39805  vec1.m_swap(vec2);
39806}
39807
39808} // namespace Parma_Polyhedra_Library
39809
39810
39811/* Automatically generated from PPL source file ../src/Swapping_Vector_defs.hh line 95. */
39812
39813/* Automatically generated from PPL source file ../src/Linear_System_defs.hh line 33. */
39814
39815/* Automatically generated from PPL source file ../src/Bit_Row_types.hh line 1. */
39816
39817
39818namespace Parma_Polyhedra_Library {
39819
39820class Bit_Row;
39821
39822} // namespace Parma_Polyhedra_Library
39823
39824/* Automatically generated from PPL source file ../src/Bit_Matrix_types.hh line 1. */
39825
39826
39827namespace Parma_Polyhedra_Library {
39828
39829class Bit_Matrix;
39830
39831} // namespace Parma_Polyhedra_Library
39832
39833/* Automatically generated from PPL source file ../src/Linear_System_defs.hh line 39. */
39834
39835// TODO: Check how much of this description is still true.
39836#ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
39837//! The base class for systems of constraints and generators.
39838/*! \ingroup PPL_CXX_interface
39839  An object of this class represents either a constraint system
39840  or a generator system. Each Linear_System object can be viewed
39841  as a finite sequence of strong-normalized Row objects,
39842  where each Row implements a constraint or a generator.
39843  Linear systems are characterized by the matrix of coefficients,
39844  also encoding the number, size and capacity of Row objects,
39845  as well as a few additional information, including:
39846   - the topological kind of (all) the rows;
39847   - an indication of whether or not some of the rows in the Linear_System
39848     are <EM>pending</EM>, meaning that they still have to undergo
39849     an (unspecified) elaboration; if there are pending rows, then these
39850     form a proper suffix of the overall sequence of rows;
39851   - a Boolean flag that, when <CODE>true</CODE>, ensures that the
39852     non-pending prefix of the sequence of rows is sorted.
39853*/
39854#endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
39855template <typename Row>
39856class Parma_Polyhedra_Library::Linear_System {
39857public:
39858
39859  // NOTE: `iterator' is actually a const_iterator.
39860  typedef typename Swapping_Vector<Row>::const_iterator iterator;
39861  typedef typename Swapping_Vector<Row>::const_iterator const_iterator;
39862
39863  //! Builds an empty linear system with specified topology.
39864  /*!
39865    Rows size and capacity are initialized to \f$0\f$.
39866  */
39867  Linear_System(Topology topol, Representation r);
39868
39869  //! Builds a system with specified topology and dimensions.
39870  /*!
39871    \param topol
39872    The topology of the system that will be created;
39873
39874    \param space_dim
39875    The number of space dimensions of the system that will be created.
39876
39877    \param r
39878    The representation for system's rows.
39879
39880    Creates a \p n_rows \f$\times\f$ \p space_dim system whose
39881    coefficients are all zero and with the given topology.
39882  */
39883  Linear_System(Topology topol, dimension_type space_dim, Representation r);
39884
39885#ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
39886  //! A tag class.
39887  /*! \ingroup PPL_CXX_interface
39888    Tag class to differentiate the Linear_System copy constructor that
39889    copies pending rows as pending from the one that transforms
39890    pending rows into non-pending ones.
39891  */
39892#endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
39893  struct With_Pending {
39894  };
39895
39896  //! Copy constructor: pending rows are transformed into non-pending ones.
39897  Linear_System(const Linear_System& y);
39898
39899  //! Copy constructor with specified representation. Pending rows are
39900  //! transformed into non-pending ones.
39901  Linear_System(const Linear_System& y, Representation r);
39902
39903  //! Full copy constructor: pending rows are copied as pending.
39904  Linear_System(const Linear_System& y, With_Pending);
39905
39906  //! Full copy constructor: pending rows are copied as pending.
39907  Linear_System(const Linear_System& y, Representation r, With_Pending);
39908
39909  //! Assignment operator: pending rows are transformed into non-pending ones.
39910  Linear_System& operator=(const Linear_System& y);
39911
39912  //! Full assignment operator: pending rows are copied as pending.
39913  void assign_with_pending(const Linear_System& y);
39914
39915  //! Swaps \p *this with \p y.
39916  void m_swap(Linear_System& y);
39917
39918  //! Returns the current representation of *this.
39919  Representation representation() const;
39920
39921  //! Converts *this to the specified representation.
39922  void set_representation(Representation r);
39923
39924  //! Returns the maximum space dimension a Linear_System can handle.
39925  static dimension_type max_space_dimension();
39926
39927  //! Returns the space dimension of the rows in the system.
39928  /*!
39929    The computation of the space dimension correctly ignores
39930    the column encoding the inhomogeneous terms of constraint
39931    (resp., the divisors of generators);
39932    if the system topology is <CODE>NOT_NECESSARILY_CLOSED</CODE>,
39933    also the column of the \f$\epsilon\f$-dimension coefficients
39934    will be ignored.
39935  */
39936  dimension_type space_dimension() const;
39937
39938  //! Sets the space dimension of the rows in the system to \p space_dim .
39939  void set_space_dimension(dimension_type space_dim);
39940
39941  //! Makes the system shrink by removing its \p n trailing rows.
39942  void remove_trailing_rows(dimension_type n);
39943
39944  //! Makes the system shrink by removing its i-th row.
39945  /*!
39946    When \p keep_sorted is \p true and the system is sorted, sortedness will
39947    be preserved, but this method costs O(n).
39948
39949    Otherwise, this method just swaps the i-th row with the last and then
39950    removes it, so it costs O(1).
39951  */
39952  void remove_row(dimension_type i, bool keep_sorted = false);
39953
39954  //! Makes the system shrink by removing the rows in [first,last).
39955  /*!
39956    When \p keep_sorted is \p true and the system is sorted, sortedness will
39957    be preserved, but this method costs O(num_rows()).
39958
39959    Otherwise, this method just swaps the rows with the last ones and then
39960    removes them, so it costs O(last - first).
39961  */
39962  void remove_rows(dimension_type first, dimension_type last,
39963                  bool keep_sorted = false);
39964
39965  // TODO: Consider removing this.
39966  //! Removes the specified rows. The row ordering of remaining rows is
39967  //! preserved.
39968  /*!
39969    \param indexes specifies a list of row indexes.
39970                   It must be sorted.
39971  */
39972  void remove_rows(const std::vector<dimension_type>& indexes);
39973
39974  // TODO: Consider making this private.
39975  //! Removes all the specified dimensions from the system.
39976  /*!
39977    The space dimension of the variable with the highest space
39978    dimension in \p vars must be at most the space dimension
39979    of \p this.
39980  */
39981  void remove_space_dimensions(const Variables_Set& vars);
39982
39983  //! Shift by \p n positions the coefficients of variables, starting from
39984  //! the coefficient of \p v. This increases the space dimension by \p n.
39985  void shift_space_dimensions(Variable v, dimension_type n);
39986
39987  // TODO: Consider making this private.
39988  //! Permutes the space dimensions of the matrix.
39989  /*
39990    \param cycle
39991    A vector representing a cycle of the permutation according to which the
39992    space dimensions must be rearranged.
39993
39994    The \p cycle vector represents a cycle of a permutation of space
39995    dimensions.
39996    For example, the permutation
39997    \f$ \{ x_1 \mapsto x_2, x_2 \mapsto x_3, x_3 \mapsto x_1 \}\f$ can be
39998    represented by the vector containing \f$ x_1, x_2, x_3 \f$.
39999  */
40000  void permute_space_dimensions(const std::vector<Variable>& cycle);
40001
40002  //! Swaps the coefficients of the variables \p v1 and \p v2 .
40003  void swap_space_dimensions(Variable v1, Variable v2);
40004
40005  //! \name Subscript operators
40006  //@{
40007  //! Returns a const reference to the \p k-th row of the system.
40008  const Row& operator[](dimension_type k) const;
40009  //@} // Subscript operators
40010
40011  iterator begin();
40012  iterator end();
40013  const_iterator begin() const;
40014  const_iterator end() const;
40015
40016  bool has_no_rows() const;
40017  dimension_type num_rows() const;
40018
40019  //! Strongly normalizes the system.
40020  void strong_normalize();
40021
40022  //! Sign-normalizes the system.
40023  void sign_normalize();
40024
40025  //! \name Accessors
40026  //@{
40027  //! Returns the system topology.
40028  Topology topology() const;
40029
40030  //! Returns the value of the sortedness flag.
40031  bool is_sorted() const;
40032
40033  /*! \brief
40034    Returns <CODE>true</CODE> if and only if
40035    the system topology is <CODE>NECESSARILY_CLOSED</CODE>.
40036  */
40037  bool is_necessarily_closed() const;
40038
40039  /*! \brief
40040    Returns the number of rows in the system
40041    that represent either lines or equalities.
40042  */
40043  dimension_type num_lines_or_equalities() const;
40044
40045  //! Returns the index of the first pending row.
40046  dimension_type first_pending_row() const;
40047
40048  //! Returns the number of rows that are in the pending part of the system.
40049  dimension_type num_pending_rows() const;
40050  //@} // Accessors
40051
40052  /*! \brief
40053    Returns <CODE>true</CODE> if and only if \p *this is sorted,
40054    without checking for duplicates.
40055  */
40056  bool check_sorted() const;
40057
40058  //! Sets the system topology to \p t .
40059  void set_topology(Topology t);
40060
40061  //! Sets the system topology to <CODE>NECESSARILY_CLOSED</CODE>.
40062  void set_necessarily_closed();
40063
40064  //! Sets the system topology to <CODE>NOT_NECESSARILY_CLOSED</CODE>.
40065  void set_not_necessarily_closed();
40066
40067  // TODO: Consider removing this, or making it private.
40068  //! Marks the epsilon dimension as a standard dimension.
40069  /*!
40070    The system topology is changed to <CODE>NOT_NECESSARILY_CLOSED</CODE>, and
40071    the number of space dimensions is increased by 1.
40072  */
40073  void mark_as_necessarily_closed();
40074
40075  // TODO: Consider removing this, or making it private.
40076  //! Marks the last dimension as the epsilon dimension.
40077  /*!
40078    The system topology is changed to <CODE>NECESSARILY_CLOSED</CODE>, and
40079    the number of space dimensions is decreased by 1.
40080  */
40081  void mark_as_not_necessarily_closed();
40082
40083  //! Sets the index to indicate that the system has no pending rows.
40084  void unset_pending_rows();
40085
40086  //! Sets the index of the first pending row to \p i.
40087  void set_index_first_pending_row(dimension_type i);
40088
40089  //! Sets the sortedness flag of the system to \p b.
40090  void set_sorted(bool b);
40091
40092  //! Adds \p n rows and space dimensions to the system.
40093  /*!
40094    \param n
40095    The number of rows and space dimensions to be added: must be strictly
40096    positive.
40097
40098    Turns the system \f$M \in \Rset^r \times \Rset^c\f$ into
40099    the system \f$N \in \Rset^{r+n} \times \Rset^{c+n}\f$
40100    such that
40101    \f$N = \bigl(\genfrac{}{}{0pt}{}{0}{M}\genfrac{}{}{0pt}{}{J}{o}\bigr)\f$,
40102    where \f$J\f$ is the specular image
40103    of the \f$n \times n\f$ identity matrix.
40104  */
40105  void add_universe_rows_and_space_dimensions(dimension_type n);
40106
40107  /*! \brief
40108    Adds a copy of \p r to the system,
40109    automatically resizing the system or the row's copy, if needed.
40110  */
40111  void insert(const Row& r);
40112
40113  /*! \brief
40114    Adds a copy of the given row to the pending part of the system,
40115    automatically resizing the system or the row, if needed.
40116  */
40117  void insert_pending(const Row& r);
40118
40119  /*! \brief
40120    Adds \p r to the system, stealing its contents and
40121    automatically resizing the system or the row, if needed.
40122  */
40123  void insert(Row& r, Recycle_Input);
40124
40125  /*! \brief
40126    Adds the given row to the pending part of the system, stealing its
40127    contents and automatically resizing the system or the row, if needed.
40128  */
40129  void insert_pending(Row& r, Recycle_Input);
40130
40131  //! Adds to \p *this a copy of  the rows of \p y.
40132  /*!
40133    It is assumed that \p *this has no pending rows.
40134  */
40135  void insert(const Linear_System& y);
40136
40137  //! Adds a copy of the rows of `y' to the pending part of `*this'.
40138  void insert_pending(const Linear_System& r);
40139
40140  //! Adds to \p *this a the rows of `y', stealing them from `y'.
40141  /*!
40142    It is assumed that \p *this has no pending rows.
40143  */
40144  void insert(Linear_System& r, Recycle_Input);
40145
40146  //! Adds the rows of `y' to the pending part of `*this', stealing them from
40147  //! `y'.
40148  void insert_pending(Linear_System& r, Recycle_Input);
40149
40150  /*! \brief
40151    Sorts the non-pending rows (in growing order) and eliminates
40152    duplicated ones.
40153  */
40154  void sort_rows();
40155
40156  /*! \brief
40157    Sorts the rows (in growing order) form \p first_row to
40158    \p last_row and eliminates duplicated ones.
40159  */
40160  void sort_rows(dimension_type first_row, dimension_type last_row);
40161
40162  /*! \brief
40163    Assigns to \p *this the result of merging its rows with
40164    those of \p y, obtaining a sorted system.
40165
40166    Duplicated rows will occur only once in the result.
40167    On entry, both systems are assumed to be sorted and have
40168    no pending rows.
40169  */
40170  void merge_rows_assign(const Linear_System& y);
40171
40172  /*! \brief
40173    Sorts the pending rows and eliminates those that also occur
40174    in the non-pending part of the system.
40175  */
40176  void sort_pending_and_remove_duplicates();
40177
40178  /*! \brief
40179    Sorts the system, removing duplicates, keeping the saturation
40180    matrix consistent.
40181
40182    \param sat
40183    Bit matrix with rows corresponding to the rows of \p *this.
40184  */
40185  void sort_and_remove_with_sat(Bit_Matrix& sat);
40186
40187  //! Minimizes the subsystem of equations contained in \p *this.
40188  /*!
40189    This method works only on the equalities of the system:
40190    the system is required to be partially sorted, so that
40191    all the equalities are grouped at its top; it is assumed that
40192    the number of equalities is exactly \p n_lines_or_equalities.
40193    The method finds a minimal system for the equalities and
40194    returns its rank, i.e., the number of linearly independent equalities.
40195    The result is an upper triangular subsystem of equalities:
40196    for each equality, the pivot is chosen starting from
40197    the right-most space dimensions.
40198  */
40199  dimension_type gauss(dimension_type n_lines_or_equalities);
40200
40201  /*! \brief
40202    Back-substitutes the coefficients to reduce
40203    the complexity of the system.
40204
40205    Takes an upper triangular system having \p n_lines_or_equalities rows.
40206    For each row, starting from the one having the minimum number of
40207    coefficients different from zero, computes the expression of an element
40208    as a function of the remaining ones and then substitutes this expression
40209    in all the other rows.
40210  */
40211  void back_substitute(dimension_type n_lines_or_equalities);
40212
40213  /*! \brief
40214    Applies Gaussian elimination and back-substitution so as to
40215    simplify the linear system.
40216  */
40217  void simplify();
40218
40219  //! Clears the system deallocating all its rows.
40220  void clear();
40221
40222  PPL_OUTPUT_DECLARATIONS
40223
40224  /*! \brief
40225    Loads from \p s an ASCII representation (as produced by
40226    ascii_dump(std::ostream&) const) and sets \p *this accordingly.
40227    Returns <CODE>true</CODE> if successful, <CODE>false</CODE> otherwise.
40228
40229    Reads into a Linear_System object the information produced by the
40230    output of ascii_dump(std::ostream&) const.  The specialized methods
40231    provided by Constraint_System and Generator_System take care of
40232    properly reading the contents of the system.
40233  */
40234  bool ascii_load(std::istream& s);
40235
40236  //! Returns the total size in bytes of the memory occupied by \p *this.
40237  memory_size_type total_memory_in_bytes() const;
40238
40239  //! Returns the size in bytes of the memory managed by \p *this.
40240  memory_size_type external_memory_in_bytes() const;
40241
40242  //! The vector that contains the rows.
40243  /*!
40244    \note This is public for convenience. Clients that modify if must preserve
40245          the class invariant.
40246  */
40247  Swapping_Vector<Row> rows;
40248
40249  //! Checks if all the invariants are satisfied.
40250  bool OK() const;
40251
40252private:
40253  //! Makes the system shrink by removing its i-th row.
40254  /*!
40255    When \p keep_sorted is \p true and the system is sorted, sortedness will
40256    be preserved, but this method costs O(n).
40257
40258    Otherwise, this method just swaps the i-th row with the last and then
40259    removes it, so it costs O(1).
40260
40261    This method is for internal use, it does *not* assert OK() at the end,
40262    so it can be used for invalid systems.
40263  */
40264  void remove_row_no_ok(dimension_type i, bool keep_sorted = false);
40265
40266  /*! \brief
40267    Adds \p r to the pending part of the system, stealing its contents and
40268    automatically resizing the system or the row, if needed.
40269
40270    This method is for internal use, it does *not* assert OK() at the end,
40271    so it can be used for invalid systems.
40272  */
40273  void insert_pending_no_ok(Row& r, Recycle_Input);
40274
40275  /*! \brief
40276    Adds \p r to the system, stealing its contents and
40277    automatically resizing the system or the row, if needed.
40278
40279    This method is for internal use, it does *not* assert OK() at the end,
40280    so it can be used for invalid systems.
40281  */
40282  void insert_no_ok(Row& r, Recycle_Input);
40283
40284  //! Sets the space dimension of the rows in the system to \p space_dim .
40285  /*!
40286    This method is for internal use, it does *not* assert OK() at the end,
40287    so it can be used for invalid systems.
40288  */
40289  void set_space_dimension_no_ok(dimension_type space_dim);
40290
40291  //! Swaps the [first,last) row interval with the
40292  //! [first + offset, last + offset) interval.
40293  /*!
40294    These intervals may not be disjunct.
40295
40296    Sorting of these intervals is *not* preserved.
40297
40298    Either both intervals contain only not-pending rows, or they both
40299    contain pending rows.
40300  */
40301  void swap_row_intervals(dimension_type first, dimension_type last,
40302                          dimension_type offset);
40303
40304  //! The space dimension of each row. All rows must have this number of
40305  //! space dimensions.
40306  dimension_type space_dimension_;
40307
40308  //! The topological kind of the rows in the system. All rows must have this
40309  //! topology.
40310  Topology row_topology;
40311
40312  //! The index of the first pending row.
40313  dimension_type index_first_pending;
40314
40315  /*! \brief
40316    <CODE>true</CODE> if rows are sorted in the ascending order as defined by
40317    <CODE>bool compare(const Row&, const Row&)</CODE>.
40318    If <CODE>false</CODE> may not be sorted.
40319  */
40320  bool sorted;
40321
40322  Representation representation_;
40323
40324  //! Ordering predicate (used when implementing the sort algorithm).
40325  struct Row_Less_Than {
40326    bool operator()(const Row& x, const Row& y) const;
40327  };
40328
40329  //! Comparison predicate (used when implementing the unique algorithm).
40330  struct Unique_Compare {
40331    Unique_Compare(const Swapping_Vector<Row>& cont,
40332                   dimension_type base = 0);
40333
40334    bool operator()(dimension_type i, dimension_type j) const;
40335
40336    const Swapping_Vector<Row>& container;
40337    const dimension_type base_index;
40338  };
40339
40340  friend class Polyhedron;
40341  friend class Generator_System;
40342};
40343
40344namespace Parma_Polyhedra_Library {
40345
40346#ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
40347//! Swaps \p x with \p y.
40348/*! \relates Linear_System */
40349#endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
40350template <typename Row>
40351void swap(Parma_Polyhedra_Library::Linear_System<Row>& x,
40352          Parma_Polyhedra_Library::Linear_System<Row>& y);
40353
40354} // namespace std
40355
40356namespace Parma_Polyhedra_Library {
40357
40358#ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
40359//! Returns <CODE>true</CODE> if and only if \p x and \p y are identical.
40360/*! \relates Linear_System */
40361#endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
40362template <typename Row>
40363bool operator==(const Linear_System<Row>& x, const Linear_System<Row>& y);
40364
40365#ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
40366//! Returns <CODE>true</CODE> if and only if \p x and \p y are different.
40367/*! \relates Linear_System */
40368#endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
40369template <typename Row>
40370bool operator!=(const Linear_System<Row>& x, const Linear_System<Row>& y);
40371
40372} // namespace Parma_Polyhedra_Library
40373
40374/* Automatically generated from PPL source file ../src/Linear_System_inlines.hh line 1. */
40375/* Linear_System class implementation: inline functions.
40376*/
40377
40378
40379/* Automatically generated from PPL source file ../src/Bit_Row_defs.hh line 1. */
40380/* Bit_Row class declaration.
40381*/
40382
40383
40384/* Automatically generated from PPL source file ../src/Bit_Row_defs.hh line 29. */
40385#include <iosfwd>
40386#include <gmpxx.h>
40387#include <vector>
40388
40389namespace Parma_Polyhedra_Library {
40390
40391#ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
40392//! Swaps \p x with \p y.
40393/*! \relates Bit_Row */
40394void swap(Bit_Row& x, Bit_Row& y);
40395#endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
40396
40397#ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
40398//! Swaps objects referred by \p x and \p y.
40399/*! \relates Bit_Row */
40400#endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
40401void
40402iter_swap(std::vector<Bit_Row>::iterator x,
40403          std::vector<Bit_Row>::iterator y);
40404
40405// Put them in the namespace here to declare them friends later.
40406
40407#ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
40408//! Returns <CODE>true</CODE> if and only if \p x and \p y are equal.
40409/*! \relates Bit_Row */
40410#endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
40411bool operator==(const Bit_Row& x, const Bit_Row& y);
40412
40413#ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
40414//! Returns <CODE>true</CODE> if and only if \p x and \p y are not equal.
40415/*! \relates Bit_Row */
40416#endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
40417bool operator!=(const Bit_Row& x, const Bit_Row& y);
40418
40419#ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
40420//! The basic comparison function.
40421/*! \relates Bit_Row
40422  Compares \p x with \p y starting from the least significant bits.
40423  The ordering is total and has the following property: if \p x and \p y
40424  are two rows seen as sets of naturals, if \p x is a strict subset
40425  of \p y, then \p x comes before \p y.
40426
40427  Returns
40428  - -1 if \p x comes before \p y in the ordering;
40429  -  0 if \p x and \p y are equal;
40430  -  1 if \p x comes after \p y in the ordering.
40431*/
40432#endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
40433int compare(const Bit_Row& x, const Bit_Row& y);
40434
40435#ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
40436//! Set-theoretic inclusion test.
40437/*! \relates Bit_Row */
40438#endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
40439bool subset_or_equal(const Bit_Row& x, const Bit_Row& y);
40440
40441#ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
40442/*! \brief
40443  Set-theoretic inclusion test: sets \p strict_subset to a Boolean
40444  indicating whether the inclusion is strict or not.
40445
40446  \relates Bit_Row
40447*/
40448#endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
40449bool subset_or_equal(const Bit_Row& x, const Bit_Row& y,
40450                     bool& strict_subset);
40451
40452#ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
40453//! Set-theoretic strict inclusion test.
40454/*! \relates Bit_Row */
40455#endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
40456bool strict_subset(const Bit_Row& x, const Bit_Row& y);
40457
40458} // namespace Parma_Polyhedra_Library
40459
40460#ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
40461//! A row in a matrix of bits.
40462/*! \ingroup PPL_CXX_interface */
40463#endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
40464class Parma_Polyhedra_Library::Bit_Row {
40465public:
40466  //! Default constructor.
40467  Bit_Row();
40468
40469  //! Copy constructor.
40470  Bit_Row(const Bit_Row& y);
40471
40472  //! Set-union constructor.
40473  /*!
40474    Constructs an object containing the set-union of \p y and \p z.
40475  */
40476  Bit_Row(const Bit_Row& y, const Bit_Row& z);
40477
40478  //! Destructor.
40479  ~Bit_Row();
40480
40481  //! Assignment operator.
40482  Bit_Row& operator=(const Bit_Row& y);
40483
40484  //! Swaps \p *this with \p y.
40485  void m_swap(Bit_Row& y);
40486
40487  //! Returns the truth value corresponding to the bit in position \p k.
40488  bool operator[](unsigned long k) const;
40489
40490  //! Sets the bit in position \p k.
40491  void set(unsigned long k);
40492
40493  //! Sets bits up to position \p k (excluded).
40494  void set_until(unsigned long k);
40495
40496  //! Clears the bit in position \p k.
40497  void clear(unsigned long k);
40498
40499  //! Clears bits from position \p k (included) onward.
40500  void clear_from(unsigned long k);
40501
40502  //! Clears all the bits of the row.
40503  void clear();
40504
40505  //! Assigns to \p *this the set-theoretic union of \p x and \p y.
40506  void union_assign(const Bit_Row& x, const Bit_Row& y);
40507
40508  //! Assigns to \p *this the set-theoretic intersection of \p x and \p y.
40509  void intersection_assign(const Bit_Row& x, const Bit_Row& y);
40510
40511  //! Assigns to \p *this the set-theoretic difference of \p x and \p y.
40512  void difference_assign(const Bit_Row& x, const Bit_Row& y);
40513
40514
40515  friend int compare(const Bit_Row& x, const Bit_Row& y);
40516  friend bool operator==(const Bit_Row& x, const Bit_Row& y);
40517  friend bool operator!=(const Bit_Row& x, const Bit_Row& y);
40518  friend bool subset_or_equal(const Bit_Row& x, const Bit_Row& y);
40519  friend bool subset_or_equal(const Bit_Row& x, const Bit_Row& y,
40520                              bool& strict_subset);
40521  friend bool strict_subset(const Bit_Row& x, const Bit_Row& y);
40522
40523  //! Returns the index of the first set bit or ULONG_MAX if no bit is set.
40524  unsigned long first() const;
40525
40526  /*! \brief
40527    Returns the index of the first set bit after \p position
40528    or ULONG_MAX if no bit after \p position is set.
40529  */
40530  unsigned long next(unsigned long position) const;
40531
40532  //! Returns the index of the last set bit or ULONG_MAX if no bit is set.
40533  unsigned long last() const;
40534
40535  /*! \brief
40536    Returns the index of the first set bit before \p position
40537    or ULONG_MAX if no bits before \p position is set.
40538  */
40539  unsigned long prev(unsigned long position) const;
40540
40541  //! Returns the number of set bits in the row.
40542  unsigned long count_ones() const;
40543
40544  //! Returns <CODE>true</CODE> if no bit is set in the row.
40545  bool empty() const;
40546
40547  //! Returns the total size in bytes of the memory occupied by \p *this.
40548  memory_size_type total_memory_in_bytes() const;
40549
40550  //! Returns the size in bytes of the memory managed by \p *this.
40551  memory_size_type external_memory_in_bytes() const;
40552
40553  //! Checks if all the invariants are satisfied
40554  bool OK() const;
40555
40556private:
40557  //! Bit-vector representing the row.
40558  mpz_t vec;
40559
40560  //! Assigns to \p *this the union of \p y and \p z.
40561  /*!
40562    The size of \p y must be be less than or equal to the size of \p z.
40563    Upon entry, \p vec must have allocated enough space to contain the result.
40564  */
40565  void union_helper(const Bit_Row& y, const Bit_Row& z);
40566};
40567
40568/* Automatically generated from PPL source file ../src/Bit_Row_inlines.hh line 1. */
40569/* Bit_Row class implementation: inline functions.
40570*/
40571
40572
40573/* Automatically generated from PPL source file ../src/Bit_Row_inlines.hh line 30. */
40574
40575// For the declaration of ffs(3).
40576#if defined(PPL_HAVE_STRINGS_H)
40577# include <strings.h>
40578#elif defined(PPL_HAVE_STRING_H)
40579# include <string.h>
40580#endif
40581
40582#define PPL_BITS_PER_GMP_LIMB sizeof_to_bits(PPL_SIZEOF_MP_LIMB_T)
40583
40584namespace Parma_Polyhedra_Library {
40585
40586inline
40587Bit_Row::Bit_Row() {
40588  mpz_init(vec);
40589}
40590
40591inline
40592Bit_Row::Bit_Row(const Bit_Row& y) {
40593  mpz_init_set(vec, y.vec);
40594}
40595
40596inline
40597Bit_Row::Bit_Row(const Bit_Row& y, const Bit_Row& z) {
40598  const mp_size_t y_size = y.vec->_mp_size;
40599  PPL_ASSERT(y_size >= 0);
40600  const mp_size_t z_size = z.vec->_mp_size;
40601  PPL_ASSERT(z_size >= 0);
40602  if (y_size < z_size) {
40603    PPL_ASSERT(static_cast<unsigned long>(z_size)
40604               <= C_Integer<unsigned long>::max / PPL_BITS_PER_GMP_LIMB);
40605    mpz_init2(vec, static_cast<unsigned long>(z_size) * PPL_BITS_PER_GMP_LIMB);
40606    union_helper(y, z);
40607  }
40608  else {
40609    PPL_ASSERT(static_cast<unsigned long>(y_size)
40610               <= C_Integer<unsigned long>::max / PPL_BITS_PER_GMP_LIMB);
40611    mpz_init2(vec, static_cast<unsigned long>(y_size) * PPL_BITS_PER_GMP_LIMB);
40612    union_helper(z, y);
40613  }
40614}
40615
40616inline
40617Bit_Row::~Bit_Row() {
40618  mpz_clear(vec);
40619}
40620
40621inline Bit_Row&
40622Bit_Row::operator=(const Bit_Row& y) {
40623  mpz_set(vec, y.vec);
40624  return *this;
40625}
40626
40627inline void
40628Bit_Row::set(const unsigned long k) {
40629  mpz_setbit(vec, k);
40630}
40631
40632inline void
40633Bit_Row::clear(const unsigned long k) {
40634  mpz_clrbit(vec, k);
40635}
40636
40637inline void
40638Bit_Row::clear_from(const unsigned long k) {
40639  mpz_tdiv_r_2exp(vec, vec, k);
40640}
40641
40642inline unsigned long
40643Bit_Row::count_ones() const {
40644  const mp_size_t x_size = vec->_mp_size;
40645  PPL_ASSERT(x_size >= 0);
40646  return (x_size == 0) ? 0 : mpn_popcount(vec->_mp_d, x_size);
40647}
40648
40649inline bool
40650Bit_Row::empty() const {
40651  return mpz_sgn(vec) == 0;
40652}
40653
40654inline void
40655Bit_Row::m_swap(Bit_Row& y) {
40656  mpz_swap(vec, y.vec);
40657}
40658
40659inline void
40660Bit_Row::clear() {
40661  mpz_set_ui(vec, 0UL);
40662}
40663
40664inline memory_size_type
40665Bit_Row::external_memory_in_bytes() const {
40666  return static_cast<memory_size_type>(vec[0]._mp_alloc) * PPL_SIZEOF_MP_LIMB_T;
40667}
40668
40669inline memory_size_type
40670Bit_Row::total_memory_in_bytes() const {
40671  return sizeof(*this) + external_memory_in_bytes();
40672}
40673
40674inline void
40675Bit_Row::union_assign(const Bit_Row& x, const Bit_Row& y) {
40676  const mp_size_t x_size = x.vec->_mp_size;
40677  PPL_ASSERT(x_size >= 0);
40678  const mp_size_t y_size = y.vec->_mp_size;
40679  PPL_ASSERT(y_size >= 0);
40680  if (x_size < y_size) {
40681    PPL_ASSERT(static_cast<unsigned long>(y_size)
40682               <= C_Integer<unsigned long>::max / PPL_BITS_PER_GMP_LIMB);
40683    mpz_realloc2(vec, static_cast<unsigned long>(y_size) * PPL_BITS_PER_GMP_LIMB);
40684    union_helper(x, y);
40685  }
40686  else {
40687    PPL_ASSERT(static_cast<unsigned long>(x_size)
40688               <= C_Integer<unsigned long>::max / PPL_BITS_PER_GMP_LIMB);
40689    mpz_realloc2(vec, static_cast<unsigned long>(x_size) * PPL_BITS_PER_GMP_LIMB);
40690    union_helper(y, x);
40691  }
40692}
40693
40694inline void
40695Bit_Row::intersection_assign(const Bit_Row& x, const Bit_Row& y) {
40696  mpz_and(vec, x.vec, y.vec);
40697}
40698
40699inline void
40700Bit_Row::difference_assign(const Bit_Row& x, const Bit_Row& y) {
40701  PPL_DIRTY_TEMP(mpz_class, complement_y);
40702  mpz_com(complement_y.get_mpz_t(), y.vec);
40703  mpz_and(vec, x.vec, complement_y.get_mpz_t());
40704}
40705
40706namespace Implementation {
40707
40708/*! \brief
40709  Assuming \p u is nonzero, returns the index of the first set bit in \p u.
40710*/
40711inline unsigned int
40712first_one(unsigned int u) {
40713  return ctz(u);
40714}
40715
40716/*! \brief
40717  Assuming \p ul is nonzero, returns the index of the first set bit in
40718  \p ul.
40719*/
40720inline unsigned int
40721first_one(unsigned long ul) {
40722  return ctz(ul);
40723}
40724
40725/*! \brief
40726  Assuming \p ull is nonzero, returns the index of the first set bit in
40727  \p ull.
40728*/
40729inline unsigned int
40730first_one(unsigned long long ull) {
40731  return ctz(ull);
40732}
40733
40734/*! \brief
40735  Assuming \p u is nonzero, returns the index of the last set bit in \p u.
40736*/
40737inline unsigned int
40738last_one(unsigned int u) {
40739  return static_cast<unsigned int>(sizeof_to_bits(sizeof(u)))
40740    - 1U - clz(u);
40741}
40742
40743/*! \brief
40744  Assuming \p ul is nonzero, returns the index of the last set bit in
40745  \p ul.
40746*/
40747inline unsigned int
40748last_one(unsigned long ul) {
40749  return static_cast<unsigned int>(sizeof_to_bits(sizeof(ul)))
40750    - 1U - clz(ul);
40751}
40752
40753/*! \brief
40754  Assuming \p ull is nonzero, returns the index of the last set bit in
40755  \p ull.
40756*/
40757inline unsigned int
40758last_one(unsigned long long ull) {
40759  return static_cast<unsigned int>(sizeof_to_bits(sizeof(ull)))
40760    - 1U - clz(ull);
40761}
40762
40763} // namespace Implementation
40764
40765/*! \relates Bit_Row */
40766inline void
40767swap(Bit_Row& x, Bit_Row& y) {
40768  x.m_swap(y);
40769}
40770
40771/*! \relates Bit_Row */
40772inline void
40773iter_swap(std::vector<Bit_Row>::iterator x,
40774          std::vector<Bit_Row>::iterator y) {
40775  swap(*x, *y);
40776}
40777
40778} // namespace Parma_Polyhedra_Library
40779
40780/* Automatically generated from PPL source file ../src/Bit_Row_defs.hh line 213. */
40781
40782/* Automatically generated from PPL source file ../src/Linear_System_inlines.hh line 29. */
40783
40784#include <algorithm>
40785
40786namespace Parma_Polyhedra_Library {
40787
40788template <typename Row>
40789inline memory_size_type
40790Linear_System<Row>::external_memory_in_bytes() const {
40791  return rows.external_memory_in_bytes();
40792}
40793
40794template <typename Row>
40795inline memory_size_type
40796Linear_System<Row>::total_memory_in_bytes() const {
40797  return sizeof(*this) + external_memory_in_bytes();
40798}
40799
40800template <typename Row>
40801inline bool
40802Linear_System<Row>::is_sorted() const {
40803  // The flag `sorted' does not really reflect the sortedness status
40804  // of a system (if `sorted' evaluates to `false' nothing is known).
40805  // This assertion is used to ensure that the system
40806  // is actually sorted when `sorted' value is 'true'.
40807  PPL_ASSERT(!sorted || check_sorted());
40808  return sorted;
40809}
40810
40811template <typename Row>
40812inline void
40813Linear_System<Row>::set_sorted(const bool b) {
40814  sorted = b;
40815  PPL_ASSERT(OK());
40816}
40817
40818template <typename Row>
40819inline
40820Linear_System<Row>::Linear_System(Topology topol, Representation r)
40821  : rows(),
40822    space_dimension_(0),
40823    row_topology(topol),
40824    index_first_pending(0),
40825    sorted(true),
40826    representation_(r) {
40827
40828  PPL_ASSERT(OK());
40829}
40830
40831template <typename Row>
40832inline
40833Linear_System<Row>::Linear_System(Topology topol,
40834                                  dimension_type space_dim,
40835                                  Representation r)
40836  : rows(),
40837    space_dimension_(0),
40838    row_topology(topol),
40839    index_first_pending(0),
40840    sorted(true),
40841    representation_(r) {
40842  set_space_dimension(space_dim);
40843  PPL_ASSERT(OK());
40844}
40845
40846template <typename Row>
40847inline dimension_type
40848Linear_System<Row>::first_pending_row() const {
40849  return index_first_pending;
40850}
40851
40852template <typename Row>
40853inline dimension_type
40854Linear_System<Row>::num_pending_rows() const {
40855  PPL_ASSERT(num_rows() >= first_pending_row());
40856  return num_rows() - first_pending_row();
40857}
40858
40859template <typename Row>
40860inline void
40861Linear_System<Row>::unset_pending_rows() {
40862  index_first_pending = num_rows();
40863  PPL_ASSERT(OK());
40864}
40865
40866template <typename Row>
40867inline void
40868Linear_System<Row>::set_index_first_pending_row(const dimension_type i) {
40869  index_first_pending = i;
40870  PPL_ASSERT(OK());
40871}
40872
40873template <typename Row>
40874inline
40875Linear_System<Row>::Linear_System(const Linear_System& y)
40876  : rows(y.rows),
40877    space_dimension_(y.space_dimension_),
40878    row_topology(y.row_topology),
40879    representation_(y.representation_) {
40880  // Previously pending rows may violate sortedness.
40881  sorted = (y.num_pending_rows() > 0) ? false : y.sorted;
40882  unset_pending_rows();
40883  PPL_ASSERT(OK());
40884}
40885
40886template <typename Row>
40887inline
40888Linear_System<Row>::Linear_System(const Linear_System& y, Representation r)
40889  : rows(),
40890    space_dimension_(y.space_dimension_),
40891    row_topology(y.row_topology),
40892    representation_(r) {
40893  rows.resize(y.num_rows());
40894  for (dimension_type i = 0; i < y.num_rows(); ++i) {
40895    // Create the copies with the right representation.
40896    Row row(y.rows[i], r);
40897    swap(rows[i], row);
40898  }
40899  // Previously pending rows may violate sortedness.
40900  sorted = (y.num_pending_rows() > 0) ? false : y.sorted;
40901  unset_pending_rows();
40902  PPL_ASSERT(OK());
40903}
40904
40905template <typename Row>
40906inline
40907Linear_System<Row>::Linear_System(const Linear_System& y, With_Pending)
40908  : rows(y.rows),
40909    space_dimension_(y.space_dimension_),
40910    row_topology(y.row_topology),
40911    index_first_pending(y.index_first_pending),
40912    sorted(y.sorted),
40913    representation_(y.representation_) {
40914  PPL_ASSERT(OK());
40915}
40916
40917template <typename Row>
40918inline
40919Linear_System<Row>::Linear_System(const Linear_System& y, Representation r,
40920                                  With_Pending)
40921  : rows(),
40922    space_dimension_(y.space_dimension_),
40923    row_topology(y.row_topology),
40924    index_first_pending(y.index_first_pending),
40925    sorted(y.sorted),
40926    representation_(r) {
40927  rows.resize(y.num_rows());
40928  for (dimension_type i = 0; i < y.num_rows(); ++i) {
40929    // Create the copies with the right representation.
40930    Row row(y.rows[i], r);
40931    swap(rows[i], row);
40932  }
40933  PPL_ASSERT(OK());
40934}
40935
40936template <typename Row>
40937inline Linear_System<Row>&
40938Linear_System<Row>::operator=(const Linear_System& y) {
40939  // NOTE: Pending rows are transformed into non-pending ones.
40940  Linear_System<Row> tmp = y;
40941  swap(*this, tmp);
40942  return *this;
40943}
40944
40945template <typename Row>
40946inline void
40947Linear_System<Row>::assign_with_pending(const Linear_System& y) {
40948  Linear_System<Row> tmp(y, With_Pending());
40949  swap(*this, tmp);
40950}
40951
40952template <typename Row>
40953inline void
40954Linear_System<Row>::m_swap(Linear_System& y) {
40955  using std::swap;
40956  swap(rows, y.rows);
40957  swap(space_dimension_, y.space_dimension_);
40958  swap(row_topology, y.row_topology);
40959  swap(index_first_pending, y.index_first_pending);
40960  swap(sorted, y.sorted);
40961  swap(representation_, y.representation_);
40962  PPL_ASSERT(OK());
40963  PPL_ASSERT(y.OK());
40964}
40965
40966template <typename Row>
40967inline void
40968Linear_System<Row>::clear() {
40969  // Note: do NOT modify the value of `row_topology' and `representation'.
40970  rows.clear();
40971  index_first_pending = 0;
40972  sorted = true;
40973  space_dimension_ = 0;
40974
40975  PPL_ASSERT(OK());
40976}
40977
40978template <typename Row>
40979inline void
40980Linear_System<Row>::mark_as_necessarily_closed() {
40981  PPL_ASSERT(topology() == NOT_NECESSARILY_CLOSED);
40982  row_topology = NECESSARILY_CLOSED;
40983  ++space_dimension_;
40984  for (dimension_type i = num_rows(); i-- > 0; ) {
40985    rows[i].mark_as_necessarily_closed();
40986  }
40987}
40988
40989template <typename Row>
40990inline void
40991Linear_System<Row>::mark_as_not_necessarily_closed() {
40992  PPL_ASSERT(topology() == NECESSARILY_CLOSED);
40993  PPL_ASSERT(space_dimension() > 0);
40994  row_topology = NOT_NECESSARILY_CLOSED;
40995  --space_dimension_;
40996  for (dimension_type i = num_rows(); i-- > 0; ) {
40997    rows[i].mark_as_not_necessarily_closed();
40998  }
40999}
41000
41001template <typename Row>
41002inline void
41003Linear_System<Row>::set_topology(Topology t) {
41004  if (topology() == t) {
41005    return;
41006  }
41007  for (dimension_type i = num_rows(); i-- > 0; ) {
41008    rows[i].set_topology(t);
41009  }
41010  row_topology = t;
41011  PPL_ASSERT(OK());
41012}
41013
41014template <typename Row>
41015inline void
41016Linear_System<Row>::set_necessarily_closed() {
41017  set_topology(NECESSARILY_CLOSED);
41018}
41019
41020template <typename Row>
41021inline void
41022Linear_System<Row>::set_not_necessarily_closed() {
41023  set_topology(NOT_NECESSARILY_CLOSED);
41024}
41025
41026template <typename Row>
41027inline bool
41028Linear_System<Row>::is_necessarily_closed() const {
41029  return row_topology == NECESSARILY_CLOSED;
41030}
41031
41032template <typename Row>
41033inline const Row&
41034Linear_System<Row>::operator[](const dimension_type k) const {
41035  return rows[k];
41036}
41037
41038template <typename Row>
41039inline typename Linear_System<Row>::iterator
41040Linear_System<Row>::begin() {
41041  return rows.begin();
41042}
41043
41044template <typename Row>
41045inline typename Linear_System<Row>::iterator
41046Linear_System<Row>::end() {
41047  return rows.end();
41048}
41049
41050template <typename Row>
41051inline typename Linear_System<Row>::const_iterator
41052Linear_System<Row>::begin() const {
41053  return rows.begin();
41054}
41055
41056template <typename Row>
41057inline typename Linear_System<Row>::const_iterator
41058Linear_System<Row>::end() const {
41059  return rows.end();
41060}
41061
41062template <typename Row>
41063inline bool
41064Linear_System<Row>::has_no_rows() const {
41065  return rows.empty();
41066}
41067
41068template <typename Row>
41069inline dimension_type
41070Linear_System<Row>::num_rows() const {
41071  return rows.size();
41072}
41073
41074template <typename Row>
41075inline Topology
41076Linear_System<Row>::topology() const {
41077  return row_topology;
41078}
41079
41080template <typename Row>
41081inline Representation
41082Linear_System<Row>::representation() const {
41083  return representation_;
41084}
41085
41086template <typename Row>
41087inline void
41088Linear_System<Row>::set_representation(Representation r) {
41089  representation_ = r;
41090  for (dimension_type i = 0; i < rows.size(); ++i) {
41091    rows[i].set_representation(r);
41092  }
41093  PPL_ASSERT(OK());
41094}
41095
41096template <typename Row>
41097inline dimension_type
41098Linear_System<Row>::max_space_dimension() {
41099  return Row::max_space_dimension();
41100}
41101
41102template <typename Row>
41103inline dimension_type
41104Linear_System<Row>::space_dimension() const {
41105  return space_dimension_;
41106}
41107
41108template <typename Row>
41109inline void
41110Linear_System<Row>::set_space_dimension_no_ok(dimension_type space_dim) {
41111  for (dimension_type i = rows.size(); i-- > 0; ) {
41112    rows[i].set_space_dimension_no_ok(space_dim);
41113  }
41114  space_dimension_ = space_dim;
41115}
41116
41117template <typename Row>
41118inline void
41119Linear_System<Row>::set_space_dimension(dimension_type space_dim) {
41120  set_space_dimension_no_ok(space_dim);
41121  PPL_ASSERT(OK());
41122}
41123
41124template <typename Row>
41125inline void
41126Linear_System<Row>::remove_row_no_ok(const dimension_type i,
41127                                     const bool keep_sorted) {
41128  PPL_ASSERT(i < num_rows());
41129  const bool was_pending = (i >= index_first_pending);
41130
41131  if (sorted && keep_sorted && !was_pending) {
41132    for (dimension_type j = i + 1; j < rows.size(); ++j) {
41133      swap(rows[j], rows[j-1]);
41134    }
41135    rows.pop_back();
41136  }
41137  else {
41138    if (!was_pending) {
41139      sorted = false;
41140    }
41141    const bool last_row_is_pending = (num_rows() - 1 >= index_first_pending);
41142    if (was_pending == last_row_is_pending) {
41143      // Either both rows are pending or both rows are not pending.
41144      swap(rows[i], rows.back());
41145    }
41146    else {
41147      // Pending rows are stored after the non-pending ones.
41148      PPL_ASSERT(!was_pending);
41149      PPL_ASSERT(last_row_is_pending);
41150
41151      // Swap the row with the last non-pending row.
41152      swap(rows[i], rows[index_first_pending - 1]);
41153
41154      // Now the (non-pending) row that has to be deleted is between the
41155      // non-pending and the pending rows.
41156      swap(rows[i], rows.back());
41157    }
41158    rows.pop_back();
41159  }
41160  if (!was_pending) {
41161    // A non-pending row has been removed.
41162    --index_first_pending;
41163  }
41164}
41165
41166template <typename Row>
41167inline void
41168Linear_System<Row>::remove_row(const dimension_type i, bool keep_sorted) {
41169  remove_row_no_ok(i, keep_sorted);
41170  PPL_ASSERT(OK());
41171}
41172
41173
41174template <typename Row>
41175inline void
41176Linear_System<Row>::remove_rows(dimension_type first,
41177                                dimension_type last,
41178                                bool keep_sorted) {
41179  PPL_ASSERT(first <= last);
41180  PPL_ASSERT(last <= num_rows());
41181  const dimension_type n = last - first;
41182
41183  if (n == 0) {
41184    return;
41185  }
41186
41187  // All the rows that have to be removed must have the same (pending or
41188  // non-pending) status.
41189  PPL_ASSERT(first >= index_first_pending || last <= index_first_pending);
41190
41191  const bool were_pending = (first >= index_first_pending);
41192
41193  // Move the rows in [first,last) at the end of the system.
41194  if (sorted && keep_sorted && !were_pending) {
41195    // Preserve the row ordering.
41196    for (dimension_type i = last; i < rows.size(); ++i) {
41197      swap(rows[i], rows[i - n]);
41198    }
41199
41200    rows.resize(rows.size() - n);
41201
41202    // `n' non-pending rows have been removed.
41203    index_first_pending -= n;
41204
41205    PPL_ASSERT(OK());
41206    return;
41207  }
41208
41209  // We can ignore the row ordering, but we must not mix pending and
41210  // non-pending rows.
41211
41212  const dimension_type offset = rows.size() - n - first;
41213  // We want to swap the rows in [first, last) and
41214  // [first + offset, last + offset) (note that these intervals may not be
41215  // disjunct).
41216
41217  if (index_first_pending == num_rows()) {
41218    // There are no pending rows.
41219    PPL_ASSERT(!were_pending);
41220
41221    swap_row_intervals(first, last, offset);
41222
41223    rows.resize(rows.size() - n);
41224
41225    // `n' non-pending rows have been removed.
41226    index_first_pending -= n;
41227  }
41228  else {
41229    // There are some pending rows in [first + offset, last + offset).
41230    if (were_pending) {
41231      // Both intervals contain only pending rows, because the second
41232      // interval is after the first.
41233
41234      swap_row_intervals(first, last, offset);
41235
41236      rows.resize(rows.size() - n);
41237
41238      // `n' non-pending rows have been removed.
41239      index_first_pending -= n;
41240    }
41241    else {
41242      PPL_ASSERT(rows.size() - n < index_first_pending);
41243      PPL_ASSERT(rows.size() > index_first_pending);
41244      PPL_ASSERT(!were_pending);
41245      // In the [size() - n, size()) interval there are some non-pending
41246      // rows and some pending ones. Be careful not to mix them.
41247
41248      PPL_ASSERT(index_first_pending >= last);
41249      swap_row_intervals(first, last, index_first_pending - last);
41250
41251      // Mark the rows that must be deleted as pending.
41252      index_first_pending -= n;
41253      first = index_first_pending;
41254      last = first + n;
41255
41256      // Move them at the end of the system.
41257      swap_row_intervals(first, last, num_rows() - last);
41258
41259      // Actually remove the rows.
41260      rows.resize(rows.size() - n);
41261    }
41262  }
41263
41264  PPL_ASSERT(OK());
41265}
41266
41267template <typename Row>
41268inline void
41269Linear_System<Row>::swap_row_intervals(dimension_type first,
41270                                       dimension_type last,
41271                                       dimension_type offset) {
41272  PPL_ASSERT(first <= last);
41273  PPL_ASSERT(last + offset <= num_rows());
41274#ifndef NDEBUG
41275  if (first < last) {
41276    bool first_interval_has_pending_rows = (last > index_first_pending);
41277    bool second_interval_has_pending_rows = (last + offset > index_first_pending);
41278    bool first_interval_has_not_pending_rows = (first < index_first_pending);
41279    bool second_interval_has_not_pending_rows = (first + offset < index_first_pending);
41280    PPL_ASSERT(first_interval_has_not_pending_rows
41281               == !first_interval_has_pending_rows);
41282    PPL_ASSERT(second_interval_has_not_pending_rows
41283               == !second_interval_has_pending_rows);
41284    PPL_ASSERT(first_interval_has_pending_rows
41285               == second_interval_has_pending_rows);
41286  }
41287#endif
41288  if (first + offset < last) {
41289    // The intervals are not disjunct, make them so.
41290    const dimension_type k = last - first - offset;
41291    last -= k;
41292    offset += k;
41293  }
41294
41295  if (first == last) {
41296    // Nothing to do.
41297    return;
41298  }
41299
41300  for (dimension_type i = first; i < last; ++i) {
41301    swap(rows[i], rows[i + offset]);
41302  }
41303
41304  if (first < index_first_pending) {
41305    // The swaps involved not pending rows, so they may not be sorted anymore.
41306    set_sorted(false);
41307  }
41308
41309  PPL_ASSERT(OK());
41310}
41311
41312template <typename Row>
41313inline void
41314Linear_System<Row>::remove_rows(const std::vector<dimension_type>& indexes) {
41315#ifndef NDEBUG
41316  {
41317    // Check that `indexes' is sorted.
41318    std::vector<dimension_type> sorted_indexes = indexes;
41319    std::sort(sorted_indexes.begin(), sorted_indexes.end());
41320    PPL_ASSERT(indexes == sorted_indexes);
41321
41322    // Check that the last index (if any) is lower than num_rows().
41323    // This guarantees that all indexes are in [0, num_rows()).
41324    if (!indexes.empty()) {
41325      PPL_ASSERT(indexes.back() < num_rows());
41326    }
41327  }
41328#endif
41329
41330  if (indexes.empty()) {
41331    return;
41332  }
41333
41334  const dimension_type rows_size = rows.size();
41335  typedef std::vector<dimension_type>::const_iterator itr_t;
41336
41337  // `i' and last_unused_row' start with the value `indexes[0]' instead
41338  // of `0', because the loop would just increment `last_unused_row' in the
41339  // preceding iterations.
41340  dimension_type last_unused_row = indexes[0];
41341  dimension_type i = indexes[0];
41342  itr_t itr = indexes.begin();
41343  itr_t itr_end = indexes.end();
41344  while (itr != itr_end) {
41345    // i <= *itr < rows_size
41346    PPL_ASSERT(i < rows_size);
41347    if (*itr == i) {
41348      // The current row has to be removed, don't increment last_unused_row.
41349      ++itr;
41350    }
41351    else {
41352      // The current row must not be removed, swap it after the last used row.
41353      swap(rows[last_unused_row], rows[i]);
41354      ++last_unused_row;
41355    }
41356    ++i;
41357  }
41358
41359  // Move up the remaining rows, if any.
41360  for ( ; i < rows_size; ++i) {
41361    swap(rows[last_unused_row], rows[i]);
41362    ++last_unused_row;
41363  }
41364
41365  PPL_ASSERT(last_unused_row == num_rows() - indexes.size());
41366
41367  // The rows that have to be removed are now at the end of the system, just
41368  // remove them.
41369  rows.resize(last_unused_row);
41370
41371  // Adjust index_first_pending.
41372  if (indexes[0] >= index_first_pending) {
41373    // Removing pending rows only.
41374  }
41375  else {
41376    if (indexes.back() < index_first_pending) {
41377      // Removing non-pending rows only.
41378      index_first_pending -= indexes.size();
41379    }
41380    else {
41381      // Removing some pending and some non-pending rows, count the
41382      // non-pending rows that must be removed.
41383      // This exploits the fact that `indexes' is sorted by using binary
41384      // search.
41385      itr_t j = std::lower_bound(indexes.begin(), indexes.end(),
41386                                 index_first_pending);
41387      std::iterator_traits<itr_t>::difference_type
41388        non_pending = j - indexes.begin();
41389      index_first_pending -= static_cast<dimension_type>(non_pending);
41390    }
41391  }
41392
41393  // NOTE: This method does *not* call set_sorted(false), because it preserves
41394  // the relative row ordering.
41395
41396  PPL_ASSERT(OK());
41397}
41398
41399template <typename Row>
41400inline void
41401Linear_System<Row>::remove_trailing_rows(const dimension_type n) {
41402  PPL_ASSERT(rows.size() >= n);
41403  rows.resize(rows.size() - n);
41404  if (first_pending_row() > rows.size()) {
41405    index_first_pending = rows.size();
41406  }
41407  PPL_ASSERT(OK());
41408}
41409
41410template <typename Row>
41411inline void
41412Linear_System<Row>
41413::permute_space_dimensions(const std::vector<Variable>& cycle) {
41414  for (dimension_type i = num_rows(); i-- > 0; ) {
41415    rows[i].permute_space_dimensions(cycle);
41416  }
41417  sorted = false;
41418  PPL_ASSERT(OK());
41419}
41420
41421template <typename Row>
41422inline void
41423Linear_System<Row>
41424::swap_space_dimensions(Variable v1, Variable v2) {
41425  PPL_ASSERT(v1.space_dimension() <= space_dimension());
41426  PPL_ASSERT(v2.space_dimension() <= space_dimension());
41427  for (dimension_type k = num_rows(); k-- > 0; ) {
41428    rows[k].swap_space_dimensions(v1, v2);
41429  }
41430  sorted = false;
41431  PPL_ASSERT(OK());
41432}
41433
41434/*! \relates Linear_System */
41435template <typename Row>
41436inline bool
41437operator!=(const Linear_System<Row>& x, const Linear_System<Row>& y) {
41438  return !(x == y);
41439}
41440
41441template <typename Row>
41442inline bool
41443Linear_System<Row>::Row_Less_Than::operator()(const Row& x,
41444                                              const Row& y) const {
41445  return compare(x, y) < 0;
41446}
41447
41448template <typename Row>
41449inline
41450Linear_System<Row>::Unique_Compare
41451::Unique_Compare(const Swapping_Vector<Row>& cont,
41452                 dimension_type base)
41453  : container(cont), base_index(base) {
41454}
41455
41456template <typename Row>
41457inline bool
41458Linear_System<Row>::Unique_Compare
41459::operator()(dimension_type i, dimension_type j) const {
41460  return container[base_index + i].is_equal_to(container[base_index + j]);
41461}
41462
41463/*! \relates Linear_System */
41464template <typename Row>
41465inline void
41466swap(Linear_System<Row>& x, Linear_System<Row>& y) {
41467  x.m_swap(y);
41468}
41469
41470} // namespace Parma_Polyhedra_Library
41471
41472/* Automatically generated from PPL source file ../src/Linear_System_templates.hh line 1. */
41473/* Linear_System class implementation: non-inline template functions.
41474*/
41475
41476
41477/* Automatically generated from PPL source file ../src/Bit_Matrix_defs.hh line 1. */
41478/* Bit_Matrix class declaration.
41479*/
41480
41481
41482/* Automatically generated from PPL source file ../src/Bit_Matrix_defs.hh line 30. */
41483#include <vector>
41484#include <iosfwd>
41485
41486namespace Parma_Polyhedra_Library {
41487
41488#ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
41489//! Swaps \p x with \p y.
41490/*! \relates Bit_Matrix */
41491void swap(Bit_Matrix& x, Bit_Matrix& y);
41492#endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
41493
41494} // namespace Parma_Polyhedra_Library
41495
41496#ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
41497//! A matrix of bits.
41498/*! \ingroup PPL_CXX_interface */
41499#endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
41500class Parma_Polyhedra_Library::Bit_Matrix {
41501public:
41502  //! Default constructor.
41503  Bit_Matrix();
41504
41505  //! Construct a bit matrix with \p n_rows rows and \p n_columns columns.
41506  Bit_Matrix(dimension_type n_rows, dimension_type n_columns);
41507
41508  //! Copy constructor.
41509  Bit_Matrix(const Bit_Matrix& y);
41510
41511  //! Destructor.
41512  ~Bit_Matrix();
41513
41514  //! Assignment operator.
41515  Bit_Matrix& operator=(const Bit_Matrix& y);
41516
41517  //! Swaps \p *this with \p y.
41518  void m_swap(Bit_Matrix& y);
41519
41520  //! Subscript operator.
41521  Bit_Row& operator[](dimension_type k);
41522
41523  //! Constant subscript operator.
41524  const Bit_Row& operator[](dimension_type k) const;
41525
41526  //! Clears the matrix deallocating all its rows.
41527  void clear();
41528
41529  //! Transposes the matrix.
41530  void transpose();
41531
41532  //! Makes \p *this a transposed copy of \p y.
41533  void transpose_assign(const Bit_Matrix& y);
41534
41535  //! Returns the maximum number of rows of a Bit_Matrix.
41536  static dimension_type max_num_rows();
41537
41538  //! Returns the number of columns of \p *this.
41539  dimension_type num_columns() const;
41540
41541  //! Returns the number of rows of \p *this.
41542  dimension_type num_rows() const;
41543
41544  //! Sorts the rows and removes duplicates.
41545  void sort_rows();
41546
41547  //! Looks for \p row in \p *this, which is assumed to be sorted.
41548  /*!
41549    \return
41550    <CODE>true</CODE> if \p row belongs to \p *this, false otherwise.
41551
41552    \param row
41553    The row that will be searched for in the matrix.
41554
41555    Given a sorted bit matrix (this ensures better efficiency),
41556    tells whether it contains the given row.
41557  */
41558  bool sorted_contains(const Bit_Row& row) const;
41559
41560  //! Adds \p row to \p *this.
41561  /*!
41562    \param row
41563    The row whose implementation will be recycled.
41564
41565    The only thing that can be done with \p row upon return is destruction.
41566  */
41567  void add_recycled_row(Bit_Row& row);
41568
41569  //! Removes the last \p n rows.
41570  void remove_trailing_rows(dimension_type n);
41571
41572  //! Removes the last \p n columns.
41573  /*!
41574    The last \p n columns of the matrix are all made of zeros.
41575    If such an assumption is not met, the behavior is undefined.
41576  */
41577  void remove_trailing_columns(dimension_type n);
41578
41579  //! Resizes the matrix copying the old contents.
41580  void resize(dimension_type new_n_rows, dimension_type new_n_columns);
41581
41582  //! Checks if all the invariants are satisfied.
41583  bool OK() const;
41584
41585  PPL_OUTPUT_DECLARATIONS
41586
41587  /*! \brief
41588    Loads from \p s an ASCII representation (as produced by
41589    ascii_dump(std::ostream&) const) and sets \p *this accordingly.
41590    Returns <CODE>true</CODE> if successful, <CODE>false</CODE> otherwise.
41591  */
41592  bool ascii_load(std::istream& s);
41593
41594  //! Returns the total size in bytes of the memory occupied by \p *this.
41595  memory_size_type total_memory_in_bytes() const;
41596
41597  //! Returns the size in bytes of the memory managed by \p *this.
41598  memory_size_type external_memory_in_bytes() const;
41599
41600#ifndef NDEBUG
41601  //! Checks whether \p *this is sorted. It does NOT check for duplicates.
41602  bool check_sorted() const;
41603#endif
41604
41605private:
41606  //! Contains the rows of the matrix.
41607  std::vector<Bit_Row> rows;
41608
41609  //! Size of the initialized part of each row.
41610  dimension_type row_size;
41611
41612  //! Ordering predicate (used when implementing the sort algorithm).
41613  /*! \ingroup PPL_CXX_interface */
41614  struct Bit_Row_Less_Than {
41615    bool operator()(const Bit_Row& x, const Bit_Row& y) const;
41616  };
41617
41618  template <typename Row>
41619  friend class Parma_Polyhedra_Library::Linear_System;
41620};
41621
41622namespace Parma_Polyhedra_Library {
41623
41624#ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
41625//! Returns <CODE>true</CODE> if and only if \p x and \p y are equal.
41626/*! \relates Bit_Matrix */
41627#endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
41628bool operator==(const Bit_Matrix& x, const Bit_Matrix& y);
41629
41630#ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
41631//! Returns <CODE>true</CODE> if and only if \p x and \p y are not equal.
41632/*! \relates Bit_Matrix */
41633#endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
41634bool operator!=(const Bit_Matrix& x, const Bit_Matrix& y);
41635
41636} // namespace Parma_Polyhedra_Library
41637
41638/* Automatically generated from PPL source file ../src/Bit_Matrix_inlines.hh line 1. */
41639/* Bit_Matrix class implementation: inline functions.
41640*/
41641
41642
41643/* Automatically generated from PPL source file ../src/Bit_Matrix_inlines.hh line 28. */
41644#include <algorithm>
41645
41646namespace Parma_Polyhedra_Library {
41647
41648inline
41649Bit_Matrix::Bit_Matrix()
41650  : rows(),
41651    row_size(0) {
41652}
41653
41654inline dimension_type
41655Bit_Matrix::max_num_rows() {
41656  return std::vector<Bit_Row>().max_size();
41657}
41658
41659inline
41660Bit_Matrix::Bit_Matrix(const dimension_type n_rows,
41661                       const dimension_type n_columns)
41662  : rows(n_rows),
41663    row_size(n_columns) {
41664}
41665
41666inline
41667Bit_Matrix::Bit_Matrix(const Bit_Matrix& y)
41668  : rows(y.rows),
41669    row_size(y.row_size) {
41670}
41671
41672inline
41673Bit_Matrix::~Bit_Matrix() {
41674}
41675
41676inline void
41677Bit_Matrix::remove_trailing_rows(const dimension_type n) {
41678  // The number of rows to be erased cannot be greater
41679  // than the actual number of the rows of the matrix.
41680  PPL_ASSERT(n <= rows.size());
41681  if (n != 0) {
41682    rows.resize(rows.size() - n);
41683  }
41684  PPL_ASSERT(OK());
41685}
41686
41687inline void
41688Bit_Matrix::remove_trailing_columns(const dimension_type n) {
41689  // The number of columns to be erased cannot be greater
41690  // than the actual number of the columns of the matrix.
41691  PPL_ASSERT(n <= row_size);
41692  row_size -= n;
41693  PPL_ASSERT(OK());
41694}
41695
41696inline void
41697Bit_Matrix::m_swap(Bit_Matrix& y) {
41698  std::swap(row_size, y.row_size);
41699  std::swap(rows, y.rows);
41700}
41701
41702inline Bit_Row&
41703Bit_Matrix::operator[](const dimension_type k) {
41704  PPL_ASSERT(k < rows.size());
41705  return rows[k];
41706}
41707
41708inline const Bit_Row&
41709Bit_Matrix::operator[](const dimension_type k) const {
41710  PPL_ASSERT(k < rows.size());
41711  return rows[k];
41712}
41713
41714inline dimension_type
41715Bit_Matrix::num_columns() const {
41716  return row_size;
41717}
41718
41719inline dimension_type
41720Bit_Matrix::num_rows() const {
41721  return rows.size();
41722}
41723
41724inline void
41725Bit_Matrix::clear() {
41726  // Clear `rows' and minimize its capacity.
41727  std::vector<Bit_Row> tmp;
41728  std::swap(tmp, rows);
41729  row_size = 0;
41730}
41731
41732inline memory_size_type
41733Bit_Matrix::total_memory_in_bytes() const {
41734  return sizeof(*this) + external_memory_in_bytes();
41735}
41736
41737inline bool
41738Bit_Matrix::Bit_Row_Less_Than::
41739operator()(const Bit_Row& x, const Bit_Row& y) const {
41740  return compare(x, y) < 0;
41741}
41742
41743inline bool
41744Bit_Matrix::sorted_contains(const Bit_Row& row) const {
41745  PPL_ASSERT(check_sorted());
41746  return std::binary_search(rows.begin(), rows.end(), row,
41747                            Bit_Row_Less_Than());
41748}
41749
41750/*! \relates Bit_Matrix */
41751inline bool
41752operator!=(const Bit_Matrix& x, const Bit_Matrix& y) {
41753  return !(x == y);
41754}
41755
41756/*! \relates Bit_Matrix */
41757inline void
41758swap(Bit_Matrix& x, Bit_Matrix& y) {
41759  x.m_swap(y);
41760}
41761
41762} // namespace Parma_Polyhedra_Library
41763
41764/* Automatically generated from PPL source file ../src/Bit_Matrix_defs.hh line 186. */
41765
41766/* Automatically generated from PPL source file ../src/Scalar_Products_defs.hh line 1. */
41767/* Scalar_Products class definition.
41768*/
41769
41770
41771/* Automatically generated from PPL source file ../src/Scalar_Products_defs.hh line 34. */
41772
41773#ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
41774//! A class implementing various scalar product functions.
41775/*! \ingroup PPL_CXX_interface
41776  When computing the scalar product of (Linear_Expression or Constraint or
41777  Generator) objects <CODE>x</CODE> and <CODE>y</CODE>, it is assumed
41778  that the space dimension of the first object <CODE>x</CODE> is less
41779  than or equal to the space dimension of the second object <CODE>y</CODE>.
41780*/
41781#endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
41782class Parma_Polyhedra_Library::Scalar_Products {
41783public:
41784  //! Computes the scalar product of \p x and \p y and assigns it to \p z.
41785  static void assign(Coefficient& z,
41786                     const Linear_Expression& x, const Linear_Expression& y);
41787
41788  //! Computes the scalar product of \p c and \p g and assigns it to \p z.
41789  static void assign(Coefficient& z, const Constraint& c, const Generator& g);
41790
41791  //! Computes the scalar product of \p g and \p c and assigns it to \p z.
41792  static void assign(Coefficient& z, const Generator& g, const Constraint& c);
41793
41794  //! Computes the scalar product of \p c and \p g and assigns it to \p z.
41795  static void assign(Coefficient& z,
41796                     const Constraint& c, const Grid_Generator& gg);
41797
41798  //! Computes the scalar product of \p g and \p cg and assigns it to \p z.
41799  static void assign(Coefficient& z,
41800                     const Grid_Generator& gg, const Congruence& cg);
41801
41802  //! Computes the scalar product of \p cg and \p g and assigns it to \p z.
41803  static void assign(Coefficient& z,
41804                     const Congruence& cg, const Grid_Generator& gg);
41805
41806  //! Returns the sign of the scalar product between \p x and \p y.
41807  static int sign(const Linear_Expression& x, const Linear_Expression& y);
41808
41809  //! Returns the sign of the scalar product between \p c and \p g.
41810  static int sign(const Constraint& c, const Generator& g);
41811
41812  //! Returns the sign of the scalar product between \p g and \p c.
41813  static int sign(const Generator& g, const Constraint& c);
41814
41815  //! Returns the sign of the scalar product between \p c and \p g.
41816  static int sign(const Constraint& c, const Grid_Generator& g);
41817
41818  /*! \brief
41819    Computes the \e reduced scalar product of \p x and \p y,
41820    where the \f$\epsilon\f$ coefficient of \p x is ignored,
41821    and assigns the result to \p z.
41822  */
41823  static void reduced_assign(Coefficient& z,
41824                             const Linear_Expression& x,
41825                             const Linear_Expression& y);
41826
41827  /*! \brief
41828    Computes the \e reduced scalar product of \p c and \p g,
41829    where the \f$\epsilon\f$ coefficient of \p c is ignored,
41830    and assigns the result to \p z.
41831  */
41832  static void reduced_assign(Coefficient& z,
41833                             const Constraint& c, const Generator& g);
41834
41835  /*! \brief
41836    Computes the \e reduced scalar product of \p g and \p c,
41837    where the \f$\epsilon\f$ coefficient of \p g is ignored,
41838    and assigns the result to \p z.
41839  */
41840  static void reduced_assign(Coefficient& z,
41841                             const Generator& g, const Constraint& c);
41842
41843  //! \brief
41844  //! Computes the \e reduced scalar product of \p g and \p cg,
41845  //! where the \f$\epsilon\f$ coefficient of \p g is ignored,
41846  //! and assigns the result to \p z.
41847  static void reduced_assign(Coefficient& z,
41848                             const Grid_Generator& gg, const Congruence& cg);
41849
41850  /*! \brief
41851    Returns the sign of the \e reduced scalar product of \p x and \p y,
41852    where the \f$\epsilon\f$ coefficient of \p x is ignored.
41853  */
41854  static int reduced_sign(const Linear_Expression& x,
41855                          const Linear_Expression& y);
41856
41857  /*! \brief
41858    Returns the sign of the \e reduced scalar product of \p c and \p g,
41859    where the \f$\epsilon\f$ coefficient of \p c is ignored.
41860  */
41861  static int reduced_sign(const Constraint& c, const Generator& g);
41862
41863  /*! \brief
41864    Returns the sign of the \e reduced scalar product of \p g and \p c,
41865    where the \f$\epsilon\f$ coefficient of \p g is ignored.
41866  */
41867  static int reduced_sign(const Generator& g, const Constraint& c);
41868
41869  /*! \brief
41870    Computes the \e homogeneous scalar product of \p x and \p y,
41871    where the inhomogeneous terms are ignored,
41872    and assigns the result to \p z.
41873  */
41874  static void homogeneous_assign(Coefficient& z,
41875                                 const Linear_Expression& x,
41876                                 const Linear_Expression& y);
41877  /*! \brief
41878    Computes the \e homogeneous scalar product of \p e and \p g,
41879    where the inhomogeneous terms are ignored,
41880    and assigns the result to \p z.
41881  */
41882  static void homogeneous_assign(Coefficient& z,
41883                                 const Linear_Expression& e,
41884                                 const Generator& g);
41885
41886  //! \brief
41887  //! Computes the \e homogeneous scalar product of \p gg and \p c,
41888  //! where the inhomogeneous terms are ignored,
41889  //! and assigns the result to \p z.
41890  static void homogeneous_assign(Coefficient& z,
41891                                 const Grid_Generator& gg,
41892                                 const Constraint& c);
41893
41894  //! \brief
41895  //! Computes the \e homogeneous scalar product of \p g and \p cg,
41896  //! where the inhomogeneous terms are ignored,
41897  //! and assigns the result to \p z.
41898  static void homogeneous_assign(Coefficient& z,
41899                                 const Grid_Generator& gg,
41900                                 const Congruence& cg);
41901
41902  //! \brief
41903  //! Computes the \e homogeneous scalar product of \p e and \p g,
41904  //! where the inhomogeneous terms are ignored,
41905  //! and assigns the result to \p z.
41906  static void homogeneous_assign(Coefficient& z,
41907                                 const Linear_Expression& e,
41908                                 const Grid_Generator& g);
41909
41910  /*! \brief
41911    Returns the sign of the \e homogeneous scalar product of \p x and \p y,
41912    where the inhomogeneous terms are ignored.
41913  */
41914  static int homogeneous_sign(const Linear_Expression& x,
41915                              const Linear_Expression& y);
41916
41917  /*! \brief
41918    Returns the sign of the \e homogeneous scalar product of \p e and \p g,
41919    where the inhomogeneous terms are ignored.
41920  */
41921  static int homogeneous_sign(const Linear_Expression& e, const Generator& g);
41922
41923  //! \brief
41924  //! Returns the sign of the \e homogeneous scalar product of \p e and \p g,
41925  //! where the inhomogeneous terms are ignored,
41926  static int homogeneous_sign(const Linear_Expression& e,
41927                              const Grid_Generator& g);
41928
41929  //! \brief
41930  //! Returns the sign of the \e homogeneous scalar product of \p g and \p c,
41931  //! where the inhomogeneous terms are ignored,
41932  static int homogeneous_sign(const Grid_Generator& g, const Constraint& c);
41933};
41934
41935#ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
41936//! Scalar product sign function object depending on topology.
41937/*! \ingroup PPL_CXX_interface */
41938#endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
41939class Parma_Polyhedra_Library::Topology_Adjusted_Scalar_Product_Sign {
41940public:
41941  //! Constructs the function object according to the topology of \p c.
41942  Topology_Adjusted_Scalar_Product_Sign(const Constraint& c);
41943
41944  //! Constructs the function object according to the topology of \p g.
41945  Topology_Adjusted_Scalar_Product_Sign(const Generator& g);
41946
41947  //! Computes the (topology adjusted) scalar product sign of \p c and \p g.
41948  int operator()(const Constraint&, const Generator&) const;
41949
41950  //! Computes the (topology adjusted) scalar product sign of \p g and \p c.
41951  int operator()(const Generator&, const Constraint&) const;
41952
41953private:
41954  //! The type of the scalar product sign function pointer.
41955  typedef int (* const SPS_type)(const Linear_Expression&,
41956                                 const Linear_Expression&);
41957
41958  //! The scalar product sign function pointer.
41959  SPS_type sps_fp;
41960};
41961
41962// NOTE: Scalar_Products_inlines.hh is NOT included here, to avoid cyclic
41963// include dependencies.
41964
41965/* Automatically generated from PPL source file ../src/Scalar_Products_inlines.hh line 1. */
41966/* Scalar_Products class implementation (inline functions).
41967*/
41968
41969
41970/* Automatically generated from PPL source file ../src/Scalar_Products_inlines.hh line 32. */
41971
41972namespace Parma_Polyhedra_Library {
41973
41974inline int
41975Scalar_Products::sign(const Linear_Expression& x, const Linear_Expression& y) {
41976  PPL_DIRTY_TEMP_COEFFICIENT(z);
41977  assign(z, x, y);
41978  return sgn(z);
41979}
41980
41981inline int
41982Scalar_Products::reduced_sign(const Linear_Expression& x,
41983                              const Linear_Expression& y) {
41984  PPL_DIRTY_TEMP_COEFFICIENT(z);
41985  reduced_assign(z, x, y);
41986  return sgn(z);
41987}
41988
41989inline int
41990Scalar_Products::homogeneous_sign(const Linear_Expression& x,
41991                                  const Linear_Expression& y) {
41992  PPL_DIRTY_TEMP_COEFFICIENT(z);
41993  homogeneous_assign(z, x, y);
41994  return sgn(z);
41995}
41996
41997inline int
41998Scalar_Products::sign(const Constraint& c, const Generator& g) {
41999  return sign(c.expr, g.expr);
42000}
42001
42002inline int
42003Scalar_Products::sign(const Generator& g, const Constraint& c) {
42004  return sign(g.expr, c.expr);
42005}
42006
42007inline int
42008Scalar_Products::sign(const Constraint& c, const Grid_Generator& g) {
42009  PPL_DIRTY_TEMP_COEFFICIENT(z);
42010  assign(z, c, g);
42011  return sgn(z);
42012}
42013
42014inline int
42015Scalar_Products::reduced_sign(const Constraint& c, const Generator& g) {
42016  // The reduced scalar product is only defined if the topology of `c' is
42017  // NNC.
42018  PPL_ASSERT(!c.is_necessarily_closed());
42019  return reduced_sign(c.expr, g.expr);
42020}
42021
42022inline int
42023Scalar_Products::reduced_sign(const Generator& g, const Constraint& c) {
42024  // The reduced scalar product is only defined if the topology of `g' is
42025  // NNC.
42026  PPL_ASSERT(!c.is_necessarily_closed());
42027  return reduced_sign(g.expr, c.expr);
42028}
42029
42030inline void
42031Scalar_Products::homogeneous_assign(Coefficient& z,
42032                                    const Linear_Expression& e,
42033                                    const Generator& g) {
42034  homogeneous_assign(z, e, g.expr);
42035}
42036
42037inline void
42038Scalar_Products::homogeneous_assign(Coefficient& z,
42039                                    const Linear_Expression& e,
42040                                    const Grid_Generator& g) {
42041  homogeneous_assign(z, e, g.expr);
42042}
42043
42044inline int
42045Scalar_Products::homogeneous_sign(const Linear_Expression& e,
42046                                  const Generator& g) {
42047  return homogeneous_sign(e, g.expr);
42048}
42049
42050inline int
42051Scalar_Products::homogeneous_sign(const Linear_Expression& e,
42052                                  const Grid_Generator& g) {
42053  return homogeneous_sign(e, g.expr);
42054}
42055
42056inline int
42057Scalar_Products::homogeneous_sign(const Grid_Generator& g,
42058                                  const Constraint& c) {
42059  PPL_DIRTY_TEMP_COEFFICIENT(z);
42060  homogeneous_assign(z, g, c);
42061  return sgn(z);
42062}
42063
42064inline
42065Topology_Adjusted_Scalar_Product_Sign
42066::Topology_Adjusted_Scalar_Product_Sign(const Constraint& c)
42067  : sps_fp(c.is_necessarily_closed()
42068           ? static_cast<SPS_type>(&Scalar_Products::sign)
42069           : static_cast<SPS_type>(&Scalar_Products::reduced_sign)) {
42070}
42071
42072inline
42073Topology_Adjusted_Scalar_Product_Sign
42074::Topology_Adjusted_Scalar_Product_Sign(const Generator& g)
42075  : sps_fp(g.is_necessarily_closed()
42076           ? static_cast<SPS_type>(&Scalar_Products::sign)
42077           : static_cast<SPS_type>(&Scalar_Products::reduced_sign)) {
42078}
42079
42080inline int
42081Topology_Adjusted_Scalar_Product_Sign::operator()(const Constraint& c,
42082                                                  const Generator& g) const {
42083  PPL_ASSERT(c.space_dimension() <= g.space_dimension());
42084  PPL_ASSERT(sps_fp == (c.is_necessarily_closed()
42085                    ? static_cast<SPS_type>(&Scalar_Products::sign)
42086                    : static_cast<SPS_type>(&Scalar_Products::reduced_sign)));
42087  return sps_fp(c.expr, g.expr);
42088}
42089
42090inline int
42091Topology_Adjusted_Scalar_Product_Sign::operator()(const Generator& g,
42092                                                  const Constraint& c) const {
42093  PPL_ASSERT(g.space_dimension() <= c.space_dimension());
42094  PPL_ASSERT(sps_fp == (g.is_necessarily_closed()
42095                    ? static_cast<SPS_type>(&Scalar_Products::sign)
42096                    : static_cast<SPS_type>(&Scalar_Products::reduced_sign)));
42097  return sps_fp(g.expr, c.expr);
42098}
42099
42100} // namespace Parma_Polyhedra_Library
42101
42102/* Automatically generated from PPL source file ../src/swapping_sort_templates.hh line 1. */
42103/* Sorting objects for which copies cost more than swaps.
42104*/
42105
42106
42107#include <vector>
42108#include <algorithm>
42109
42110namespace Parma_Polyhedra_Library {
42111
42112namespace Implementation {
42113
42114template <typename RA_Container, typename Compare>
42115struct Indirect_Sort_Compare {
42116  typedef typename RA_Container::size_type size_type;
42117
42118  Indirect_Sort_Compare(const RA_Container& cont,
42119                        size_type base = 0,
42120                        Compare comp = Compare())
42121    : container(cont), base_index(base), compare(comp) {
42122  }
42123
42124  bool operator()(size_type i, size_type j) const {
42125    return compare(container[base_index + i], container[base_index + j]);
42126  }
42127
42128  const RA_Container& container;
42129  const size_type base_index;
42130  const Compare compare;
42131}; // struct Indirect_Sort_Compare
42132
42133template <typename RA_Container>
42134struct Indirect_Unique_Compare {
42135  typedef typename RA_Container::size_type size_type;
42136
42137  Indirect_Unique_Compare(const RA_Container& cont, size_type base = 0)
42138    : container(cont), base_index(base) {
42139  }
42140
42141  bool operator()(size_type i, size_type j) const {
42142    return container[base_index + i] == container[base_index + j];
42143  }
42144
42145  const RA_Container& container;
42146  const size_type base_index;
42147}; // struct Indirect_Unique_Compare
42148
42149template <typename RA_Container>
42150struct Indirect_Swapper {
42151  typedef typename RA_Container::size_type size_type;
42152
42153  Indirect_Swapper(RA_Container& cont, size_type base = 0)
42154    : container(cont), base_index(base) {
42155  }
42156
42157  void operator()(size_type i, size_type j) const {
42158    using std::swap;
42159    swap(container[base_index + i], container[base_index + j]);
42160  }
42161
42162  RA_Container& container;
42163  const size_type base_index;
42164}; // struct Indirect_Swapper
42165
42166template <typename RA_Container1, typename RA_Container2>
42167struct Indirect_Swapper2 {
42168  typedef typename RA_Container1::size_type size_type;
42169
42170  Indirect_Swapper2(RA_Container1& cont1, RA_Container2& cont2)
42171    : container1(cont1), container2(cont2) {
42172  }
42173
42174  void operator()(size_type i, size_type j) const {
42175    using std::swap;
42176    swap(container1[i], container1[j]);
42177    swap(container2[i], container2[j]);
42178  }
42179
42180  RA_Container1& container1;
42181  RA_Container2& container2;
42182}; // struct Indirect_Swapper2
42183
42184template <typename Sort_Comparer, typename Unique_Comparer, typename Swapper>
42185typename Sort_Comparer::size_type
42186indirect_sort_and_unique(typename Sort_Comparer::size_type num_elems,
42187                         Sort_Comparer sort_cmp,
42188                         Unique_Comparer unique_cmp,
42189                         Swapper indirect_swap) {
42190  typedef typename Sort_Comparer::size_type index_type;
42191  // `iv' is a vector of indices for the portion of rows to be sorted.
42192  PPL_ASSERT(num_elems >= 2);
42193  std::vector<index_type> iv;
42194  iv.reserve(num_elems);
42195  for (index_type i = 0, i_end = num_elems; i != i_end; ++i) {
42196    iv.push_back(i);
42197  }
42198
42199  typedef typename std::vector<index_type>::iterator Iter;
42200  const Iter iv_begin = iv.begin();
42201  Iter iv_end = iv.end();
42202
42203  // Sort `iv' by comparing the rows indexed by its elements.
42204  std::sort(iv_begin, iv_end, sort_cmp);
42205
42206  // Swap the indexed rows according to `iv':
42207  // for each index `i', the element that should be placed in
42208  // position dst = i is the one placed in position src = iv[i].
42209  for (index_type i = num_elems; i-- > 0; ) {
42210    if (i != iv[i]) {
42211      index_type dst = i;
42212      index_type src = iv[i];
42213      do {
42214        indirect_swap(src, dst);
42215        iv[dst] = dst;
42216        dst = src;
42217        src = iv[dst];
42218      } while (i != src);
42219      iv[dst] = dst;
42220    }
42221  }
42222
42223  // Restore `iv' indices to 0 .. num_elems-1 for the call to unique.
42224  for (index_type i = num_elems; i-- > 0; ) {
42225    iv[i] = i;
42226  }
42227
42228  // Unique `iv' by comparing the rows indexed by its elements.
42229  iv_end = std::unique(iv_begin, iv_end, unique_cmp);
42230
42231  const index_type num_sorted = static_cast<index_type>(iv_end - iv_begin);
42232  const index_type num_duplicates = num_elems - num_sorted;
42233  if (num_duplicates == 0) {
42234    return 0;
42235  }
42236
42237  // There were duplicates: swap the rows according to `iv'.
42238  index_type dst = 0;
42239  while (dst < num_sorted && dst == iv[dst]) {
42240    ++dst;
42241  }
42242  if (dst == num_sorted) {
42243    return num_duplicates;
42244  }
42245  do {
42246    const index_type src = iv[dst];
42247    indirect_swap(src, dst);
42248    ++dst;
42249  }
42250  while (dst < num_sorted);
42251  return num_duplicates;
42252}
42253
42254template <typename Iter>
42255Iter
42256swapping_unique(Iter first, Iter last) {
42257  return swapping_unique(first, last, std::iter_swap<Iter, Iter>);
42258}
42259
42260} // namespace Implementation
42261
42262} // namespace Parma_Polyhedra_Library
42263
42264/* Automatically generated from PPL source file ../src/Linear_System_templates.hh line 32. */
42265#include <algorithm>
42266#include <iostream>
42267#include <string>
42268#include <deque>
42269
42270namespace Parma_Polyhedra_Library {
42271
42272template <typename Row>
42273dimension_type
42274Linear_System<Row>::num_lines_or_equalities() const {
42275  PPL_ASSERT(num_pending_rows() == 0);
42276  const Linear_System& x = *this;
42277  dimension_type n = 0;
42278  for (dimension_type i = num_rows(); i-- > 0; ) {
42279    if (x[i].is_line_or_equality()) {
42280      ++n;
42281    }
42282  }
42283  return n;
42284}
42285
42286template <typename Row>
42287void
42288Linear_System<Row>::merge_rows_assign(const Linear_System& y) {
42289  PPL_ASSERT(space_dimension() >= y.space_dimension());
42290  // Both systems have to be sorted and have no pending rows.
42291  PPL_ASSERT(check_sorted() && y.check_sorted());
42292  PPL_ASSERT(num_pending_rows() == 0 && y.num_pending_rows() == 0);
42293
42294  Linear_System& x = *this;
42295
42296  // A temporary vector...
42297  Swapping_Vector<Row> tmp;
42298  // ... with enough capacity not to require any reallocations.
42299  tmp.reserve(compute_capacity(x.rows.size() + y.rows.size(),
42300                               tmp.max_num_rows()));
42301
42302  dimension_type xi = 0;
42303  const dimension_type x_num_rows = x.num_rows();
42304  dimension_type yi = 0;
42305  const dimension_type y_num_rows = y.num_rows();
42306
42307  while (xi < x_num_rows && yi < y_num_rows) {
42308    const int comp = compare(x[xi], y[yi]);
42309    if (comp <= 0) {
42310      // Elements that can be taken from `x' are actually _stolen_ from `x'
42311      tmp.resize(tmp.size() + 1);
42312      swap(tmp.back(), x.rows[xi++]);
42313      tmp.back().set_representation(representation());
42314      if (comp == 0) {
42315        // A duplicate element.
42316        ++yi;
42317      }
42318    }
42319    else {
42320      // (comp > 0)
42321      tmp.resize(tmp.size() + 1);
42322      Row copy(y[yi++], space_dimension(), representation());
42323      swap(tmp.back(), copy);
42324    }
42325  }
42326  // Insert what is left.
42327  if (xi < x_num_rows) {
42328    while (xi < x_num_rows) {
42329      tmp.resize(tmp.size() + 1);
42330      swap(tmp.back(), x.rows[xi++]);
42331      tmp.back().set_representation(representation());
42332    }
42333  }
42334  else {
42335    while (yi < y_num_rows) {
42336      tmp.resize(tmp.size() + 1);
42337      Row copy(y[yi++], space_dimension(), representation());
42338      swap(tmp.back(), copy);
42339    }
42340  }
42341
42342  // We get the result matrix and let the old one be destroyed.
42343  swap(tmp, rows);
42344  // There are no pending rows.
42345  unset_pending_rows();
42346  PPL_ASSERT(check_sorted());
42347  PPL_ASSERT(OK());
42348}
42349
42350template <typename Row>
42351void
42352Linear_System<Row>::ascii_dump(std::ostream& s) const {
42353  // Prints the topology, the number of rows, the number of columns
42354  // and the sorted flag.  The specialized methods provided by
42355  // Constraint_System and Generator_System take care of properly
42356  // printing the contents of the system.
42357  s << "topology " << (is_necessarily_closed()
42358                       ? "NECESSARILY_CLOSED"
42359                       : "NOT_NECESSARILY_CLOSED")
42360    << "\n"
42361    << num_rows() << " x " << space_dimension() << " ";
42362  Parma_Polyhedra_Library::ascii_dump(s, representation());
42363  s << " " << (sorted ? "(sorted)" : "(not_sorted)")
42364    << "\n"
42365    << "index_first_pending " << first_pending_row()
42366    << "\n";
42367  for (dimension_type i = 0; i < rows.size(); ++i) {
42368    rows[i].ascii_dump(s);
42369  }
42370}
42371
42372PPL_OUTPUT_TEMPLATE_DEFINITIONS_ASCII_ONLY(Row, Linear_System<Row>)
42373
42374template <typename Row>
42375bool
42376Linear_System<Row>::ascii_load(std::istream& s) {
42377  std::string str;
42378  if (!(s >> str) || str != "topology") {
42379    return false;
42380  }
42381  if (!(s >> str)) {
42382    return false;
42383  }
42384
42385  clear();
42386
42387  Topology t;
42388  if (str == "NECESSARILY_CLOSED") {
42389    t = NECESSARILY_CLOSED;
42390  }
42391  else {
42392    if (str != "NOT_NECESSARILY_CLOSED") {
42393      return false;
42394    }
42395    t = NOT_NECESSARILY_CLOSED;
42396  }
42397
42398  set_topology(t);
42399
42400  dimension_type nrows;
42401  dimension_type space_dims;
42402  if (!(s >> nrows)) {
42403    return false;
42404  }
42405  if (!(s >> str) || str != "x") {
42406    return false;
42407  }
42408  if (!(s >> space_dims)) {
42409    return false;
42410  }
42411
42412  space_dimension_ = space_dims;
42413
42414  if (!Parma_Polyhedra_Library::ascii_load(s, representation_)) {
42415    return false;
42416  }
42417
42418  if (!(s >> str) || (str != "(sorted)" && str != "(not_sorted)")) {
42419    return false;
42420  }
42421  const bool sortedness = (str == "(sorted)");
42422  dimension_type index;
42423  if (!(s >> str) || str != "index_first_pending") {
42424    return false;
42425  }
42426  if (!(s >> index)) {
42427    return false;
42428  }
42429
42430  Row row;
42431  for (dimension_type i = 0; i < nrows; ++i) {
42432    if (!row.ascii_load(s)) {
42433      return false;
42434    }
42435    insert(row, Recycle_Input());
42436  }
42437  index_first_pending = index;
42438  sorted = sortedness;
42439
42440  // Check invariants.
42441  PPL_ASSERT(OK());
42442  return true;
42443}
42444
42445template <typename Row>
42446void
42447Linear_System<Row>::insert(const Row& r) {
42448  Row tmp(r, representation());
42449  insert(tmp, Recycle_Input());
42450}
42451
42452template <typename Row>
42453void
42454Linear_System<Row>::insert(Row& r, Recycle_Input) {
42455  insert_no_ok(r, Recycle_Input());
42456  PPL_ASSERT(OK());
42457}
42458
42459template <typename Row>
42460void
42461Linear_System<Row>::insert_no_ok(Row& r, Recycle_Input) {
42462  PPL_ASSERT(topology() == r.topology());
42463  // This method is only used when the system has no pending rows.
42464  PPL_ASSERT(num_pending_rows() == 0);
42465
42466  const bool was_sorted = is_sorted();
42467
42468  insert_pending_no_ok(r, Recycle_Input());
42469
42470  if (was_sorted) {
42471    const dimension_type nrows = num_rows();
42472    // The added row may have caused the system to be not sorted anymore.
42473    if (nrows > 1) {
42474      // If the system is not empty and the inserted row is the
42475      // greatest one, the system is set to be sorted.
42476      // If it is not the greatest one then the system is no longer sorted.
42477      sorted = (compare(rows[nrows-2], rows[nrows-1]) <= 0);
42478    }
42479    else {
42480      // A system having only one row is sorted.
42481      sorted = true;
42482    }
42483  }
42484
42485  unset_pending_rows();
42486}
42487
42488template <typename Row>
42489void
42490Linear_System<Row>::insert_pending_no_ok(Row& r, Recycle_Input) {
42491  // TODO: A Grid_Generator_System may contain non-normalized lines that
42492  // represent parameters, so this check is disabled. Consider re-enabling it
42493  // when it's possibile.
42494#if 0
42495  // The added row must be strongly normalized and have the same
42496  // number of elements as the existing rows of the system.
42497  PPL_ASSERT(r.check_strong_normalized());
42498#endif
42499
42500  PPL_ASSERT(r.topology() == topology());
42501
42502  r.set_representation(representation());
42503
42504  if (space_dimension() < r.space_dimension()) {
42505    set_space_dimension_no_ok(r.space_dimension());
42506  }
42507  else {
42508    r.set_space_dimension_no_ok(space_dimension());
42509  }
42510
42511  rows.resize(rows.size() + 1);
42512  swap(rows.back(), r);
42513}
42514
42515template <typename Row>
42516void
42517Linear_System<Row>::insert_pending(const Row& r) {
42518  Row tmp(r, representation());
42519  insert_pending(tmp, Recycle_Input());
42520}
42521
42522template <typename Row>
42523void
42524Linear_System<Row>::insert_pending(Row& r, Recycle_Input) {
42525  insert_pending_no_ok(r, Recycle_Input());
42526  PPL_ASSERT(OK());
42527}
42528
42529template <typename Row>
42530void
42531Linear_System<Row>::insert_pending(const Linear_System& y) {
42532  Linear_System tmp(y, representation(), With_Pending());
42533  insert_pending(tmp, Recycle_Input());
42534}
42535
42536template <typename Row>
42537void
42538Linear_System<Row>::insert_pending(Linear_System& y, Recycle_Input) {
42539  Linear_System& x = *this;
42540  PPL_ASSERT(x.space_dimension() == y.space_dimension());
42541
42542  // Steal the rows of `y'.
42543  // This loop must use an increasing index (instead of a decreasing one) to
42544  // preserve the row ordering.
42545  for (dimension_type i = 0; i < y.num_rows(); ++i) {
42546    x.insert_pending(y.rows[i], Recycle_Input());
42547  }
42548
42549  y.clear();
42550
42551  PPL_ASSERT(x.OK());
42552}
42553
42554template <typename Row>
42555void
42556Linear_System<Row>::insert(const Linear_System& y) {
42557  Linear_System tmp(y, representation(), With_Pending());
42558  insert(tmp, Recycle_Input());
42559}
42560
42561template <typename Row>
42562void
42563Linear_System<Row>::insert(Linear_System& y, Recycle_Input) {
42564  PPL_ASSERT(num_pending_rows() == 0);
42565
42566  // Adding no rows is a no-op.
42567  if (y.has_no_rows()) {
42568    return;
42569  }
42570
42571  // Check if sortedness is preserved.
42572  if (is_sorted()) {
42573    if (!y.is_sorted() || y.num_pending_rows() > 0) {
42574      sorted = false;
42575    }
42576    else {
42577      // `y' is sorted and has no pending rows.
42578      const dimension_type n_rows = num_rows();
42579      if (n_rows > 0) {
42580        sorted = (compare(rows[n_rows-1], y[0]) <= 0);
42581      }
42582    }
42583  }
42584
42585  // Add the rows of `y' as if they were pending.
42586  insert_pending(y, Recycle_Input());
42587
42588  // TODO: May y have pending rows? Should they remain pending?
42589
42590  // There are no pending_rows.
42591  unset_pending_rows();
42592
42593  PPL_ASSERT(OK());
42594}
42595
42596template <typename Row>
42597void
42598Linear_System<Row>::remove_space_dimensions(const Variables_Set& vars) {
42599  // Dimension-compatibility assertion.
42600  PPL_ASSERT(space_dimension() >= vars.space_dimension());
42601
42602  // The removal of no dimensions from any system is a no-op.  This
42603  // case also captures the only legal removal of dimensions from a
42604  // 0-dim system.
42605  if (vars.empty()) {
42606    return;
42607  }
42608
42609  // NOTE: num_rows() is *not* constant, because it may be decreased by
42610  // remove_row_no_ok().
42611  for (dimension_type i = 0; i < num_rows(); ) {
42612    const bool valid = rows[i].remove_space_dimensions(vars);
42613    if (!valid) {
42614      // Remove the current row.
42615      // We can't call remove_row(i) here, because the system is not OK as
42616      // some rows already have the new space dimension and others still have
42617      // the old one.
42618      remove_row_no_ok(i, false);
42619    }
42620    else {
42621      ++i;
42622    }
42623  }
42624
42625  space_dimension_ -= vars.size();
42626
42627  PPL_ASSERT(OK());
42628}
42629
42630template <typename Row>
42631void
42632Linear_System<Row>::shift_space_dimensions(Variable v, dimension_type n) {
42633  // NOTE: v.id() may be equal to the space dimension of the system
42634  // (when no space dimension need to be shifted).
42635  PPL_ASSERT(v.id() <= space_dimension());
42636  for (dimension_type i = rows.size(); i-- > 0; ) {
42637    rows[i].shift_space_dimensions(v, n);
42638  }
42639  space_dimension_ += n;
42640  PPL_ASSERT(OK());
42641}
42642
42643template <typename Row>
42644void
42645Linear_System<Row>::sort_rows() {
42646  // We sort the non-pending rows only.
42647  sort_rows(0, first_pending_row());
42648  sorted = true;
42649  PPL_ASSERT(OK());
42650}
42651
42652template <typename Row>
42653void
42654Linear_System<Row>::sort_rows(const dimension_type first_row,
42655                              const dimension_type last_row) {
42656  PPL_ASSERT(first_row <= last_row && last_row <= num_rows());
42657  // We cannot mix pending and non-pending rows.
42658  PPL_ASSERT(first_row >= first_pending_row()
42659             || last_row <= first_pending_row());
42660
42661  const bool sorting_pending = (first_row >= first_pending_row());
42662  const dimension_type old_num_pending = num_pending_rows();
42663
42664  const dimension_type num_elems = last_row - first_row;
42665  if (num_elems < 2) {
42666    return;
42667  }
42668
42669  // Build the function objects implementing indirect sort comparison,
42670  // indirect unique comparison and indirect swap operation.
42671  using namespace Implementation;
42672  typedef Swapping_Vector<Row> Cont;
42673  typedef Indirect_Sort_Compare<Cont, Row_Less_Than> Sort_Compare;
42674  typedef Indirect_Swapper<Cont> Swapper;
42675  const dimension_type num_duplicates
42676    = indirect_sort_and_unique(num_elems,
42677                               Sort_Compare(rows, first_row),
42678                               Unique_Compare(rows, first_row),
42679                               Swapper(rows, first_row));
42680
42681  if (num_duplicates > 0) {
42682    typedef typename Cont::iterator Iter;
42683    typedef typename std::iterator_traits<Iter>::difference_type diff_t;
42684    Iter last = rows.begin() + static_cast<diff_t>(last_row);
42685    Iter first = last - + static_cast<diff_t>(num_duplicates);
42686    rows.erase(first, last);
42687  }
42688
42689  if (sorting_pending) {
42690    PPL_ASSERT(old_num_pending >= num_duplicates);
42691    index_first_pending = num_rows() - (old_num_pending - num_duplicates);
42692  }
42693  else {
42694    index_first_pending = num_rows() - old_num_pending;
42695  }
42696
42697  PPL_ASSERT(OK());
42698}
42699
42700template <typename Row>
42701void
42702Linear_System<Row>::strong_normalize() {
42703  const dimension_type nrows = rows.size();
42704  // We strongly normalize also the pending rows.
42705  for (dimension_type i = nrows; i-- > 0; ) {
42706    rows[i].strong_normalize();
42707  }
42708  sorted = (nrows <= 1);
42709  PPL_ASSERT(OK());
42710}
42711
42712template <typename Row>
42713void
42714Linear_System<Row>::sign_normalize() {
42715  const dimension_type nrows = rows.size();
42716  // We sign-normalize also the pending rows.
42717  for (dimension_type i = nrows; i-- > 0; ) {
42718    rows[i].sign_normalize();
42719  }
42720  sorted = (nrows <= 1);
42721  PPL_ASSERT(OK());
42722}
42723
42724/*! \relates Parma_Polyhedra_Library::Linear_System */
42725template <typename Row>
42726bool
42727operator==(const Linear_System<Row>& x, const Linear_System<Row>& y) {
42728  if (x.space_dimension() != y.space_dimension()) {
42729    return false;
42730  }
42731  const dimension_type x_num_rows = x.num_rows();
42732  const dimension_type y_num_rows = y.num_rows();
42733  if (x_num_rows != y_num_rows) {
42734    return false;
42735  }
42736  if (x.first_pending_row() != y.first_pending_row()) {
42737    return false;
42738  }
42739  // TODO: Check if the following comment is up to date.
42740  // Notice that calling operator==(const Swapping_Vector<Row>&,
42741  //                                const Swapping_Vector<Row>&)
42742  // would be wrong here, as equality of the type fields would
42743  // not be checked.
42744  for (dimension_type i = x_num_rows; i-- > 0; ) {
42745    if (x[i] != y[i]) {
42746      return false;
42747    }
42748  }
42749  return true;
42750}
42751
42752template <typename Row>
42753void
42754Linear_System<Row>::sort_and_remove_with_sat(Bit_Matrix& sat) {
42755  // We can only sort the non-pending part of the system.
42756  PPL_ASSERT(first_pending_row() == sat.num_rows());
42757  if (first_pending_row() <= 1) {
42758    set_sorted(true);
42759    return;
42760  }
42761
42762  const dimension_type num_elems = sat.num_rows();
42763  // Build the function objects implementing indirect sort comparison,
42764  // indirect unique comparison and indirect swap operation.
42765  typedef Swapping_Vector<Row> Cont;
42766  const Implementation::Indirect_Sort_Compare<Cont, Row_Less_Than>
42767    sort_cmp(rows);
42768  const Unique_Compare unique_cmp(rows);
42769  const Implementation::Indirect_Swapper2<Cont, Bit_Matrix> swapper(rows, sat);
42770
42771  const dimension_type num_duplicates
42772    = Implementation::indirect_sort_and_unique(num_elems, sort_cmp,
42773                                               unique_cmp, swapper);
42774
42775  const dimension_type new_first_pending_row
42776    = first_pending_row() - num_duplicates;
42777
42778  if (num_pending_rows() > 0) {
42779    // In this case, we must put the duplicates after the pending rows.
42780    const dimension_type n_rows = num_rows() - 1;
42781    for (dimension_type i = 0; i < num_duplicates; ++i) {
42782      swap(rows[new_first_pending_row + i], rows[n_rows - i]);
42783    }
42784  }
42785
42786  // Erasing the duplicated rows...
42787  rows.resize(rows.size() - num_duplicates);
42788  index_first_pending = new_first_pending_row;
42789  // ... and the corresponding rows of the saturation matrix.
42790  sat.remove_trailing_rows(num_duplicates);
42791
42792  // Now the system is sorted.
42793  sorted = true;
42794
42795  PPL_ASSERT(OK());
42796}
42797
42798template <typename Row>
42799dimension_type
42800Linear_System<Row>::gauss(const dimension_type n_lines_or_equalities) {
42801  // This method is only applied to a linear system having no pending rows and
42802  // exactly `n_lines_or_equalities' lines or equalities, all of which occur
42803  // before the rays or points or inequalities.
42804  PPL_ASSERT(num_pending_rows() == 0);
42805  PPL_ASSERT(n_lines_or_equalities == num_lines_or_equalities());
42806#ifndef NDEBUG
42807  for (dimension_type i = n_lines_or_equalities; i-- > 0; ) {
42808    PPL_ASSERT((*this)[i].is_line_or_equality());
42809  }
42810#endif
42811
42812  dimension_type rank = 0;
42813  // Will keep track of the variations on the system of equalities.
42814  bool changed = false;
42815  // TODO: Don't use the number of columns.
42816  const dimension_type num_cols
42817    = is_necessarily_closed() ? space_dimension() + 1 : space_dimension() + 2;
42818  // TODO: Consider exploiting the row (possible) sparseness of rows in the
42819  // following loop, if needed. It would probably make it more cache-efficient
42820  // for dense rows, too.
42821  for (dimension_type j = num_cols; j-- > 0; ) {
42822    for (dimension_type i = rank; i < n_lines_or_equalities; ++i) {
42823      // Search for the first row having a non-zero coefficient
42824      // (the pivot) in the j-th column.
42825      if ((*this)[i].expr.get(j) == 0) {
42826        continue;
42827      }
42828      // Pivot found: if needed, swap rows so that this one becomes
42829      // the rank-th row in the linear system.
42830      if (i > rank) {
42831        swap(rows[i], rows[rank]);
42832        // After swapping the system is no longer sorted.
42833        changed = true;
42834      }
42835      // Combine the row containing the pivot with all the lines or
42836      // equalities following it, so that all the elements on the j-th
42837      // column in these rows become 0.
42838      for (dimension_type k = i + 1; k < n_lines_or_equalities; ++k) {
42839        if (rows[k].expr.get(Variable(j - 1)) != 0) {
42840          rows[k].linear_combine(rows[rank], j);
42841          changed = true;
42842        }
42843      }
42844      // Already dealt with the rank-th row.
42845      ++rank;
42846      // Consider another column index `j'.
42847      break;
42848    }
42849  }
42850  if (changed) {
42851    sorted = false;
42852  }
42853
42854  PPL_ASSERT(OK());
42855  return rank;
42856}
42857
42858template <typename Row>
42859void
42860Linear_System<Row>
42861::back_substitute(const dimension_type n_lines_or_equalities) {
42862  // This method is only applied to a system having no pending rows and
42863  // exactly `n_lines_or_equalities' lines or equalities, all of which occur
42864  // before the first ray or point or inequality.
42865  PPL_ASSERT(num_pending_rows() == 0);
42866  PPL_ASSERT(n_lines_or_equalities <= num_lines_or_equalities());
42867#ifndef NDEBUG
42868  for (dimension_type i = n_lines_or_equalities; i-- > 0; ) {
42869    PPL_ASSERT((*this)[i].is_line_or_equality());
42870  }
42871#endif
42872
42873  const dimension_type nrows = num_rows();
42874  // Trying to keep sortedness.
42875  bool still_sorted = is_sorted();
42876  // This deque of Booleans will be used to flag those rows that,
42877  // before exiting, need to be re-checked for sortedness.
42878  std::deque<bool> check_for_sortedness;
42879  if (still_sorted) {
42880    check_for_sortedness.insert(check_for_sortedness.end(), nrows, false);
42881  }
42882
42883  for (dimension_type k = n_lines_or_equalities; k-- > 0; ) {
42884    // For each line or equality, starting from the last one,
42885    // looks for the last non-zero element.
42886    // `j' will be the index of such a element.
42887    Row& row_k = rows[k];
42888    const dimension_type j = row_k.expr.last_nonzero();
42889    // TODO: Check this.
42890    PPL_ASSERT(j != 0);
42891
42892    // Go through the equalities above `row_k'.
42893    for (dimension_type i = k; i-- > 0; ) {
42894      Row& row_i = rows[i];
42895      if (row_i.expr.get(Variable(j - 1)) != 0) {
42896        // Combine linearly `row_i' with `row_k'
42897        // so that `row_i[j]' becomes zero.
42898        row_i.linear_combine(row_k, j);
42899        if (still_sorted) {
42900          // Trying to keep sortedness: remember which rows
42901          // have to be re-checked for sortedness at the end.
42902          if (i > 0) {
42903            check_for_sortedness[i-1] = true;
42904          }
42905          check_for_sortedness[i] = true;
42906        }
42907      }
42908    }
42909
42910    // Due to strong normalization during previous iterations,
42911    // the pivot coefficient `row_k[j]' may now be negative.
42912    // Since an inequality (or ray or point) cannot be multiplied
42913    // by a negative factor, the coefficient of the pivot must be
42914    // forced to be positive.
42915    const bool have_to_negate = (row_k.expr.get(Variable(j - 1)) < 0);
42916    if (have_to_negate) {
42917      neg_assign(row_k.expr);
42918    }
42919
42920    // NOTE: Here row_k will *not* be ok if we have negated it.
42921
42922    // Note: we do not mark index `k' in `check_for_sortedness',
42923    // because we will later negate back the row.
42924
42925    // Go through all the other rows of the system.
42926    for (dimension_type i = n_lines_or_equalities; i < nrows; ++i) {
42927      Row& row_i = rows[i];
42928      if (row_i.expr.get(Variable(j - 1)) != 0) {
42929        // Combine linearly the `row_i' with `row_k'
42930        // so that `row_i[j]' becomes zero.
42931        row_i.linear_combine(row_k, j);
42932        if (still_sorted) {
42933          // Trying to keep sortedness: remember which rows
42934          // have to be re-checked for sortedness at the end.
42935          if (i > n_lines_or_equalities) {
42936            check_for_sortedness[i-1] = true;
42937          }
42938          check_for_sortedness[i] = true;
42939        }
42940      }
42941    }
42942    if (have_to_negate) {
42943      // Negate `row_k' to restore strong-normalization.
42944      neg_assign(row_k.expr);
42945    }
42946
42947    PPL_ASSERT(row_k.OK());
42948  }
42949
42950  // Trying to keep sortedness.
42951  for (dimension_type i = 0; still_sorted && i+1 < nrows; ++i) {
42952    if (check_for_sortedness[i]) {
42953      // Have to check sortedness of `(*this)[i]' with respect to `(*this)[i+1]'.
42954      still_sorted = (compare((*this)[i], (*this)[i+1]) <= 0);
42955    }
42956  }
42957
42958  // Set the sortedness flag.
42959  sorted = still_sorted;
42960
42961  PPL_ASSERT(OK());
42962}
42963
42964template <typename Row>
42965void
42966Linear_System<Row>::simplify() {
42967  // This method is only applied to a system having no pending rows.
42968  PPL_ASSERT(num_pending_rows() == 0);
42969
42970  // Partially sort the linear system so that all lines/equalities come first.
42971  const dimension_type old_nrows = num_rows();
42972  dimension_type nrows = old_nrows;
42973  dimension_type n_lines_or_equalities = 0;
42974  for (dimension_type i = 0; i < nrows; ++i) {
42975    if ((*this)[i].is_line_or_equality()) {
42976      if (n_lines_or_equalities < i) {
42977        swap(rows[i], rows[n_lines_or_equalities]);
42978        // The system was not sorted.
42979        PPL_ASSERT(!sorted);
42980      }
42981      ++n_lines_or_equalities;
42982    }
42983  }
42984  // Apply Gaussian elimination to the subsystem of lines/equalities.
42985  const dimension_type rank = gauss(n_lines_or_equalities);
42986  // Eliminate any redundant line/equality that has been detected.
42987  if (rank < n_lines_or_equalities) {
42988    const dimension_type
42989      n_rays_or_points_or_inequalities = nrows - n_lines_or_equalities;
42990    const dimension_type
42991      num_swaps = std::min(n_lines_or_equalities - rank,
42992                           n_rays_or_points_or_inequalities);
42993    for (dimension_type i = num_swaps; i-- > 0; ) {
42994      swap(rows[--nrows], rows[rank + i]);
42995    }
42996    remove_trailing_rows(old_nrows - nrows);
42997    if (n_rays_or_points_or_inequalities > num_swaps) {
42998      set_sorted(false);
42999    }
43000    unset_pending_rows();
43001    n_lines_or_equalities = rank;
43002  }
43003  // Apply back-substitution to the system of rays/points/inequalities.
43004  back_substitute(n_lines_or_equalities);
43005
43006  PPL_ASSERT(OK());
43007}
43008
43009template <typename Row>
43010void
43011Linear_System<Row>
43012::add_universe_rows_and_space_dimensions(const dimension_type n) {
43013  PPL_ASSERT(n > 0);
43014  const bool was_sorted = is_sorted();
43015  const dimension_type old_n_rows = num_rows();
43016  const dimension_type old_space_dim
43017    = is_necessarily_closed() ? space_dimension() : space_dimension() + 1;
43018  set_space_dimension(space_dimension() + n);
43019  rows.resize(rows.size() + n);
43020  // The old system is moved to the bottom.
43021  for (dimension_type i = old_n_rows; i-- > 0; ) {
43022    swap(rows[i], rows[i + n]);
43023  }
43024  for (dimension_type i = n, c = old_space_dim; i-- > 0; ) {
43025    // The top right-hand sub-system (i.e., the system made of new
43026    // rows and columns) is set to the specular image of the identity
43027    // matrix.
43028    if (Variable(c).space_dimension() <= space_dimension()) {
43029      // Variable(c) is a user variable.
43030      Linear_Expression le(representation());
43031      le.set_space_dimension(space_dimension());
43032      le += Variable(c);
43033      Row r(le, Row::LINE_OR_EQUALITY, row_topology);
43034      swap(r, rows[i]);
43035    }
43036    else {
43037      // Variable(c) is the epsilon dimension.
43038      PPL_ASSERT(row_topology == NOT_NECESSARILY_CLOSED);
43039      Linear_Expression le(Variable(c), representation());
43040      Row r(le, Row::LINE_OR_EQUALITY, NECESSARILY_CLOSED);
43041      r.mark_as_not_necessarily_closed();
43042      swap(r, rows[i]);
43043      // Note: `r' is strongly normalized.
43044    }
43045    ++c;
43046  }
43047  // If the old system was empty, the last row added is either
43048  // a positivity constraint or a point.
43049  if (was_sorted) {
43050    sorted = (compare(rows[n-1], rows[n]) <= 0);
43051  }
43052
43053  // If the system is not necessarily closed, move the epsilon coefficients to
43054  // the last column.
43055  if (!is_necessarily_closed()) {
43056    // Try to preserve sortedness of `gen_sys'.
43057    PPL_ASSERT(old_space_dim != 0);
43058    if (!is_sorted()) {
43059      for (dimension_type i = n; i-- > 0; ) {
43060        rows[i].expr.swap_space_dimensions(Variable(old_space_dim - 1),
43061                                           Variable(old_space_dim - 1 + n));
43062        PPL_ASSERT(rows[i].OK());
43063      }
43064    }
43065    else {
43066      dimension_type old_eps_index = old_space_dim - 1;
43067      // The upper-right corner of `rows' contains the J matrix:
43068      // swap coefficients to preserve sortedness.
43069      for (dimension_type i = n; i-- > 0; ++old_eps_index) {
43070        rows[i].expr.swap_space_dimensions(Variable(old_eps_index),
43071                                           Variable(old_eps_index + 1));
43072        PPL_ASSERT(rows[i].OK());
43073      }
43074
43075      sorted = true;
43076    }
43077  }
43078  // NOTE: this already checks for OK().
43079  set_index_first_pending_row(index_first_pending + n);
43080}
43081
43082template <typename Row>
43083void
43084Linear_System<Row>::sort_pending_and_remove_duplicates() {
43085  PPL_ASSERT(num_pending_rows() > 0);
43086  PPL_ASSERT(is_sorted());
43087
43088  // The non-pending part of the system is already sorted.
43089  // Now sorting the pending part..
43090  const dimension_type first_pending = first_pending_row();
43091  sort_rows(first_pending, num_rows());
43092  // Recompute the number of rows, because we may have removed
43093  // some rows occurring more than once in the pending part.
43094  const dimension_type old_num_rows = num_rows();
43095  dimension_type num_rows = old_num_rows;
43096
43097  dimension_type k1 = 0;
43098  dimension_type k2 = first_pending;
43099  dimension_type num_duplicates = 0;
43100  // In order to erase them, put at the end of the system
43101  // those pending rows that also occur in the non-pending part.
43102  while (k1 < first_pending && k2 < num_rows) {
43103    const int cmp = compare(rows[k1], rows[k2]);
43104    if (cmp == 0) {
43105      // We found the same row.
43106      ++num_duplicates;
43107      --num_rows;
43108      // By initial sortedness, we can increment index `k1'.
43109      ++k1;
43110      // Do not increment `k2'; instead, swap there the next pending row.
43111      if (k2 < num_rows) {
43112        swap(rows[k2], rows[k2 + num_duplicates]);
43113      }
43114    }
43115    else if (cmp < 0) {
43116      // By initial sortedness, we can increment `k1'.
43117      ++k1;
43118    }
43119    else {
43120      // Here `cmp > 0'.
43121      // Increment `k2' and, if we already found any duplicate,
43122      // swap the next pending row in position `k2'.
43123      ++k2;
43124      if (num_duplicates > 0 && k2 < num_rows) {
43125        swap(rows[k2], rows[k2 + num_duplicates]);
43126      }
43127    }
43128  }
43129  // If needed, swap any duplicates found past the pending rows
43130  // that has not been considered yet; then erase the duplicates.
43131  if (num_duplicates > 0) {
43132    if (k2 < num_rows) {
43133      for (++k2; k2 < num_rows; ++k2)  {
43134        swap(rows[k2], rows[k2 + num_duplicates]);
43135      }
43136    }
43137    rows.resize(num_rows);
43138  }
43139  sorted = true;
43140  PPL_ASSERT(OK());
43141}
43142
43143template <typename Row>
43144bool
43145Linear_System<Row>::check_sorted() const {
43146  for (dimension_type i = first_pending_row(); i-- > 1; ) {
43147    if (compare(rows[i], rows[i-1]) < 0) {
43148      return false;
43149    }
43150  }
43151  return true;
43152}
43153
43154template <typename Row>
43155bool
43156Linear_System<Row>::OK() const {
43157#ifndef NDEBUG
43158  using std::endl;
43159  using std::cerr;
43160#endif
43161
43162  for (dimension_type i = rows.size(); i-- > 0; ) {
43163    if (rows[i].representation() != representation()) {
43164#ifndef NDEBUG
43165      cerr << "Linear_System has a row with the wrong representation!"
43166           << endl;
43167#endif
43168      return false;
43169    }
43170    if (rows[i].space_dimension() != space_dimension()) {
43171#ifndef NDEBUG
43172      cerr << "Linear_System has a row with the wrong number of space dimensions!"
43173           << endl;
43174#endif
43175      return false;
43176    }
43177  }
43178
43179  for (dimension_type i = rows.size(); i-- > 0; ) {
43180    if (rows[i].topology() != topology()) {
43181#ifndef NDEBUG
43182      cerr << "Linear_System has a row with the wrong topology!"
43183           << endl;
43184#endif
43185      return false;
43186    }
43187
43188  }
43189  // `index_first_pending' must be less than or equal to `num_rows()'.
43190  if (first_pending_row() > num_rows()) {
43191#ifndef NDEBUG
43192    cerr << "Linear_System has a negative number of pending rows!"
43193         << endl;
43194#endif
43195    return false;
43196  }
43197
43198  // Check for topology mismatches.
43199  const dimension_type n_rows = num_rows();
43200  for (dimension_type i = 0; i < n_rows; ++i) {
43201    if (topology() != rows[i].topology()) {
43202#ifndef NDEBUG
43203      cerr << "Topology mismatch between the system "
43204           << "and one of its rows!"
43205           << endl;
43206#endif
43207      return false;
43208    }
43209
43210  }
43211  if (sorted && !check_sorted()) {
43212#ifndef NDEBUG
43213    cerr << "The system declares itself to be sorted but it is not!"
43214         << endl;
43215#endif
43216    return false;
43217  }
43218
43219  // All checks passed.
43220  return true;
43221}
43222
43223} // namespace Parma_Polyhedra_Library
43224
43225/* Automatically generated from PPL source file ../src/Linear_System_defs.hh line 581. */
43226
43227/* Automatically generated from PPL source file ../src/Constraint_System_defs.hh line 31. */
43228
43229/* Automatically generated from PPL source file ../src/Constraint_System_defs.hh line 38. */
43230#include <iterator>
43231#include <iosfwd>
43232#include <cstddef>
43233
43234namespace Parma_Polyhedra_Library {
43235
43236namespace IO_Operators {
43237
43238//! Output operator.
43239/*!
43240  \relates Parma_Polyhedra_Library::Constraint_System
43241  Writes <CODE>true</CODE> if \p cs is empty.  Otherwise, writes on
43242  \p s the constraints of \p cs, all in one row and separated by ", ".
43243*/
43244std::ostream& operator<<(std::ostream& s, const Constraint_System& cs);
43245
43246} // namespace IO_Operators
43247
43248// TODO: Consider removing this.
43249#ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
43250//! Returns <CODE>true</CODE> if and only if \p x and \p y are identical.
43251/*! \relates Constraint_System */
43252#endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
43253bool operator==(const Constraint_System& x, const Constraint_System& y);
43254
43255// TODO: Consider removing this.
43256#ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
43257//! Returns <CODE>true</CODE> if and only if \p x and \p y are different.
43258/*! \relates Constraint_System */
43259#endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
43260bool operator!=(const Constraint_System& x, const Constraint_System& y);
43261
43262/*! \relates Constraint_System */
43263void
43264swap(Constraint_System& x, Constraint_System& y);
43265
43266} // namespace Parma_Polyhedra_Library
43267
43268//! A system of constraints.
43269/*! \ingroup PPL_CXX_interface
43270    An object of the class Constraint_System is a system of constraints,
43271    i.e., a multiset of objects of the class Constraint.
43272    When inserting constraints in a system, space dimensions are
43273    automatically adjusted so that all the constraints in the system
43274    are defined on the same vector space.
43275
43276    \par
43277    In all the examples it is assumed that variables
43278    <CODE>x</CODE> and <CODE>y</CODE> are defined as follows:
43279    \code
43280  Variable x(0);
43281  Variable y(1);
43282    \endcode
43283
43284    \par Example 1
43285    The following code builds a system of constraints corresponding to
43286    a square in \f$\Rset^2\f$:
43287    \code
43288  Constraint_System cs;
43289  cs.insert(x >= 0);
43290  cs.insert(x <= 3);
43291  cs.insert(y >= 0);
43292  cs.insert(y <= 3);
43293    \endcode
43294    Note that:
43295    the constraint system is created with space dimension zero;
43296    the first and third constraint insertions increase the space
43297    dimension to \f$1\f$ and \f$2\f$, respectively.
43298
43299    \par Example 2
43300    By adding four strict inequalities to the constraint system
43301    of the previous example, we can remove just the four
43302    vertices from the square defined above.
43303    \code
43304  cs.insert(x + y > 0);
43305  cs.insert(x + y < 6);
43306  cs.insert(x - y < 3);
43307  cs.insert(y - x < 3);
43308    \endcode
43309
43310    \par Example 3
43311    The following code builds a system of constraints corresponding to
43312    a half-strip in \f$\Rset^2\f$:
43313    \code
43314  Constraint_System cs;
43315  cs.insert(x >= 0);
43316  cs.insert(x - y <= 0);
43317  cs.insert(x - y + 1 >= 0);
43318    \endcode
43319
43320    \note
43321    After inserting a multiset of constraints in a constraint system,
43322    there are no guarantees that an <EM>exact</EM> copy of them
43323    can be retrieved:
43324    in general, only an <EM>equivalent</EM> constraint system
43325    will be available, where original constraints may have been
43326    reordered, removed (if they are trivial, duplicate or
43327    implied by other constraints), linearly combined, etc.
43328*/
43329class Parma_Polyhedra_Library::Constraint_System {
43330public:
43331  typedef Constraint row_type;
43332
43333  static const Representation default_representation = SPARSE;
43334
43335  //! Default constructor: builds an empty system of constraints.
43336  explicit Constraint_System(Representation r = default_representation);
43337
43338  //! Builds the singleton system containing only constraint \p c.
43339  explicit Constraint_System(const Constraint& c,
43340                             Representation r = default_representation);
43341
43342  //! Builds a system containing copies of any equalities in \p cgs.
43343  explicit Constraint_System(const Congruence_System& cgs,
43344                             Representation r = default_representation);
43345
43346  //! Ordinary copy constructor.
43347  /*!
43348    \note The copy will have the same representation as `cs', to make it
43349          indistinguishable from `cs'.
43350  */
43351  Constraint_System(const Constraint_System& cs);
43352
43353  //! Copy constructor with specified representation.
43354  Constraint_System(const Constraint_System& cs, Representation r);
43355
43356  //! Destructor.
43357  ~Constraint_System();
43358
43359  //! Assignment operator.
43360  Constraint_System& operator=(const Constraint_System& y);
43361
43362  //! Returns the current representation of *this.
43363  Representation representation() const;
43364
43365  //! Converts *this to the specified representation.
43366  void set_representation(Representation r);
43367
43368  //! Returns the maximum space dimension a Constraint_System can handle.
43369  static dimension_type max_space_dimension();
43370
43371  //! Returns the dimension of the vector space enclosing \p *this.
43372  dimension_type space_dimension() const;
43373
43374  //! Sets the space dimension of the rows in the system to \p space_dim .
43375  void set_space_dimension(dimension_type space_dim);
43376
43377  /*! \brief
43378    Returns <CODE>true</CODE> if and only if \p *this
43379    contains one or more equality constraints.
43380  */
43381  bool has_equalities() const;
43382
43383  /*! \brief
43384    Returns <CODE>true</CODE> if and only if \p *this
43385    contains one or more strict inequality constraints.
43386  */
43387  bool has_strict_inequalities() const;
43388
43389  /*! \brief
43390    Inserts in \p *this a copy of the constraint \p c,
43391    increasing the number of space dimensions if needed.
43392  */
43393  void insert(const Constraint& c);
43394
43395  //! Initializes the class.
43396  static void initialize();
43397
43398  //! Finalizes the class.
43399  static void finalize();
43400
43401  /*! \brief
43402    Returns the singleton system containing only Constraint::zero_dim_false().
43403  */
43404  static const Constraint_System& zero_dim_empty();
43405
43406  typedef Constraint_System_const_iterator const_iterator;
43407
43408  //! Returns <CODE>true</CODE> if and only if \p *this has no constraints.
43409  bool empty() const;
43410
43411  /*! \brief
43412    Removes all the constraints from the constraint system
43413    and sets its space dimension to 0.
43414  */
43415  void clear();
43416
43417  /*! \brief
43418    Returns the const_iterator pointing to the first constraint,
43419    if \p *this is not empty;
43420    otherwise, returns the past-the-end const_iterator.
43421  */
43422  const_iterator begin() const;
43423
43424  //! Returns the past-the-end const_iterator.
43425  const_iterator end() const;
43426
43427  //! Checks if all the invariants are satisfied.
43428  bool OK() const;
43429
43430  PPL_OUTPUT_DECLARATIONS
43431
43432  /*! \brief
43433    Loads from \p s an ASCII representation (as produced by
43434    ascii_dump(std::ostream&) const) and sets \p *this accordingly.
43435    Returns <CODE>true</CODE> if successful, <CODE>false</CODE> otherwise.
43436  */
43437  bool ascii_load(std::istream& s);
43438
43439  //! Returns the total size in bytes of the memory occupied by \p *this.
43440  memory_size_type total_memory_in_bytes() const;
43441
43442  //! Returns the size in bytes of the memory managed by \p *this.
43443  memory_size_type external_memory_in_bytes() const;
43444
43445  //! Swaps \p *this with \p y.
43446  void m_swap(Constraint_System& y);
43447
43448private:
43449  Linear_System<Constraint> sys;
43450
43451  /*! \brief
43452    Holds (between class initialization and finalization) a pointer to
43453    the singleton system containing only Constraint::zero_dim_false().
43454  */
43455  static const Constraint_System* zero_dim_empty_p;
43456
43457  friend class Constraint_System_const_iterator;
43458
43459  friend bool operator==(const Constraint_System& x,
43460                         const Constraint_System& y);
43461
43462  //! Builds an empty system of constraints having the specified topology.
43463  explicit Constraint_System(Topology topol,
43464                             Representation r = default_representation);
43465
43466  /*! \brief
43467    Builds a system of constraints on a \p space_dim dimensional space. If
43468    \p topol is <CODE>NOT_NECESSARILY_CLOSED</CODE> the \f$\epsilon\f$
43469    dimension is added.
43470  */
43471  Constraint_System(Topology topol, dimension_type space_dim,
43472                    Representation r = default_representation);
43473
43474  //! Returns the number of equality constraints.
43475  dimension_type num_equalities() const;
43476
43477  //! Returns the number of inequality constraints.
43478  dimension_type num_inequalities() const;
43479
43480  /*! \brief
43481    Applies Gaussian elimination and back-substitution so as
43482    to provide a partial simplification of the system of constraints.
43483
43484    It is assumed that the system has no pending constraints.
43485  */
43486  void simplify();
43487
43488  /*! \brief
43489    Adjusts \p *this so that it matches \p new_topology and
43490    \p new_space_dim (adding or removing columns if needed).
43491    Returns <CODE>false</CODE> if and only if \p topol is
43492    equal to <CODE>NECESSARILY_CLOSED</CODE> and \p *this
43493    contains strict inequalities.
43494  */
43495  bool adjust_topology_and_space_dimension(Topology new_topology,
43496                                           dimension_type new_space_dim);
43497
43498  //! Returns a constant reference to the \p k- th constraint of the system.
43499  const Constraint& operator[](dimension_type k) const;
43500
43501  //! Returns <CODE>true</CODE> if \p g satisfies all the constraints.
43502  bool satisfies_all_constraints(const Generator& g) const;
43503
43504  //! Substitutes a given column of coefficients by a given affine expression.
43505  /*!
43506    \param v
43507    The variable to which the affine transformation is substituted.
43508
43509    \param expr
43510    The numerator of the affine transformation:
43511    \f$\sum_{i = 0}^{n - 1} a_i x_i + b\f$;
43512
43513    \param denominator
43514    The denominator of the affine transformation.
43515
43516    We want to allow affine transformations
43517    (see Section \ref Images_and_Preimages_of_Affine_Transfer_Relations)
43518    having any rational coefficients. Since the coefficients of the
43519    constraints are integers we must also provide an integer \p
43520    denominator that will be used as denominator of the affine
43521    transformation.
43522    The denominator is required to be a positive integer.
43523
43524    The affine transformation substitutes the matrix of constraints
43525    by a new matrix whose elements \f${a'}_{ij}\f$ are built from
43526    the old one \f$a_{ij}\f$ as follows:
43527    \f[
43528      {a'}_{ij} =
43529        \begin{cases}
43530          a_{ij} * \mathrm{denominator} + a_{iv} * \mathrm{expr}[j]
43531            \quad \text{for } j \neq v; \\
43532          \mathrm{expr}[v] * a_{iv}
43533            \quad \text{for } j = v.
43534        \end{cases}
43535    \f]
43536
43537    \p expr is a constant parameter and unaltered by this computation.
43538  */
43539  void affine_preimage(Variable v,
43540                       const Linear_Expression& expr,
43541                       Coefficient_traits::const_reference denominator);
43542
43543  /*! \brief
43544    Inserts in \p *this a copy of the constraint \p c,
43545    increasing the number of space dimensions if needed.
43546    It is a pending constraint.
43547  */
43548  void insert_pending(const Constraint& c);
43549
43550  //! Adds low-level constraints to the constraint system.
43551  void add_low_level_constraints();
43552
43553  //! Returns the system topology.
43554  Topology topology() const;
43555
43556  dimension_type num_rows() const;
43557
43558  /*! \brief
43559    Returns <CODE>true</CODE> if and only if
43560    the system topology is <CODE>NECESSARILY_CLOSED</CODE>.
43561  */
43562  bool is_necessarily_closed() const;
43563
43564  //! Returns the number of rows that are in the pending part of the system.
43565  dimension_type num_pending_rows() const;
43566
43567  //! Returns the index of the first pending row.
43568  dimension_type first_pending_row() const;
43569
43570  //! Returns the value of the sortedness flag.
43571  bool is_sorted() const;
43572
43573  //! Sets the index to indicate that the system has no pending rows.
43574  void unset_pending_rows();
43575
43576  //! Sets the index of the first pending row to \p i.
43577  void set_index_first_pending_row(dimension_type i);
43578
43579  //! Sets the sortedness flag of the system to \p b.
43580  void set_sorted(bool b);
43581
43582  //! Makes the system shrink by removing its i-th row.
43583  /*!
43584    When \p keep_sorted is \p true and the system is sorted, sortedness will
43585    be preserved, but this method costs O(n).
43586
43587    Otherwise, this method just swaps the i-th row with the last and then
43588    removes it, so it costs O(1).
43589  */
43590  void remove_row(dimension_type i, bool keep_sorted = false);
43591
43592  //! Removes the specified rows. The row ordering of remaining rows is
43593  //! preserved.
43594  /*!
43595    \param indexes specifies a list of row indexes.
43596                   It must be sorted.
43597  */
43598  void remove_rows(const std::vector<dimension_type>& indexes);
43599
43600  //! Makes the system shrink by removing the rows in [first,last).
43601  /*!
43602    When \p keep_sorted is \p true and the system is sorted, sortedness will
43603    be preserved, but this method costs O(num_rows()).
43604
43605    Otherwise, this method just swaps the rows with the last ones and then
43606    removes them, so it costs O(last - first).
43607  */
43608  void remove_rows(dimension_type first, dimension_type last,
43609                   bool keep_sorted = false);
43610
43611  //! Makes the system shrink by removing its \p n trailing rows.
43612  void remove_trailing_rows(dimension_type n);
43613
43614  //! Removes all the specified dimensions from the constraint system.
43615  /*!
43616    The space dimension of the variable with the highest space
43617    dimension in \p vars must be at most the space dimension
43618    of \p this.
43619  */
43620  void remove_space_dimensions(const Variables_Set& vars);
43621
43622  //! Shift by \p n positions the coefficients of variables, starting from
43623  //! the coefficient of \p v. This increases the space dimension by \p n.
43624  void shift_space_dimensions(Variable v, dimension_type n);
43625
43626  //! Permutes the space dimensions of the matrix.
43627  /*
43628    \param cycle
43629    A vector representing a cycle of the permutation according to which the
43630    columns must be rearranged.
43631
43632    The \p cycle vector represents a cycle of a permutation of space
43633    dimensions.
43634    For example, the permutation
43635    \f$ \{ x_1 \mapsto x_2, x_2 \mapsto x_3, x_3 \mapsto x_1 \}\f$ can be
43636    represented by the vector containing \f$ x_1, x_2, x_3 \f$.
43637  */
43638  void permute_space_dimensions(const std::vector<Variable>& cycle);
43639
43640  //! Swaps the coefficients of the variables \p v1 and \p v2 .
43641  void swap_space_dimensions(Variable v1, Variable v2);
43642
43643  bool has_no_rows() const;
43644
43645  //! Strongly normalizes the system.
43646  void strong_normalize();
43647
43648  /*! \brief
43649    Sorts the non-pending rows (in growing order) and eliminates
43650    duplicated ones.
43651  */
43652  void sort_rows();
43653
43654  /*! \brief
43655    Adds the given row to the pending part of the system, stealing its
43656    contents and automatically resizing the system or the row, if needed.
43657  */
43658  void insert_pending(Constraint& r, Recycle_Input);
43659
43660  //! Adds the rows of `y' to the pending part of `*this', stealing them from
43661  //! `y'.
43662  void insert_pending(Constraint_System& r, Recycle_Input);
43663
43664  /*! \brief
43665    Adds \p r to the system, stealing its contents and
43666    automatically resizing the system or the row, if needed.
43667  */
43668  void insert(Constraint& r, Recycle_Input);
43669
43670  //! Adds to \p *this a the rows of `y', stealing them from `y'.
43671  /*!
43672    It is assumed that \p *this has no pending rows.
43673  */
43674  void insert(Constraint_System& r, Recycle_Input);
43675
43676  //! Adds a copy of the rows of `y' to the pending part of `*this'.
43677  void insert_pending(const Constraint_System& r);
43678
43679  /*! \brief
43680    Assigns to \p *this the result of merging its rows with
43681    those of \p y, obtaining a sorted system.
43682
43683    Duplicated rows will occur only once in the result.
43684    On entry, both systems are assumed to be sorted and have
43685    no pending rows.
43686  */
43687  void merge_rows_assign(const Constraint_System& y);
43688
43689  //! Adds to \p *this a copy of  the rows of \p y.
43690  /*!
43691    It is assumed that \p *this has no pending rows.
43692  */
43693  void insert(const Constraint_System& y);
43694
43695  //! Marks the epsilon dimension as a standard dimension.
43696  /*!
43697    The system topology is changed to <CODE>NOT_NECESSARILY_CLOSED</CODE>, and
43698    the number of space dimensions is increased by 1.
43699  */
43700  void mark_as_necessarily_closed();
43701
43702  //! Marks the last dimension as the epsilon dimension.
43703  /*!
43704    The system topology is changed to <CODE>NECESSARILY_CLOSED</CODE>, and
43705    the number of space dimensions is decreased by 1.
43706  */
43707  void mark_as_not_necessarily_closed();
43708
43709  //! Minimizes the subsystem of equations contained in \p *this.
43710  /*!
43711    This method works only on the equalities of the system:
43712    the system is required to be partially sorted, so that
43713    all the equalities are grouped at its top; it is assumed that
43714    the number of equalities is exactly \p n_lines_or_equalities.
43715    The method finds a minimal system for the equalities and
43716    returns its rank, i.e., the number of linearly independent equalities.
43717    The result is an upper triangular subsystem of equalities:
43718    for each equality, the pivot is chosen starting from
43719    the right-most columns.
43720  */
43721  dimension_type gauss(dimension_type n_lines_or_equalities);
43722
43723  /*! \brief
43724    Back-substitutes the coefficients to reduce
43725    the complexity of the system.
43726
43727    Takes an upper triangular system having \p n_lines_or_equalities rows.
43728    For each row, starting from the one having the minimum number of
43729    coefficients different from zero, computes the expression of an element
43730    as a function of the remaining ones and then substitutes this expression
43731    in all the other rows.
43732  */
43733  void back_substitute(dimension_type n_lines_or_equalities);
43734
43735  //! Full assignment operator: pending rows are copied as pending.
43736  void assign_with_pending(const Constraint_System& y);
43737
43738  /*! \brief
43739    Sorts the pending rows and eliminates those that also occur
43740    in the non-pending part of the system.
43741  */
43742  void sort_pending_and_remove_duplicates();
43743
43744  /*! \brief
43745    Sorts the system, removing duplicates, keeping the saturation
43746    matrix consistent.
43747
43748    \param sat
43749    Bit matrix with rows corresponding to the rows of \p *this.
43750  */
43751  void sort_and_remove_with_sat(Bit_Matrix& sat);
43752
43753  /*! \brief
43754    Returns <CODE>true</CODE> if and only if \p *this is sorted,
43755    without checking for duplicates.
43756  */
43757  bool check_sorted() const;
43758
43759  /*! \brief
43760    Returns the number of rows in the system
43761    that represent either lines or equalities.
43762  */
43763  dimension_type num_lines_or_equalities() const;
43764
43765  //! Adds \p n rows and space dimensions to the system.
43766  /*!
43767    \param n
43768    The number of rows and space dimensions to be added: must be strictly
43769    positive.
43770
43771    Turns the system \f$M \in \Rset^r \times \Rset^c\f$ into
43772    the system \f$N \in \Rset^{r+n} \times \Rset^{c+n}\f$
43773    such that
43774    \f$N = \bigl(\genfrac{}{}{0pt}{}{0}{M}\genfrac{}{}{0pt}{}{J}{o}\bigr)\f$,
43775    where \f$J\f$ is the specular image
43776    of the \f$n \times n\f$ identity matrix.
43777  */
43778  void add_universe_rows_and_space_dimensions(dimension_type n);
43779
43780  friend class Polyhedron;
43781  friend class Termination_Helpers;
43782};
43783
43784//! An iterator over a system of constraints.
43785/*! \ingroup PPL_CXX_interface
43786  A const_iterator is used to provide read-only access
43787  to each constraint contained in a Constraint_System object.
43788
43789  \par Example
43790  The following code prints the system of constraints
43791  defining the polyhedron <CODE>ph</CODE>:
43792  \code
43793const Constraint_System& cs = ph.constraints();
43794for (Constraint_System::const_iterator i = cs.begin(),
43795        cs_end = cs.end(); i != cs_end; ++i)
43796  cout << *i << endl;
43797  \endcode
43798*/
43799// NOTE: This is not an inner class of Constraint_System, so Constraint can
43800// declare that this class is his friend without including this file
43801// (the .types.hh file suffices).
43802class Parma_Polyhedra_Library::Constraint_System_const_iterator
43803  : public std::iterator<std::forward_iterator_tag,
43804                         Constraint,
43805                         std::ptrdiff_t,
43806                         const Constraint*,
43807                         const Constraint&> {
43808public:
43809  //! Default constructor.
43810  Constraint_System_const_iterator();
43811
43812  //! Ordinary copy constructor.
43813  Constraint_System_const_iterator(const Constraint_System_const_iterator& y);
43814
43815  //! Destructor.
43816  ~Constraint_System_const_iterator();
43817
43818  //! Assignment operator.
43819  Constraint_System_const_iterator&
43820  operator=(const Constraint_System_const_iterator& y);
43821
43822  //! Dereference operator.
43823  const Constraint& operator*() const;
43824
43825  //! Indirect member selector.
43826  const Constraint* operator->() const;
43827
43828  //! Prefix increment operator.
43829  Constraint_System_const_iterator& operator++();
43830
43831  //! Postfix increment operator.
43832  Constraint_System_const_iterator operator++(int);
43833
43834  /*! \brief
43835    Returns <CODE>true</CODE> if and only if
43836    \p *this and \p y are identical.
43837  */
43838  bool operator==(const Constraint_System_const_iterator& y) const;
43839
43840  /*! \brief
43841    Returns <CODE>true</CODE> if and only if
43842    \p *this and \p y are different.
43843  */
43844  bool operator!=(const Constraint_System_const_iterator& y) const;
43845
43846private:
43847  friend class Constraint_System;
43848
43849  //! The const iterator over the matrix of constraints.
43850  Linear_System<Constraint>::const_iterator i;
43851
43852  //! A const pointer to the matrix of constraints.
43853  const Linear_System<Constraint>* csp;
43854
43855  //! Constructor.
43856  Constraint_System_const_iterator(const Linear_System<Constraint>
43857                                   ::const_iterator& iter,
43858                                   const Constraint_System& cs);
43859
43860  //! \p *this skips to the next non-trivial constraint.
43861  void skip_forward();
43862};
43863
43864namespace Parma_Polyhedra_Library {
43865
43866namespace Implementation {
43867
43868#ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
43869//! Helper returning number of constraints in system.
43870#endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
43871dimension_type
43872num_constraints(const Constraint_System& cs);
43873
43874} // namespace Implementation
43875
43876} // namespace Parma_Polyhedra_Library
43877
43878// Constraint_System_inlines.hh is not included here on purpose.
43879
43880/* Automatically generated from PPL source file ../src/Constraint_System_inlines.hh line 1. */
43881/* Constraint_System class implementation: inline functions.
43882*/
43883
43884
43885/* Automatically generated from PPL source file ../src/Constraint_System_inlines.hh line 28. */
43886
43887namespace Parma_Polyhedra_Library {
43888
43889inline
43890Constraint_System::Constraint_System(Representation r)
43891  : sys(NECESSARILY_CLOSED, r) {
43892}
43893
43894inline
43895Constraint_System::Constraint_System(const Constraint& c, Representation r)
43896  : sys(c.topology(), r) {
43897  sys.insert(c);
43898}
43899
43900inline
43901Constraint_System::Constraint_System(const Constraint_System& cs)
43902  : sys(cs.sys) {
43903}
43904
43905inline
43906Constraint_System::Constraint_System(const Constraint_System& cs,
43907                                     Representation r)
43908  : sys(cs.sys, r) {
43909}
43910
43911inline
43912Constraint_System::Constraint_System(const Topology topol, Representation r)
43913  : sys(topol, r) {
43914}
43915
43916inline
43917Constraint_System::Constraint_System(const Topology topol,
43918                                     const dimension_type space_dim,
43919                                     Representation r)
43920  : sys(topol, space_dim, r) {
43921}
43922
43923inline
43924Constraint_System::~Constraint_System() {
43925}
43926
43927inline Constraint_System&
43928Constraint_System::operator=(const Constraint_System& y) {
43929  Constraint_System tmp = y;
43930  swap(*this, tmp);
43931  return *this;
43932}
43933
43934inline const Constraint&
43935Constraint_System::operator[](const dimension_type k) const {
43936  return sys[k];
43937}
43938
43939inline Representation
43940Constraint_System::representation() const {
43941  return sys.representation();
43942}
43943
43944inline void
43945Constraint_System::set_representation(Representation r) {
43946  sys.set_representation(r);
43947}
43948
43949inline dimension_type
43950Constraint_System::max_space_dimension() {
43951  return Linear_System<Constraint>::max_space_dimension();
43952}
43953
43954inline dimension_type
43955Constraint_System::space_dimension() const {
43956  return sys.space_dimension();
43957}
43958
43959inline void
43960Constraint_System::set_space_dimension(dimension_type space_dim) {
43961  return sys.set_space_dimension(space_dim);
43962}
43963
43964inline void
43965Constraint_System::clear() {
43966  sys.clear();
43967}
43968
43969inline const Constraint_System&
43970Constraint_System::zero_dim_empty() {
43971  PPL_ASSERT(zero_dim_empty_p != 0);
43972  return *zero_dim_empty_p;
43973}
43974
43975inline
43976Constraint_System_const_iterator::Constraint_System_const_iterator()
43977  : i(), csp(0) {
43978}
43979
43980inline
43981Constraint_System_const_iterator::Constraint_System_const_iterator(const Constraint_System_const_iterator& y)
43982  : i(y.i), csp(y.csp) {
43983}
43984
43985inline
43986Constraint_System_const_iterator::~Constraint_System_const_iterator() {
43987}
43988
43989inline Constraint_System_const_iterator&
43990Constraint_System_const_iterator::operator=(const Constraint_System_const_iterator& y) {
43991  i = y.i;
43992  csp = y.csp;
43993  return *this;
43994}
43995
43996inline const Constraint&
43997Constraint_System_const_iterator::operator*() const {
43998  return *i;
43999}
44000
44001inline const Constraint*
44002Constraint_System_const_iterator::operator->() const {
44003  return i.operator->();
44004}
44005
44006inline Constraint_System_const_iterator&
44007Constraint_System_const_iterator::operator++() {
44008  ++i;
44009  skip_forward();
44010  return *this;
44011}
44012
44013inline Constraint_System_const_iterator
44014Constraint_System_const_iterator::operator++(int) {
44015  const Constraint_System_const_iterator tmp = *this;
44016  operator++();
44017  return tmp;
44018}
44019
44020inline bool
44021Constraint_System_const_iterator::operator==(const Constraint_System_const_iterator& y) const {
44022  return i == y.i;
44023}
44024
44025inline bool
44026Constraint_System_const_iterator::operator!=(const Constraint_System_const_iterator& y) const {
44027  return i != y.i;
44028}
44029
44030inline
44031Constraint_System_const_iterator::
44032Constraint_System_const_iterator(const Linear_System<Constraint>::const_iterator& iter,
44033               const Constraint_System& cs)
44034  : i(iter), csp(&cs.sys) {
44035}
44036
44037inline Constraint_System_const_iterator
44038Constraint_System::begin() const {
44039  const_iterator i(sys.begin(), *this);
44040  i.skip_forward();
44041  return i;
44042}
44043
44044inline Constraint_System_const_iterator
44045Constraint_System::end() const {
44046  const Constraint_System_const_iterator i(sys.end(), *this);
44047  return i;
44048}
44049
44050inline bool
44051Constraint_System::empty() const {
44052  return begin() == end();
44053}
44054
44055inline void
44056Constraint_System::add_low_level_constraints() {
44057  if (sys.is_necessarily_closed()) {
44058    // The positivity constraint.
44059    insert(Constraint::zero_dim_positivity());
44060  }
44061  else {
44062    // Add the epsilon constraints.
44063    insert(Constraint::epsilon_leq_one());
44064    insert(Constraint::epsilon_geq_zero());
44065  }
44066}
44067
44068inline void
44069Constraint_System::m_swap(Constraint_System& y) {
44070  swap(sys, y.sys);
44071}
44072
44073inline memory_size_type
44074Constraint_System::external_memory_in_bytes() const {
44075  return sys.external_memory_in_bytes();
44076}
44077
44078inline memory_size_type
44079Constraint_System::total_memory_in_bytes() const {
44080  return external_memory_in_bytes() + sizeof(*this);
44081}
44082
44083inline void
44084Constraint_System::simplify() {
44085  sys.simplify();
44086}
44087
44088inline Topology
44089Constraint_System::topology() const {
44090  return sys.topology();
44091}
44092
44093inline dimension_type
44094Constraint_System::num_rows() const {
44095  return sys.num_rows();
44096}
44097
44098inline bool
44099Constraint_System::is_necessarily_closed() const {
44100  return sys.is_necessarily_closed();
44101}
44102
44103inline dimension_type
44104Constraint_System::num_pending_rows() const {
44105  return sys.num_pending_rows();
44106}
44107
44108inline dimension_type
44109Constraint_System::first_pending_row() const {
44110  return sys.first_pending_row();
44111}
44112
44113inline bool
44114Constraint_System::is_sorted() const {
44115  return sys.is_sorted();
44116}
44117
44118inline void
44119Constraint_System::unset_pending_rows() {
44120  sys.unset_pending_rows();
44121}
44122
44123inline void
44124Constraint_System::set_index_first_pending_row(dimension_type i) {
44125  sys.set_index_first_pending_row(i);
44126}
44127
44128inline void
44129Constraint_System::set_sorted(bool b) {
44130  sys.set_sorted(b);
44131}
44132
44133inline void
44134Constraint_System::remove_row(dimension_type i, bool keep_sorted) {
44135  sys.remove_row(i, keep_sorted);
44136}
44137
44138inline void
44139Constraint_System::remove_rows(dimension_type first, dimension_type last,
44140                               bool keep_sorted) {
44141  sys.remove_rows(first, last, keep_sorted);
44142}
44143
44144inline void
44145Constraint_System::remove_rows(const std::vector<dimension_type>& indexes) {
44146  sys.remove_rows(indexes);
44147}
44148
44149inline void
44150Constraint_System::remove_trailing_rows(dimension_type n) {
44151  sys.remove_trailing_rows(n);
44152}
44153
44154inline void
44155Constraint_System
44156::remove_space_dimensions(const Variables_Set& vars) {
44157  sys.remove_space_dimensions(vars);
44158}
44159
44160inline void
44161Constraint_System
44162::shift_space_dimensions(Variable v, dimension_type n) {
44163  sys.shift_space_dimensions(v, n);
44164}
44165
44166inline void
44167Constraint_System
44168::permute_space_dimensions(const std::vector<Variable>& cycle) {
44169  sys.permute_space_dimensions(cycle);
44170}
44171
44172inline void
44173Constraint_System
44174::swap_space_dimensions(Variable v1, Variable v2) {
44175  sys.swap_space_dimensions(v1, v2);
44176}
44177
44178inline bool
44179Constraint_System::has_no_rows() const {
44180  return sys.has_no_rows();
44181}
44182
44183inline void
44184Constraint_System::strong_normalize() {
44185  sys.strong_normalize();
44186}
44187
44188inline void
44189Constraint_System::sort_rows() {
44190  sys.sort_rows();
44191}
44192
44193inline void
44194Constraint_System::insert_pending(Constraint_System& r, Recycle_Input) {
44195  sys.insert_pending(r.sys, Recycle_Input());
44196}
44197
44198inline void
44199Constraint_System::insert(Constraint_System& r, Recycle_Input) {
44200  sys.insert(r.sys, Recycle_Input());
44201}
44202
44203inline void
44204Constraint_System::insert_pending(const Constraint_System& r) {
44205  sys.insert_pending(r.sys);
44206}
44207
44208inline void
44209Constraint_System::merge_rows_assign(const Constraint_System& y) {
44210  sys.merge_rows_assign(y.sys);
44211}
44212
44213inline void
44214Constraint_System::insert(const Constraint_System& y) {
44215  sys.insert(y.sys);
44216}
44217
44218inline void
44219Constraint_System::mark_as_necessarily_closed() {
44220  sys.mark_as_necessarily_closed();
44221}
44222
44223inline void
44224Constraint_System::mark_as_not_necessarily_closed() {
44225  sys.mark_as_not_necessarily_closed();
44226}
44227
44228inline dimension_type
44229Constraint_System::gauss(dimension_type n_lines_or_equalities) {
44230  return sys.gauss(n_lines_or_equalities);
44231}
44232
44233inline void
44234Constraint_System::back_substitute(dimension_type n_lines_or_equalities) {
44235  sys.back_substitute(n_lines_or_equalities);
44236}
44237
44238inline void
44239Constraint_System::assign_with_pending(const Constraint_System& y) {
44240  sys.assign_with_pending(y.sys);
44241}
44242
44243inline void
44244Constraint_System::sort_pending_and_remove_duplicates() {
44245  sys.sort_pending_and_remove_duplicates();
44246}
44247
44248inline void
44249Constraint_System::sort_and_remove_with_sat(Bit_Matrix& sat) {
44250  sys.sort_and_remove_with_sat(sat);
44251}
44252
44253inline bool
44254Constraint_System::check_sorted() const {
44255  return sys.check_sorted();
44256}
44257
44258inline dimension_type
44259Constraint_System::num_lines_or_equalities() const {
44260  return sys.num_lines_or_equalities();
44261}
44262
44263inline void
44264Constraint_System::add_universe_rows_and_space_dimensions(dimension_type n) {
44265  sys.add_universe_rows_and_space_dimensions(n);
44266}
44267
44268inline bool
44269operator==(const Constraint_System& x, const Constraint_System& y) {
44270  return x.sys == y.sys;
44271}
44272
44273inline bool
44274operator!=(const Constraint_System& x, const Constraint_System& y) {
44275  return !(x == y);
44276}
44277
44278/*! \relates Constraint_System */
44279inline void
44280swap(Constraint_System& x, Constraint_System& y) {
44281  x.m_swap(y);
44282}
44283
44284namespace Implementation {
44285
44286#ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
44287/*! \relates Parma_Polyhedra_Library::Constraint_System */
44288#endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
44289inline dimension_type
44290num_constraints(const Constraint_System& cs) {
44291  return static_cast<dimension_type>(std::distance(cs.begin(), cs.end()));
44292}
44293
44294} // namespace Implementation
44295
44296} // namespace Parma_Polyhedra_Library
44297
44298/* Automatically generated from PPL source file ../src/Congruence_System_defs.hh line 1. */
44299/* Congruence_System class declaration.
44300*/
44301
44302
44303/* Automatically generated from PPL source file ../src/Congruence_System_defs.hh line 35. */
44304#include <iosfwd>
44305#include <cstddef>
44306
44307namespace Parma_Polyhedra_Library {
44308
44309/*! \relates Congruence_System */
44310bool
44311operator==(const Congruence_System& x, const Congruence_System& y);
44312
44313}
44314
44315//! A system of congruences.
44316/*! \ingroup PPL_CXX_interface
44317    An object of the class Congruence_System is a system of congruences,
44318    i.e., a multiset of objects of the class Congruence.
44319    When inserting congruences in a system, space dimensions are
44320    automatically adjusted so that all the congruences in the system
44321    are defined on the same vector space.
44322
44323    \par
44324    In all the examples it is assumed that variables
44325    <CODE>x</CODE> and <CODE>y</CODE> are defined as follows:
44326    \code
44327  Variable x(0);
44328  Variable y(1);
44329    \endcode
44330
44331    \par Example 1
44332    The following code builds a system of congruences corresponding to
44333    an integer grid in \f$\Rset^2\f$:
44334    \code
44335  Congruence_System cgs;
44336  cgs.insert(x %= 0);
44337  cgs.insert(y %= 0);
44338    \endcode
44339    Note that:
44340    the congruence system is created with space dimension zero;
44341    the first and second congruence insertions increase the space
44342    dimension to \f$1\f$ and \f$2\f$, respectively.
44343
44344    \par Example 2
44345    By adding to the congruence system of the previous example,
44346    the congruence \f$x + y = 1 \pmod{2}\f$:
44347    \code
44348  cgs.insert((x + y %= 1) / 2);
44349    \endcode
44350    we obtain the grid containing just those integral
44351    points where the sum of the \p x and \p y values is odd.
44352
44353    \par Example 3
44354    The following code builds a system of congruences corresponding to
44355    the grid in \f$\Zset^2\f$ containing just the integral points on
44356    the \p x axis:
44357    \code
44358  Congruence_System cgs;
44359  cgs.insert(x %= 0);
44360  cgs.insert((y %= 0) / 0);
44361    \endcode
44362
44363    \note
44364    After inserting a multiset of congruences in a congruence system,
44365    there are no guarantees that an <EM>exact</EM> copy of them
44366    can be retrieved:
44367    in general, only an <EM>equivalent</EM> congruence system
44368    will be available, where original congruences may have been
44369    reordered, removed (if they are trivial, duplicate or
44370    implied by other congruences), linearly combined, etc.
44371*/
44372class Parma_Polyhedra_Library::Congruence_System {
44373public:
44374
44375  typedef Congruence row_type;
44376
44377  static const Representation default_representation = SPARSE;
44378
44379  //! Default constructor: builds an empty system of congruences.
44380  explicit Congruence_System(Representation r = default_representation);
44381
44382  //! Builds an empty (i.e. zero rows) system of dimension \p d.
44383  explicit Congruence_System(dimension_type d,
44384                             Representation r = default_representation);
44385
44386  //! Builds the singleton system containing only congruence \p cg.
44387  explicit Congruence_System(const Congruence& cg,
44388                             Representation r = default_representation);
44389
44390  /*! \brief
44391    If \p c represents the constraint \f$ e_1 = e_2 \f$, builds the
44392    singleton system containing only constraint \f$ e_1 = e_2
44393    \pmod{0}\f$.
44394
44395    \exception std::invalid_argument
44396    Thrown if \p c is not an equality constraint.
44397  */
44398  explicit Congruence_System(const Constraint& c,
44399                             Representation r = default_representation);
44400
44401  //! Builds a system containing copies of any equalities in \p cs.
44402  explicit Congruence_System(const Constraint_System& cs,
44403                             Representation r = default_representation);
44404
44405  //! Ordinary copy constructor.
44406  /*!
44407    \note
44408    The new Congruence_System will have the same Representation as `cgs'
44409    so that it's indistinguishable from `cgs'.
44410  */
44411  Congruence_System(const Congruence_System& cgs);
44412
44413  //! Copy constructor with specified representation.
44414  Congruence_System(const Congruence_System& cgs, Representation r);
44415
44416  //! Destructor.
44417  ~Congruence_System();
44418
44419  //! Assignment operator.
44420  Congruence_System& operator=(const Congruence_System& y);
44421
44422  //! Returns the current representation of *this.
44423  Representation representation() const;
44424
44425  //! Converts *this to the specified representation.
44426  void set_representation(Representation r);
44427
44428  //! Returns the maximum space dimension a Congruence_System can handle.
44429  static dimension_type max_space_dimension();
44430
44431  //! Returns the dimension of the vector space enclosing \p *this.
44432  dimension_type space_dimension() const;
44433
44434  /*! \brief
44435    Returns <CODE>true</CODE> if and only if \p *this is exactly equal
44436    to \p y.
44437  */
44438  bool is_equal_to(const Congruence_System& y) const;
44439
44440  /*! \brief
44441    Returns <CODE>true</CODE> if and only if \p *this contains one or
44442    more linear equalities.
44443  */
44444  bool has_linear_equalities() const;
44445
44446  //! Removes all the congruences and sets the space dimension to 0.
44447  void clear();
44448
44449  /*! \brief
44450    Inserts in \p *this a copy of the congruence \p cg, increasing the
44451    number of space dimensions if needed.
44452
44453    The copy of \p cg will be strongly normalized after being
44454    inserted.
44455  */
44456  void insert(const Congruence& cg);
44457
44458  /*! \brief
44459    Inserts in \p *this the congruence \p cg, stealing its contents and
44460    increasing the number of space dimensions if needed.
44461
44462    \p cg will be strongly normalized.
44463  */
44464  void insert(Congruence& cg, Recycle_Input);
44465
44466  /*! \brief
44467    Inserts in \p *this a copy of the equality constraint \p c, seen
44468    as a modulo 0 congruence, increasing the number of space
44469    dimensions if needed.
44470
44471    The modulo 0 congruence will be strongly normalized after being
44472    inserted.
44473
44474    \exception std::invalid_argument
44475    Thrown if \p c is a relational constraint.
44476  */
44477  void insert(const Constraint& c);
44478
44479  // TODO: Consider adding a insert(cg, Recycle_Input).
44480
44481  /*! \brief
44482    Inserts in \p *this a copy of the congruences in \p y,
44483    increasing the number of space dimensions if needed.
44484
44485    The inserted copies will be strongly normalized.
44486  */
44487  void insert(const Congruence_System& y);
44488
44489  /*! \brief
44490    Inserts into \p *this the congruences in \p cgs, increasing the
44491    number of space dimensions if needed.
44492  */
44493  void insert(Congruence_System& cgs, Recycle_Input);
44494
44495  //! Initializes the class.
44496  static void initialize();
44497
44498  //! Finalizes the class.
44499  static void finalize();
44500
44501  //! Returns the system containing only Congruence::zero_dim_false().
44502  static const Congruence_System& zero_dim_empty();
44503
44504  //! An iterator over a system of congruences.
44505  /*! \ingroup PPL_CXX_interface
44506    A const_iterator is used to provide read-only access
44507    to each congruence contained in an object of Congruence_System.
44508
44509    \par Example
44510    The following code prints the system of congruences
44511    defining the grid <CODE>gr</CODE>:
44512    \code
44513  const Congruence_System& cgs = gr.congruences();
44514  for (Congruence_System::const_iterator i = cgs.begin(),
44515         cgs_end = cgs.end(); i != cgs_end; ++i)
44516    cout << *i << endl;
44517    \endcode
44518  */
44519  class const_iterator
44520    : public std::iterator<std::forward_iterator_tag,
44521                           Congruence,
44522                           std::ptrdiff_t,
44523                           const Congruence*,
44524                           const Congruence&> {
44525  public:
44526    //! Default constructor.
44527    const_iterator();
44528
44529    //! Ordinary copy constructor.
44530    const_iterator(const const_iterator& y);
44531
44532    //! Destructor.
44533    ~const_iterator();
44534
44535    //! Assignment operator.
44536    const_iterator& operator=(const const_iterator& y);
44537
44538    //! Dereference operator.
44539    const Congruence& operator*() const;
44540
44541    //! Indirect member selector.
44542    const Congruence* operator->() const;
44543
44544    //! Prefix increment operator.
44545    const_iterator& operator++();
44546
44547    //! Postfix increment operator.
44548    const_iterator operator++(int);
44549
44550    /*! \brief
44551      Returns <CODE>true</CODE> if and only if \p *this and \p y are
44552      identical.
44553    */
44554    bool operator==(const const_iterator& y) const;
44555
44556    /*! \brief
44557      Returns <CODE>true</CODE> if and only if \p *this and \p y are
44558      different.
44559    */
44560    bool operator!=(const const_iterator& y) const;
44561
44562  private:
44563    friend class Congruence_System;
44564
44565    //! The const iterator over the vector of congruences.
44566    Swapping_Vector<Congruence>::const_iterator i;
44567
44568    //! A const pointer to the vector of congruences.
44569    const Swapping_Vector<Congruence>* csp;
44570
44571    //! Constructor.
44572    const_iterator(const Swapping_Vector<Congruence>::const_iterator& iter,
44573                   const Congruence_System& cgs);
44574
44575    //! \p *this skips to the next non-trivial congruence.
44576    void skip_forward();
44577  };
44578
44579  //! Returns <CODE>true</CODE> if and only if \p *this has no congruences.
44580  bool empty() const;
44581
44582  /*! \brief
44583    Returns the const_iterator pointing to the first congruence, if \p
44584    *this is not empty; otherwise, returns the past-the-end
44585    const_iterator.
44586  */
44587  const_iterator begin() const;
44588
44589  //! Returns the past-the-end const_iterator.
44590  const_iterator end() const;
44591
44592  //! Checks if all the invariants are satisfied.
44593#ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
44594  /*!
44595    Returns <CODE>true</CODE> if and only if all rows have space dimension
44596    space_dimension_, each row in the system is a valid Congruence and the
44597    space dimension is consistent with the number of congruences.
44598  */
44599#endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
44600  bool OK() const;
44601
44602  PPL_OUTPUT_DECLARATIONS
44603
44604  /*! \brief
44605    Loads from \p s an ASCII representation (as produced by
44606    ascii_dump(std::ostream&) const) and sets \p *this accordingly.
44607    Returns <CODE>true</CODE> if successful, <CODE>false</CODE> otherwise.
44608  */
44609  bool ascii_load(std::istream& s);
44610
44611  //! Returns the total size in bytes of the memory occupied by \p *this.
44612  memory_size_type total_memory_in_bytes() const;
44613
44614  //! Returns the size in bytes of the memory managed by \p *this.
44615  memory_size_type external_memory_in_bytes() const;
44616
44617  //! Returns the number of equalities.
44618  dimension_type num_equalities() const;
44619
44620  //! Returns the number of proper congruences.
44621  dimension_type num_proper_congruences() const;
44622
44623  //! Swaps \p *this with \p y.
44624  void m_swap(Congruence_System& y);
44625
44626  /*! \brief
44627    Adds \p dims rows and \p dims space dimensions to the matrix,
44628    initializing the added rows as in the unit congruence system.
44629
44630    \param dims
44631    The number of rows and space dimensions to be added: must be strictly
44632    positive.
44633
44634    Turns the \f$r \times c\f$ matrix \f$A\f$ into the \f$(r+dims) \times
44635    (c+dims)\f$ matrix
44636    \f$\bigl(\genfrac{}{}{0pt}{}{0}{A} \genfrac{}{}{0pt}{}{B}{A}\bigr)\f$
44637    where \f$B\f$ is the \f$dims \times dims\f$ unit matrix of the form
44638    \f$\bigl(\genfrac{}{}{0pt}{}{0}{1} \genfrac{}{}{0pt}{}{1}{0}\bigr)\f$.
44639    The matrix is expanded avoiding reallocation whenever possible.
44640  */
44641  void add_unit_rows_and_space_dimensions(dimension_type dims);
44642
44643  //! Permutes the space dimensions of the system.
44644  /*!
44645    \param cycle
44646    A vector representing a cycle of the permutation according to which the
44647    columns must be rearranged.
44648
44649    The \p cycle vector represents a cycle of a permutation of space
44650    dimensions.
44651    For example, the permutation
44652    \f$ \{ x_1 \mapsto x_2, x_2 \mapsto x_3, x_3 \mapsto x_1 \}\f$ can be
44653    represented by the vector containing \f$ x_1, x_2, x_3 \f$.
44654  */
44655  void permute_space_dimensions(const std::vector<Variable>& cycle);
44656
44657  //! Swaps the columns having indexes \p i and \p j.
44658  void swap_space_dimensions(Variable v1, Variable v2);
44659
44660  //! Sets the number of space dimensions to \p new_space_dim.
44661  /*!
44662    If \p new_space_dim is lower than the current space dimension, the
44663    coefficients referring to the removed space dimensions are lost.
44664  */
44665  bool set_space_dimension(dimension_type new_space_dim);
44666
44667  // Note: the following method is protected to allow tests/Grid/congruences2
44668  // to call it using a derived class.
44669protected:
44670  //! Returns <CODE>true</CODE> if \p g satisfies all the congruences.
44671  bool satisfies_all_congruences(const Grid_Generator& g) const;
44672
44673private:
44674  //! Returns the number of rows in the system.
44675  dimension_type num_rows() const;
44676
44677  //! Returns \c true if num_rows()==0.
44678  bool has_no_rows() const;
44679
44680  //! Returns a constant reference to the \p k- th congruence of the system.
44681  const Congruence& operator[](dimension_type k) const;
44682
44683  //! Adjusts all expressions to have the same moduli.
44684  void normalize_moduli();
44685
44686  /*! \brief
44687    Substitutes a given column of coefficients by a given affine
44688    expression.
44689
44690    \param v
44691    Index of the column to which the affine transformation is
44692    substituted;
44693
44694    \param expr
44695    The numerator of the affine transformation:
44696    \f$\sum_{i = 0}^{n - 1} a_i x_i + b\f$;
44697
44698    \param denominator
44699    The denominator of the affine transformation.
44700
44701    We allow affine transformations (see the Section \ref
44702    rational_grid_operations) to have rational
44703    coefficients. Since the coefficients of linear expressions are
44704    integers we also provide an integer \p denominator that will
44705    be used as denominator of the affine transformation.  The
44706    denominator is required to be a positive integer and its default value
44707    is 1.
44708
44709    The affine transformation substitutes the matrix of congruences
44710    by a new matrix whose elements \f${a'}_{ij}\f$ are built from
44711    the old one \f$a_{ij}\f$ as follows:
44712    \f[
44713      {a'}_{ij} =
44714        \begin{cases}
44715          a_{ij} * \mathrm{denominator} + a_{iv} * \mathrm{expr}[j]
44716            \quad \text{for } j \neq v; \\
44717          \mathrm{expr}[v] * a_{iv}
44718            \quad \text{for } j = v.
44719        \end{cases}
44720    \f]
44721
44722    \p expr is a constant parameter and unaltered by this computation.
44723  */
44724  void affine_preimage(Variable v,
44725                       const Linear_Expression& expr,
44726                       Coefficient_traits::const_reference denominator);
44727
44728  // TODO: Consider making this private.
44729  /*! \brief
44730    Concatenates copies of the congruences from \p y onto \p *this.
44731
44732    \param y
44733    The congruence system to append to \p this.  The number of rows in
44734    \p y must be strictly positive.
44735
44736    The matrix for the new system of congruences is obtained by
44737    leaving the old system in the upper left-hand side and placing the
44738    congruences of \p y in the lower right-hand side, and padding
44739    with zeroes.
44740  */
44741  void concatenate(const Congruence_System& y);
44742
44743  /*! \brief
44744    Inserts in \p *this the congruence \p cg, stealing its contents and
44745    increasing the number of space dimensions if needed.
44746
44747    This method inserts \p cg in the given form, instead of first strong
44748    normalizing \p cg as \ref insert would do.
44749  */
44750  void insert_verbatim(Congruence& cg, Recycle_Input);
44751
44752  //! Makes the system shrink by removing the rows in [first,last).
44753  /*!
44754    If \p keep_sorted is <CODE>true</CODE>, the ordering of the remaining rows
44755    will be preserved.
44756  */
44757  void remove_rows(dimension_type first, dimension_type last,
44758                   bool keep_sorted);
44759
44760  void remove_trailing_rows(dimension_type n);
44761
44762  /*! \brief
44763    Holds (between class initialization and finalization) a pointer to
44764    the singleton system containing only Congruence::zero_dim_false().
44765  */
44766  static const Congruence_System* zero_dim_empty_p;
44767
44768  Swapping_Vector<Congruence> rows;
44769
44770  dimension_type space_dimension_;
44771
44772  Representation representation_;
44773
44774  /*! \brief
44775    Returns <CODE>true</CODE> if and only if any of the dimensions in
44776    \p *this is free of constraint.
44777
44778    Any equality or proper congruence affecting a dimension constrains
44779    that dimension.
44780
44781    This method assumes the system is in minimal form.
44782  */
44783  bool has_a_free_dimension() const;
44784
44785  friend class Grid;
44786
44787  friend bool
44788  operator==(const Congruence_System& x, const Congruence_System& y);
44789};
44790
44791namespace Parma_Polyhedra_Library {
44792
44793namespace IO_Operators {
44794
44795//! Output operator.
44796/*!
44797  \relates Parma_Polyhedra_Library::Congruence_System
44798  Writes <CODE>true</CODE> if \p cgs is empty.  Otherwise, writes on
44799  \p s the congruences of \p cgs, all in one row and separated by ", ".
44800*/
44801std::ostream&
44802operator<<(std::ostream& s, const Congruence_System& cgs);
44803
44804} // namespace IO_Operators
44805
44806/*! \relates Congruence_System */
44807void
44808swap(Congruence_System& x, Congruence_System& y);
44809
44810} // namespace Parma_Polyhedra_Library
44811
44812// Congruence_System_inlines.hh is not included here on purpose.
44813
44814/* Automatically generated from PPL source file ../src/Congruence_System_inlines.hh line 1. */
44815/* Congruence_System class implementation: inline functions.
44816*/
44817
44818
44819/* Automatically generated from PPL source file ../src/Congruence_System_inlines.hh line 28. */
44820
44821namespace Parma_Polyhedra_Library {
44822
44823inline const Congruence&
44824Congruence_System::operator[](const dimension_type k) const {
44825  return rows[k];
44826}
44827
44828inline dimension_type
44829Congruence_System::num_rows() const {
44830  return rows.size();
44831}
44832
44833inline bool
44834Congruence_System::has_no_rows() const {
44835  return num_rows() == 0;
44836}
44837
44838inline void
44839Congruence_System::remove_trailing_rows(dimension_type n) {
44840  PPL_ASSERT(num_rows() >= n);
44841  rows.resize(num_rows() - n);
44842}
44843
44844inline void
44845Congruence_System::insert(const Congruence& cg) {
44846  Congruence tmp = cg;
44847  insert(tmp, Recycle_Input());
44848}
44849
44850inline void
44851Congruence_System::insert(Congruence& cg, Recycle_Input) {
44852  PPL_ASSERT(cg.OK());
44853  cg.strong_normalize();
44854  PPL_ASSERT(cg.OK());
44855  insert_verbatim(cg, Recycle_Input());
44856  PPL_ASSERT(OK());
44857}
44858
44859inline
44860Congruence_System::Congruence_System(Representation r)
44861  : rows(),
44862    space_dimension_(0),
44863    representation_(r) {
44864}
44865
44866inline
44867Congruence_System::Congruence_System(const Congruence& cg, Representation r)
44868  : rows(),
44869    space_dimension_(0),
44870    representation_(r) {
44871  insert(cg);
44872}
44873
44874inline
44875Congruence_System::Congruence_System(const Constraint& c, Representation r)
44876  : rows(),
44877    space_dimension_(0),
44878    representation_(r) {
44879  insert(c);
44880}
44881
44882inline
44883Congruence_System::Congruence_System(const Congruence_System& cgs)
44884  : rows(cgs.rows),
44885    space_dimension_(cgs.space_dimension_),
44886    representation_(cgs.representation_) {
44887}
44888
44889inline
44890Congruence_System::Congruence_System(const Congruence_System& cgs,
44891                                     Representation r)
44892  : rows(cgs.rows),
44893    space_dimension_(cgs.space_dimension_),
44894    representation_(r) {
44895  if (cgs.representation() != r) {
44896    for (dimension_type i = 0; i < num_rows(); ++i) {
44897      rows[i].set_representation(representation());
44898    }
44899  }
44900}
44901
44902inline
44903Congruence_System::Congruence_System(const dimension_type d, Representation r)
44904  : rows(),
44905    space_dimension_(d),
44906    representation_(r) {
44907}
44908
44909inline
44910Congruence_System::~Congruence_System() {
44911}
44912
44913inline Congruence_System&
44914Congruence_System::operator=(const Congruence_System& y) {
44915  Congruence_System tmp = y;
44916  swap(*this, tmp);
44917  return *this;
44918}
44919
44920inline Representation
44921Congruence_System::representation() const {
44922  return representation_;
44923}
44924
44925inline void
44926Congruence_System::set_representation(Representation r) {
44927  if (representation_ == r) {
44928    return;
44929  }
44930  representation_ = r;
44931  for (dimension_type i = 0; i < num_rows(); ++i) {
44932    rows[i].set_representation(r);
44933  }
44934  PPL_ASSERT(OK());
44935}
44936
44937inline dimension_type
44938Congruence_System::max_space_dimension() {
44939  return Congruence::max_space_dimension();
44940}
44941
44942inline dimension_type
44943Congruence_System::space_dimension() const {
44944  return space_dimension_;
44945}
44946
44947inline void
44948Congruence_System::clear() {
44949  rows.clear();
44950  space_dimension_ = 0;
44951}
44952
44953inline const Congruence_System&
44954Congruence_System::zero_dim_empty() {
44955  PPL_ASSERT(zero_dim_empty_p != 0);
44956  return *zero_dim_empty_p;
44957}
44958
44959inline
44960Congruence_System::const_iterator::const_iterator()
44961  : i(), csp(0) {
44962}
44963
44964inline
44965Congruence_System::const_iterator::const_iterator(const const_iterator& y)
44966  : i(y.i), csp(y.csp) {
44967}
44968
44969inline
44970Congruence_System::const_iterator::~const_iterator() {
44971}
44972
44973inline Congruence_System::const_iterator&
44974Congruence_System::const_iterator::operator=(const const_iterator& y) {
44975  i = y.i;
44976  csp = y.csp;
44977  return *this;
44978}
44979
44980inline const Congruence&
44981Congruence_System::const_iterator::operator*() const {
44982  return *i;
44983}
44984
44985inline const Congruence*
44986Congruence_System::const_iterator::operator->() const {
44987  return i.operator->();
44988}
44989
44990inline Congruence_System::const_iterator&
44991Congruence_System::const_iterator::operator++() {
44992  ++i;
44993  skip_forward();
44994  return *this;
44995}
44996
44997inline Congruence_System::const_iterator
44998Congruence_System::const_iterator::operator++(int) {
44999  const const_iterator tmp = *this;
45000  operator++();
45001  return tmp;
45002}
45003
45004inline bool
45005Congruence_System::const_iterator::operator==(const const_iterator& y) const {
45006  return i == y.i;
45007}
45008
45009inline bool
45010Congruence_System::const_iterator::operator!=(const const_iterator& y) const {
45011  return i != y.i;
45012}
45013
45014inline
45015Congruence_System::const_iterator::
45016const_iterator(const Swapping_Vector<Congruence>::const_iterator& iter,
45017               const Congruence_System& cgs)
45018  : i(iter), csp(&cgs.rows) {
45019}
45020
45021inline Congruence_System::const_iterator
45022Congruence_System::begin() const {
45023  const_iterator i(rows.begin(), *this);
45024  i.skip_forward();
45025  return i;
45026}
45027
45028inline Congruence_System::const_iterator
45029Congruence_System::end() const {
45030  const const_iterator i(rows.end(), *this);
45031  return i;
45032}
45033
45034inline bool
45035Congruence_System::empty() const {
45036  return begin() == end();
45037}
45038
45039inline void
45040Congruence_System::m_swap(Congruence_System& y) {
45041  using std::swap;
45042  swap(rows, y.rows);
45043  swap(space_dimension_, y.space_dimension_);
45044  swap(representation_, y.representation_);
45045  PPL_ASSERT(OK());
45046  PPL_ASSERT(y.OK());
45047}
45048
45049inline memory_size_type
45050Congruence_System::external_memory_in_bytes() const {
45051  return rows.external_memory_in_bytes();
45052}
45053
45054inline memory_size_type
45055Congruence_System::total_memory_in_bytes() const {
45056  return rows.external_memory_in_bytes() + sizeof(*this);
45057}
45058
45059/*! \relates Congruence_System */
45060inline void
45061swap(Congruence_System& x, Congruence_System& y) {
45062  x.m_swap(y);
45063}
45064
45065} // namespace Parma_Polyhedra_Library
45066
45067/* Automatically generated from PPL source file ../src/Box_inlines.hh line 33. */
45068
45069namespace Parma_Polyhedra_Library {
45070
45071template <typename ITV>
45072inline bool
45073Box<ITV>::marked_empty() const {
45074  return status.test_empty_up_to_date() && status.test_empty();
45075}
45076
45077template <typename ITV>
45078inline void
45079Box<ITV>::set_empty() {
45080  status.set_empty();
45081  status.set_empty_up_to_date();
45082}
45083
45084template <typename ITV>
45085inline void
45086Box<ITV>::set_nonempty() {
45087  status.reset_empty();
45088  status.set_empty_up_to_date();
45089}
45090
45091template <typename ITV>
45092inline void
45093Box<ITV>::set_empty_up_to_date() {
45094  status.set_empty_up_to_date();
45095}
45096
45097template <typename ITV>
45098inline void
45099Box<ITV>::reset_empty_up_to_date() {
45100  return status.reset_empty_up_to_date();
45101}
45102
45103template <typename ITV>
45104inline
45105Box<ITV>::Box(const Box& y, Complexity_Class)
45106  : seq(y.seq), status(y.status) {
45107}
45108
45109template <typename ITV>
45110inline Box<ITV>&
45111Box<ITV>::operator=(const Box& y) {
45112  seq = y.seq;
45113  status = y.status;
45114  return *this;
45115}
45116
45117template <typename ITV>
45118inline void
45119Box<ITV>::m_swap(Box& y) {
45120  Box& x = *this;
45121  using std::swap;
45122  swap(x.seq, y.seq);
45123  swap(x.status, y.status);
45124}
45125
45126template <typename ITV>
45127inline
45128Box<ITV>::Box(const Constraint_System& cs, Recycle_Input) {
45129  // Recycling is useless: just delegate.
45130  Box<ITV> tmp(cs);
45131  this->m_swap(tmp);
45132}
45133
45134template <typename ITV>
45135inline
45136Box<ITV>::Box(const Generator_System& gs, Recycle_Input) {
45137  // Recycling is useless: just delegate.
45138  Box<ITV> tmp(gs);
45139  this->m_swap(tmp);
45140}
45141
45142template <typename ITV>
45143inline
45144Box<ITV>::Box(const Congruence_System& cgs, Recycle_Input) {
45145  // Recycling is useless: just delegate.
45146  Box<ITV> tmp(cgs);
45147  this->m_swap(tmp);
45148}
45149
45150template <typename ITV>
45151inline memory_size_type
45152Box<ITV>::total_memory_in_bytes() const {
45153  return sizeof(*this) + external_memory_in_bytes();
45154}
45155
45156template <typename ITV>
45157inline dimension_type
45158Box<ITV>::space_dimension() const {
45159  return seq.size();
45160}
45161
45162template <typename ITV>
45163inline dimension_type
45164Box<ITV>::max_space_dimension() {
45165  // One dimension is reserved to have a value of type dimension_type
45166  // that does not represent a legal dimension.
45167  return Sequence().max_size() - 1;
45168}
45169
45170template <typename ITV>
45171inline int32_t
45172Box<ITV>::hash_code() const {
45173  return hash_code_from_dimension(space_dimension());
45174}
45175
45176template <typename ITV>
45177inline const ITV&
45178Box<ITV>::operator[](const dimension_type k) const {
45179  PPL_ASSERT(k < seq.size());
45180  return seq[k];
45181}
45182
45183template <typename ITV>
45184inline const ITV&
45185Box<ITV>::get_interval(const Variable var) const {
45186  if (space_dimension() < var.space_dimension()) {
45187    throw_dimension_incompatible("get_interval(v)", "v", var);
45188  }
45189  if (is_empty()) {
45190    static ITV empty_interval(EMPTY);
45191    return empty_interval;
45192  }
45193
45194  return seq[var.id()];
45195}
45196
45197template <typename ITV>
45198inline void
45199Box<ITV>::set_interval(const Variable var, const ITV& i) {
45200  const dimension_type space_dim = space_dimension();
45201  if (space_dim < var.space_dimension()) {
45202    throw_dimension_incompatible("set_interval(v, i)", "v", var);
45203  }
45204
45205  if (is_empty() && space_dim >= 2) {
45206    // If the box is empty, and has dimension >= 2, setting only one
45207    // interval will not make it non-empty.
45208    return;
45209  }
45210  seq[var.id()] = i;
45211  reset_empty_up_to_date();
45212
45213  PPL_ASSERT(OK());
45214}
45215
45216template <typename ITV>
45217inline bool
45218Box<ITV>::is_empty() const {
45219  return marked_empty() || check_empty();
45220}
45221
45222template <typename ITV>
45223inline bool
45224Box<ITV>::bounds_from_above(const Linear_Expression& expr) const {
45225  return bounds(expr, true);
45226}
45227
45228template <typename ITV>
45229inline bool
45230Box<ITV>::bounds_from_below(const Linear_Expression& expr) const {
45231  return bounds(expr, false);
45232}
45233
45234template <typename ITV>
45235inline bool
45236Box<ITV>::maximize(const Linear_Expression& expr,
45237                   Coefficient& sup_n, Coefficient& sup_d,
45238                   bool& maximum) const {
45239  return max_min(expr, true, sup_n, sup_d, maximum);
45240}
45241
45242template <typename ITV>
45243inline bool
45244Box<ITV>::maximize(const Linear_Expression& expr,
45245                   Coefficient& sup_n, Coefficient& sup_d, bool& maximum,
45246                   Generator& g) const {
45247  return max_min(expr, true, sup_n, sup_d, maximum, g);
45248}
45249
45250template <typename ITV>
45251inline bool
45252Box<ITV>::minimize(const Linear_Expression& expr,
45253                   Coefficient& inf_n, Coefficient& inf_d,
45254                   bool& minimum) const {
45255  return max_min(expr, false, inf_n, inf_d, minimum);
45256}
45257
45258template <typename ITV>
45259inline bool
45260Box<ITV>::minimize(const Linear_Expression& expr,
45261                   Coefficient& inf_n, Coefficient& inf_d, bool& minimum,
45262                   Generator& g) const {
45263  return max_min(expr, false, inf_n, inf_d, minimum, g);
45264}
45265
45266template <typename ITV>
45267inline bool
45268Box<ITV>::strictly_contains(const Box& y) const {
45269  const Box& x = *this;
45270  return x.contains(y) && !y.contains(x);
45271}
45272
45273template <typename ITV>
45274inline void
45275Box<ITV>::expand_space_dimension(const Variable var,
45276                                 const dimension_type m) {
45277  const dimension_type space_dim = space_dimension();
45278  // `var' should be one of the dimensions of the vector space.
45279  if (var.space_dimension() > space_dim) {
45280    throw_dimension_incompatible("expand_space_dimension(v, m)", "v", var);
45281  }
45282
45283  // The space dimension of the resulting Box should not
45284  // overflow the maximum allowed space dimension.
45285  if (m > max_space_dimension() - space_dim) {
45286    throw_invalid_argument("expand_dimension(v, m)",
45287                           "adding m new space dimensions exceeds "
45288                           "the maximum allowed space dimension");
45289  }
45290
45291  // To expand the space dimension corresponding to variable `var',
45292  // we append to the box `m' copies of the corresponding interval.
45293  seq.insert(seq.end(), m, seq[var.id()]);
45294  PPL_ASSERT(OK());
45295}
45296
45297template <typename ITV>
45298inline bool
45299operator!=(const Box<ITV>& x, const Box<ITV>& y) {
45300  return !(x == y);
45301}
45302
45303template <typename ITV>
45304inline bool
45305Box<ITV>::has_lower_bound(const Variable var,
45306                          Coefficient& n, Coefficient& d, bool& closed) const {
45307  // NOTE: assertion !is_empty() would be wrong;
45308  // see the calls in method Box<ITV>::constraints().
45309  PPL_ASSERT(!marked_empty());
45310  const dimension_type k = var.id();
45311  PPL_ASSERT(k < seq.size());
45312  const ITV& seq_k = seq[k];
45313
45314  if (seq_k.lower_is_boundary_infinity()) {
45315    return false;
45316  }
45317  closed = !seq_k.lower_is_open();
45318
45319  PPL_DIRTY_TEMP(mpq_class, lr);
45320  assign_r(lr, seq_k.lower(), ROUND_NOT_NEEDED);
45321  n = lr.get_num();
45322  d = lr.get_den();
45323
45324  return true;
45325}
45326
45327template <typename ITV>
45328inline bool
45329Box<ITV>::has_upper_bound(const Variable var,
45330                          Coefficient& n, Coefficient& d, bool& closed) const {
45331  // NOTE: assertion !is_empty() would be wrong;
45332  // see the calls in method Box<ITV>::constraints().
45333  PPL_ASSERT(!marked_empty());
45334  const dimension_type k = var.id();
45335  PPL_ASSERT(k < seq.size());
45336  const ITV& seq_k = seq[k];
45337
45338  if (seq_k.upper_is_boundary_infinity()) {
45339    return false;
45340  }
45341
45342  closed = !seq_k.upper_is_open();
45343
45344  PPL_DIRTY_TEMP(mpq_class, ur);
45345  assign_r(ur, seq_k.upper(), ROUND_NOT_NEEDED);
45346  n = ur.get_num();
45347  d = ur.get_den();
45348
45349  return true;
45350}
45351
45352template <typename ITV>
45353inline void
45354Box<ITV>::add_constraint(const Constraint& c) {
45355  const dimension_type c_space_dim = c.space_dimension();
45356  // Dimension-compatibility check.
45357  if (c_space_dim > space_dimension()) {
45358    throw_dimension_incompatible("add_constraint(c)", c);
45359  }
45360
45361  add_constraint_no_check(c);
45362}
45363
45364template <typename ITV>
45365inline void
45366Box<ITV>::add_constraints(const Constraint_System& cs) {
45367  // Dimension-compatibility check.
45368  if (cs.space_dimension() > space_dimension()) {
45369    throw_dimension_incompatible("add_constraints(cs)", cs);
45370  }
45371
45372  add_constraints_no_check(cs);
45373}
45374
45375template <typename T>
45376inline void
45377Box<T>::add_recycled_constraints(Constraint_System& cs) {
45378  add_constraints(cs);
45379}
45380
45381template <typename ITV>
45382inline void
45383Box<ITV>::add_congruence(const Congruence& cg) {
45384  const dimension_type cg_space_dim = cg.space_dimension();
45385  // Dimension-compatibility check.
45386  if (cg_space_dim > space_dimension()) {
45387    throw_dimension_incompatible("add_congruence(cg)", cg);
45388  }
45389
45390  add_congruence_no_check(cg);
45391}
45392
45393template <typename ITV>
45394inline void
45395Box<ITV>::add_congruences(const Congruence_System& cgs) {
45396  if (cgs.space_dimension() > space_dimension()) {
45397    throw_dimension_incompatible("add_congruences(cgs)", cgs);
45398  }
45399  add_congruences_no_check(cgs);
45400}
45401
45402template <typename T>
45403inline void
45404Box<T>::add_recycled_congruences(Congruence_System& cgs) {
45405  add_congruences(cgs);
45406}
45407
45408template <typename T>
45409inline bool
45410Box<T>::can_recycle_constraint_systems() {
45411  return false;
45412}
45413
45414template <typename T>
45415inline bool
45416Box<T>::can_recycle_congruence_systems() {
45417  return false;
45418}
45419
45420template <typename T>
45421inline void
45422Box<T>::widening_assign(const Box& y, unsigned* tp) {
45423  CC76_widening_assign(y, tp);
45424}
45425
45426template <typename ITV>
45427inline Congruence_System
45428Box<ITV>::minimized_congruences() const {
45429  // Only equalities can be congruences and these are already minimized.
45430  return congruences();
45431}
45432
45433template <typename ITV>
45434inline I_Result
45435Box<ITV>
45436::refine_interval_no_check(ITV& itv,
45437                           const Constraint::Type type,
45438                           Coefficient_traits::const_reference numer,
45439                           Coefficient_traits::const_reference denom) {
45440  PPL_ASSERT(denom != 0);
45441  // The interval constraint is of the form
45442  // `var + numer / denom rel 0',
45443  // where `rel' is either the relation `==', `>=', or `>'.
45444  // For the purpose of refining the interval, this is
45445  // (morally) turned into `var rel -numer/denom'.
45446  PPL_DIRTY_TEMP(mpq_class, q);
45447  assign_r(q.get_num(), numer, ROUND_NOT_NEEDED);
45448  assign_r(q.get_den(), denom, ROUND_NOT_NEEDED);
45449  q.canonicalize();
45450  // Turn `numer/denom' into `-numer/denom'.
45451  q = -q;
45452
45453  Relation_Symbol rel_sym;
45454  switch (type) {
45455  case Constraint::EQUALITY:
45456    rel_sym = EQUAL;
45457    break;
45458  case Constraint::NONSTRICT_INEQUALITY:
45459    rel_sym = (denom > 0) ? GREATER_OR_EQUAL : LESS_OR_EQUAL;
45460    break;
45461  case Constraint::STRICT_INEQUALITY:
45462    rel_sym = (denom > 0) ? GREATER_THAN : LESS_THAN;
45463    break;
45464  default:
45465    // Silence compiler warning.
45466    PPL_UNREACHABLE;
45467    return I_ANY;
45468  }
45469  I_Result res = itv.add_constraint(i_constraint(rel_sym, q));
45470  PPL_ASSERT(itv.OK());
45471  return res;
45472}
45473
45474template <typename ITV>
45475inline void
45476Box<ITV>
45477::add_interval_constraint_no_check(const dimension_type var_id,
45478                                   const Constraint::Type type,
45479                                   Coefficient_traits::const_reference numer,
45480                                   Coefficient_traits::const_reference denom) {
45481  PPL_ASSERT(!marked_empty());
45482  PPL_ASSERT(var_id < space_dimension());
45483  PPL_ASSERT(denom != 0);
45484  refine_interval_no_check(seq[var_id], type, numer, denom);
45485  // FIXME: do check the value returned and set `empty' and
45486  // `empty_up_to_date' as appropriate.
45487  // This has to be done after reimplementation of intervals.
45488  reset_empty_up_to_date();
45489  PPL_ASSERT(OK());
45490}
45491
45492template <typename ITV>
45493inline void
45494Box<ITV>::refine_with_constraint(const Constraint& c) {
45495  const dimension_type c_space_dim = c.space_dimension();
45496  // Dimension-compatibility check.
45497  if (c_space_dim > space_dimension()) {
45498    throw_dimension_incompatible("refine_with_constraint(c)", c);
45499  }
45500
45501  // If the box is already empty, there is nothing left to do.
45502  if (marked_empty()) {
45503    return;
45504  }
45505
45506  refine_no_check(c);
45507}
45508
45509template <typename ITV>
45510inline void
45511Box<ITV>::refine_with_constraints(const Constraint_System& cs) {
45512  // Dimension-compatibility check.
45513  if (cs.space_dimension() > space_dimension()) {
45514    throw_dimension_incompatible("refine_with_constraints(cs)", cs);
45515  }
45516
45517  // If the box is already empty, there is nothing left to do.
45518  if (marked_empty()) {
45519    return;
45520  }
45521  refine_no_check(cs);
45522}
45523
45524template <typename ITV>
45525inline void
45526Box<ITV>::refine_with_congruence(const Congruence& cg) {
45527  const dimension_type cg_space_dim = cg.space_dimension();
45528  // Dimension-compatibility check.
45529  if (cg_space_dim > space_dimension()) {
45530    throw_dimension_incompatible("refine_with_congruence(cg)", cg);
45531  }
45532  // If the box is already empty, there is nothing left to do.
45533  if (marked_empty()) {
45534    return;
45535  }
45536  refine_no_check(cg);
45537}
45538
45539template <typename ITV>
45540inline void
45541Box<ITV>::refine_with_congruences(const Congruence_System& cgs) {
45542  // Dimension-compatibility check.
45543  if (cgs.space_dimension() > space_dimension()) {
45544    throw_dimension_incompatible("refine_with_congruences(cgs)", cgs);
45545  }
45546
45547  // If the box is already empty, there is nothing left to do.
45548  if (marked_empty()) {
45549    return;
45550  }
45551
45552  refine_no_check(cgs);
45553}
45554
45555template <typename ITV>
45556inline void
45557Box<ITV>::propagate_constraint(const Constraint& c) {
45558  const dimension_type c_space_dim = c.space_dimension();
45559  // Dimension-compatibility check.
45560  if (c_space_dim > space_dimension()) {
45561    throw_dimension_incompatible("propagate_constraint(c)", c);
45562  }
45563
45564  // If the box is already empty, there is nothing left to do.
45565  if (marked_empty()) {
45566    return;
45567  }
45568  propagate_constraint_no_check(c);
45569}
45570
45571template <typename ITV>
45572inline void
45573Box<ITV>::propagate_constraints(const Constraint_System& cs,
45574                                const dimension_type max_iterations) {
45575  // Dimension-compatibility check.
45576  if (cs.space_dimension() > space_dimension()) {
45577    throw_dimension_incompatible("propagate_constraints(cs)", cs);
45578  }
45579
45580  // If the box is already empty, there is nothing left to do.
45581  if (marked_empty()) {
45582    return;
45583  }
45584
45585  propagate_constraints_no_check(cs, max_iterations);
45586}
45587
45588template <typename ITV>
45589inline void
45590Box<ITV>::unconstrain(const Variable var) {
45591  const dimension_type var_id = var.id();
45592  // Dimension-compatibility check.
45593  if (space_dimension() < var_id + 1) {
45594    throw_dimension_incompatible("unconstrain(var)", var_id + 1);
45595  }
45596
45597  // If the box is already empty, there is nothing left to do.
45598  if (marked_empty()) {
45599    return;
45600  }
45601
45602  // Here the box might still be empty (but we haven't detected it yet):
45603  // check emptiness of the interval for `var' before cylindrification.
45604  ITV& seq_var = seq[var_id];
45605  if (seq_var.is_empty()) {
45606    set_empty();
45607  }
45608  else {
45609    seq_var.assign(UNIVERSE);
45610  }
45611
45612  PPL_ASSERT(OK());
45613}
45614
45615/*! \relates Box */
45616template <typename Temp, typename To, typename ITV>
45617inline bool
45618rectilinear_distance_assign(Checked_Number<To, Extended_Number_Policy>& r,
45619                            const Box<ITV>& x,
45620                            const Box<ITV>& y,
45621                            const Rounding_Dir dir,
45622                            Temp& tmp0,
45623                            Temp& tmp1,
45624                            Temp& tmp2) {
45625  return l_m_distance_assign<Rectilinear_Distance_Specialization<Temp> >
45626    (r, x, y, dir, tmp0, tmp1, tmp2);
45627}
45628
45629/*! \relates Box */
45630template <typename Temp, typename To, typename ITV>
45631inline bool
45632rectilinear_distance_assign(Checked_Number<To, Extended_Number_Policy>& r,
45633                            const Box<ITV>& x,
45634                            const Box<ITV>& y,
45635                            const Rounding_Dir dir) {
45636  typedef Checked_Number<Temp, Extended_Number_Policy> Checked_Temp;
45637  PPL_DIRTY_TEMP(Checked_Temp, tmp0);
45638  PPL_DIRTY_TEMP(Checked_Temp, tmp1);
45639  PPL_DIRTY_TEMP(Checked_Temp, tmp2);
45640  return rectilinear_distance_assign(r, x, y, dir, tmp0, tmp1, tmp2);
45641}
45642
45643/*! \relates Box */
45644template <typename To, typename ITV>
45645inline bool
45646rectilinear_distance_assign(Checked_Number<To, Extended_Number_Policy>& r,
45647                            const Box<ITV>& x,
45648                            const Box<ITV>& y,
45649                            const Rounding_Dir dir) {
45650  // FIXME: the following qualification is only to work around a bug
45651  // in the Intel C/C++ compiler version 10.1.x.
45652  return Parma_Polyhedra_Library
45653    ::rectilinear_distance_assign<To, To, ITV>(r, x, y, dir);
45654}
45655
45656/*! \relates Box */
45657template <typename Temp, typename To, typename ITV>
45658inline bool
45659euclidean_distance_assign(Checked_Number<To, Extended_Number_Policy>& r,
45660                          const Box<ITV>& x,
45661                          const Box<ITV>& y,
45662                          const Rounding_Dir dir,
45663                          Temp& tmp0,
45664                          Temp& tmp1,
45665                          Temp& tmp2) {
45666  return l_m_distance_assign<Euclidean_Distance_Specialization<Temp> >
45667    (r, x, y, dir, tmp0, tmp1, tmp2);
45668}
45669
45670/*! \relates Box */
45671template <typename Temp, typename To, typename ITV>
45672inline bool
45673euclidean_distance_assign(Checked_Number<To, Extended_Number_Policy>& r,
45674                          const Box<ITV>& x,
45675                          const Box<ITV>& y,
45676                          const Rounding_Dir dir) {
45677  typedef Checked_Number<Temp, Extended_Number_Policy> Checked_Temp;
45678  PPL_DIRTY_TEMP(Checked_Temp, tmp0);
45679  PPL_DIRTY_TEMP(Checked_Temp, tmp1);
45680  PPL_DIRTY_TEMP(Checked_Temp, tmp2);
45681  return euclidean_distance_assign(r, x, y, dir, tmp0, tmp1, tmp2);
45682}
45683
45684/*! \relates Box */
45685template <typename To, typename ITV>
45686inline bool
45687euclidean_distance_assign(Checked_Number<To, Extended_Number_Policy>& r,
45688                          const Box<ITV>& x,
45689                          const Box<ITV>& y,
45690                          const Rounding_Dir dir) {
45691  // FIXME: the following qualification is only to work around a bug
45692  // in the Intel C/C++ compiler version 10.1.x.
45693  return Parma_Polyhedra_Library
45694    ::euclidean_distance_assign<To, To, ITV>(r, x, y, dir);
45695}
45696
45697/*! \relates Box */
45698template <typename Temp, typename To, typename ITV>
45699inline bool
45700l_infinity_distance_assign(Checked_Number<To, Extended_Number_Policy>& r,
45701                           const Box<ITV>& x,
45702                           const Box<ITV>& y,
45703                           const Rounding_Dir dir,
45704                           Temp& tmp0,
45705                           Temp& tmp1,
45706                           Temp& tmp2) {
45707  return l_m_distance_assign<L_Infinity_Distance_Specialization<Temp> >
45708    (r, x, y, dir, tmp0, tmp1, tmp2);
45709}
45710
45711/*! \relates Box */
45712template <typename Temp, typename To, typename ITV>
45713inline bool
45714l_infinity_distance_assign(Checked_Number<To, Extended_Number_Policy>& r,
45715                           const Box<ITV>& x,
45716                           const Box<ITV>& y,
45717                           const Rounding_Dir dir) {
45718  typedef Checked_Number<Temp, Extended_Number_Policy> Checked_Temp;
45719  PPL_DIRTY_TEMP(Checked_Temp, tmp0);
45720  PPL_DIRTY_TEMP(Checked_Temp, tmp1);
45721  PPL_DIRTY_TEMP(Checked_Temp, tmp2);
45722  return l_infinity_distance_assign(r, x, y, dir, tmp0, tmp1, tmp2);
45723}
45724
45725/*! \relates Box */
45726template <typename To, typename ITV>
45727inline bool
45728l_infinity_distance_assign(Checked_Number<To, Extended_Number_Policy>& r,
45729                           const Box<ITV>& x,
45730                           const Box<ITV>& y,
45731                           const Rounding_Dir dir) {
45732  // FIXME: the following qualification is only to work around a bug
45733  // in the Intel C/C++ compiler version 10.1.x.
45734  return Parma_Polyhedra_Library
45735    ::l_infinity_distance_assign<To, To, ITV>(r, x, y, dir);
45736}
45737
45738/*! \relates Box */
45739template <typename ITV>
45740inline void
45741swap(Box<ITV>& x, Box<ITV>& y) {
45742  x.m_swap(y);
45743}
45744
45745} // namespace Parma_Polyhedra_Library
45746
45747/* Automatically generated from PPL source file ../src/Box_templates.hh line 1. */
45748/* Box class implementation: non-inline template functions.
45749*/
45750
45751
45752/* Automatically generated from PPL source file ../src/Generator_System_defs.hh line 1. */
45753/* Generator_System class declaration.
45754*/
45755
45756
45757/* Automatically generated from PPL source file ../src/Generator_System_defs.hh line 28. */
45758
45759/* Automatically generated from PPL source file ../src/Poly_Con_Relation_defs.hh line 1. */
45760/* Poly_Con_Relation class declaration.
45761*/
45762
45763
45764/* Automatically generated from PPL source file ../src/Poly_Con_Relation_defs.hh line 29. */
45765#include <iosfwd>
45766
45767namespace Parma_Polyhedra_Library {
45768
45769// Put them in the namespace here to declare them friend later.
45770
45771//! True if and only if \p x and \p y are logically equivalent.
45772/*! \relates Poly_Con_Relation */
45773bool operator==(const Poly_Con_Relation& x, const Poly_Con_Relation& y);
45774
45775//! True if and only if \p x and \p y are not logically equivalent.
45776/*! \relates Poly_Con_Relation */
45777bool operator!=(const Poly_Con_Relation& x, const Poly_Con_Relation& y);
45778
45779//! Yields the logical conjunction of \p x and \p y.
45780/*! \relates Poly_Con_Relation */
45781Poly_Con_Relation operator&&(const Poly_Con_Relation& x,
45782                             const Poly_Con_Relation& y);
45783
45784/*! \brief
45785  Yields the assertion with all the conjuncts of \p x
45786  that are not in \p y.
45787
45788  \relates Poly_Con_Relation
45789*/
45790Poly_Con_Relation operator-(const Poly_Con_Relation& x,
45791                            const Poly_Con_Relation& y);
45792
45793namespace IO_Operators {
45794
45795//! Output operator.
45796/*! \relates Parma_Polyhedra_Library::Poly_Con_Relation */
45797std::ostream& operator<<(std::ostream& s, const Poly_Con_Relation& r);
45798
45799} // namespace IO_Operators
45800
45801} // namespace Parma_Polyhedra_Library
45802
45803
45804//! The relation between a polyhedron and a constraint.
45805/*! \ingroup PPL_CXX_interface
45806  This class implements conjunctions of assertions on the relation
45807  between a polyhedron and a constraint.
45808*/
45809class Parma_Polyhedra_Library::Poly_Con_Relation {
45810private:
45811  //! Poly_Con_Relation is implemented by means of a finite bitset.
45812  typedef unsigned int flags_t;
45813
45814  //! \name Bit-masks for the individual assertions
45815  //@{
45816  static const flags_t NOTHING             = 0U;
45817  static const flags_t IS_DISJOINT         = 1U << 0;
45818  static const flags_t STRICTLY_INTERSECTS = 1U << 1;
45819  static const flags_t IS_INCLUDED         = 1U << 2;
45820  static const flags_t SATURATES           = 1U << 3;
45821  //@} // Bit-masks for the individual assertions
45822
45823  //! All assertions together.
45824  static const flags_t EVERYTHING
45825  = IS_DISJOINT
45826  | STRICTLY_INTERSECTS
45827  | IS_INCLUDED
45828  | SATURATES;
45829
45830  //! This holds the current bitset.
45831  flags_t flags;
45832
45833  //! True if and only if the conjunction \p x implies the conjunction \p y.
45834  static bool implies(flags_t x, flags_t y);
45835
45836  //! Construct from a bit-mask.
45837  Poly_Con_Relation(flags_t mask);
45838
45839  friend bool
45840  operator==(const Poly_Con_Relation& x, const Poly_Con_Relation& y);
45841  friend bool
45842  operator!=(const Poly_Con_Relation& x, const Poly_Con_Relation& y);
45843
45844  friend Poly_Con_Relation
45845  operator&&(const Poly_Con_Relation& x, const Poly_Con_Relation& y);
45846
45847  friend Poly_Con_Relation
45848  operator-(const Poly_Con_Relation& x, const Poly_Con_Relation& y);
45849
45850  friend std::ostream&
45851  Parma_Polyhedra_Library::
45852  IO_Operators::operator<<(std::ostream& s, const Poly_Con_Relation& r);
45853
45854public:
45855#ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
45856  /*! \brief
45857    Access the internal flags: this is needed for some language
45858    interfaces.
45859  */
45860#endif
45861  flags_t get_flags() const;
45862
45863public:
45864  //! The assertion that says nothing.
45865  static Poly_Con_Relation nothing();
45866
45867  /*! \brief
45868    The polyhedron and the set of points satisfying
45869    the constraint are disjoint.
45870  */
45871  static Poly_Con_Relation is_disjoint();
45872
45873  /*! \brief
45874    The polyhedron intersects the set of points satisfying
45875    the constraint, but it is not included in it.
45876  */
45877  static Poly_Con_Relation strictly_intersects();
45878
45879  /*! \brief
45880    The polyhedron is included in the set of points satisfying
45881    the constraint.
45882  */
45883  static Poly_Con_Relation is_included();
45884
45885  /*! \brief
45886    The polyhedron is included in the set of points saturating
45887    the constraint.
45888  */
45889  static Poly_Con_Relation saturates();
45890
45891  PPL_OUTPUT_DECLARATIONS
45892
45893  //! True if and only if \p *this implies \p y.
45894  bool implies(const Poly_Con_Relation& y) const;
45895
45896  //! Checks if all the invariants are satisfied.
45897  bool OK() const;
45898};
45899
45900/* Automatically generated from PPL source file ../src/Poly_Con_Relation_inlines.hh line 1. */
45901/* Poly_Con_Relation class implementation: inline functions.
45902*/
45903
45904
45905namespace Parma_Polyhedra_Library {
45906
45907inline
45908Poly_Con_Relation::Poly_Con_Relation(flags_t mask)
45909  : flags(mask) {
45910}
45911
45912inline Poly_Con_Relation::flags_t
45913Poly_Con_Relation::get_flags() const {
45914  return flags;
45915}
45916
45917inline Poly_Con_Relation
45918Poly_Con_Relation::nothing() {
45919  return Poly_Con_Relation(NOTHING);
45920}
45921
45922inline Poly_Con_Relation
45923Poly_Con_Relation::is_disjoint() {
45924  return Poly_Con_Relation(IS_DISJOINT);
45925}
45926
45927inline Poly_Con_Relation
45928Poly_Con_Relation::strictly_intersects() {
45929  return Poly_Con_Relation(STRICTLY_INTERSECTS);
45930}
45931
45932inline Poly_Con_Relation
45933Poly_Con_Relation::is_included() {
45934  return Poly_Con_Relation(IS_INCLUDED);
45935}
45936
45937inline Poly_Con_Relation
45938Poly_Con_Relation::saturates() {
45939  return Poly_Con_Relation(SATURATES);
45940}
45941
45942inline bool
45943Poly_Con_Relation::implies(flags_t x, flags_t y) {
45944  return (x & y) == y;
45945}
45946
45947inline bool
45948Poly_Con_Relation::implies(const Poly_Con_Relation& y) const {
45949  return implies(flags, y.flags);
45950}
45951
45952/*! \relates Poly_Con_Relation */
45953inline bool
45954operator==(const Poly_Con_Relation& x, const Poly_Con_Relation& y) {
45955  return x.flags == y.flags;
45956}
45957
45958/*! \relates Poly_Con_Relation */
45959inline bool
45960operator!=(const Poly_Con_Relation& x, const Poly_Con_Relation& y) {
45961  return x.flags != y.flags;
45962}
45963
45964/*! \relates Poly_Con_Relation */
45965inline Poly_Con_Relation
45966operator&&(const Poly_Con_Relation& x, const Poly_Con_Relation& y) {
45967  return Poly_Con_Relation(x.flags | y.flags);
45968}
45969
45970/*! \relates Poly_Con_Relation */
45971inline Poly_Con_Relation
45972operator-(const Poly_Con_Relation& x, const Poly_Con_Relation& y) {
45973  return Poly_Con_Relation(x.flags & ~y.flags);
45974}
45975
45976} // namespace Parma_Polyhedra_Library
45977
45978/* Automatically generated from PPL source file ../src/Poly_Con_Relation_defs.hh line 165. */
45979
45980/* Automatically generated from PPL source file ../src/Generator_System_defs.hh line 35. */
45981#include <iosfwd>
45982#include <cstddef>
45983
45984namespace Parma_Polyhedra_Library {
45985
45986namespace IO_Operators {
45987
45988//! Output operator.
45989/*!
45990  \relates Parma_Polyhedra_Library::Generator_System
45991  Writes <CODE>false</CODE> if \p gs is empty.  Otherwise, writes on
45992  \p s the generators of \p gs, all in one row and separated by ", ".
45993*/
45994std::ostream& operator<<(std::ostream& s, const Generator_System& gs);
45995
45996} // namespace IO_Operators
45997
45998// TODO: Consider removing this.
45999#ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
46000//! Returns <CODE>true</CODE> if and only if \p x and \p y are identical.
46001/*! \relates Generator_System */
46002#endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
46003bool operator==(const Generator_System& x, const Generator_System& y);
46004
46005// TODO: Consider removing this.
46006#ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
46007//! Returns <CODE>true</CODE> if and only if \p x and \p y are different.
46008/*! \relates Generator_System */
46009#endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
46010bool operator!=(const Generator_System& x, const Generator_System& y);
46011
46012/*! \relates Generator_System */
46013void
46014swap(Generator_System& x, Generator_System& y);
46015
46016} // namespace Parma_Polyhedra_Library
46017
46018//! A system of generators.
46019/*! \ingroup PPL_CXX_interface
46020    An object of the class Generator_System is a system of generators,
46021    i.e., a multiset of objects of the class Generator
46022    (lines, rays, points and closure points).
46023    When inserting generators in a system, space dimensions are automatically
46024    adjusted so that all the generators in the system are defined
46025    on the same vector space.
46026    A system of generators which is meant to define a non-empty
46027    polyhedron must include at least one point: the reason is that
46028    lines, rays and closure points need a supporting point
46029    (lines and rays only specify directions while closure points only
46030    specify points in the topological closure of the NNC polyhedron).
46031
46032    \par
46033     In all the examples it is assumed that variables
46034    <CODE>x</CODE> and <CODE>y</CODE> are defined as follows:
46035    \code
46036  Variable x(0);
46037  Variable y(1);
46038    \endcode
46039
46040    \par Example 1
46041    The following code defines the line having the same direction
46042    as the \f$x\f$ axis (i.e., the first Cartesian axis)
46043    in \f$\Rset^2\f$:
46044    \code
46045  Generator_System gs;
46046  gs.insert(line(x + 0*y));
46047    \endcode
46048    As said above, this system of generators corresponds to
46049    an empty polyhedron, because the line has no supporting point.
46050    To define a system of generators that does correspond to
46051    the \f$x\f$ axis, we can add the following code which
46052    inserts the origin of the space as a point:
46053    \code
46054  gs.insert(point(0*x + 0*y));
46055    \endcode
46056    Since space dimensions are automatically adjusted, the following
46057    code obtains the same effect:
46058    \code
46059  gs.insert(point(0*x));
46060    \endcode
46061    In contrast, if we had added the following code, we would have
46062    defined a line parallel to the \f$x\f$ axis through
46063    the point \f$(0, 1)^\transpose \in \Rset^2\f$.
46064    \code
46065  gs.insert(point(0*x + 1*y));
46066    \endcode
46067
46068    \par Example 2
46069    The following code builds a ray having the same direction as
46070    the positive part of the \f$x\f$ axis in \f$\Rset^2\f$:
46071    \code
46072  Generator_System gs;
46073  gs.insert(ray(x + 0*y));
46074    \endcode
46075    To define a system of generators indeed corresponding to the set
46076    \f[
46077      \bigl\{\,
46078        (x, 0)^\transpose \in \Rset^2
46079      \bigm|
46080        x \geq 0
46081      \,\bigr\},
46082    \f]
46083    one just has to add the origin:
46084    \code
46085  gs.insert(point(0*x + 0*y));
46086    \endcode
46087
46088    \par Example 3
46089    The following code builds a system of generators having four points
46090    and corresponding to a square in \f$\Rset^2\f$
46091    (the same as Example 1 for the system of constraints):
46092    \code
46093  Generator_System gs;
46094  gs.insert(point(0*x + 0*y));
46095  gs.insert(point(0*x + 3*y));
46096  gs.insert(point(3*x + 0*y));
46097  gs.insert(point(3*x + 3*y));
46098    \endcode
46099
46100    \par Example 4
46101    By using closure points, we can define the \e kernel
46102    (i.e., the largest open set included in a given set)
46103    of the square defined in the previous example.
46104    Note that a supporting point is needed and, for that purpose,
46105    any inner point could be considered.
46106    \code
46107  Generator_System gs;
46108  gs.insert(point(x + y));
46109  gs.insert(closure_point(0*x + 0*y));
46110  gs.insert(closure_point(0*x + 3*y));
46111  gs.insert(closure_point(3*x + 0*y));
46112  gs.insert(closure_point(3*x + 3*y));
46113    \endcode
46114
46115    \par Example 5
46116    The following code builds a system of generators having two points
46117    and a ray, corresponding to a half-strip in \f$\Rset^2\f$
46118    (the same as Example 2 for the system of constraints):
46119    \code
46120  Generator_System gs;
46121  gs.insert(point(0*x + 0*y));
46122  gs.insert(point(0*x + 1*y));
46123  gs.insert(ray(x - y));
46124    \endcode
46125
46126    \note
46127    After inserting a multiset of generators in a generator system,
46128    there are no guarantees that an <EM>exact</EM> copy of them
46129    can be retrieved:
46130    in general, only an <EM>equivalent</EM> generator system
46131    will be available, where original generators may have been
46132    reordered, removed (if they are duplicate or redundant), etc.
46133*/
46134class Parma_Polyhedra_Library::Generator_System {
46135public:
46136  typedef Generator row_type;
46137
46138  static const Representation default_representation = SPARSE;
46139
46140  //! Default constructor: builds an empty system of generators.
46141  Generator_System(Representation r = default_representation);
46142
46143  //! Builds the singleton system containing only generator \p g.
46144  explicit Generator_System(const Generator& g,
46145                            Representation r = default_representation);
46146
46147  //! Ordinary copy constructor.
46148  //! The new Generator_System will have the same representation as `gs'.
46149  Generator_System(const Generator_System& gs);
46150
46151  //! Copy constructor with specified representation.
46152  Generator_System(const Generator_System& gs, Representation r);
46153
46154  //! Destructor.
46155  ~Generator_System();
46156
46157  //! Assignment operator.
46158  Generator_System& operator=(const Generator_System& y);
46159
46160  //! Returns the current representation of *this.
46161  Representation representation() const;
46162
46163  //! Converts *this to the specified representation.
46164  void set_representation(Representation r);
46165
46166  //! Returns the maximum space dimension a Generator_System can handle.
46167  static dimension_type max_space_dimension();
46168
46169  //! Returns the dimension of the vector space enclosing \p *this.
46170  dimension_type space_dimension() const;
46171
46172  //! Sets the space dimension of the rows in the system to \p space_dim .
46173  void set_space_dimension(dimension_type space_dim);
46174
46175  /*! \brief
46176    Removes all the generators from the generator system
46177    and sets its space dimension to 0.
46178  */
46179  void clear();
46180
46181  /*! \brief
46182    Inserts in \p *this a copy of the generator \p g,
46183    increasing the number of space dimensions if needed.
46184  */
46185  void insert(const Generator& g);
46186
46187  /*! \brief
46188    Inserts in \p *this the generator \p g, stealing its contents and
46189    increasing the number of space dimensions if needed.
46190  */
46191  void insert(Generator& g, Recycle_Input);
46192
46193  //! Initializes the class.
46194  static void initialize();
46195
46196  //! Finalizes the class.
46197  static void finalize();
46198
46199  /*! \brief
46200    Returns the singleton system containing only Generator::zero_dim_point().
46201  */
46202  static const Generator_System& zero_dim_univ();
46203
46204  typedef Generator_System_const_iterator const_iterator;
46205
46206  //! Returns <CODE>true</CODE> if and only if \p *this has no generators.
46207  bool empty() const;
46208
46209  /*! \brief
46210    Returns the const_iterator pointing to the first generator,
46211    if \p *this is not empty;
46212    otherwise, returns the past-the-end const_iterator.
46213  */
46214  const_iterator begin() const;
46215
46216  //! Returns the past-the-end const_iterator.
46217  const_iterator end() const;
46218
46219  //! Checks if all the invariants are satisfied.
46220  bool OK() const;
46221
46222  PPL_OUTPUT_DECLARATIONS
46223
46224  /*! \brief
46225    Loads from \p s an ASCII representation (as produced by
46226    ascii_dump(std::ostream&) const) and sets \p *this accordingly.
46227    Returns <CODE>true</CODE> if successful, <CODE>false</CODE> otherwise.
46228
46229    Resizes the matrix of generators using the numbers of rows and columns
46230    read from \p s, then initializes the coordinates of each generator
46231    and its type reading the contents from \p s.
46232  */
46233  bool ascii_load(std::istream& s);
46234
46235  //! Returns the total size in bytes of the memory occupied by \p *this.
46236  memory_size_type total_memory_in_bytes() const;
46237
46238  //! Returns the size in bytes of the memory managed by \p *this.
46239  memory_size_type external_memory_in_bytes() const;
46240
46241  //! Swaps \p *this with \p y.
46242  void m_swap(Generator_System& y);
46243
46244private:
46245
46246  bool has_no_rows() const;
46247
46248  //! Removes all the specified dimensions from the generator system.
46249  /*!
46250    The space dimension of the variable with the highest space
46251    dimension in \p vars must be at most the space dimension
46252    of \p this.
46253  */
46254  void remove_space_dimensions(const Variables_Set& vars);
46255
46256  //! Shift by \p n positions the coefficients of variables, starting from
46257  //! the coefficient of \p v. This increases the space dimension by \p n.
46258  void shift_space_dimensions(Variable v, dimension_type n);
46259
46260  //! Permutes the space dimensions of the matrix.
46261  /*
46262    \param cycle
46263    A vector representing a cycle of the permutation according to which the
46264    columns must be rearranged.
46265
46266    The \p cycle vector represents a cycle of a permutation of space
46267    dimensions.
46268    For example, the permutation
46269    \f$ \{ x_1 \mapsto x_2, x_2 \mapsto x_3, x_3 \mapsto x_1 \}\f$ can be
46270    represented by the vector containing \f$ x_1, x_2, x_3 \f$.
46271  */
46272  void permute_space_dimensions(const std::vector<Variable>& cycle);
46273
46274  //! Swaps the coefficients of the variables \p v1 and \p v2 .
46275  void swap_space_dimensions(Variable v1, Variable v2);
46276
46277  dimension_type num_rows() const;
46278
46279  //! Adds \p n rows and space dimensions to the system.
46280  /*!
46281    \param n
46282    The number of rows and space dimensions to be added: must be strictly
46283    positive.
46284
46285    Turns the system \f$M \in \Rset^r \times \Rset^c\f$ into
46286    the system \f$N \in \Rset^{r+n} \times \Rset^{c+n}\f$
46287    such that
46288    \f$N = \bigl(\genfrac{}{}{0pt}{}{0}{M}\genfrac{}{}{0pt}{}{J}{o}\bigr)\f$,
46289    where \f$J\f$ is the specular image
46290    of the \f$n \times n\f$ identity matrix.
46291  */
46292  void add_universe_rows_and_space_dimensions(dimension_type n);
46293
46294  Topology topology() const;
46295
46296  //! Returns the index of the first pending row.
46297  dimension_type first_pending_row() const;
46298
46299  //! Sets the index to indicate that the system has no pending rows.
46300  void unset_pending_rows();
46301
46302  //! Sets the sortedness flag of the system to \p b.
46303  void set_sorted(bool b);
46304
46305  //! Returns the value of the sortedness flag.
46306  bool is_sorted() const;
46307
46308  //! Sets the index of the first pending row to \p i.
46309  void set_index_first_pending_row(dimension_type i);
46310
46311  /*! \brief
46312    Returns <CODE>true</CODE> if and only if
46313    the system topology is <CODE>NECESSARILY_CLOSED</CODE>.
46314  */
46315  bool is_necessarily_closed() const;
46316
46317  //! Full assignment operator: pending rows are copied as pending.
46318  void assign_with_pending(const Generator_System& y);
46319
46320  //! Returns the number of rows that are in the pending part of the system.
46321  dimension_type num_pending_rows() const;
46322
46323  /*! \brief
46324    Sorts the pending rows and eliminates those that also occur
46325    in the non-pending part of the system.
46326  */
46327  void sort_pending_and_remove_duplicates();
46328
46329  /*! \brief
46330    Sorts the system, removing duplicates, keeping the saturation
46331    matrix consistent.
46332
46333    \param sat
46334    Bit matrix with rows corresponding to the rows of \p *this.
46335  */
46336  void sort_and_remove_with_sat(Bit_Matrix& sat);
46337
46338  /*! \brief
46339    Sorts the non-pending rows (in growing order) and eliminates
46340    duplicated ones.
46341  */
46342  void sort_rows();
46343
46344  /*! \brief
46345    Returns <CODE>true</CODE> if and only if \p *this is sorted,
46346    without checking for duplicates.
46347  */
46348  bool check_sorted() const;
46349
46350  /*! \brief
46351    Returns the number of rows in the system
46352    that represent either lines or equalities.
46353  */
46354  dimension_type num_lines_or_equalities() const;
46355
46356  //! Makes the system shrink by removing its i-th row.
46357  /*!
46358    When \p keep_sorted is \p true and the system is sorted, sortedness will
46359    be preserved, but this method costs O(n).
46360
46361    Otherwise, this method just swaps the i-th row with the last and then
46362    removes it, so it costs O(1).
46363  */
46364  void remove_row(dimension_type i, bool keep_sorted = false);
46365
46366  //! Makes the system shrink by removing the rows in [first,last).
46367  /*!
46368    When \p keep_sorted is \p true and the system is sorted, sortedness will
46369    be preserved, but this method costs O(num_rows()).
46370
46371    Otherwise, this method just swaps the rows with the last ones and then
46372    removes them, so it costs O(last - first).
46373  */
46374  void remove_rows(dimension_type first, dimension_type last,
46375                   bool keep_sorted = false);
46376
46377  //! Removes the specified rows. The row ordering of remaining rows is
46378  //! preserved.
46379  /*!
46380    \param indexes specifies a list of row indexes.
46381                   It must be sorted.
46382  */
46383  void remove_rows(const std::vector<dimension_type>& indexes);
46384
46385  //! Makes the system shrink by removing its \p n trailing rows.
46386  void remove_trailing_rows(dimension_type n);
46387
46388  //! Minimizes the subsystem of equations contained in \p *this.
46389  /*!
46390    This method works only on the equalities of the system:
46391    the system is required to be partially sorted, so that
46392    all the equalities are grouped at its top; it is assumed that
46393    the number of equalities is exactly \p n_lines_or_equalities.
46394    The method finds a minimal system for the equalities and
46395    returns its rank, i.e., the number of linearly independent equalities.
46396    The result is an upper triangular subsystem of equalities:
46397    for each equality, the pivot is chosen starting from
46398    the right-most columns.
46399  */
46400  dimension_type gauss(dimension_type n_lines_or_equalities);
46401
46402  /*! \brief
46403    Back-substitutes the coefficients to reduce
46404    the complexity of the system.
46405
46406    Takes an upper triangular system having \p n_lines_or_equalities rows.
46407    For each row, starting from the one having the minimum number of
46408    coefficients different from zero, computes the expression of an element
46409    as a function of the remaining ones and then substitutes this expression
46410    in all the other rows.
46411  */
46412  void back_substitute(dimension_type n_lines_or_equalities);
46413
46414  //! Strongly normalizes the system.
46415  void strong_normalize();
46416
46417  /*! \brief
46418    Assigns to \p *this the result of merging its rows with
46419    those of \p y, obtaining a sorted system.
46420
46421    Duplicated rows will occur only once in the result.
46422    On entry, both systems are assumed to be sorted and have
46423    no pending rows.
46424  */
46425  void merge_rows_assign(const Generator_System& y);
46426
46427  //! Adds to \p *this a copy of  the rows of \p y.
46428  /*!
46429    It is assumed that \p *this has no pending rows.
46430  */
46431  void insert(const Generator_System& y);
46432
46433  //! Adds a copy of the rows of `y' to the pending part of `*this'.
46434  void insert_pending(const Generator_System& r);
46435
46436  /*! \brief
46437    Holds (between class initialization and finalization) a pointer to
46438    the singleton system containing only Generator::zero_dim_point().
46439  */
46440  static const Generator_System* zero_dim_univ_p;
46441
46442  friend class Generator_System_const_iterator;
46443
46444  //! Builds an empty system of generators having the specified topology.
46445  explicit Generator_System(Topology topol,
46446                            Representation r = default_representation);
46447
46448  /*! \brief
46449    Builds a system of rays/points on a \p space_dim dimensional space. If
46450    \p topol is <CODE>NOT_NECESSARILY_CLOSED</CODE> the \f$\epsilon\f$
46451    dimension is added.
46452  */
46453  Generator_System(Topology topol, dimension_type space_dim,
46454                   Representation r = default_representation);
46455
46456  /*! \brief
46457    Adjusts \p *this so that it matches the \p new_topology and
46458    \p new_space_dim (adding or removing columns if needed).
46459    Returns <CODE>false</CODE> if and only if \p topol is
46460    equal to <CODE>NECESSARILY_CLOSED</CODE> and \p *this
46461    contains closure points.
46462  */
46463  bool adjust_topology_and_space_dimension(Topology new_topology,
46464                                           dimension_type new_space_dim);
46465
46466  /*! \brief
46467    For each unmatched closure point in \p *this, adds the
46468    corresponding point.
46469
46470    It is assumed that the topology of \p *this
46471    is <CODE>NOT_NECESSARILY_CLOSED</CODE>.
46472  */
46473  void add_corresponding_points();
46474
46475  /*! \brief
46476    Returns <CODE>true</CODE> if and only if \p *this
46477    contains one or more points.
46478  */
46479  bool has_points() const;
46480
46481  /*! \brief
46482    For each unmatched point in \p *this, adds the corresponding
46483    closure point.
46484
46485    It is assumed that the topology of \p *this
46486    is <CODE>NOT_NECESSARILY_CLOSED</CODE>.
46487  */
46488  void add_corresponding_closure_points();
46489
46490  /*! \brief
46491    Returns <CODE>true</CODE> if and only if \p *this
46492    contains one or more closure points.
46493
46494    Note: the check for the presence of closure points is
46495    done under the point of view of the user. Namely, we scan
46496    the generator system using high-level iterators, so that
46497    closure points that are matching the corresponding points
46498    will be disregarded.
46499  */
46500  bool has_closure_points() const;
46501
46502  //! Converts this generator system into a non-necessarily closed generator
46503  //! system.
46504  void convert_into_non_necessarily_closed();
46505
46506  //! Returns a constant reference to the \p k- th generator of the system.
46507  const Generator& operator[](dimension_type k) const;
46508
46509  /*! \brief
46510    Returns the relations holding between the generator system
46511    and the constraint \p c.
46512  */
46513  Parma_Polyhedra_Library::Poly_Con_Relation
46514  relation_with(const Constraint& c) const;
46515
46516  //! Returns <CODE>true</CODE> if all the generators satisfy \p c.
46517  bool satisfied_by_all_generators(const Constraint& c) const;
46518
46519  //! Returns <CODE>true</CODE> if all the generators satisfy \p c.
46520  /*!
46521    It is assumed that <CODE>c.is_necessarily_closed()</CODE> holds.
46522  */
46523  bool satisfied_by_all_generators_C(const Constraint& c) const;
46524
46525  //! Returns <CODE>true</CODE> if all the generators satisfy \p c.
46526  /*!
46527    It is assumed that <CODE>c.is_necessarily_closed()</CODE> does not hold.
46528  */
46529  bool satisfied_by_all_generators_NNC(const Constraint& c) const;
46530
46531  //! Assigns to a given variable an affine expression.
46532  /*!
46533    \param v
46534    The variable to which the affine transformation is assigned;
46535
46536    \param expr
46537    The numerator of the affine transformation:
46538    \f$\sum_{i = 0}^{n - 1} a_i x_i + b\f$;
46539
46540    \param denominator
46541    The denominator of the affine transformation.
46542
46543    We want to allow affine transformations (see the Introduction) having
46544    any rational coefficients. Since the coefficients of the
46545    constraints are integers we must also provide an integer \p denominator
46546    that will be used as denominator of the affine transformation.
46547    The denominator is required to be a positive integer.
46548
46549    The affine transformation assigns to each element of the column containing
46550    the coefficients of v the follow expression:
46551    \f[
46552      \frac{\sum_{i = 0}^{n - 1} a_i x_i + b}
46553           {\mathrm{denominator}}.
46554    \f]
46555
46556    \p expr is a constant parameter and unaltered by this computation.
46557  */
46558  void affine_image(Variable v,
46559                    const Linear_Expression& expr,
46560                    Coefficient_traits::const_reference denominator);
46561
46562  //! Returns the number of lines of the system.
46563  dimension_type num_lines() const;
46564
46565  //! Returns the number of rays of the system.
46566  dimension_type num_rays() const;
46567
46568  //! Removes all the invalid lines and rays.
46569  /*!
46570    The invalid lines and rays are those with all
46571    the homogeneous terms set to zero.
46572  */
46573  void remove_invalid_lines_and_rays();
46574
46575  /*! \brief
46576    Applies Gaussian elimination and back-substitution so as
46577    to provide a partial simplification of the system of generators.
46578
46579    It is assumed that the system has no pending generators.
46580  */
46581  void simplify();
46582
46583  /*! \brief
46584    Inserts in \p *this a copy of the generator \p g,
46585    increasing the number of space dimensions if needed.
46586    It is a pending generator.
46587  */
46588  void insert_pending(const Generator& g);
46589
46590  /*! \brief
46591    Inserts in \p *this the generator \p g, stealing its contents and
46592    increasing the number of space dimensions if needed.
46593    It is a pending generator.
46594  */
46595  void insert_pending(Generator& g, Recycle_Input);
46596
46597  Linear_System<Generator> sys;
46598
46599  friend bool
46600  operator==(const Generator_System& x, const Generator_System& y);
46601
46602  friend class Polyhedron;
46603};
46604
46605//! An iterator over a system of generators
46606/*! \ingroup PPL_CXX_interface
46607    A const_iterator is used to provide read-only access
46608    to each generator contained in an object of Generator_System.
46609
46610    \par Example
46611    The following code prints the system of generators
46612    of the polyhedron <CODE>ph</CODE>:
46613    \code
46614const Generator_System& gs = ph.generators();
46615for (Generator_System::const_iterator i = gs.begin(),
46616        gs_end = gs.end(); i != gs_end; ++i)
46617  cout << *i << endl;
46618    \endcode
46619    The same effect can be obtained more concisely by using
46620    more features of the STL:
46621    \code
46622const Generator_System& gs = ph.generators();
46623copy(gs.begin(), gs.end(), ostream_iterator<Generator>(cout, "\n"));
46624    \endcode
46625*/
46626class Parma_Polyhedra_Library::Generator_System_const_iterator
46627  : public std::iterator<std::forward_iterator_tag,
46628        Generator,
46629        std::ptrdiff_t,
46630        const Generator*,
46631        const Generator&> {
46632public:
46633  //! Default constructor.
46634  Generator_System_const_iterator();
46635
46636  //! Ordinary copy constructor.
46637  Generator_System_const_iterator(const Generator_System_const_iterator& y);
46638
46639  //! Destructor.
46640  ~Generator_System_const_iterator();
46641
46642  //! Assignment operator.
46643  Generator_System_const_iterator& operator=(const Generator_System_const_iterator& y);
46644
46645  //! Dereference operator.
46646  const Generator& operator*() const;
46647
46648  //! Indirect member selector.
46649  const Generator* operator->() const;
46650
46651  //! Prefix increment operator.
46652  Generator_System_const_iterator& operator++();
46653
46654  //! Postfix increment operator.
46655  Generator_System_const_iterator operator++(int);
46656
46657  /*! \brief
46658    Returns <CODE>true</CODE> if and only if
46659    \p *this and \p y are identical.
46660  */
46661  bool operator==(const Generator_System_const_iterator& y) const;
46662
46663  /*! \brief
46664    Returns <CODE>true</CODE> if and only if
46665    \p *this and \p y are different.
46666  */
46667  bool operator!=(const Generator_System_const_iterator& y) const;
46668
46669private:
46670  friend class Generator_System;
46671
46672  //! The const iterator over the Linear_System.
46673  Linear_System<Generator>::const_iterator i;
46674
46675  //! A const pointer to the Linear_System.
46676  const Linear_System<Generator>* gsp;
46677
46678  //! Constructor.
46679  Generator_System_const_iterator(const Linear_System<Generator>::const_iterator& iter,
46680      const Generator_System& gsys);
46681
46682  /*! \brief
46683    \p *this skips to the next generator, skipping those
46684    closure points that are immediately followed by a matching point.
46685  */
46686  void skip_forward();
46687};
46688
46689// Generator_System_inlines.hh is not included here on purpose.
46690
46691/* Automatically generated from PPL source file ../src/Generator_System_inlines.hh line 1. */
46692/* Generator_System class implementation: inline functions.
46693*/
46694
46695
46696/* Automatically generated from PPL source file ../src/Generator_System_inlines.hh line 28. */
46697
46698namespace Parma_Polyhedra_Library {
46699
46700inline
46701Generator_System::Generator_System(Representation r)
46702  : sys(NECESSARILY_CLOSED, r) {
46703}
46704
46705inline
46706Generator_System::Generator_System(const Generator& g, Representation r)
46707  : sys(g.topology(), r) {
46708  sys.insert(g);
46709}
46710
46711inline
46712Generator_System::Generator_System(const Generator_System& gs)
46713  : sys(gs.sys) {
46714}
46715
46716inline
46717Generator_System::Generator_System(const Generator_System& gs,
46718                                   Representation r)
46719  : sys(gs.sys, r) {
46720}
46721
46722inline
46723Generator_System::Generator_System(const Topology topol, Representation r)
46724  : sys(topol, r) {
46725}
46726
46727inline
46728Generator_System::Generator_System(const Topology topol,
46729                                   const dimension_type space_dim,
46730                                   Representation r)
46731  : sys(topol, space_dim, r) {
46732}
46733
46734inline
46735Generator_System::~Generator_System() {
46736}
46737
46738inline Generator_System&
46739Generator_System::operator=(const Generator_System& y) {
46740  Generator_System tmp = y;
46741  swap(*this, tmp);
46742  return *this;
46743}
46744
46745inline Representation
46746Generator_System::representation() const {
46747  return sys.representation();
46748}
46749
46750inline void
46751Generator_System::set_representation(Representation r) {
46752  sys.set_representation(r);
46753}
46754
46755inline dimension_type
46756Generator_System::max_space_dimension() {
46757  return Linear_System<Generator>::max_space_dimension();
46758}
46759
46760inline dimension_type
46761Generator_System::space_dimension() const {
46762  return sys.space_dimension();
46763}
46764
46765inline void
46766Generator_System::set_space_dimension(dimension_type space_dim) {
46767  const dimension_type old_space_dim = space_dimension();
46768  sys.set_space_dimension_no_ok(space_dim);
46769
46770  if (space_dim < old_space_dim) {
46771    // We may have invalid lines and rays now.
46772    remove_invalid_lines_and_rays();
46773  }
46774
46775#ifndef NDEBUG
46776  for (dimension_type i = 0; i < sys.num_rows(); ++i) {
46777    PPL_ASSERT(sys[i].OK());
46778  }
46779#endif
46780  PPL_ASSERT(sys.OK());
46781  PPL_ASSERT(OK());
46782}
46783
46784inline void
46785Generator_System::clear() {
46786  sys.clear();
46787}
46788
46789inline const Generator&
46790Generator_System::operator[](const dimension_type k) const {
46791  return sys[k];
46792}
46793
46794inline void
46795Generator_System
46796::remove_space_dimensions(const Variables_Set& vars) {
46797  sys.remove_space_dimensions(vars);
46798}
46799
46800inline void
46801Generator_System
46802::shift_space_dimensions(Variable v, dimension_type n) {
46803  sys.shift_space_dimensions(v, n);
46804}
46805
46806inline void
46807Generator_System
46808::permute_space_dimensions(const std::vector<Variable>& cycle) {
46809  sys.permute_space_dimensions(cycle);
46810}
46811
46812inline void
46813Generator_System
46814::swap_space_dimensions(Variable v1, Variable v2) {
46815  sys.swap_space_dimensions(v1, v2);
46816}
46817
46818inline dimension_type
46819Generator_System::num_rows() const {
46820  return sys.num_rows();
46821}
46822
46823inline void
46824Generator_System::add_universe_rows_and_space_dimensions(dimension_type n) {
46825  sys.add_universe_rows_and_space_dimensions(n);
46826}
46827
46828inline Topology
46829Generator_System::topology() const {
46830  return sys.topology();
46831}
46832
46833inline dimension_type
46834Generator_System::first_pending_row() const {
46835  return sys.first_pending_row();
46836}
46837
46838inline void
46839Generator_System::unset_pending_rows() {
46840  sys.unset_pending_rows();
46841}
46842
46843inline void
46844Generator_System::set_sorted(bool b) {
46845  sys.set_sorted(b);
46846}
46847
46848inline bool
46849Generator_System::is_sorted() const {
46850  return sys.is_sorted();
46851}
46852
46853inline void
46854Generator_System::set_index_first_pending_row(dimension_type i) {
46855  sys.set_index_first_pending_row(i);
46856}
46857
46858inline bool
46859Generator_System::is_necessarily_closed() const {
46860  return sys.is_necessarily_closed();
46861}
46862
46863inline void
46864Generator_System::assign_with_pending(const Generator_System& y) {
46865  sys.assign_with_pending(y.sys);
46866}
46867
46868inline dimension_type
46869Generator_System::num_pending_rows() const {
46870  return sys.num_pending_rows();
46871}
46872
46873inline void
46874Generator_System::sort_pending_and_remove_duplicates() {
46875  return sys.sort_pending_and_remove_duplicates();
46876}
46877
46878inline void
46879Generator_System::sort_and_remove_with_sat(Bit_Matrix& sat) {
46880  sys.sort_and_remove_with_sat(sat);
46881}
46882
46883inline void
46884Generator_System::sort_rows() {
46885  sys.sort_rows();
46886}
46887
46888inline bool
46889Generator_System::check_sorted() const {
46890  return sys.check_sorted();
46891}
46892
46893inline dimension_type
46894Generator_System::num_lines_or_equalities() const {
46895  return sys.num_lines_or_equalities();
46896}
46897
46898inline void
46899Generator_System::remove_row(dimension_type i, bool keep_sorted) {
46900  sys.remove_row(i, keep_sorted);
46901}
46902
46903inline void
46904Generator_System::remove_rows(dimension_type first, dimension_type last,
46905                              bool keep_sorted) {
46906  sys.remove_rows(first, last, keep_sorted);
46907}
46908
46909inline void
46910Generator_System::remove_rows(const std::vector<dimension_type>& indexes) {
46911  sys.remove_rows(indexes);
46912}
46913
46914inline void
46915Generator_System::remove_trailing_rows(dimension_type n) {
46916  sys.remove_trailing_rows(n);
46917}
46918
46919inline dimension_type
46920Generator_System::gauss(dimension_type n_lines_or_equalities) {
46921  return sys.gauss(n_lines_or_equalities);
46922}
46923
46924inline void
46925Generator_System::back_substitute(dimension_type n_lines_or_equalities) {
46926  sys.back_substitute(n_lines_or_equalities);
46927}
46928
46929inline void
46930Generator_System::strong_normalize() {
46931  sys.strong_normalize();
46932}
46933
46934inline void
46935Generator_System::merge_rows_assign(const Generator_System& y) {
46936  sys.merge_rows_assign(y.sys);
46937}
46938
46939inline void
46940Generator_System::insert(const Generator_System& y) {
46941  sys.insert(y.sys);
46942}
46943
46944inline void
46945Generator_System::insert_pending(const Generator_System& r) {
46946  sys.insert_pending(r.sys);
46947}
46948
46949inline bool
46950operator==(const Generator_System& x, const Generator_System& y) {
46951  return x.sys == y.sys;
46952}
46953
46954inline bool
46955operator!=(const Generator_System& x, const Generator_System& y) {
46956  return !(x == y);
46957}
46958
46959inline
46960Generator_System_const_iterator::Generator_System_const_iterator()
46961  : i(), gsp(0) {
46962}
46963
46964inline
46965Generator_System_const_iterator::Generator_System_const_iterator(const Generator_System_const_iterator& y)
46966  : i(y.i), gsp(y.gsp) {
46967}
46968
46969inline
46970Generator_System_const_iterator::~Generator_System_const_iterator() {
46971}
46972
46973inline
46974Generator_System_const_iterator&
46975Generator_System_const_iterator::operator=(const Generator_System_const_iterator& y) {
46976  i = y.i;
46977  gsp = y.gsp;
46978  return *this;
46979}
46980
46981inline const Generator&
46982Generator_System_const_iterator::operator*() const {
46983  return *i;
46984}
46985
46986inline const Generator*
46987Generator_System_const_iterator::operator->() const {
46988  return i.operator->();
46989}
46990
46991inline Generator_System_const_iterator&
46992Generator_System_const_iterator::operator++() {
46993  ++i;
46994  if (!gsp->is_necessarily_closed()) {
46995    skip_forward();
46996  }
46997  return *this;
46998}
46999
47000inline Generator_System_const_iterator
47001Generator_System_const_iterator::operator++(int) {
47002  const Generator_System_const_iterator tmp = *this;
47003  operator++();
47004  return tmp;
47005}
47006
47007inline bool
47008Generator_System_const_iterator::operator==(const Generator_System_const_iterator& y) const {
47009  return i == y.i;
47010}
47011
47012inline bool
47013Generator_System_const_iterator::operator!=(const Generator_System_const_iterator& y) const {
47014  return i != y.i;
47015}
47016
47017inline
47018Generator_System_const_iterator::
47019Generator_System_const_iterator(const Linear_System<Generator>::const_iterator& iter,
47020                                const Generator_System& gs)
47021  : i(iter), gsp(&gs.sys) {
47022}
47023
47024inline bool
47025Generator_System::empty() const {
47026  return sys.has_no_rows();
47027}
47028
47029inline bool
47030Generator_System::has_no_rows() const {
47031  return sys.has_no_rows();
47032}
47033
47034inline Generator_System::const_iterator
47035Generator_System::begin() const {
47036  const_iterator i(sys.begin(), *this);
47037  if (!sys.is_necessarily_closed()) {
47038    i.skip_forward();
47039  }
47040  return i;
47041}
47042
47043inline Generator_System::const_iterator
47044Generator_System::end() const {
47045  const const_iterator i(sys.end(), *this);
47046  return i;
47047}
47048
47049inline const Generator_System&
47050Generator_System::zero_dim_univ() {
47051  PPL_ASSERT(zero_dim_univ_p != 0);
47052  return *zero_dim_univ_p;
47053}
47054
47055inline void
47056Generator_System::m_swap(Generator_System& y) {
47057  swap(sys, y.sys);
47058}
47059
47060inline memory_size_type
47061Generator_System::external_memory_in_bytes() const {
47062  return sys.external_memory_in_bytes();
47063}
47064
47065inline memory_size_type
47066Generator_System::total_memory_in_bytes() const {
47067  return external_memory_in_bytes() + sizeof(*this);
47068}
47069
47070inline void
47071Generator_System::simplify() {
47072  sys.simplify();
47073  remove_invalid_lines_and_rays();
47074}
47075
47076/*! \relates Generator_System */
47077inline void
47078swap(Generator_System& x, Generator_System& y) {
47079  x.m_swap(y);
47080}
47081
47082} // namespace Parma_Polyhedra_Library
47083
47084/* Automatically generated from PPL source file ../src/Poly_Gen_Relation_defs.hh line 1. */
47085/* Poly_Gen_Relation class declaration.
47086*/
47087
47088
47089/* Automatically generated from PPL source file ../src/Poly_Gen_Relation_defs.hh line 29. */
47090#include <iosfwd>
47091
47092namespace Parma_Polyhedra_Library {
47093
47094// Put them in the namespace here to declare them friend later.
47095
47096//! True if and only if \p x and \p y are logically equivalent.
47097/*! \relates Poly_Gen_Relation */
47098bool operator==(const Poly_Gen_Relation& x, const Poly_Gen_Relation& y);
47099
47100//! True if and only if \p x and \p y are not logically equivalent.
47101/*! \relates Poly_Gen_Relation */
47102bool operator!=(const Poly_Gen_Relation& x, const Poly_Gen_Relation& y);
47103
47104//! Yields the logical conjunction of \p x and \p y.
47105/*! \relates Poly_Gen_Relation */
47106Poly_Gen_Relation operator&&(const Poly_Gen_Relation& x,
47107                             const Poly_Gen_Relation& y);
47108
47109/*! \brief
47110  Yields the assertion with all the conjuncts of \p x
47111  that are not in \p y.
47112
47113  \relates Poly_Gen_Relation
47114*/
47115Poly_Gen_Relation operator-(const Poly_Gen_Relation& x,
47116                            const Poly_Gen_Relation& y);
47117
47118namespace IO_Operators {
47119
47120//! Output operator.
47121/*! \relates Parma_Polyhedra_Library::Poly_Gen_Relation */
47122std::ostream& operator<<(std::ostream& s, const Poly_Gen_Relation& r);
47123
47124} // namespace IO_Operators
47125
47126} // namespace Parma_Polyhedra_Library
47127
47128
47129//! The relation between a polyhedron and a generator
47130/*! \ingroup PPL_CXX_interface
47131  This class implements conjunctions of assertions on the relation
47132  between a polyhedron and a generator.
47133*/
47134class Parma_Polyhedra_Library::Poly_Gen_Relation {
47135private:
47136  //! Poly_Gen_Relation is implemented by means of a finite bitset.
47137  typedef unsigned int flags_t;
47138
47139  //! \name Bit-masks for the individual assertions
47140  //@{
47141  static const flags_t NOTHING  = 0U;
47142  static const flags_t SUBSUMES = 1U << 0;
47143  //@} // Bit-masks for the individual assertions
47144
47145  //! All assertions together.
47146  static const flags_t EVERYTHING
47147  = SUBSUMES;
47148
47149  //! This holds the current bitset.
47150  flags_t flags;
47151
47152  //! True if and only if the conjunction \p x implies the conjunction \p y.
47153  static bool implies(flags_t x, flags_t y);
47154
47155  //! Construct from a bit-mask.
47156  Poly_Gen_Relation(flags_t mask);
47157
47158  friend bool
47159  operator==(const Poly_Gen_Relation& x, const Poly_Gen_Relation& y);
47160  friend bool
47161  operator!=(const Poly_Gen_Relation& x, const Poly_Gen_Relation& y);
47162
47163  friend Poly_Gen_Relation
47164  operator&&(const Poly_Gen_Relation& x, const Poly_Gen_Relation& y);
47165
47166  friend Poly_Gen_Relation
47167  operator-(const Poly_Gen_Relation& x, const Poly_Gen_Relation& y);
47168
47169  friend std::ostream&
47170  Parma_Polyhedra_Library::
47171  IO_Operators::operator<<(std::ostream& s, const Poly_Gen_Relation& r);
47172
47173public:
47174#ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
47175  /*! \brief
47176    Access the internal flags: this is needed for some language
47177    interfaces.
47178  */
47179#endif
47180  flags_t get_flags() const;
47181
47182public:
47183  //! The assertion that says nothing.
47184  static Poly_Gen_Relation nothing();
47185
47186  //! Adding the generator would not change the polyhedron.
47187  static Poly_Gen_Relation subsumes();
47188
47189  PPL_OUTPUT_DECLARATIONS
47190
47191  //! True if and only if \p *this implies \p y.
47192  bool implies(const Poly_Gen_Relation& y) const;
47193
47194  //! Checks if all the invariants are satisfied.
47195  bool OK() const;
47196};
47197
47198/* Automatically generated from PPL source file ../src/Poly_Gen_Relation_inlines.hh line 1. */
47199/* Poly_Gen_Relation class implementation: inline functions.
47200*/
47201
47202
47203namespace Parma_Polyhedra_Library {
47204
47205inline
47206Poly_Gen_Relation::Poly_Gen_Relation(flags_t mask)
47207  : flags(mask) {
47208}
47209
47210inline Poly_Gen_Relation::flags_t
47211Poly_Gen_Relation::get_flags() const {
47212  return flags;
47213}
47214
47215inline Poly_Gen_Relation
47216Poly_Gen_Relation::nothing() {
47217  return Poly_Gen_Relation(NOTHING);
47218}
47219
47220inline Poly_Gen_Relation
47221Poly_Gen_Relation::subsumes() {
47222  return Poly_Gen_Relation(SUBSUMES);
47223}
47224
47225inline bool
47226Poly_Gen_Relation::implies(flags_t x, flags_t y) {
47227  return (x & y) == y;
47228}
47229
47230inline bool
47231Poly_Gen_Relation::implies(const Poly_Gen_Relation& y) const {
47232  return implies(flags, y.flags);
47233}
47234
47235/*! \relates Poly_Gen_Relation */
47236inline bool
47237operator==(const Poly_Gen_Relation& x, const Poly_Gen_Relation& y) {
47238  return x.flags == y.flags;
47239}
47240
47241/*! \relates Poly_Gen_Relation */
47242inline bool
47243operator!=(const Poly_Gen_Relation& x, const Poly_Gen_Relation& y) {
47244  return x.flags != y.flags;
47245}
47246
47247/*! \relates Poly_Gen_Relation */
47248inline Poly_Gen_Relation
47249operator&&(const Poly_Gen_Relation& x, const Poly_Gen_Relation& y) {
47250  return Poly_Gen_Relation(x.flags | y.flags);
47251}
47252
47253/*! \relates Poly_Gen_Relation */
47254inline Poly_Gen_Relation
47255operator-(const Poly_Gen_Relation& x, const Poly_Gen_Relation& y) {
47256  return Poly_Gen_Relation(x.flags & ~y.flags);
47257}
47258
47259} // namespace Parma_Polyhedra_Library
47260
47261/* Automatically generated from PPL source file ../src/Poly_Gen_Relation_defs.hh line 138. */
47262
47263/* Automatically generated from PPL source file ../src/Polyhedron_defs.hh line 1. */
47264/* Polyhedron class declaration.
47265*/
47266
47267
47268/* Automatically generated from PPL source file ../src/H79_Certificate_types.hh line 1. */
47269
47270
47271namespace Parma_Polyhedra_Library {
47272
47273class H79_Certificate;
47274
47275} // namespace Parma_Polyhedra_Library
47276
47277/* Automatically generated from PPL source file ../src/Polyhedron_defs.hh line 51. */
47278#include <vector>
47279#include <iosfwd>
47280
47281namespace Parma_Polyhedra_Library {
47282
47283namespace IO_Operators {
47284
47285//! Output operator.
47286/*!
47287  \relates Parma_Polyhedra_Library::Polyhedron
47288  Writes a textual representation of \p ph on \p s:
47289  <CODE>false</CODE> is written if \p ph is an empty polyhedron;
47290  <CODE>true</CODE> is written if \p ph is a universe polyhedron;
47291  a minimized system of constraints defining \p ph is written otherwise,
47292  all constraints in one row separated by ", ".
47293*/
47294std::ostream&
47295operator<<(std::ostream& s, const Polyhedron& ph);
47296
47297} // namespace IO_Operators
47298
47299//! Swaps \p x with \p y.
47300/*! \relates Polyhedron */
47301void swap(Polyhedron& x, Polyhedron& y);
47302
47303/*! \brief
47304  Returns <CODE>true</CODE> if and only if
47305  \p x and \p y are the same polyhedron.
47306
47307  \relates Polyhedron
47308  Note that \p x and \p y may be topology- and/or dimension-incompatible
47309  polyhedra: in those cases, the value <CODE>false</CODE> is returned.
47310*/
47311bool operator==(const Polyhedron& x, const Polyhedron& y);
47312
47313/*! \brief
47314  Returns <CODE>true</CODE> if and only if
47315  \p x and \p y are different polyhedra.
47316
47317  \relates Polyhedron
47318  Note that \p x and \p y may be topology- and/or dimension-incompatible
47319  polyhedra: in those cases, the value <CODE>true</CODE> is returned.
47320*/
47321bool operator!=(const Polyhedron& x, const Polyhedron& y);
47322
47323namespace Interfaces {
47324
47325#ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
47326/*! \brief
47327  Returns \c true if and only if
47328  <code>ph.topology() == NECESSARILY_CLOSED</code>.
47329*/
47330#endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
47331bool is_necessarily_closed_for_interfaces(const Polyhedron& ph);
47332
47333} // namespace Interfaces
47334
47335} // namespace Parma_Polyhedra_Library
47336
47337
47338//! The base class for convex polyhedra.
47339/*! \ingroup PPL_CXX_interface
47340  An object of the class Polyhedron represents a convex polyhedron
47341  in the vector space \f$\Rset^n\f$.
47342
47343  A polyhedron can be specified as either a finite system of constraints
47344  or a finite system of generators (see Section \ref representation)
47345  and it is always possible to obtain either representation.
47346  That is, if we know the system of constraints, we can obtain
47347  from this the system of generators that define the same polyhedron
47348  and vice versa.
47349  These systems can contain redundant members: in this case we say
47350  that they are not in the minimal form.
47351
47352  Two key attributes of any polyhedron are its topological kind
47353  (recording whether it is a C_Polyhedron or an NNC_Polyhedron object)
47354  and its space dimension (the dimension \f$n \in \Nset\f$ of
47355  the enclosing vector space):
47356
47357  - all polyhedra, the empty ones included, are endowed with
47358    a specific topology and space dimension;
47359  - most operations working on a polyhedron and another object
47360    (i.e., another polyhedron, a constraint or generator,
47361    a set of variables, etc.) will throw an exception if
47362    the polyhedron and the object are not both topology-compatible
47363    and dimension-compatible (see Section \ref representation);
47364  - the topology of a polyhedron cannot be changed;
47365    rather, there are constructors for each of the two derived classes
47366    that will build a new polyhedron with the topology of that class
47367    from another polyhedron from either class and any topology;
47368  - the only ways in which the space dimension of a polyhedron can
47369    be changed are:
47370    - <EM>explicit</EM> calls to operators provided for that purpose;
47371    - standard copy, assignment and swap operators.
47372
47373  Note that four different polyhedra can be defined on
47374  the zero-dimension space:
47375  the empty polyhedron, either closed or NNC,
47376  and the universe polyhedron \f$R^0\f$, again either closed or NNC.
47377
47378  \par
47379  In all the examples it is assumed that variables
47380  <CODE>x</CODE> and <CODE>y</CODE> are defined (where they are
47381  used) as follows:
47382  \code
47383  Variable x(0);
47384  Variable y(1);
47385  \endcode
47386
47387  \par Example 1
47388  The following code builds a polyhedron corresponding to
47389  a square in \f$\Rset^2\f$, given as a system of constraints:
47390  \code
47391  Constraint_System cs;
47392  cs.insert(x >= 0);
47393  cs.insert(x <= 3);
47394  cs.insert(y >= 0);
47395  cs.insert(y <= 3);
47396  C_Polyhedron ph(cs);
47397  \endcode
47398  The following code builds the same polyhedron as above,
47399  but starting from a system of generators specifying
47400  the four vertices of the square:
47401  \code
47402  Generator_System gs;
47403  gs.insert(point(0*x + 0*y));
47404  gs.insert(point(0*x + 3*y));
47405  gs.insert(point(3*x + 0*y));
47406  gs.insert(point(3*x + 3*y));
47407  C_Polyhedron ph(gs);
47408  \endcode
47409
47410  \par Example 2
47411  The following code builds an unbounded polyhedron
47412  corresponding to a half-strip in \f$\Rset^2\f$,
47413  given as a system of constraints:
47414  \code
47415  Constraint_System cs;
47416  cs.insert(x >= 0);
47417  cs.insert(x - y <= 0);
47418  cs.insert(x - y + 1 >= 0);
47419  C_Polyhedron ph(cs);
47420  \endcode
47421  The following code builds the same polyhedron as above,
47422  but starting from the system of generators specifying
47423  the two vertices of the polyhedron and one ray:
47424  \code
47425  Generator_System gs;
47426  gs.insert(point(0*x + 0*y));
47427  gs.insert(point(0*x + y));
47428  gs.insert(ray(x - y));
47429  C_Polyhedron ph(gs);
47430  \endcode
47431
47432  \par Example 3
47433  The following code builds the polyhedron corresponding to
47434  a half-plane by adding a single constraint
47435  to the universe polyhedron in \f$\Rset^2\f$:
47436  \code
47437  C_Polyhedron ph(2);
47438  ph.add_constraint(y >= 0);
47439  \endcode
47440  The following code builds the same polyhedron as above,
47441  but starting from the empty polyhedron in the space \f$\Rset^2\f$
47442  and inserting the appropriate generators
47443  (a point, a ray and a line).
47444  \code
47445  C_Polyhedron ph(2, EMPTY);
47446  ph.add_generator(point(0*x + 0*y));
47447  ph.add_generator(ray(y));
47448  ph.add_generator(line(x));
47449  \endcode
47450  Note that, although the above polyhedron has no vertices, we must add
47451  one point, because otherwise the result of the Minkowski's sum
47452  would be an empty polyhedron.
47453  To avoid subtle errors related to the minimization process,
47454  it is required that the first generator inserted in an empty
47455  polyhedron is a point (otherwise, an exception is thrown).
47456
47457  \par Example 4
47458  The following code shows the use of the function
47459  <CODE>add_space_dimensions_and_embed</CODE>:
47460  \code
47461  C_Polyhedron ph(1);
47462  ph.add_constraint(x == 2);
47463  ph.add_space_dimensions_and_embed(1);
47464  \endcode
47465  We build the universe polyhedron in the 1-dimension space \f$\Rset\f$.
47466  Then we add a single equality constraint,
47467  thus obtaining the polyhedron corresponding to the singleton set
47468  \f$\{ 2 \} \sseq \Rset\f$.
47469  After the last line of code, the resulting polyhedron is
47470  \f[
47471    \bigl\{\,
47472      (2, y)^\transpose \in \Rset^2
47473    \bigm|
47474      y \in \Rset
47475    \,\bigr\}.
47476  \f]
47477
47478  \par Example 5
47479  The following code shows the use of the function
47480  <CODE>add_space_dimensions_and_project</CODE>:
47481  \code
47482  C_Polyhedron ph(1);
47483  ph.add_constraint(x == 2);
47484  ph.add_space_dimensions_and_project(1);
47485  \endcode
47486  The first two lines of code are the same as in Example 4 for
47487  <CODE>add_space_dimensions_and_embed</CODE>.
47488  After the last line of code, the resulting polyhedron is
47489  the singleton set
47490  \f$\bigl\{ (2, 0)^\transpose \bigr\} \sseq \Rset^2\f$.
47491
47492  \par Example 6
47493  The following code shows the use of the function
47494  <CODE>affine_image</CODE>:
47495  \code
47496  C_Polyhedron ph(2, EMPTY);
47497  ph.add_generator(point(0*x + 0*y));
47498  ph.add_generator(point(0*x + 3*y));
47499  ph.add_generator(point(3*x + 0*y));
47500  ph.add_generator(point(3*x + 3*y));
47501  Linear_Expression expr = x + 4;
47502  ph.affine_image(x, expr);
47503  \endcode
47504  In this example the starting polyhedron is a square in
47505  \f$\Rset^2\f$, the considered variable is \f$x\f$ and the affine
47506  expression is \f$x+4\f$.  The resulting polyhedron is the same
47507  square translated to the right.  Moreover, if the affine
47508  transformation for the same variable \p x is \f$x+y\f$:
47509  \code
47510  Linear_Expression expr = x + y;
47511  \endcode
47512  the resulting polyhedron is a parallelogram with the height equal to
47513  the side of the square and the oblique sides parallel to the line
47514  \f$x-y\f$.
47515  Instead, if we do not use an invertible transformation for the same
47516  variable; for example, the affine expression \f$y\f$:
47517  \code
47518  Linear_Expression expr = y;
47519  \endcode
47520  the resulting polyhedron is a diagonal of the square.
47521
47522  \par Example 7
47523  The following code shows the use of the function
47524  <CODE>affine_preimage</CODE>:
47525  \code
47526  C_Polyhedron ph(2);
47527  ph.add_constraint(x >= 0);
47528  ph.add_constraint(x <= 3);
47529  ph.add_constraint(y >= 0);
47530  ph.add_constraint(y <= 3);
47531  Linear_Expression expr = x + 4;
47532  ph.affine_preimage(x, expr);
47533  \endcode
47534  In this example the starting polyhedron, \p var and the affine
47535  expression and the denominator are the same as in Example 6,
47536  while the resulting polyhedron is again the same square,
47537  but translated to the left.
47538  Moreover, if the affine transformation for \p x is \f$x+y\f$
47539  \code
47540  Linear_Expression expr = x + y;
47541  \endcode
47542  the resulting polyhedron is a parallelogram with the height equal to
47543  the side of the square and the oblique sides parallel to the line
47544  \f$x+y\f$.
47545  Instead, if we do not use an invertible transformation for the same
47546  variable \p x, for example, the affine expression \f$y\f$:
47547  \code
47548  Linear_Expression expr = y;
47549  \endcode
47550  the resulting polyhedron is a line that corresponds to the \f$y\f$ axis.
47551
47552  \par Example 8
47553  For this example we use also the variables:
47554  \code
47555  Variable z(2);
47556  Variable w(3);
47557  \endcode
47558  The following code shows the use of the function
47559  <CODE>remove_space_dimensions</CODE>:
47560  \code
47561  Generator_System gs;
47562  gs.insert(point(3*x + y + 0*z + 2*w));
47563  C_Polyhedron ph(gs);
47564  Variables_Set vars;
47565  vars.insert(y);
47566  vars.insert(z);
47567  ph.remove_space_dimensions(vars);
47568  \endcode
47569  The starting polyhedron is the singleton set
47570  \f$\bigl\{ (3, 1, 0, 2)^\transpose \bigr\} \sseq \Rset^4\f$, while
47571  the resulting polyhedron is
47572  \f$\bigl\{ (3, 2)^\transpose \bigr\} \sseq \Rset^2\f$.
47573  Be careful when removing space dimensions <EM>incrementally</EM>:
47574  since dimensions are automatically renamed after each application
47575  of the <CODE>remove_space_dimensions</CODE> operator, unexpected
47576  results can be obtained.
47577  For instance, by using the following code we would obtain
47578  a different result:
47579  \code
47580  set<Variable> vars1;
47581  vars1.insert(y);
47582  ph.remove_space_dimensions(vars1);
47583  set<Variable> vars2;
47584  vars2.insert(z);
47585  ph.remove_space_dimensions(vars2);
47586  \endcode
47587  In this case, the result is the polyhedron
47588  \f$\bigl\{(3, 0)^\transpose \bigr\} \sseq \Rset^2\f$:
47589  when removing the set of dimensions \p vars2
47590  we are actually removing variable \f$w\f$ of the original polyhedron.
47591  For the same reason, the operator \p remove_space_dimensions
47592  is not idempotent: removing twice the same non-empty set of dimensions
47593  is never the same as removing them just once.
47594*/
47595
47596class Parma_Polyhedra_Library::Polyhedron {
47597public:
47598  //! The numeric type of coefficients.
47599  typedef Coefficient coefficient_type;
47600
47601  //! Returns the maximum space dimension all kinds of Polyhedron can handle.
47602  static dimension_type max_space_dimension();
47603
47604  /*! \brief
47605    Returns \c true indicating that this domain has methods that
47606    can recycle constraints.
47607  */
47608  static bool can_recycle_constraint_systems();
47609
47610  //! Initializes the class.
47611  static void initialize();
47612
47613  //! Finalizes the class.
47614  static void finalize();
47615
47616  /*! \brief
47617    Returns \c false indicating that this domain cannot recycle congruences.
47618  */
47619  static bool can_recycle_congruence_systems();
47620
47621protected:
47622  //! Builds a polyhedron having the specified properties.
47623  /*!
47624    \param topol
47625    The topology of the polyhedron;
47626
47627    \param num_dimensions
47628    The number of dimensions of the vector space enclosing the polyhedron;
47629
47630    \param kind
47631    Specifies whether the universe or the empty polyhedron has to be built.
47632  */
47633  Polyhedron(Topology topol,
47634             dimension_type num_dimensions,
47635             Degenerate_Element kind);
47636
47637  //! Ordinary copy constructor.
47638  /*!
47639    The complexity argument is ignored.
47640  */
47641  Polyhedron(const Polyhedron& y,
47642             Complexity_Class complexity = ANY_COMPLEXITY);
47643
47644  //! Builds a polyhedron from a system of constraints.
47645  /*!
47646    The polyhedron inherits the space dimension of the constraint system.
47647
47648    \param topol
47649    The topology of the polyhedron;
47650
47651    \param cs
47652    The system of constraints defining the polyhedron.
47653
47654    \exception std::invalid_argument
47655    Thrown if the topology of \p cs is incompatible with \p topol.
47656  */
47657  Polyhedron(Topology topol, const Constraint_System& cs);
47658
47659  //! Builds a polyhedron recycling a system of constraints.
47660  /*!
47661    The polyhedron inherits the space dimension of the constraint system.
47662
47663    \param topol
47664    The topology of the polyhedron;
47665
47666    \param cs
47667    The system of constraints defining the polyhedron.  It is not
47668    declared <CODE>const</CODE> because its data-structures may be
47669    recycled to build the polyhedron.
47670
47671    \param dummy
47672    A dummy tag to syntactically differentiate this one
47673    from the other constructors.
47674
47675    \exception std::invalid_argument
47676    Thrown if the topology of \p cs is incompatible with \p topol.
47677  */
47678  Polyhedron(Topology topol, Constraint_System& cs, Recycle_Input dummy);
47679
47680  //! Builds a polyhedron from a system of generators.
47681  /*!
47682    The polyhedron inherits the space dimension of the generator system.
47683
47684    \param topol
47685    The topology of the polyhedron;
47686
47687    \param gs
47688    The system of generators defining the polyhedron.
47689
47690    \exception std::invalid_argument
47691    Thrown if the topology of \p gs is incompatible with \p topol,
47692    or if the system of generators is not empty but has no points.
47693  */
47694  Polyhedron(Topology topol, const Generator_System& gs);
47695
47696  //! Builds a polyhedron recycling a system of generators.
47697  /*!
47698    The polyhedron inherits the space dimension of the generator system.
47699
47700    \param topol
47701    The topology of the polyhedron;
47702
47703    \param gs
47704    The system of generators defining the polyhedron.  It is not
47705    declared <CODE>const</CODE> because its data-structures may be
47706    recycled to build the polyhedron.
47707
47708    \param dummy
47709    A dummy tag to syntactically differentiate this one
47710    from the other constructors.
47711
47712    \exception std::invalid_argument
47713    Thrown if the topology of \p gs is incompatible with \p topol,
47714    or if the system of generators is not empty but has no points.
47715  */
47716  Polyhedron(Topology topol, Generator_System& gs, Recycle_Input dummy);
47717
47718  //! Builds a polyhedron from a box.
47719  /*!
47720    This will use an algorithm whose complexity is polynomial and build
47721    the smallest polyhedron with topology \p topol containing \p box.
47722
47723    \param topol
47724    The topology of the polyhedron;
47725
47726    \param box
47727    The box representing the polyhedron to be built;
47728
47729    \param complexity
47730    This argument is ignored.
47731  */
47732  template <typename Interval>
47733  Polyhedron(Topology topol, const Box<Interval>& box,
47734             Complexity_Class complexity = ANY_COMPLEXITY);
47735
47736  /*! \brief
47737    The assignment operator.
47738    (\p *this and \p y can be dimension-incompatible.)
47739  */
47740  Polyhedron& operator=(const Polyhedron& y);
47741
47742public:
47743  //! \name Member Functions that Do Not Modify the Polyhedron
47744  //@{
47745
47746  //! Returns the dimension of the vector space enclosing \p *this.
47747  dimension_type space_dimension() const;
47748
47749  /*! \brief
47750    Returns \f$0\f$, if \p *this is empty; otherwise, returns the
47751    \ref Affine_Independence_and_Affine_Dimension "affine dimension"
47752    of \p *this.
47753  */
47754  dimension_type affine_dimension() const;
47755
47756  //! Returns the system of constraints.
47757  const Constraint_System& constraints() const;
47758
47759  //! Returns the system of constraints, with no redundant constraint.
47760  const Constraint_System& minimized_constraints() const;
47761
47762  //! Returns the system of generators.
47763  const Generator_System& generators() const;
47764
47765  //! Returns the system of generators, with no redundant generator.
47766  const Generator_System& minimized_generators() const;
47767
47768  //! Returns a system of (equality) congruences satisfied by \p *this.
47769  Congruence_System congruences() const;
47770
47771  /*! \brief
47772    Returns a system of (equality) congruences satisfied by \p *this,
47773    with no redundant congruences and having the same affine dimension
47774    as \p *this.
47775  */
47776  Congruence_System minimized_congruences() const;
47777
47778  /*! \brief
47779    Returns the relations holding between the polyhedron \p *this
47780    and the constraint \p c.
47781
47782    \exception std::invalid_argument
47783    Thrown if \p *this and constraint \p c are dimension-incompatible.
47784  */
47785  Poly_Con_Relation relation_with(const Constraint& c) const;
47786
47787  /*! \brief
47788    Returns the relations holding between the polyhedron \p *this
47789    and the generator \p g.
47790
47791    \exception std::invalid_argument
47792    Thrown if \p *this and generator \p g are dimension-incompatible.
47793  */
47794  Poly_Gen_Relation relation_with(const Generator& g) const;
47795
47796  /*! \brief
47797    Returns the relations holding between the polyhedron \p *this
47798    and the congruence \p c.
47799
47800    \exception std::invalid_argument
47801    Thrown if \p *this and congruence \p c are dimension-incompatible.
47802  */
47803  Poly_Con_Relation relation_with(const Congruence& cg) const;
47804
47805  /*! \brief
47806    Returns <CODE>true</CODE> if and only if \p *this is
47807    an empty polyhedron.
47808  */
47809  bool is_empty() const;
47810
47811  /*! \brief
47812    Returns <CODE>true</CODE> if and only if \p *this
47813    is a universe polyhedron.
47814  */
47815  bool is_universe() const;
47816
47817  /*! \brief
47818    Returns <CODE>true</CODE> if and only if \p *this
47819    is a topologically closed subset of the vector space.
47820  */
47821  bool is_topologically_closed() const;
47822
47823  //! Returns <CODE>true</CODE> if and only if \p *this and \p y are disjoint.
47824  /*!
47825    \exception std::invalid_argument
47826    Thrown if \p x and \p y are topology-incompatible or
47827    dimension-incompatible.
47828  */
47829  bool is_disjoint_from(const Polyhedron& y) const;
47830
47831  //! Returns <CODE>true</CODE> if and only if \p *this is discrete.
47832  bool is_discrete() const;
47833
47834  /*! \brief
47835    Returns <CODE>true</CODE> if and only if \p *this
47836    is a bounded polyhedron.
47837  */
47838  bool is_bounded() const;
47839
47840  /*! \brief
47841    Returns <CODE>true</CODE> if and only if \p *this
47842    contains at least one integer point.
47843  */
47844  bool contains_integer_point() const;
47845
47846  /*! \brief
47847    Returns <CODE>true</CODE> if and only if \p var is constrained in
47848    \p *this.
47849
47850    \exception std::invalid_argument
47851    Thrown if \p var is not a space dimension of \p *this.
47852  */
47853  bool constrains(Variable var) const;
47854
47855  /*! \brief
47856    Returns <CODE>true</CODE> if and only if \p expr is
47857    bounded from above in \p *this.
47858
47859    \exception std::invalid_argument
47860    Thrown if \p expr and \p *this are dimension-incompatible.
47861  */
47862  bool bounds_from_above(const Linear_Expression& expr) const;
47863
47864  /*! \brief
47865    Returns <CODE>true</CODE> if and only if \p expr is
47866    bounded from below in \p *this.
47867
47868    \exception std::invalid_argument
47869    Thrown if \p expr and \p *this are dimension-incompatible.
47870  */
47871  bool bounds_from_below(const Linear_Expression& expr) const;
47872
47873  /*! \brief
47874    Returns <CODE>true</CODE> if and only if \p *this is not empty
47875    and \p expr is bounded from above in \p *this, in which case
47876    the supremum value is computed.
47877
47878    \param expr
47879    The linear expression to be maximized subject to \p *this;
47880
47881    \param sup_n
47882    The numerator of the supremum value;
47883
47884    \param sup_d
47885    The denominator of the supremum value;
47886
47887    \param maximum
47888    <CODE>true</CODE> if and only if the supremum is also the maximum value.
47889
47890    \exception std::invalid_argument
47891    Thrown if \p expr and \p *this are dimension-incompatible.
47892
47893    If \p *this is empty or \p expr is not bounded from above,
47894    <CODE>false</CODE> is returned and \p sup_n, \p sup_d
47895    and \p maximum are left untouched.
47896  */
47897  bool maximize(const Linear_Expression& expr,
47898                Coefficient& sup_n, Coefficient& sup_d, bool& maximum) const;
47899
47900  /*! \brief
47901    Returns <CODE>true</CODE> if and only if \p *this is not empty
47902    and \p expr is bounded from above in \p *this, in which case
47903    the supremum value and a point where \p expr reaches it are computed.
47904
47905    \param expr
47906    The linear expression to be maximized subject to \p *this;
47907
47908    \param sup_n
47909    The numerator of the supremum value;
47910
47911    \param sup_d
47912    The denominator of the supremum value;
47913
47914    \param maximum
47915    <CODE>true</CODE> if and only if the supremum is also the maximum value;
47916
47917    \param g
47918    When maximization succeeds, will be assigned the point or
47919    closure point where \p expr reaches its supremum value.
47920
47921    \exception std::invalid_argument
47922    Thrown if \p expr and \p *this are dimension-incompatible.
47923
47924    If \p *this is empty or \p expr is not bounded from above,
47925    <CODE>false</CODE> is returned and \p sup_n, \p sup_d, \p maximum
47926    and \p g are left untouched.
47927  */
47928  bool maximize(const Linear_Expression& expr,
47929                Coefficient& sup_n, Coefficient& sup_d, bool& maximum,
47930                Generator& g) const;
47931
47932  /*! \brief
47933    Returns <CODE>true</CODE> if and only if \p *this is not empty
47934    and \p expr is bounded from below in \p *this, in which case
47935    the infimum value is computed.
47936
47937    \param expr
47938    The linear expression to be minimized subject to \p *this;
47939
47940    \param inf_n
47941    The numerator of the infimum value;
47942
47943    \param inf_d
47944    The denominator of the infimum value;
47945
47946    \param minimum
47947    <CODE>true</CODE> if and only if the infimum is also the minimum value.
47948
47949    \exception std::invalid_argument
47950    Thrown if \p expr and \p *this are dimension-incompatible.
47951
47952    If \p *this is empty or \p expr is not bounded from below,
47953    <CODE>false</CODE> is returned and \p inf_n, \p inf_d
47954    and \p minimum are left untouched.
47955  */
47956  bool minimize(const Linear_Expression& expr,
47957                Coefficient& inf_n, Coefficient& inf_d, bool& minimum) const;
47958
47959  /*! \brief
47960    Returns <CODE>true</CODE> if and only if \p *this is not empty
47961    and \p expr is bounded from below in \p *this, in which case
47962    the infimum value and a point where \p expr reaches it are computed.
47963
47964    \param expr
47965    The linear expression to be minimized subject to \p *this;
47966
47967    \param inf_n
47968    The numerator of the infimum value;
47969
47970    \param inf_d
47971    The denominator of the infimum value;
47972
47973    \param minimum
47974    <CODE>true</CODE> if and only if the infimum is also the minimum value;
47975
47976    \param g
47977    When minimization succeeds, will be assigned a point or
47978    closure point where \p expr reaches its infimum value.
47979
47980    \exception std::invalid_argument
47981    Thrown if \p expr and \p *this are dimension-incompatible.
47982
47983    If \p *this is empty or \p expr is not bounded from below,
47984    <CODE>false</CODE> is returned and \p inf_n, \p inf_d, \p minimum
47985    and \p g are left untouched.
47986  */
47987  bool minimize(const Linear_Expression& expr,
47988                Coefficient& inf_n, Coefficient& inf_d, bool& minimum,
47989                Generator& g) const;
47990
47991  /*! \brief
47992    Returns <CODE>true</CODE> if and only if there exist a
47993    unique value \p val such that \p *this
47994    saturates the equality <CODE>expr = val</CODE>.
47995
47996    \param expr
47997    The linear expression for which the frequency is needed;
47998
47999    \param freq_n
48000    If <CODE>true</CODE> is returned, the value is set to \f$0\f$;
48001    Present for interface compatibility with class Grid, where
48002    the \ref Grid_Frequency "frequency" can have a non-zero value;
48003
48004    \param freq_d
48005    If <CODE>true</CODE> is returned, the value is set to \f$1\f$;
48006
48007    \param val_n
48008    The numerator of \p val;
48009
48010    \param val_d
48011    The denominator of \p val;
48012
48013    \exception std::invalid_argument
48014    Thrown if \p expr and \p *this are dimension-incompatible.
48015
48016    If <CODE>false</CODE> is returned, then \p freq_n, \p freq_d,
48017    \p val_n and \p val_d are left untouched.
48018  */
48019  bool frequency(const Linear_Expression& expr,
48020                 Coefficient& freq_n, Coefficient& freq_d,
48021                 Coefficient& val_n, Coefficient& val_d) const;
48022
48023  //! Returns <CODE>true</CODE> if and only if \p *this contains \p y.
48024  /*!
48025    \exception std::invalid_argument
48026    Thrown if \p *this and \p y are topology-incompatible or
48027    dimension-incompatible.
48028  */
48029  bool contains(const Polyhedron& y) const;
48030
48031  //! Returns <CODE>true</CODE> if and only if \p *this strictly contains \p y.
48032  /*!
48033    \exception std::invalid_argument
48034    Thrown if \p *this and \p y are topology-incompatible or
48035    dimension-incompatible.
48036  */
48037  bool strictly_contains(const Polyhedron& y) const;
48038
48039  //! Checks if all the invariants are satisfied.
48040  /*!
48041    \return
48042    <CODE>true</CODE> if and only if \p *this satisfies all the
48043    invariants and either \p check_not_empty is <CODE>false</CODE> or
48044    \p *this is not empty.
48045
48046    \param check_not_empty
48047    <CODE>true</CODE> if and only if, in addition to checking the
48048    invariants, \p *this must be checked to be not empty.
48049
48050    The check is performed so as to intrude as little as possible.  If
48051    the library has been compiled with run-time assertions enabled,
48052    error messages are written on <CODE>std::cerr</CODE> in case
48053    invariants are violated. This is useful for the purpose of
48054    debugging the library.
48055  */
48056  bool OK(bool check_not_empty = false) const;
48057
48058  //@} // Member Functions that Do Not Modify the Polyhedron
48059
48060  //! \name Space Dimension Preserving Member Functions that May Modify the Polyhedron
48061  //@{
48062
48063  /*! \brief
48064    Adds a copy of constraint \p c to the system of constraints
48065    of \p *this (without minimizing the result).
48066
48067    \param c
48068    The constraint that will be added to the system of
48069    constraints of \p *this.
48070
48071    \exception std::invalid_argument
48072    Thrown if \p *this and constraint \p c are topology-incompatible
48073    or dimension-incompatible.
48074  */
48075  void add_constraint(const Constraint& c);
48076
48077  /*! \brief
48078    Adds a copy of generator \p g to the system of generators
48079    of \p *this (without minimizing the result).
48080
48081    \exception std::invalid_argument
48082    Thrown if \p *this and generator \p g are topology-incompatible or
48083    dimension-incompatible, or if \p *this is an empty polyhedron and
48084    \p g is not a point.
48085  */
48086  void add_generator(const Generator& g);
48087
48088  /*! \brief
48089    Adds a copy of congruence \p cg to \p *this,
48090    if \p cg can be exactly represented by a polyhedron.
48091
48092    \exception std::invalid_argument
48093    Thrown if \p *this and congruence \p cg are dimension-incompatible,
48094    of if \p cg is a proper congruence which is neither a tautology,
48095    nor a contradiction.
48096  */
48097  void add_congruence(const Congruence& cg);
48098
48099  /*! \brief
48100    Adds a copy of the constraints in \p cs to the system
48101    of constraints of \p *this (without minimizing the result).
48102
48103    \param cs
48104    Contains the constraints that will be added to the system of
48105    constraints of \p *this.
48106
48107    \exception std::invalid_argument
48108    Thrown if \p *this and \p cs are topology-incompatible or
48109    dimension-incompatible.
48110  */
48111  void add_constraints(const Constraint_System& cs);
48112
48113  /*! \brief
48114    Adds the constraints in \p cs to the system of constraints
48115    of \p *this (without minimizing the result).
48116
48117    \param cs
48118    The constraint system to be added to \p *this.  The constraints in
48119    \p cs may be recycled.
48120
48121    \exception std::invalid_argument
48122    Thrown if \p *this and \p cs are topology-incompatible or
48123    dimension-incompatible.
48124
48125    \warning
48126    The only assumption that can be made on \p cs upon successful or
48127    exceptional return is that it can be safely destroyed.
48128  */
48129  void add_recycled_constraints(Constraint_System& cs);
48130
48131  /*! \brief
48132    Adds a copy of the generators in \p gs to the system
48133    of generators of \p *this (without minimizing the result).
48134
48135    \param gs
48136    Contains the generators that will be added to the system of
48137    generators of \p *this.
48138
48139    \exception std::invalid_argument
48140    Thrown if \p *this and \p gs are topology-incompatible or
48141    dimension-incompatible, or if \p *this is empty and the system of
48142    generators \p gs is not empty, but has no points.
48143  */
48144  void add_generators(const Generator_System& gs);
48145
48146  /*! \brief
48147    Adds the generators in \p gs to the system of generators
48148    of \p *this (without minimizing the result).
48149
48150    \param gs
48151    The generator system to be added to \p *this.  The generators in
48152    \p gs may be recycled.
48153
48154    \exception std::invalid_argument
48155    Thrown if \p *this and \p gs are topology-incompatible or
48156    dimension-incompatible, or if \p *this is empty and the system of
48157    generators \p gs is not empty, but has no points.
48158
48159    \warning
48160    The only assumption that can be made on \p gs upon successful or
48161    exceptional return is that it can be safely destroyed.
48162  */
48163  void add_recycled_generators(Generator_System& gs);
48164
48165  /*! \brief
48166    Adds a copy of the congruences in \p cgs to \p *this,
48167    if all the congruences can be exactly represented by a polyhedron.
48168
48169    \param cgs
48170    The congruences to be added.
48171
48172    \exception std::invalid_argument
48173    Thrown if \p *this and \p cgs are dimension-incompatible,
48174    of if there exists in \p cgs a proper congruence which is
48175    neither a tautology, nor a contradiction.
48176  */
48177  void add_congruences(const Congruence_System& cgs);
48178
48179  /*! \brief
48180    Adds the congruences in \p cgs to \p *this,
48181    if all the congruences can be exactly represented by a polyhedron.
48182
48183    \param cgs
48184    The congruences to be added. Its elements may be recycled.
48185
48186    \exception std::invalid_argument
48187    Thrown if \p *this and \p cgs are dimension-incompatible,
48188    of if there exists in \p cgs a proper congruence which is
48189    neither a tautology, nor a contradiction
48190
48191    \warning
48192    The only assumption that can be made on \p cgs upon successful or
48193    exceptional return is that it can be safely destroyed.
48194  */
48195  void add_recycled_congruences(Congruence_System& cgs);
48196
48197  /*! \brief
48198    Uses a copy of constraint \p c to refine \p *this.
48199
48200    \exception std::invalid_argument
48201    Thrown if \p *this and constraint \p c are dimension-incompatible.
48202  */
48203  void refine_with_constraint(const Constraint& c);
48204
48205  /*! \brief
48206    Uses a copy of congruence \p cg to refine \p *this.
48207
48208    \exception std::invalid_argument
48209    Thrown if \p *this and congruence \p cg are dimension-incompatible.
48210  */
48211  void refine_with_congruence(const Congruence& cg);
48212
48213  /*! \brief
48214    Uses a copy of the constraints in \p cs to refine \p *this.
48215
48216    \param cs
48217    Contains the constraints used to refine the system of
48218    constraints of \p *this.
48219
48220    \exception std::invalid_argument
48221    Thrown if \p *this and \p cs are dimension-incompatible.
48222  */
48223  void refine_with_constraints(const Constraint_System& cs);
48224
48225  /*! \brief
48226    Uses a copy of the congruences in \p cgs to refine \p *this.
48227
48228    \param cgs
48229    Contains the congruences used to refine the system of
48230    constraints of \p *this.
48231
48232    \exception std::invalid_argument
48233    Thrown if \p *this and \p cgs are dimension-incompatible.
48234  */
48235  void refine_with_congruences(const Congruence_System& cgs);
48236
48237  /*! \brief
48238    Refines \p *this with the constraint expressed by \p left \f$<\f$
48239    \p right if \p is_strict is set, with the constraint \p left \f$\leq\f$
48240    \p right otherwise.
48241
48242    \param left
48243    The linear form on intervals with floating point boundaries that
48244    is on the left of the comparison operator. All of its coefficients
48245    MUST be bounded.
48246
48247    \param right
48248    The linear form on intervals with floating point boundaries that
48249    is on the right of the comparison operator. All of its coefficients
48250    MUST be bounded.
48251
48252    \param is_strict
48253    True if the comparison is strict.
48254
48255    \exception std::invalid_argument
48256    Thrown if \p left (or \p right) is dimension-incompatible with \p *this.
48257
48258    This function is used in abstract interpretation to model a filter
48259    that is generated by a comparison of two expressions that are correctly
48260    approximated by \p left and \p right respectively.
48261  */
48262  template <typename FP_Format, typename Interval_Info>
48263  void refine_with_linear_form_inequality(
48264  const Linear_Form< Interval<FP_Format, Interval_Info> >& left,
48265  const Linear_Form< Interval<FP_Format, Interval_Info> >& right,
48266  bool is_strict = false);
48267
48268  /*! \brief
48269    Refines \p *this with the constraint expressed by \p left \f$\relsym\f$
48270    \p right, where \f$\relsym\f$ is the relation symbol specified by
48271    \p relsym..
48272
48273    \param left
48274    The linear form on intervals with floating point boundaries that
48275    is on the left of the comparison operator. All of its coefficients
48276    MUST be bounded.
48277
48278    \param right
48279    The linear form on intervals with floating point boundaries that
48280    is on the right of the comparison operator. All of its coefficients
48281    MUST be bounded.
48282
48283    \param relsym
48284    The relation symbol.
48285
48286    \exception std::invalid_argument
48287    Thrown if \p left (or \p right) is dimension-incompatible with \p *this.
48288
48289    \exception std::runtime_error
48290    Thrown if \p relsym is not a valid relation symbol.
48291
48292    This function is used in abstract interpretation to model a filter
48293    that is generated by a comparison of two expressions that are correctly
48294    approximated by \p left and \p right respectively.
48295  */
48296  template <typename FP_Format, typename Interval_Info>
48297  void generalized_refine_with_linear_form_inequality(
48298  const Linear_Form< Interval<FP_Format, Interval_Info> >& left,
48299  const Linear_Form< Interval<FP_Format, Interval_Info> >& right,
48300  Relation_Symbol relsym);
48301
48302  //! Refines \p store with the constraints defining \p *this.
48303  /*!
48304    \param store
48305    The interval floating point abstract store to refine.
48306  */
48307  template <typename FP_Format, typename Interval_Info>
48308  void refine_fp_interval_abstract_store(
48309       Box< Interval<FP_Format, Interval_Info> >& store)
48310       const;
48311
48312  /*! \brief
48313    Computes the \ref Cylindrification "cylindrification" of \p *this with
48314    respect to space dimension \p var, assigning the result to \p *this.
48315
48316    \param var
48317    The space dimension that will be unconstrained.
48318
48319    \exception std::invalid_argument
48320    Thrown if \p var is not a space dimension of \p *this.
48321  */
48322  void unconstrain(Variable var);
48323
48324  /*! \brief
48325    Computes the \ref Cylindrification "cylindrification" of \p *this with
48326    respect to the set of space dimensions \p vars,
48327    assigning the result to \p *this.
48328
48329    \param vars
48330    The set of space dimension that will be unconstrained.
48331
48332    \exception std::invalid_argument
48333    Thrown if \p *this is dimension-incompatible with one of the
48334    Variable objects contained in \p vars.
48335  */
48336  void unconstrain(const Variables_Set& vars);
48337
48338  /*! \brief
48339    Assigns to \p *this the intersection of \p *this and \p y.
48340
48341    \exception std::invalid_argument
48342    Thrown if \p *this and \p y are topology-incompatible or
48343    dimension-incompatible.
48344  */
48345  void intersection_assign(const Polyhedron& y);
48346
48347  /*! \brief
48348    Assigns to \p *this the poly-hull of \p *this and \p y.
48349
48350    \exception std::invalid_argument
48351    Thrown if \p *this and \p y are topology-incompatible or
48352    dimension-incompatible.
48353  */
48354  void poly_hull_assign(const Polyhedron& y);
48355
48356  //! Same as poly_hull_assign(y).
48357  void upper_bound_assign(const Polyhedron& y);
48358
48359  /*! \brief
48360    Assigns to \p *this
48361    the \ref Convex_Polyhedral_Difference "poly-difference"
48362    of \p *this and \p y.
48363
48364    \exception std::invalid_argument
48365    Thrown if \p *this and \p y are topology-incompatible or
48366    dimension-incompatible.
48367  */
48368  void poly_difference_assign(const Polyhedron& y);
48369
48370  //! Same as poly_difference_assign(y).
48371  void difference_assign(const Polyhedron& y);
48372
48373  /*! \brief
48374    Assigns to \p *this a \ref Meet_Preserving_Simplification
48375    "meet-preserving simplification" of \p *this with respect to \p y.
48376    If \c false is returned, then the intersection is empty.
48377
48378    \exception std::invalid_argument
48379    Thrown if \p *this and \p y are topology-incompatible or
48380    dimension-incompatible.
48381  */
48382  bool simplify_using_context_assign(const Polyhedron& y);
48383
48384  /*! \brief
48385    Assigns to \p *this the
48386    \ref Single_Update_Affine_Functions "affine image"
48387    of \p *this under the function mapping variable \p var to the
48388    affine expression specified by \p expr and \p denominator.
48389
48390    \param var
48391    The variable to which the affine expression is assigned;
48392
48393    \param expr
48394    The numerator of the affine expression;
48395
48396    \param denominator
48397    The denominator of the affine expression (optional argument with
48398    default value 1).
48399
48400    \exception std::invalid_argument
48401    Thrown if \p denominator is zero or if \p expr and \p *this are
48402    dimension-incompatible or if \p var is not a space dimension of
48403    \p *this.
48404
48405    \if Include_Implementation_Details
48406
48407    When considering the generators of a polyhedron, the
48408    affine transformation
48409    \f[
48410      \frac{\sum_{i=0}^{n-1} a_i x_i + b}{\mathrm{denominator}}
48411    \f]
48412    is assigned to \p var where \p expr is
48413    \f$\sum_{i=0}^{n-1} a_i x_i + b\f$
48414    (\f$b\f$ is the inhomogeneous term).
48415
48416    If constraints are up-to-date, it uses the specialized function
48417    affine_preimage() (for the system of constraints)
48418    and inverse transformation to reach the same result.
48419    To obtain the inverse transformation we use the following observation.
48420
48421    Observation:
48422    -# The affine transformation is invertible if the coefficient
48423       of \p var in this transformation (i.e., \f$a_\mathrm{var}\f$)
48424       is different from zero.
48425    -# If the transformation is invertible, then we can write
48426       \f[
48427         \mathrm{denominator} * {x'}_\mathrm{var}
48428           = \sum_{i = 0}^{n - 1} a_i x_i + b
48429           = a_\mathrm{var} x_\mathrm{var}
48430             + \sum_{i \neq var} a_i x_i + b,
48431       \f]
48432       so that the inverse transformation is
48433       \f[
48434         a_\mathrm{var} x_\mathrm{var}
48435           = \mathrm{denominator} * {x'}_\mathrm{var}
48436             - \sum_{i \neq j} a_i x_i - b.
48437       \f]
48438
48439    Then, if the transformation is invertible, all the entities that
48440    were up-to-date remain up-to-date. Otherwise only generators remain
48441    up-to-date.
48442
48443    In other words, if \f$R\f$ is a \f$m_1 \times n\f$ matrix representing
48444    the rays of the polyhedron, \f$V\f$ is a \f$m_2 \times n\f$
48445    matrix representing the points of the polyhedron and
48446    \f[
48447      P = \bigl\{\,
48448            \vect{x} = (x_0, \ldots, x_{n-1})^\mathrm{T}
48449          \bigm|
48450            \vect{x} = \vect{\lambda} R + \vect{\mu} V,
48451            \vect{\lambda} \in \Rset^{m_1}_+,
48452            \vect{\mu} \in \Rset^{m_2}_+,
48453            \sum_{i = 0}^{m_2 - 1} \mu_i = 1
48454          \,\bigr\}
48455    \f]
48456    and \f$T\f$ is the affine transformation to apply to \f$P\f$, then
48457    the resulting polyhedron is
48458    \f[
48459      P' = \bigl\{\,
48460             (x_0, \ldots, T(x_0, \ldots, x_{n-1}),
48461                     \ldots, x_{n-1})^\mathrm{T}
48462           \bigm|
48463             (x_0, \ldots, x_{n-1})^\mathrm{T} \in P
48464           \,\bigr\}.
48465    \f]
48466
48467    Affine transformations are, for example:
48468    - translations
48469    - rotations
48470    - symmetries.
48471    \endif
48472  */
48473  void affine_image(Variable var,
48474                    const Linear_Expression& expr,
48475                    Coefficient_traits::const_reference denominator
48476                      = Coefficient_one());
48477
48478  // FIXME: To be completed.
48479  /*!
48480    Assigns to \p *this the
48481    \ref affine_form_relation "affine form image"
48482    of \p *this under the function mapping variable \p var into the
48483    affine expression(s) specified by \p lf.
48484
48485    \param var
48486    The variable to which the affine expression is assigned.
48487
48488    \param lf
48489    The linear form on intervals with floating point boundaries that
48490    defines the affine expression(s). ALL of its coefficients MUST be bounded.
48491
48492    \exception std::invalid_argument
48493    Thrown if \p lf and \p *this are dimension-incompatible or if \p var is
48494    not a space dimension of \p *this.
48495
48496    This function is used in abstract interpretation to model an assignment
48497    of a value that is correctly overapproximated by \p lf to the
48498    floating point variable represented by \p var.
48499  */
48500  template <typename FP_Format, typename Interval_Info>
48501  void affine_form_image(Variable var,
48502  const Linear_Form<Interval <FP_Format, Interval_Info> >& lf);
48503
48504  /*! \brief
48505    Assigns to \p *this the
48506    \ref Single_Update_Affine_Functions "affine preimage"
48507    of \p *this under the function mapping variable \p var to the
48508    affine expression specified by \p expr and \p denominator.
48509
48510    \param var
48511    The variable to which the affine expression is substituted;
48512
48513    \param expr
48514    The numerator of the affine expression;
48515
48516    \param denominator
48517    The denominator of the affine expression (optional argument with
48518    default value 1).
48519
48520    \exception std::invalid_argument
48521    Thrown if \p denominator is zero or if \p expr and \p *this are
48522    dimension-incompatible or if \p var is not a space dimension of \p *this.
48523
48524    \if Include_Implementation_Details
48525
48526    When considering constraints of a polyhedron, the affine transformation
48527    \f[
48528      \frac{\sum_{i=0}^{n-1} a_i x_i + b}{denominator},
48529    \f]
48530    is assigned to \p var where \p expr is
48531    \f$\sum_{i=0}^{n-1} a_i x_i + b\f$
48532    (\f$b\f$ is the inhomogeneous term).
48533
48534    If generators are up-to-date, then the specialized function
48535    affine_image() is used (for the system of generators)
48536    and inverse transformation to reach the same result.
48537    To obtain the inverse transformation, we use the following observation.
48538
48539    Observation:
48540    -# The affine transformation is invertible if the coefficient
48541       of \p var in this transformation (i.e. \f$a_\mathrm{var}\f$)
48542       is different from zero.
48543    -# If the transformation is invertible, then we can write
48544       \f[
48545         \mathrm{denominator} * {x'}_\mathrm{var}
48546           = \sum_{i = 0}^{n - 1} a_i x_i + b
48547           = a_\mathrm{var} x_\mathrm{var}
48548               + \sum_{i \neq \mathrm{var}} a_i x_i + b,
48549       \f],
48550       the inverse transformation is
48551       \f[
48552         a_\mathrm{var} x_\mathrm{var}
48553           = \mathrm{denominator} * {x'}_\mathrm{var}
48554               - \sum_{i \neq j} a_i x_i - b.
48555       \f].
48556
48557    Then, if the transformation is invertible, all the entities that
48558    were up-to-date remain up-to-date. Otherwise only constraints remain
48559    up-to-date.
48560
48561    In other words, if \f$A\f$ is a \f$m \times n\f$ matrix representing
48562    the constraints of the polyhedron, \f$T\f$ is the affine transformation
48563    to apply to \f$P\f$ and
48564    \f[
48565      P = \bigl\{\,
48566            \vect{x} = (x_0, \ldots, x_{n-1})^\mathrm{T}
48567          \bigm|
48568            A\vect{x} \geq \vect{0}
48569          \,\bigr\}.
48570    \f]
48571    The resulting polyhedron is
48572    \f[
48573      P' = \bigl\{\,
48574             \vect{x} = (x_0, \ldots, x_{n-1}))^\mathrm{T}
48575           \bigm|
48576             A'\vect{x} \geq \vect{0}
48577           \,\bigr\},
48578    \f]
48579    where \f$A'\f$ is defined as follows:
48580    \f[
48581      {a'}_{ij}
48582        = \begin{cases}
48583            a_{ij} * \mathrm{denominator} + a_{i\mathrm{var}}*\mathrm{expr}[j]
48584              \quad \mathrm{for } j \neq \mathrm{var}; \\
48585            \mathrm{expr}[\mathrm{var}] * a_{i\mathrm{var}},
48586              \quad \text{for } j = \mathrm{var}.
48587          \end{cases}
48588    \f]
48589    \endif
48590  */
48591  void affine_preimage(Variable var,
48592                       const Linear_Expression& expr,
48593                       Coefficient_traits::const_reference denominator
48594                         = Coefficient_one());
48595
48596  /*! \brief
48597    Assigns to \p *this the image of \p *this with respect to the
48598    \ref Generalized_Affine_Relations "generalized affine relation"
48599    \f$\mathrm{var}' \relsym \frac{\mathrm{expr}}{\mathrm{denominator}}\f$,
48600    where \f$\mathord{\relsym}\f$ is the relation symbol encoded
48601    by \p relsym.
48602
48603    \param var
48604    The left hand side variable of the generalized affine relation;
48605
48606    \param relsym
48607    The relation symbol;
48608
48609    \param expr
48610    The numerator of the right hand side affine expression;
48611
48612    \param denominator
48613    The denominator of the right hand side affine expression (optional
48614    argument with default value 1).
48615
48616    \exception std::invalid_argument
48617    Thrown if \p denominator is zero or if \p expr and \p *this are
48618    dimension-incompatible or if \p var is not a space dimension of \p *this
48619    or if \p *this is a C_Polyhedron and \p relsym is a strict
48620    relation symbol.
48621  */
48622  void generalized_affine_image(Variable var,
48623                                Relation_Symbol relsym,
48624                                const Linear_Expression& expr,
48625                                Coefficient_traits::const_reference denominator
48626                                = Coefficient_one());
48627
48628  /*! \brief
48629    Assigns to \p *this the preimage of \p *this with respect to the
48630    \ref Generalized_Affine_Relations "generalized affine relation"
48631    \f$\mathrm{var}' \relsym \frac{\mathrm{expr}}{\mathrm{denominator}}\f$,
48632    where \f$\mathord{\relsym}\f$ is the relation symbol encoded
48633    by \p relsym.
48634
48635    \param var
48636    The left hand side variable of the generalized affine relation;
48637
48638    \param relsym
48639    The relation symbol;
48640
48641    \param expr
48642    The numerator of the right hand side affine expression;
48643
48644    \param denominator
48645    The denominator of the right hand side affine expression (optional
48646    argument with default value 1).
48647
48648    \exception std::invalid_argument
48649    Thrown if \p denominator is zero or if \p expr and \p *this are
48650    dimension-incompatible or if \p var is not a space dimension of \p *this
48651    or if \p *this is a C_Polyhedron and \p relsym is a strict
48652    relation symbol.
48653  */
48654  void
48655  generalized_affine_preimage(Variable var,
48656                              Relation_Symbol relsym,
48657                              const Linear_Expression& expr,
48658                              Coefficient_traits::const_reference denominator
48659                              = Coefficient_one());
48660
48661  /*! \brief
48662    Assigns to \p *this the image of \p *this with respect to the
48663    \ref Generalized_Affine_Relations "generalized affine relation"
48664    \f$\mathrm{lhs}' \relsym \mathrm{rhs}\f$, where
48665    \f$\mathord{\relsym}\f$ is the relation symbol encoded by \p relsym.
48666
48667    \param lhs
48668    The left hand side affine expression;
48669
48670    \param relsym
48671    The relation symbol;
48672
48673    \param rhs
48674    The right hand side affine expression.
48675
48676    \exception std::invalid_argument
48677    Thrown if \p *this is dimension-incompatible with \p lhs or \p rhs
48678    or if \p *this is a C_Polyhedron and \p relsym is a strict
48679    relation symbol.
48680  */
48681  void generalized_affine_image(const Linear_Expression& lhs,
48682                                Relation_Symbol relsym,
48683                                const Linear_Expression& rhs);
48684
48685  /*! \brief
48686    Assigns to \p *this the preimage of \p *this with respect to the
48687    \ref Generalized_Affine_Relations "generalized affine relation"
48688    \f$\mathrm{lhs}' \relsym \mathrm{rhs}\f$, where
48689    \f$\mathord{\relsym}\f$ is the relation symbol encoded by \p relsym.
48690
48691    \param lhs
48692    The left hand side affine expression;
48693
48694    \param relsym
48695    The relation symbol;
48696
48697    \param rhs
48698    The right hand side affine expression.
48699
48700    \exception std::invalid_argument
48701    Thrown if \p *this is dimension-incompatible with \p lhs or \p rhs
48702    or if \p *this is a C_Polyhedron and \p relsym is a strict
48703    relation symbol.
48704  */
48705  void generalized_affine_preimage(const Linear_Expression& lhs,
48706                                   Relation_Symbol relsym,
48707                                   const Linear_Expression& rhs);
48708
48709  /*!
48710    \brief
48711    Assigns to \p *this the image of \p *this with respect to the
48712    \ref Single_Update_Bounded_Affine_Relations "bounded affine relation"
48713    \f$\frac{\mathrm{lb\_expr}}{\mathrm{denominator}}
48714         \leq \mathrm{var}'
48715           \leq \frac{\mathrm{ub\_expr}}{\mathrm{denominator}}\f$.
48716
48717    \param var
48718    The variable updated by the affine relation;
48719
48720    \param lb_expr
48721    The numerator of the lower bounding affine expression;
48722
48723    \param ub_expr
48724    The numerator of the upper bounding affine expression;
48725
48726    \param denominator
48727    The (common) denominator for the lower and upper bounding
48728    affine expressions (optional argument with default value 1).
48729
48730    \exception std::invalid_argument
48731    Thrown if \p denominator is zero or if \p lb_expr (resp., \p ub_expr)
48732    and \p *this are dimension-incompatible or if \p var is not a space
48733    dimension of \p *this.
48734  */
48735  void bounded_affine_image(Variable var,
48736                            const Linear_Expression& lb_expr,
48737                            const Linear_Expression& ub_expr,
48738                            Coefficient_traits::const_reference denominator
48739                            = Coefficient_one());
48740
48741  /*!
48742    \brief
48743    Assigns to \p *this the preimage of \p *this with respect to the
48744    \ref Single_Update_Bounded_Affine_Relations "bounded affine relation"
48745    \f$\frac{\mathrm{lb\_expr}}{\mathrm{denominator}}
48746         \leq \mathrm{var}'
48747           \leq \frac{\mathrm{ub\_expr}}{\mathrm{denominator}}\f$.
48748
48749    \param var
48750    The variable updated by the affine relation;
48751
48752    \param lb_expr
48753    The numerator of the lower bounding affine expression;
48754
48755    \param ub_expr
48756    The numerator of the upper bounding affine expression;
48757
48758    \param denominator
48759    The (common) denominator for the lower and upper bounding
48760    affine expressions (optional argument with default value 1).
48761
48762    \exception std::invalid_argument
48763    Thrown if \p denominator is zero or if \p lb_expr (resp., \p ub_expr)
48764    and \p *this are dimension-incompatible or if \p var is not a space
48765    dimension of \p *this.
48766  */
48767  void bounded_affine_preimage(Variable var,
48768                               const Linear_Expression& lb_expr,
48769                               const Linear_Expression& ub_expr,
48770                               Coefficient_traits::const_reference denominator
48771                               = Coefficient_one());
48772
48773  /*! \brief
48774    Assigns to \p *this the result of computing the
48775    \ref Time_Elapse_Operator "time-elapse" between \p *this and \p y.
48776
48777    \exception std::invalid_argument
48778    Thrown if \p *this and \p y are topology-incompatible or
48779    dimension-incompatible.
48780  */
48781  void time_elapse_assign(const Polyhedron& y);
48782
48783  /*! \brief
48784    Assigns to \p *this (the best approximation of) the result of
48785    computing the
48786    \ref Positive_Time_Elapse_Operator "positive time-elapse"
48787    between \p *this and \p y.
48788
48789    \exception std::invalid_argument
48790    Thrown if \p *this and \p y are dimension-incompatible.
48791  */
48792  void positive_time_elapse_assign(const Polyhedron& y);
48793
48794  /*! \brief
48795    \ref Wrapping_Operator "Wraps" the specified dimensions of the
48796    vector space.
48797
48798    \param vars
48799    The set of Variable objects corresponding to the space dimensions
48800    to be wrapped.
48801
48802    \param w
48803    The width of the bounded integer type corresponding to
48804    all the dimensions to be wrapped.
48805
48806    \param r
48807    The representation of the bounded integer type corresponding to
48808    all the dimensions to be wrapped.
48809
48810    \param o
48811    The overflow behavior of the bounded integer type corresponding to
48812    all the dimensions to be wrapped.
48813
48814    \param cs_p
48815    Possibly null pointer to a constraint system whose variables
48816    are contained in \p vars.  If <CODE>*cs_p</CODE> depends on
48817    variables not in \p vars, the behavior is undefined.
48818    When non-null, the pointed-to constraint system is assumed to
48819    represent the conditional or looping construct guard with respect
48820    to which wrapping is performed.  Since wrapping requires the
48821    computation of upper bounds and due to non-distributivity of
48822    constraint refinement over upper bounds, passing a constraint
48823    system in this way can be more precise than refining the result of
48824    the wrapping operation with the constraints in <CODE>*cs_p</CODE>.
48825
48826    \param complexity_threshold
48827    A precision parameter of the \ref Wrapping_Operator "wrapping operator":
48828    higher values result in possibly improved precision.
48829
48830    \param wrap_individually
48831    <CODE>true</CODE> if the dimensions should be wrapped individually
48832    (something that results in much greater efficiency to the detriment of
48833    precision).
48834
48835    \exception std::invalid_argument
48836    Thrown if <CODE>*cs_p</CODE> is dimension-incompatible with
48837    \p vars, or if \p *this is dimension-incompatible \p vars or with
48838    <CODE>*cs_p</CODE>.
48839  */
48840  void wrap_assign(const Variables_Set& vars,
48841                   Bounded_Integer_Type_Width w,
48842                   Bounded_Integer_Type_Representation r,
48843                   Bounded_Integer_Type_Overflow o,
48844                   const Constraint_System* cs_p = 0,
48845                   unsigned complexity_threshold = 16,
48846                   bool wrap_individually = true);
48847
48848  /*! \brief
48849    Possibly tightens \p *this by dropping some points with non-integer
48850    coordinates.
48851
48852    \param complexity
48853    The maximal complexity of any algorithms used.
48854
48855    \note
48856    Currently there is no optimality guarantee, not even if
48857    \p complexity is <CODE>ANY_COMPLEXITY</CODE>.
48858  */
48859  void drop_some_non_integer_points(Complexity_Class complexity
48860                                    = ANY_COMPLEXITY);
48861
48862  /*! \brief
48863    Possibly tightens \p *this by dropping some points with non-integer
48864    coordinates for the space dimensions corresponding to \p vars.
48865
48866    \param vars
48867    Points with non-integer coordinates for these variables/space-dimensions
48868    can be discarded.
48869
48870    \param complexity
48871    The maximal complexity of any algorithms used.
48872
48873    \note
48874    Currently there is no optimality guarantee, not even if
48875    \p complexity is <CODE>ANY_COMPLEXITY</CODE>.
48876  */
48877  void drop_some_non_integer_points(const Variables_Set& vars,
48878                                    Complexity_Class complexity
48879                                    = ANY_COMPLEXITY);
48880
48881  //! Assigns to \p *this its topological closure.
48882  void topological_closure_assign();
48883
48884  /*! \brief
48885    Assigns to \p *this the result of computing the
48886    \ref BHRZ03_widening "BHRZ03-widening" between \p *this and \p y.
48887
48888    \param y
48889    A polyhedron that <EM>must</EM> be contained in \p *this;
48890
48891    \param tp
48892    An optional pointer to an unsigned variable storing the number of
48893    available tokens (to be used when applying the
48894    \ref Widening_with_Tokens "widening with tokens" delay technique).
48895
48896    \exception std::invalid_argument
48897    Thrown if \p *this and \p y are topology-incompatible or
48898    dimension-incompatible.
48899  */
48900  void BHRZ03_widening_assign(const Polyhedron& y, unsigned* tp = 0);
48901
48902  /*! \brief
48903    Assigns to \p *this the result of computing the
48904    \ref limited_extrapolation "limited extrapolation"
48905    between \p *this and \p y using the \ref BHRZ03_widening
48906    "BHRZ03-widening" operator.
48907
48908    \param y
48909    A polyhedron that <EM>must</EM> be contained in \p *this;
48910
48911    \param cs
48912    The system of constraints used to improve the widened polyhedron;
48913
48914    \param tp
48915    An optional pointer to an unsigned variable storing the number of
48916    available tokens (to be used when applying the
48917    \ref Widening_with_Tokens "widening with tokens" delay technique).
48918
48919    \exception std::invalid_argument
48920    Thrown if \p *this, \p y and \p cs are topology-incompatible or
48921    dimension-incompatible.
48922  */
48923  void limited_BHRZ03_extrapolation_assign(const Polyhedron& y,
48924                                           const Constraint_System& cs,
48925                                           unsigned* tp = 0);
48926
48927  /*! \brief
48928    Assigns to \p *this the result of computing the
48929    \ref bounded_extrapolation "bounded extrapolation"
48930    between \p *this and \p y using the \ref BHRZ03_widening
48931    "BHRZ03-widening" operator.
48932
48933    \param y
48934    A polyhedron that <EM>must</EM> be contained in \p *this;
48935
48936    \param cs
48937    The system of constraints used to improve the widened polyhedron;
48938
48939    \param tp
48940    An optional pointer to an unsigned variable storing the number of
48941    available tokens (to be used when applying the
48942    \ref Widening_with_Tokens "widening with tokens" delay technique).
48943
48944    \exception std::invalid_argument
48945    Thrown if \p *this, \p y and \p cs are topology-incompatible or
48946    dimension-incompatible.
48947  */
48948  void bounded_BHRZ03_extrapolation_assign(const Polyhedron& y,
48949                                           const Constraint_System& cs,
48950                                           unsigned* tp = 0);
48951
48952  /*! \brief
48953    Assigns to \p *this the result of computing the
48954    \ref H79_widening "H79_widening" between \p *this and \p y.
48955
48956    \param y
48957    A polyhedron that <EM>must</EM> be contained in \p *this;
48958
48959    \param tp
48960    An optional pointer to an unsigned variable storing the number of
48961    available tokens (to be used when applying the
48962    \ref Widening_with_Tokens "widening with tokens" delay technique).
48963
48964    \exception std::invalid_argument
48965    Thrown if \p *this and \p y are topology-incompatible or
48966    dimension-incompatible.
48967  */
48968  void H79_widening_assign(const Polyhedron& y, unsigned* tp = 0);
48969
48970  //! Same as H79_widening_assign(y, tp).
48971  void widening_assign(const Polyhedron& y, unsigned* tp = 0);
48972
48973  /*! \brief
48974    Assigns to \p *this the result of computing the
48975    \ref limited_extrapolation "limited extrapolation"
48976    between \p *this and \p y using the \ref H79_widening
48977    "H79-widening" operator.
48978
48979    \param y
48980    A polyhedron that <EM>must</EM> be contained in \p *this;
48981
48982    \param cs
48983    The system of constraints used to improve the widened polyhedron;
48984
48985    \param tp
48986    An optional pointer to an unsigned variable storing the number of
48987    available tokens (to be used when applying the
48988    \ref Widening_with_Tokens "widening with tokens" delay technique).
48989
48990    \exception std::invalid_argument
48991    Thrown if \p *this, \p y and \p cs are topology-incompatible or
48992    dimension-incompatible.
48993  */
48994  void limited_H79_extrapolation_assign(const Polyhedron& y,
48995                                        const Constraint_System& cs,
48996                                        unsigned* tp = 0);
48997
48998  /*! \brief
48999    Assigns to \p *this the result of computing the
49000    \ref bounded_extrapolation "bounded extrapolation"
49001    between \p *this and \p y using the \ref H79_widening
49002    "H79-widening" operator.
49003
49004    \param y
49005    A polyhedron that <EM>must</EM> be contained in \p *this;
49006
49007    \param cs
49008    The system of constraints used to improve the widened polyhedron;
49009
49010    \param tp
49011    An optional pointer to an unsigned variable storing the number of
49012    available tokens (to be used when applying the
49013    \ref Widening_with_Tokens "widening with tokens" delay technique).
49014
49015    \exception std::invalid_argument
49016    Thrown if \p *this, \p y and \p cs are topology-incompatible or
49017    dimension-incompatible.
49018  */
49019  void bounded_H79_extrapolation_assign(const Polyhedron& y,
49020                                        const Constraint_System& cs,
49021                                        unsigned* tp = 0);
49022
49023  //@} // Space Dimension Preserving Member Functions that May Modify [...]
49024
49025  //! \name Member Functions that May Modify the Dimension of the Vector Space
49026  //@{
49027
49028  /*! \brief
49029    Adds \p m new space dimensions and embeds the old polyhedron
49030    in the new vector space.
49031
49032    \param m
49033    The number of dimensions to add.
49034
49035    \exception std::length_error
49036    Thrown if adding \p m new space dimensions would cause the
49037    vector space to exceed dimension <CODE>max_space_dimension()</CODE>.
49038
49039    The new space dimensions will be those having the highest indexes
49040    in the new polyhedron, which is characterized by a system
49041    of constraints in which the variables running through
49042    the new dimensions are not constrained.
49043    For instance, when starting from the polyhedron \f$\cP \sseq \Rset^2\f$
49044    and adding a third space dimension, the result will be the polyhedron
49045    \f[
49046      \bigl\{\,
49047        (x, y, z)^\transpose \in \Rset^3
49048      \bigm|
49049        (x, y)^\transpose \in \cP
49050      \,\bigr\}.
49051    \f]
49052  */
49053  void add_space_dimensions_and_embed(dimension_type m);
49054
49055  /*! \brief
49056    Adds \p m new space dimensions to the polyhedron
49057    and does not embed it in the new vector space.
49058
49059    \param m
49060    The number of space dimensions to add.
49061
49062    \exception std::length_error
49063    Thrown if adding \p m new space dimensions would cause the
49064    vector space to exceed dimension <CODE>max_space_dimension()</CODE>.
49065
49066    The new space dimensions will be those having the highest indexes
49067    in the new polyhedron, which is characterized by a system
49068    of constraints in which the variables running through
49069    the new dimensions are all constrained to be equal to 0.
49070    For instance, when starting from the polyhedron \f$\cP \sseq \Rset^2\f$
49071    and adding a third space dimension, the result will be the polyhedron
49072    \f[
49073      \bigl\{\,
49074        (x, y, 0)^\transpose \in \Rset^3
49075      \bigm|
49076        (x, y)^\transpose \in \cP
49077      \,\bigr\}.
49078    \f]
49079  */
49080  void add_space_dimensions_and_project(dimension_type m);
49081
49082  /*! \brief
49083    Assigns to \p *this the \ref Concatenating_Polyhedra "concatenation"
49084    of \p *this and \p y, taken in this order.
49085
49086    \exception std::invalid_argument
49087    Thrown if \p *this and \p y are topology-incompatible.
49088
49089    \exception std::length_error
49090    Thrown if the concatenation would cause the vector space
49091    to exceed dimension <CODE>max_space_dimension()</CODE>.
49092  */
49093  void concatenate_assign(const Polyhedron& y);
49094
49095  //! Removes all the specified dimensions from the vector space.
49096  /*!
49097    \param vars
49098    The set of Variable objects corresponding to the space dimensions
49099    to be removed.
49100
49101    \exception std::invalid_argument
49102    Thrown if \p *this is dimension-incompatible with one of the
49103    Variable objects contained in \p vars.
49104  */
49105  void remove_space_dimensions(const Variables_Set& vars);
49106
49107  /*! \brief
49108    Removes the higher dimensions of the vector space so that
49109    the resulting space will have dimension \p new_dimension.
49110
49111    \exception std::invalid_argument
49112    Thrown if \p new_dimensions is greater than the space dimension of
49113    \p *this.
49114  */
49115  void remove_higher_space_dimensions(dimension_type new_dimension);
49116
49117  /*! \brief
49118    Remaps the dimensions of the vector space according to
49119    a \ref Mapping_the_Dimensions_of_the_Vector_Space "partial function".
49120
49121    \param pfunc
49122    The partial function specifying the destiny of each space dimension.
49123
49124    The template type parameter Partial_Function must provide
49125    the following methods.
49126    \code
49127      bool has_empty_codomain() const
49128    \endcode
49129    returns <CODE>true</CODE> if and only if the represented partial
49130    function has an empty codomain (i.e., it is always undefined).
49131    The <CODE>has_empty_codomain()</CODE> method will always be called
49132    before the methods below.  However, if
49133    <CODE>has_empty_codomain()</CODE> returns <CODE>true</CODE>, none
49134    of the functions below will be called.
49135    \code
49136      dimension_type max_in_codomain() const
49137    \endcode
49138    returns the maximum value that belongs to the codomain
49139    of the partial function.
49140    The <CODE>max_in_codomain()</CODE> method is called at most once.
49141    \code
49142      bool maps(dimension_type i, dimension_type& j) const
49143    \endcode
49144    Let \f$f\f$ be the represented function and \f$k\f$ be the value
49145    of \p i.  If \f$f\f$ is defined in \f$k\f$, then \f$f(k)\f$ is
49146    assigned to \p j and <CODE>true</CODE> is returned.
49147    If \f$f\f$ is undefined in \f$k\f$, then <CODE>false</CODE> is
49148    returned.
49149    This method is called at most \f$n\f$ times, where \f$n\f$ is the
49150    dimension of the vector space enclosing the polyhedron.
49151
49152    The result is undefined if \p pfunc does not encode a partial
49153    function with the properties described in the
49154    \ref Mapping_the_Dimensions_of_the_Vector_Space
49155    "specification of the mapping operator".
49156  */
49157  template <typename Partial_Function>
49158  void map_space_dimensions(const Partial_Function& pfunc);
49159
49160  //! Creates \p m copies of the space dimension corresponding to \p var.
49161  /*!
49162    \param var
49163    The variable corresponding to the space dimension to be replicated;
49164
49165    \param m
49166    The number of replicas to be created.
49167
49168    \exception std::invalid_argument
49169    Thrown if \p var does not correspond to a dimension of the vector space.
49170
49171    \exception std::length_error
49172    Thrown if adding \p m new space dimensions would cause the
49173    vector space to exceed dimension <CODE>max_space_dimension()</CODE>.
49174
49175    If \p *this has space dimension \f$n\f$, with \f$n > 0\f$,
49176    and <CODE>var</CODE> has space dimension \f$k \leq n\f$,
49177    then the \f$k\f$-th space dimension is
49178    \ref expand_space_dimension "expanded" to \p m new space dimensions
49179    \f$n\f$, \f$n+1\f$, \f$\dots\f$, \f$n+m-1\f$.
49180  */
49181  void expand_space_dimension(Variable var, dimension_type m);
49182
49183  //! Folds the space dimensions in \p vars into \p dest.
49184  /*!
49185    \param vars
49186    The set of Variable objects corresponding to the space dimensions
49187    to be folded;
49188
49189    \param dest
49190    The variable corresponding to the space dimension that is the
49191    destination of the folding operation.
49192
49193    \exception std::invalid_argument
49194    Thrown if \p *this is dimension-incompatible with \p dest or with
49195    one of the Variable objects contained in \p vars.
49196    Also thrown if \p dest is contained in \p vars.
49197
49198    If \p *this has space dimension \f$n\f$, with \f$n > 0\f$,
49199    <CODE>dest</CODE> has space dimension \f$k \leq n\f$,
49200    \p vars is a set of variables whose maximum space dimension
49201    is also less than or equal to \f$n\f$, and \p dest is not a member
49202    of \p vars, then the space dimensions corresponding to
49203    variables in \p vars are \ref fold_space_dimensions "folded"
49204    into the \f$k\f$-th space dimension.
49205  */
49206  void fold_space_dimensions(const Variables_Set& vars, Variable dest);
49207
49208  //@} // Member Functions that May Modify the Dimension of the Vector Space
49209
49210  friend bool operator==(const Polyhedron& x, const Polyhedron& y);
49211
49212  //! \name Miscellaneous Member Functions
49213  //@{
49214
49215  //! Destructor.
49216  ~Polyhedron();
49217
49218  /*! \brief
49219    Swaps \p *this with polyhedron \p y.
49220    (\p *this and \p y can be dimension-incompatible.)
49221
49222    \exception std::invalid_argument
49223    Thrown if \p x and \p y are topology-incompatible.
49224  */
49225  void m_swap(Polyhedron& y);
49226
49227  PPL_OUTPUT_DECLARATIONS
49228
49229  /*! \brief
49230    Loads from \p s an ASCII representation (as produced by
49231    ascii_dump(std::ostream&) const) and sets \p *this accordingly.
49232    Returns <CODE>true</CODE> if successful, <CODE>false</CODE> otherwise.
49233  */
49234  bool ascii_load(std::istream& s);
49235
49236  //! Returns the total size in bytes of the memory occupied by \p *this.
49237  memory_size_type total_memory_in_bytes() const;
49238
49239  //! Returns the size in bytes of the memory managed by \p *this.
49240  memory_size_type external_memory_in_bytes() const;
49241
49242  /*! \brief
49243    Returns a 32-bit hash code for \p *this.
49244
49245    If \p x and \p y are such that <CODE>x == y</CODE>,
49246    then <CODE>x.hash_code() == y.hash_code()</CODE>.
49247  */
49248  int32_t hash_code() const;
49249
49250  //@} // Miscellaneous Member Functions
49251
49252private:
49253  static const Representation default_con_sys_repr = DENSE;
49254  static const Representation default_gen_sys_repr = DENSE;
49255
49256  //! The system of constraints.
49257  Constraint_System con_sys;
49258
49259  //! The system of generators.
49260  Generator_System gen_sys;
49261
49262  //! The saturation matrix having constraints on its columns.
49263  Bit_Matrix sat_c;
49264
49265  //! The saturation matrix having generators on its columns.
49266  Bit_Matrix sat_g;
49267
49268#define PPL_IN_Polyhedron_CLASS
49269/* Automatically generated from PPL source file ../src/Ph_Status_idefs.hh line 1. */
49270/* Polyhedron::Status class declaration.
49271*/
49272
49273
49274#ifndef PPL_IN_Polyhedron_CLASS
49275#error "Do not include Ph_Status_idefs.hh directly; use Polyhedron_defs.hh instead"
49276#endif
49277
49278//! A conjunctive assertion about a polyhedron.
49279/*! \ingroup PPL_CXX_interface
49280  The assertions supported are:
49281  - <EM>zero-dim universe</EM>: the polyhedron is the zero-dimension
49282    vector space \f$\Rset^0 = \{\cdot\}\f$;
49283  - <EM>empty</EM>: the polyhedron is the empty set;
49284  - <EM>constraints pending</EM>: the polyhedron is correctly
49285    characterized by the attached system of constraints, which is
49286    split in two non-empty subsets: the already processed constraints,
49287    which are in minimal form, and the pending constraints, which
49288    still have to be processed and may thus be inconsistent or
49289    contain redundancies;
49290  - <EM>generators pending</EM>: the polyhedron is correctly
49291    characterized by the attached system of generators, which is
49292    split in two non-empty subsets: the already processed generators,
49293    which are in minimal form, and the pending generators, which still
49294    have to be processed and may thus contain redundancies;
49295  - <EM>constraints up-to-date</EM>: the polyhedron is correctly
49296    characterized by the attached system of constraints, modulo the
49297    processing of pending generators;
49298  - <EM>generators up-to-date</EM>: the polyhedron is correctly
49299    characterized by the attached system of generators, modulo the
49300    processing of pending constraints;
49301  - <EM>constraints minimized</EM>: the non-pending part of the system
49302    of constraints attached to the polyhedron is in minimal form;
49303  - <EM>generators minimized</EM>: the non-pending part of the system
49304    of generators attached to the polyhedron is in minimal form;
49305  - <EM>constraints' saturation matrix up-to-date</EM>: the attached
49306    saturation matrix having rows indexed by non-pending generators and
49307    columns indexed by non-pending constraints correctly expresses
49308    the saturation relation between the attached non-pending constraints
49309    and generators;
49310  - <EM>generators' saturation matrix up-to-date</EM>: the attached
49311    saturation matrix having rows indexed by non-pending constraints and
49312    columns indexed by non-pending generators correctly expresses
49313    the saturation relation between the attached non-pending constraints
49314    and generators;
49315
49316  Not all the conjunctions of these elementary assertions constitute
49317  a legal Status.  In fact:
49318  - <EM>zero-dim universe</EM> excludes any other assertion;
49319  - <EM>empty</EM>: excludes any other assertion;
49320  - <EM>constraints pending</EM> and <EM>generators pending</EM>
49321    are mutually exclusive;
49322  - <EM>constraints pending</EM> implies both <EM>constraints minimized</EM>
49323    and <EM>generators minimized</EM>;
49324  - <EM>generators pending</EM> implies both <EM>constraints minimized</EM>
49325    and <EM>generators minimized</EM>;
49326  - <EM>constraints minimized</EM> implies <EM>constraints up-to-date</EM>;
49327  - <EM>generators minimized</EM> implies <EM>generators up-to-date</EM>;
49328  - <EM>constraints' saturation matrix up-to-date</EM> implies both
49329    <EM>constraints up-to-date</EM> and <EM>generators up-to-date</EM>;
49330  - <EM>generators' saturation matrix up-to-date</EM> implies both
49331    <EM>constraints up-to-date</EM> and <EM>generators up-to-date</EM>.
49332*/
49333class Status {
49334public:
49335  //! By default Status is the <EM>zero-dim universe</EM> assertion.
49336  Status();
49337
49338  //! \name Test, remove or add an individual assertion from the conjunction
49339  //@{
49340  bool test_zero_dim_univ() const;
49341  void reset_zero_dim_univ();
49342  void set_zero_dim_univ();
49343
49344  bool test_empty() const;
49345  void reset_empty();
49346  void set_empty();
49347
49348  bool test_c_up_to_date() const;
49349  void reset_c_up_to_date();
49350  void set_c_up_to_date();
49351
49352  bool test_g_up_to_date() const;
49353  void reset_g_up_to_date();
49354  void set_g_up_to_date();
49355
49356  bool test_c_minimized() const;
49357  void reset_c_minimized();
49358  void set_c_minimized();
49359
49360  bool test_g_minimized() const;
49361  void reset_g_minimized();
49362  void set_g_minimized();
49363
49364  bool test_sat_c_up_to_date() const;
49365  void reset_sat_c_up_to_date();
49366  void set_sat_c_up_to_date();
49367
49368  bool test_sat_g_up_to_date() const;
49369  void reset_sat_g_up_to_date();
49370  void set_sat_g_up_to_date();
49371
49372  bool test_c_pending() const;
49373  void reset_c_pending();
49374  void set_c_pending();
49375
49376  bool test_g_pending() const;
49377  void reset_g_pending();
49378  void set_g_pending();
49379  //@} // Test, remove or add an individual assertion from the conjunction
49380
49381  //! Checks if all the invariants are satisfied.
49382  bool OK() const;
49383
49384  PPL_OUTPUT_DECLARATIONS
49385
49386  /*! \brief
49387    Loads from \p s an ASCII representation (as produced by
49388    ascii_dump(std::ostream&) const) and sets \p *this accordingly.
49389    Returns <CODE>true</CODE> if successful, <CODE>false</CODE> otherwise.
49390  */
49391  bool ascii_load(std::istream& s);
49392
49393private:
49394  //! Status is implemented by means of a finite bitset.
49395  typedef unsigned int flags_t;
49396
49397  //! \name Bit-masks for the individual assertions
49398  //@{
49399  static const flags_t ZERO_DIM_UNIV    = 0U;
49400  static const flags_t EMPTY            = 1U << 0;
49401  static const flags_t C_UP_TO_DATE     = 1U << 1;
49402  static const flags_t G_UP_TO_DATE     = 1U << 2;
49403  static const flags_t C_MINIMIZED      = 1U << 3;
49404  static const flags_t G_MINIMIZED      = 1U << 4;
49405  static const flags_t SAT_C_UP_TO_DATE = 1U << 5;
49406  static const flags_t SAT_G_UP_TO_DATE = 1U << 6;
49407  static const flags_t CS_PENDING       = 1U << 7;
49408  static const flags_t GS_PENDING       = 1U << 8;
49409  //@} // Bit-masks for the individual assertions
49410
49411  //! This holds the current bitset.
49412  flags_t flags;
49413
49414  //! Construct from a bit-mask.
49415  Status(flags_t mask);
49416
49417  //! Check whether <EM>all</EM> bits in \p mask are set.
49418  bool test_all(flags_t mask) const;
49419
49420  //! Check whether <EM>at least one</EM> bit in \p mask is set.
49421  bool test_any(flags_t mask) const;
49422
49423  //! Set the bits in \p mask.
49424  void set(flags_t mask);
49425
49426  //! Reset the bits in \p mask.
49427  void reset(flags_t mask);
49428};
49429
49430/* Automatically generated from PPL source file ../src/Polyhedron_defs.hh line 2043. */
49431#undef PPL_IN_Polyhedron_CLASS
49432
49433  //! The status flags to keep track of the polyhedron's internal state.
49434  Status status;
49435
49436  //! The number of dimensions of the enclosing vector space.
49437  dimension_type space_dim;
49438
49439  //! Returns the topological kind of the polyhedron.
49440  Topology topology() const;
49441
49442  /*! \brief
49443    Returns <CODE>true</CODE> if and only if the polyhedron
49444    is necessarily closed.
49445  */
49446  bool is_necessarily_closed() const;
49447
49448  friend bool
49449  Parma_Polyhedra_Library::Interfaces
49450  ::is_necessarily_closed_for_interfaces(const Polyhedron&);
49451
49452  /*! \brief
49453    Uses a copy of constraint \p c to refine the system of constraints
49454    of \p *this.
49455
49456    \param c The constraint to be added. If it is dimension-incompatible
49457    with \p *this, the behavior is undefined.
49458  */
49459  void refine_no_check(const Constraint& c);
49460
49461  //! \name Private Verifiers: Verify if Individual Flags are Set
49462  //@{
49463
49464  //! Returns <CODE>true</CODE> if the polyhedron is known to be empty.
49465  /*!
49466    The return value <CODE>false</CODE> does not necessarily
49467    implies that \p *this is non-empty.
49468  */
49469  bool marked_empty() const;
49470
49471  //! Returns <CODE>true</CODE> if the system of constraints is up-to-date.
49472  bool constraints_are_up_to_date() const;
49473
49474  //! Returns <CODE>true</CODE> if the system of generators is up-to-date.
49475  bool generators_are_up_to_date() const;
49476
49477  //! Returns <CODE>true</CODE> if the system of constraints is minimized.
49478  /*!
49479    Note that only \em weak minimization is entailed, so that
49480    an NNC polyhedron may still have \f$\epsilon\f$-redundant constraints.
49481  */
49482  bool constraints_are_minimized() const;
49483
49484  //! Returns <CODE>true</CODE> if the system of generators is minimized.
49485  /*!
49486    Note that only \em weak minimization is entailed, so that
49487    an NNC polyhedron may still have \f$\epsilon\f$-redundant generators.
49488  */
49489  bool generators_are_minimized() const;
49490
49491  //! Returns <CODE>true</CODE> if there are pending constraints.
49492  bool has_pending_constraints() const;
49493
49494  //! Returns <CODE>true</CODE> if there are pending generators.
49495  bool has_pending_generators() const;
49496
49497  /*! \brief
49498    Returns <CODE>true</CODE> if there are
49499    either pending constraints or pending generators.
49500  */
49501  bool has_something_pending() const;
49502
49503  //! Returns <CODE>true</CODE> if the polyhedron can have something pending.
49504  bool can_have_something_pending() const;
49505
49506  /*! \brief
49507    Returns <CODE>true</CODE> if the saturation matrix \p sat_c
49508    is up-to-date.
49509  */
49510  bool sat_c_is_up_to_date() const;
49511
49512  /*! \brief
49513    Returns <CODE>true</CODE> if the saturation matrix \p sat_g
49514    is up-to-date.
49515  */
49516  bool sat_g_is_up_to_date() const;
49517
49518  //@} // Private Verifiers: Verify if Individual Flags are Set
49519
49520  //! \name State Flag Setters: Set Only the Specified Flags
49521  //@{
49522
49523  /*! \brief
49524    Sets \p status to express that the polyhedron is the universe
49525    0-dimension vector space, clearing all corresponding matrices.
49526  */
49527  void set_zero_dim_univ();
49528
49529  /*! \brief
49530    Sets \p status to express that the polyhedron is empty,
49531    clearing all corresponding matrices.
49532  */
49533  void set_empty();
49534
49535  //! Sets \p status to express that constraints are up-to-date.
49536  void set_constraints_up_to_date();
49537
49538  //! Sets \p status to express that generators are up-to-date.
49539  void set_generators_up_to_date();
49540
49541  //! Sets \p status to express that constraints are minimized.
49542  void set_constraints_minimized();
49543
49544  //! Sets \p status to express that generators are minimized.
49545  void set_generators_minimized();
49546
49547  //! Sets \p status to express that constraints are pending.
49548  void set_constraints_pending();
49549
49550  //! Sets \p status to express that generators are pending.
49551  void set_generators_pending();
49552
49553  //! Sets \p status to express that \p sat_c is up-to-date.
49554  void set_sat_c_up_to_date();
49555
49556  //! Sets \p status to express that \p sat_g is up-to-date.
49557  void set_sat_g_up_to_date();
49558
49559  //@} // State Flag Setters: Set Only the Specified Flags
49560
49561  //! \name State Flag Cleaners: Clear Only the Specified Flag
49562  //@{
49563
49564  //! Clears the \p status flag indicating that the polyhedron is empty.
49565  void clear_empty();
49566
49567  //! Sets \p status to express that constraints are no longer up-to-date.
49568  /*!
49569    This also implies that they are neither minimized
49570    and both saturation matrices are no longer meaningful.
49571  */
49572  void clear_constraints_up_to_date();
49573
49574  //! Sets \p status to express that generators are no longer up-to-date.
49575  /*!
49576    This also implies that they are neither minimized
49577    and both saturation matrices are no longer meaningful.
49578  */
49579  void clear_generators_up_to_date();
49580
49581  //! Sets \p status to express that constraints are no longer minimized.
49582  void clear_constraints_minimized();
49583
49584  //! Sets \p status to express that generators are no longer minimized.
49585  void clear_generators_minimized();
49586
49587  //! Sets \p status to express that there are no longer pending constraints.
49588  void clear_pending_constraints();
49589
49590  //! Sets \p status to express that there are no longer pending generators.
49591  void clear_pending_generators();
49592
49593  //! Sets \p status to express that \p sat_c is no longer up-to-date.
49594  void clear_sat_c_up_to_date();
49595
49596  //! Sets \p status to express that \p sat_g is no longer up-to-date.
49597  void clear_sat_g_up_to_date();
49598
49599  //@} // State Flag Cleaners: Clear Only the Specified Flag
49600
49601  //! \name The Handling of Pending Rows
49602  //@{
49603
49604  /*! \brief
49605    Processes the pending rows of either description of the polyhedron
49606    and obtains a minimized polyhedron.
49607
49608    \return
49609    <CODE>false</CODE> if and only if \p *this turns out to be an
49610    empty polyhedron.
49611
49612    It is assumed that the polyhedron does have some constraints or
49613    generators pending.
49614  */
49615  bool process_pending() const;
49616
49617  //! Processes the pending constraints and obtains a minimized polyhedron.
49618  /*!
49619    \return
49620    <CODE>false</CODE> if and only if \p *this turns out to be an
49621    empty polyhedron.
49622
49623    It is assumed that the polyhedron does have some pending constraints.
49624  */
49625  bool process_pending_constraints() const;
49626
49627  //! Processes the pending generators and obtains a minimized polyhedron.
49628  /*!
49629    It is assumed that the polyhedron does have some pending generators.
49630  */
49631  void process_pending_generators() const;
49632
49633  /*! \brief
49634    Lazily integrates the pending descriptions of the polyhedron
49635    to obtain a constraint system without pending rows.
49636
49637    It is assumed that the polyhedron does have some constraints or
49638    generators pending.
49639  */
49640  void remove_pending_to_obtain_constraints() const;
49641
49642  /*! \brief
49643    Lazily integrates the pending descriptions of the polyhedron
49644    to obtain a generator system without pending rows.
49645
49646    \return
49647    <CODE>false</CODE> if and only if \p *this turns out to be an
49648    empty polyhedron.
49649
49650    It is assumed that the polyhedron does have some constraints or
49651    generators pending.
49652  */
49653  bool remove_pending_to_obtain_generators() const;
49654
49655  //@} // The Handling of Pending Rows
49656
49657  //! \name Updating and Sorting Matrices
49658  //@{
49659
49660  //! Updates constraints starting from generators and minimizes them.
49661  /*!
49662    The resulting system of constraints is only partially sorted:
49663    the equalities are in the upper part of the matrix,
49664    while the inequalities in the lower part.
49665  */
49666  void update_constraints() const;
49667
49668  //! Updates generators starting from constraints and minimizes them.
49669  /*!
49670    \return
49671    <CODE>false</CODE> if and only if \p *this turns out to be an
49672    empty polyhedron.
49673
49674    The resulting system of generators is only partially sorted:
49675    the lines are in the upper part of the matrix,
49676    while rays and points are in the lower part.
49677    It is illegal to call this method when the Status field
49678    already declares the polyhedron to be empty.
49679  */
49680  bool update_generators() const;
49681
49682  //! Updates \p sat_c using the updated constraints and generators.
49683  /*!
49684    It is assumed that constraints and generators are up-to-date
49685    and minimized and that the Status field does not already flag
49686    \p sat_c to be up-to-date.
49687    The values of the saturation matrix are computed as follows:
49688    \f[
49689      \begin{cases}
49690        sat\_c[i][j] = 0,
49691          \quad \text{if } G[i] \cdot C^\mathrm{T}[j] = 0; \\
49692        sat\_c[i][j] = 1,
49693          \quad \text{if } G[i] \cdot C^\mathrm{T}[j] > 0.
49694      \end{cases}
49695    \f]
49696  */
49697  void update_sat_c() const;
49698
49699  //! Updates \p sat_g using the updated constraints and generators.
49700  /*!
49701    It is assumed that constraints and generators are up-to-date
49702    and minimized and that the Status field does not already flag
49703    \p sat_g to be up-to-date.
49704    The values of the saturation matrix are computed as follows:
49705    \f[
49706      \begin{cases}
49707        sat\_g[i][j] = 0,
49708          \quad \text{if } C[i] \cdot G^\mathrm{T}[j] = 0; \\
49709        sat\_g[i][j] = 1,
49710          \quad \text{if } C[i] \cdot G^\mathrm{T}[j] > 0.
49711      \end{cases}
49712    \f]
49713  */
49714  void update_sat_g() const;
49715
49716  //! Sorts the matrix of constraints keeping status consistency.
49717  /*!
49718    It is assumed that constraints are up-to-date.
49719    If at least one of the saturation matrices is up-to-date,
49720    then \p sat_g is kept consistent with the sorted matrix
49721    of constraints.
49722    The method is declared \p const because reordering
49723    the constraints does not modify the polyhedron
49724    from a \e logical point of view.
49725  */
49726  void obtain_sorted_constraints() const;
49727
49728  //! Sorts the matrix of generators keeping status consistency.
49729  /*!
49730    It is assumed that generators are up-to-date.
49731    If at least one of the saturation matrices is up-to-date,
49732    then \p sat_c is kept consistent with the sorted matrix
49733    of generators.
49734    The method is declared \p const because reordering
49735    the generators does not modify the polyhedron
49736    from a \e logical point of view.
49737  */
49738  void obtain_sorted_generators() const;
49739
49740  //! Sorts the matrix of constraints and updates \p sat_c.
49741  /*!
49742    It is assumed that both constraints and generators
49743    are up-to-date and minimized.
49744    The method is declared \p const because reordering
49745    the constraints does not modify the polyhedron
49746    from a \e logical point of view.
49747  */
49748  void obtain_sorted_constraints_with_sat_c() const;
49749
49750  //! Sorts the matrix of generators and updates \p sat_g.
49751  /*!
49752    It is assumed that both constraints and generators
49753    are up-to-date and minimized.
49754    The method is declared \p const because reordering
49755    the generators does not modify the polyhedron
49756    from a \e logical point of view.
49757  */
49758  void obtain_sorted_generators_with_sat_g() const;
49759
49760  //@} // Updating and Sorting Matrices
49761
49762  //! \name Weak and Strong Minimization of Descriptions
49763  //@{
49764
49765  //! Applies (weak) minimization to both the constraints and generators.
49766  /*!
49767    \return
49768    <CODE>false</CODE> if and only if \p *this turns out to be an
49769    empty polyhedron.
49770
49771    Minimization is not attempted if the Status field already declares
49772    both systems to be minimized.
49773  */
49774  bool minimize() const;
49775
49776  //! Applies strong minimization to the constraints of an NNC polyhedron.
49777  /*!
49778    \return
49779    <CODE>false</CODE> if and only if \p *this turns out to be an
49780    empty polyhedron.
49781  */
49782  bool strongly_minimize_constraints() const;
49783
49784  //! Applies strong minimization to the generators of an NNC polyhedron.
49785  /*!
49786    \return
49787    <CODE>false</CODE> if and only if \p *this turns out to be an
49788    empty polyhedron.
49789  */
49790  bool strongly_minimize_generators() const;
49791
49792  //! If constraints are up-to-date, obtain a simplified copy of them.
49793  Constraint_System simplified_constraints() const;
49794
49795  //@} // Weak and Strong Minimization of Descriptions
49796
49797  enum Three_Valued_Boolean {
49798    TVB_TRUE,
49799    TVB_FALSE,
49800    TVB_DONT_KNOW
49801  };
49802
49803  //! Polynomial but incomplete equivalence test between polyhedra.
49804  Three_Valued_Boolean quick_equivalence_test(const Polyhedron& y) const;
49805
49806  //! Returns <CODE>true</CODE> if and only if \p *this is included in \p y.
49807  bool is_included_in(const Polyhedron& y) const;
49808
49809  //! Checks if and how \p expr is bounded in \p *this.
49810  /*!
49811    Returns <CODE>true</CODE> if and only if \p from_above is
49812    <CODE>true</CODE> and \p expr is bounded from above in \p *this,
49813    or \p from_above is <CODE>false</CODE> and \p expr is bounded
49814    from below in \p *this.
49815
49816    \param expr
49817    The linear expression to test;
49818
49819    \param from_above
49820    <CODE>true</CODE> if and only if the boundedness of interest is
49821    "from above".
49822
49823    \exception std::invalid_argument
49824    Thrown if \p expr and \p *this are dimension-incompatible.
49825  */
49826  bool bounds(const Linear_Expression& expr, bool from_above) const;
49827
49828  //! Maximizes or minimizes \p expr subject to \p *this.
49829  /*!
49830    \param expr
49831    The linear expression to be maximized or minimized subject to \p
49832    *this;
49833
49834    \param maximize
49835    <CODE>true</CODE> if maximization is what is wanted;
49836
49837    \param ext_n
49838    The numerator of the extremum value;
49839
49840    \param ext_d
49841    The denominator of the extremum value;
49842
49843    \param included
49844    <CODE>true</CODE> if and only if the extremum of \p expr can
49845    actually be reached in \p * this;
49846
49847    \param g
49848    When maximization or minimization succeeds, will be assigned
49849    a point or closure point where \p expr reaches the
49850    corresponding extremum value.
49851
49852    \exception std::invalid_argument
49853    Thrown if \p expr and \p *this are dimension-incompatible.
49854
49855    If \p *this is empty or \p expr is not bounded in the appropriate
49856    direction, <CODE>false</CODE> is returned and \p ext_n, \p ext_d,
49857    \p included and \p g are left untouched.
49858  */
49859  bool max_min(const Linear_Expression& expr,
49860               bool maximize,
49861               Coefficient& ext_n, Coefficient& ext_d, bool& included,
49862               Generator& g) const;
49863
49864  //! \name Widening- and Extrapolation-Related Functions
49865  //@{
49866
49867  /*! \brief
49868    Copies to \p cs_selection the constraints of \p y corresponding
49869    to the definition of the CH78-widening of \p *this and \p y.
49870  */
49871  void select_CH78_constraints(const Polyhedron& y,
49872                               Constraint_System& cs_selection) const;
49873
49874  /*! \brief
49875    Splits the constraints of `x' into two subsets, depending on whether
49876    or not they are selected to compute the \ref H79_widening "H79-widening"
49877    of \p *this and \p y.
49878  */
49879  void select_H79_constraints(const Polyhedron& y,
49880                              Constraint_System& cs_selected,
49881                              Constraint_System& cs_not_selected) const;
49882
49883  bool BHRZ03_combining_constraints(const Polyhedron& y,
49884                                    const BHRZ03_Certificate& y_cert,
49885                                    const Polyhedron& H79,
49886                                    const Constraint_System& x_minus_H79_cs);
49887
49888  bool BHRZ03_evolving_points(const Polyhedron& y,
49889                              const BHRZ03_Certificate& y_cert,
49890                              const Polyhedron& H79);
49891
49892  bool BHRZ03_evolving_rays(const Polyhedron& y,
49893                            const BHRZ03_Certificate& y_cert,
49894                            const Polyhedron& H79);
49895
49896  static void modify_according_to_evolution(Linear_Expression& ray,
49897                                            const Linear_Expression& x,
49898                                            const Linear_Expression& y);
49899
49900  //@} // Widening- and Extrapolation-Related Functions
49901
49902  //! Adds new space dimensions to the given linear systems.
49903  /*!
49904    \param sys1
49905    The linear system to which columns are added;
49906
49907    \param sys2
49908    The linear system to which rows and columns are added;
49909
49910    \param sat1
49911    The saturation matrix whose columns are indexed by the rows of
49912    \p sys1. On entry it is up-to-date;
49913
49914    \param sat2
49915    The saturation matrix whose columns are indexed by the rows of \p
49916    sys2;
49917
49918    \param add_dim
49919    The number of space dimensions to add.
49920
49921    Adds new space dimensions to the vector space modifying the linear
49922    systems and saturation matrices.
49923    This function is invoked only by
49924    <CODE>add_space_dimensions_and_embed()</CODE> and
49925    <CODE>add_space_dimensions_and_project()</CODE>, passing the
49926    linear system of constraints and that of generators (and the
49927    corresponding saturation matrices) in different order (see those
49928    methods for details).
49929  */
49930  template <typename Linear_System1, typename Linear_System2>
49931  static void add_space_dimensions(Linear_System1& sys1,
49932                                   Linear_System2& sys2,
49933                                   Bit_Matrix& sat1,
49934                                   Bit_Matrix& sat2,
49935                                   dimension_type add_dim);
49936
49937  //! \name Minimization-Related Static Member Functions
49938  //@{
49939
49940  //! Builds and simplifies constraints from generators (or vice versa).
49941  // Detailed Doxygen comment to be found in file minimize.cc.
49942  template <typename Source_Linear_System, typename Dest_Linear_System>
49943  static bool minimize(bool con_to_gen,
49944                       Source_Linear_System& source,
49945                       Dest_Linear_System& dest,
49946                       Bit_Matrix& sat);
49947
49948  /*! \brief
49949    Adds given constraints and builds minimized corresponding generators
49950    or vice versa.
49951  */
49952  // Detailed Doxygen comment to be found in file minimize.cc.
49953  template <typename Source_Linear_System1, typename Source_Linear_System2,
49954            typename Dest_Linear_System>
49955  static bool add_and_minimize(bool con_to_gen,
49956                               Source_Linear_System1& source1,
49957                               Dest_Linear_System& dest,
49958                               Bit_Matrix& sat,
49959                               const Source_Linear_System2& source2);
49960
49961  /*! \brief
49962    Adds given constraints and builds minimized corresponding generators
49963    or vice versa. The given constraints are in \p source.
49964  */
49965  // Detailed Doxygen comment to be found in file minimize.cc.
49966  template <typename Source_Linear_System, typename Dest_Linear_System>
49967  static bool add_and_minimize(bool con_to_gen,
49968                               Source_Linear_System& source,
49969                               Dest_Linear_System& dest,
49970                               Bit_Matrix& sat);
49971
49972  //! Performs the conversion from constraints to generators and vice versa.
49973  // Detailed Doxygen comment to be found in file conversion.cc.
49974  template <typename Source_Linear_System, typename Dest_Linear_System>
49975  static dimension_type conversion(Source_Linear_System& source,
49976                                   dimension_type start,
49977                                   Dest_Linear_System& dest,
49978                                   Bit_Matrix& sat,
49979                                   dimension_type num_lines_or_equalities);
49980
49981  /*! \brief
49982    Uses Gauss' elimination method to simplify the result of
49983    <CODE>conversion()</CODE>.
49984  */
49985  // Detailed Doxygen comment to be found in file simplify.cc.
49986  template <typename Linear_System1>
49987  static dimension_type simplify(Linear_System1& sys, Bit_Matrix& sat);
49988
49989  //@} // Minimization-Related Static Member Functions
49990
49991  /*! \brief
49992    Pointer to an array used by simplify().
49993
49994    Holds (between class initialization and finalization) a pointer to
49995    an array, allocated with operator new[](), of
49996    simplify_num_saturators_size elements.
49997  */
49998  static dimension_type* simplify_num_saturators_p;
49999
50000  /*! \brief
50001    Dimension of an array used by simplify().
50002
50003    Holds (between class initialization and finalization) the size of the
50004    array pointed to by simplify_num_saturators_p.
50005  */
50006  static size_t simplify_num_saturators_size;
50007
50008  template <typename Interval> friend class Parma_Polyhedra_Library::Box;
50009  template <typename T> friend class Parma_Polyhedra_Library::BD_Shape;
50010  template <typename T> friend class Parma_Polyhedra_Library::Octagonal_Shape;
50011  friend class Parma_Polyhedra_Library::Grid;
50012  friend class Parma_Polyhedra_Library::BHRZ03_Certificate;
50013  friend class Parma_Polyhedra_Library::H79_Certificate;
50014
50015protected:
50016#ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
50017  /*! \brief
50018    If the poly-hull of \p *this and \p y is exact it is assigned
50019    to \p *this and \c true is returned, otherwise \c false is returned.
50020
50021    Current implementation is based on (a variant of) Algorithm 8.1 in
50022      A. Bemporad, K. Fukuda, and F. D. Torrisi
50023      <em>Convexity Recognition of the Union of Polyhedra</em>
50024      Technical Report AUT00-13, ETH Zurich, 2000
50025
50026    \note
50027    It is assumed that \p *this and \p y are topologically closed
50028    and dimension-compatible;
50029    if the assumption does not hold, the behavior is undefined.
50030  */
50031#endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
50032  bool BFT00_poly_hull_assign_if_exact(const Polyhedron& y);
50033
50034  bool BHZ09_poly_hull_assign_if_exact(const Polyhedron& y);
50035  bool BHZ09_C_poly_hull_assign_if_exact(const Polyhedron& y);
50036  bool BHZ09_NNC_poly_hull_assign_if_exact(const Polyhedron& y);
50037
50038#ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
50039  //! \name Exception Throwers
50040  //@{
50041#endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
50042protected:
50043  void throw_invalid_argument(const char* method, const char* reason) const;
50044
50045  void throw_topology_incompatible(const char* method,
50046                                   const char* ph_name,
50047                                   const Polyhedron& ph) const;
50048  void throw_topology_incompatible(const char* method,
50049                                   const char* c_name,
50050                                   const Constraint& c) const;
50051  void throw_topology_incompatible(const char* method,
50052                                   const char* g_name,
50053                                   const Generator& g) const;
50054  void throw_topology_incompatible(const char* method,
50055                                   const char* cs_name,
50056                                   const Constraint_System& cs) const;
50057  void throw_topology_incompatible(const char* method,
50058                                   const char* gs_name,
50059                                   const Generator_System& gs) const;
50060
50061  void throw_dimension_incompatible(const char* method,
50062                                    const char* other_name,
50063                                    dimension_type other_dim) const;
50064  void throw_dimension_incompatible(const char* method,
50065                                    const char* ph_name,
50066                                    const Polyhedron& ph) const;
50067  void throw_dimension_incompatible(const char* method,
50068                                    const char* le_name,
50069                                    const Linear_Expression& le) const;
50070  void throw_dimension_incompatible(const char* method,
50071                                    const char* c_name,
50072                                    const Constraint& c) const;
50073  void throw_dimension_incompatible(const char* method,
50074                                    const char* g_name,
50075                                    const Generator& g) const;
50076  void throw_dimension_incompatible(const char* method,
50077                                    const char* cg_name,
50078                                    const Congruence& cg) const;
50079  void throw_dimension_incompatible(const char* method,
50080                                    const char* cs_name,
50081                                    const Constraint_System& cs) const;
50082  void throw_dimension_incompatible(const char* method,
50083                                    const char* gs_name,
50084                                    const Generator_System& gs) const;
50085  void throw_dimension_incompatible(const char* method,
50086                                    const char* cgs_name,
50087                                    const Congruence_System& cgs) const;
50088  template <typename C>
50089  void throw_dimension_incompatible(const char* method,
50090                                    const char* lf_name,
50091                                    const Linear_Form<C>& lf) const;
50092  void throw_dimension_incompatible(const char* method,
50093                                    const char* var_name,
50094                                    Variable var) const;
50095  void throw_dimension_incompatible(const char* method,
50096                                    dimension_type required_space_dim) const;
50097
50098  // Note: the following three methods need to be static, because they
50099  // can be called inside constructors (before actually constructing the
50100  // polyhedron object).
50101  static dimension_type
50102  check_space_dimension_overflow(dimension_type dim, dimension_type max,
50103                                 const Topology topol,
50104                                 const char* method, const char* reason);
50105
50106  static dimension_type
50107  check_space_dimension_overflow(dimension_type dim, const Topology topol,
50108                                 const char* method, const char* reason);
50109
50110  template <typename Object>
50111  static Object&
50112  check_obj_space_dimension_overflow(Object& input, Topology topol,
50113                                     const char* method, const char* reason);
50114
50115  void throw_invalid_generator(const char* method,
50116                               const char* g_name) const;
50117
50118  void throw_invalid_generators(const char* method,
50119                                const char* gs_name) const;
50120#ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
50121  //@} // Exception Throwers
50122#endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
50123
50124  /*! \brief
50125    Possibly tightens \p *this by dropping some points with non-integer
50126    coordinates for the space dimensions corresponding to \p *vars_p.
50127
50128    \param vars_p
50129    When nonzero, points with non-integer coordinates for the
50130    variables/space-dimensions contained in \p *vars_p can be discarded.
50131
50132    \param complexity
50133    The maximal complexity of any algorithms used.
50134
50135    \note
50136    Currently there is no optimality guarantee, not even if
50137    \p complexity is <CODE>ANY_COMPLEXITY</CODE>.
50138  */
50139  void drop_some_non_integer_points(const Variables_Set* vars_p,
50140                                    Complexity_Class complexity);
50141
50142  //! Helper function that overapproximates an interval linear form.
50143  /*!
50144    \param lf
50145    The linear form on intervals with floating point boundaries to approximate.
50146    ALL of its coefficients MUST be bounded.
50147
50148    \param lf_dimension
50149    Must be the space dimension of \p lf.
50150
50151    \param result
50152    Used to store the result.
50153
50154    This function makes \p result become a linear form that is a correct
50155    approximation of \p lf under the constraints specified by \p *this.
50156    The resulting linear form has the property that all of its variable
50157    coefficients have a non-significant upper bound and can thus be
50158    considered as singletons.
50159  */
50160  template <typename FP_Format, typename Interval_Info>
50161  void overapproximate_linear_form(
50162  const Linear_Form<Interval <FP_Format, Interval_Info> >& lf,
50163  const dimension_type lf_dimension,
50164  Linear_Form<Interval <FP_Format, Interval_Info> >& result);
50165
50166  /*! \brief
50167    Helper function that makes \p result become a Linear_Expression obtained
50168    by normalizing the denominators in \p lf.
50169
50170    \param lf
50171    The linear form on intervals with floating point boundaries to normalize.
50172    It should be the result of an application of static method
50173    <CODE>overapproximate_linear_form</CODE>.
50174
50175    \param lf_dimension
50176    Must be the space dimension of \p lf.
50177
50178    \param result
50179    Used to store the result.
50180
50181    This function ignores the upper bound of intervals in \p lf,
50182    so that in fact \p result can be seen as \p lf multiplied by a proper
50183    normalization constant.
50184  */
50185  template <typename FP_Format, typename Interval_Info>
50186  static void convert_to_integer_expression(
50187              const Linear_Form<Interval <FP_Format, Interval_Info> >& lf,
50188              const dimension_type lf_dimension,
50189              Linear_Expression& result);
50190
50191  //! Normalization helper function.
50192  /*!
50193    \param lf
50194    The linear form on intervals with floating point boundaries to normalize.
50195    It should be the result of an application of static method
50196    <CODE>overapproximate_linear_form</CODE>.
50197
50198    \param lf_dimension
50199    Must be the space dimension of \p lf.
50200
50201    \param res
50202    Stores the normalized linear form, except its inhomogeneous term.
50203
50204    \param res_low_coeff
50205    Stores the lower boundary of the inhomogeneous term of the result.
50206
50207    \param res_hi_coeff
50208    Stores the higher boundary of the inhomogeneous term of the result.
50209
50210    \param denominator
50211    Becomes the common denominator of \p res_low_coeff, \p res_hi_coeff
50212    and all coefficients in \p res.
50213
50214    Results are obtained by normalizing denominators in \p lf, ignoring
50215    the upper bounds of variable coefficients in \p lf.
50216  */
50217  template <typename FP_Format, typename Interval_Info>
50218  static void
50219  convert_to_integer_expressions(const Linear_Form<Interval<FP_Format,
50220                                                            Interval_Info> >&
50221                                 lf,
50222                                 const dimension_type lf_dimension,
50223                                 Linear_Expression& res,
50224                                 Coefficient& res_low_coeff,
50225                                 Coefficient& res_hi_coeff,
50226                                 Coefficient& denominator);
50227
50228  template <typename Linear_System1, typename Row2>
50229  static bool
50230  add_to_system_and_check_independence(Linear_System1& eq_sys,
50231                                       const Row2& eq);
50232
50233  /*! \brief
50234    Assuming \p *this is NNC, assigns to \p *this the result of the
50235    "positive time-elapse" between \p *this and \p y.
50236
50237    \exception std::invalid_argument
50238    Thrown if \p *this and \p y are dimension-incompatible.
50239  */
50240  void positive_time_elapse_assign_impl(const Polyhedron& y);
50241};
50242
50243/* Automatically generated from PPL source file ../src/Ph_Status_inlines.hh line 1. */
50244/* Polyhedron::Status class implementation: inline functions.
50245*/
50246
50247
50248namespace Parma_Polyhedra_Library {
50249
50250inline
50251Polyhedron::Status::Status(flags_t mask)
50252  : flags(mask) {
50253}
50254
50255inline
50256Polyhedron::Status::Status()
50257  : flags(ZERO_DIM_UNIV) {
50258}
50259
50260inline bool
50261Polyhedron::Status::test_all(flags_t mask) const {
50262  return (flags & mask) == mask;
50263}
50264
50265inline bool
50266Polyhedron::Status::test_any(flags_t mask) const {
50267  return (flags & mask) != 0;
50268}
50269
50270inline void
50271Polyhedron::Status::set(flags_t mask) {
50272  flags |= mask;
50273}
50274
50275inline void
50276Polyhedron::Status::reset(flags_t mask) {
50277  flags &= ~mask;
50278}
50279
50280inline bool
50281Polyhedron::Status::test_zero_dim_univ() const {
50282  return flags == ZERO_DIM_UNIV;
50283}
50284
50285inline void
50286Polyhedron::Status::reset_zero_dim_univ() {
50287  // This is a no-op if the current status is not zero-dim.
50288  if (flags == ZERO_DIM_UNIV) {
50289    // In the zero-dim space, if it is not the universe it is empty.
50290    flags = EMPTY;
50291  }
50292}
50293
50294inline void
50295Polyhedron::Status::set_zero_dim_univ() {
50296  // Zero-dim universe is incompatible with anything else.
50297  flags = ZERO_DIM_UNIV;
50298}
50299
50300inline bool
50301Polyhedron::Status::test_empty() const {
50302  return test_any(EMPTY);
50303}
50304
50305inline void
50306Polyhedron::Status::reset_empty() {
50307  reset(EMPTY);
50308}
50309
50310inline void
50311Polyhedron::Status::set_empty() {
50312  flags = EMPTY;
50313}
50314
50315inline bool
50316Polyhedron::Status::test_c_up_to_date() const {
50317  return test_any(C_UP_TO_DATE);
50318}
50319
50320inline void
50321Polyhedron::Status::reset_c_up_to_date() {
50322  reset(C_UP_TO_DATE);
50323}
50324
50325inline void
50326Polyhedron::Status::set_c_up_to_date() {
50327  set(C_UP_TO_DATE);
50328}
50329
50330inline bool
50331Polyhedron::Status::test_g_up_to_date() const {
50332  return test_any(G_UP_TO_DATE);
50333}
50334
50335inline void
50336Polyhedron::Status::reset_g_up_to_date() {
50337  reset(G_UP_TO_DATE);
50338}
50339
50340inline void
50341Polyhedron::Status::set_g_up_to_date() {
50342  set(G_UP_TO_DATE);
50343}
50344
50345inline bool
50346Polyhedron::Status::test_c_minimized() const {
50347  return test_any(C_MINIMIZED);
50348}
50349
50350inline void
50351Polyhedron::Status::reset_c_minimized() {
50352  reset(C_MINIMIZED);
50353}
50354
50355inline void
50356Polyhedron::Status::set_c_minimized() {
50357  set(C_MINIMIZED);
50358}
50359
50360inline bool
50361Polyhedron::Status::test_g_minimized() const {
50362  return test_any(G_MINIMIZED);
50363}
50364
50365inline void
50366Polyhedron::Status::reset_g_minimized() {
50367  reset(G_MINIMIZED);
50368}
50369
50370inline void
50371Polyhedron::Status::set_g_minimized() {
50372  set(G_MINIMIZED);
50373}
50374
50375
50376inline bool
50377Polyhedron::Status::test_c_pending() const {
50378  return test_any(CS_PENDING);
50379}
50380
50381inline void
50382Polyhedron::Status::reset_c_pending() {
50383  reset(CS_PENDING);
50384}
50385
50386inline void
50387Polyhedron::Status::set_c_pending() {
50388  set(CS_PENDING);
50389}
50390
50391inline bool
50392Polyhedron::Status::test_g_pending() const {
50393  return test_any(GS_PENDING);
50394}
50395
50396inline void
50397Polyhedron::Status::reset_g_pending() {
50398  reset(GS_PENDING);
50399}
50400
50401inline void
50402Polyhedron::Status::set_g_pending() {
50403  set(GS_PENDING);
50404}
50405
50406
50407inline bool
50408Polyhedron::Status::test_sat_c_up_to_date() const {
50409  return test_any(SAT_C_UP_TO_DATE);
50410}
50411
50412inline void
50413Polyhedron::Status::reset_sat_c_up_to_date() {
50414  reset(SAT_C_UP_TO_DATE);
50415}
50416
50417inline void
50418Polyhedron::Status::set_sat_c_up_to_date() {
50419  set(SAT_C_UP_TO_DATE);
50420}
50421
50422inline bool
50423Polyhedron::Status::test_sat_g_up_to_date() const {
50424  return test_any(SAT_G_UP_TO_DATE);
50425}
50426
50427inline void
50428Polyhedron::Status::reset_sat_g_up_to_date() {
50429  reset(SAT_G_UP_TO_DATE);
50430}
50431
50432inline void
50433Polyhedron::Status::set_sat_g_up_to_date() {
50434  set(SAT_G_UP_TO_DATE);
50435}
50436
50437} // namespace Parma_Polyhedra_Library
50438
50439/* Automatically generated from PPL source file ../src/Polyhedron_inlines.hh line 1. */
50440/* Polyhedron class implementation: inline functions.
50441*/
50442
50443
50444/* Automatically generated from PPL source file ../src/Polyhedron_inlines.hh line 29. */
50445#include <algorithm>
50446#include <deque>
50447
50448namespace Parma_Polyhedra_Library {
50449
50450inline memory_size_type
50451Polyhedron::total_memory_in_bytes() const {
50452  return sizeof(*this) + external_memory_in_bytes();
50453}
50454
50455inline dimension_type
50456Polyhedron::space_dimension() const {
50457  return space_dim;
50458}
50459
50460inline int32_t
50461Polyhedron::hash_code() const {
50462  return hash_code_from_dimension(space_dimension());
50463}
50464
50465inline dimension_type
50466Polyhedron::max_space_dimension() {
50467  using std::min;
50468  // One dimension is reserved to have a value of type dimension_type
50469  // that does not represent a legal dimension.
50470  return min(std::numeric_limits<dimension_type>::max() - 1,
50471             min(Constraint_System::max_space_dimension(),
50472                 Generator_System::max_space_dimension()
50473                 )
50474             );
50475}
50476
50477inline Topology
50478Polyhedron::topology() const {
50479  // We can check either one of the two matrices.
50480  // (`con_sys' is slightly better, since it is placed at offset 0.)
50481  return con_sys.topology();
50482}
50483
50484inline bool
50485Polyhedron::is_discrete() const {
50486  return affine_dimension() == 0;
50487}
50488
50489inline bool
50490Polyhedron::is_necessarily_closed() const {
50491  // We can check either one of the two matrices.
50492  // (`con_sys' is slightly better, since it is placed at offset 0.)
50493  return con_sys.is_necessarily_closed();
50494}
50495
50496inline void
50497Polyhedron::upper_bound_assign(const Polyhedron& y) {
50498  poly_hull_assign(y);
50499}
50500
50501inline void
50502Polyhedron::difference_assign(const Polyhedron& y) {
50503  poly_difference_assign(y);
50504}
50505
50506inline void
50507Polyhedron::widening_assign(const Polyhedron& y, unsigned* tp) {
50508  H79_widening_assign(y, tp);
50509}
50510
50511inline
50512Polyhedron::~Polyhedron() {
50513}
50514
50515inline void
50516Polyhedron::m_swap(Polyhedron& y) {
50517  if (topology() != y.topology()) {
50518    throw_topology_incompatible("swap(y)", "y", y);
50519  }
50520  using std::swap;
50521  swap(con_sys, y.con_sys);
50522  swap(gen_sys, y.gen_sys);
50523  swap(sat_c, y.sat_c);
50524  swap(sat_g, y.sat_g);
50525  swap(status, y.status);
50526  swap(space_dim, y.space_dim);
50527}
50528
50529/*! \relates Polyhedron */
50530inline void
50531swap(Polyhedron& x, Polyhedron& y) {
50532  x.m_swap(y);
50533}
50534
50535inline bool
50536Polyhedron::can_recycle_constraint_systems() {
50537  return true;
50538}
50539
50540inline bool
50541Polyhedron::can_recycle_congruence_systems() {
50542  return false;
50543}
50544
50545inline bool
50546Polyhedron::marked_empty() const {
50547  return status.test_empty();
50548}
50549
50550inline bool
50551Polyhedron::constraints_are_up_to_date() const {
50552  return status.test_c_up_to_date();
50553}
50554
50555inline bool
50556Polyhedron::generators_are_up_to_date() const {
50557  return status.test_g_up_to_date();
50558}
50559
50560inline bool
50561Polyhedron::constraints_are_minimized() const {
50562  return status.test_c_minimized();
50563}
50564
50565inline bool
50566Polyhedron::generators_are_minimized() const {
50567  return status.test_g_minimized();
50568}
50569
50570inline bool
50571Polyhedron::sat_c_is_up_to_date() const {
50572  return status.test_sat_c_up_to_date();
50573}
50574
50575inline bool
50576Polyhedron::sat_g_is_up_to_date() const {
50577  return status.test_sat_g_up_to_date();
50578}
50579
50580inline bool
50581Polyhedron::has_pending_constraints() const {
50582  return status.test_c_pending();
50583}
50584
50585inline bool
50586Polyhedron::has_pending_generators() const {
50587  return status.test_g_pending();
50588}
50589
50590inline bool
50591Polyhedron::has_something_pending() const {
50592  return status.test_c_pending() || status.test_g_pending();
50593}
50594
50595inline bool
50596Polyhedron::can_have_something_pending() const {
50597  return constraints_are_minimized()
50598    && generators_are_minimized()
50599    && (sat_c_is_up_to_date() || sat_g_is_up_to_date());
50600}
50601
50602inline bool
50603Polyhedron::is_empty() const {
50604  if (marked_empty()) {
50605    return true;
50606  }
50607  // Try a fast-fail test: if generators are up-to-date and
50608  // there are no pending constraints, then the generator system
50609  // (since it is well formed) contains a point.
50610  if (generators_are_up_to_date() && !has_pending_constraints()) {
50611    return false;
50612  }
50613  return !minimize();
50614}
50615
50616inline void
50617Polyhedron::set_constraints_up_to_date() {
50618  status.set_c_up_to_date();
50619}
50620
50621inline void
50622Polyhedron::set_generators_up_to_date() {
50623  status.set_g_up_to_date();
50624}
50625
50626inline void
50627Polyhedron::set_constraints_minimized() {
50628  set_constraints_up_to_date();
50629  status.set_c_minimized();
50630}
50631
50632inline void
50633Polyhedron::set_generators_minimized() {
50634  set_generators_up_to_date();
50635  status.set_g_minimized();
50636}
50637
50638inline void
50639Polyhedron::set_constraints_pending() {
50640  status.set_c_pending();
50641}
50642
50643inline void
50644Polyhedron::set_generators_pending() {
50645  status.set_g_pending();
50646}
50647
50648inline void
50649Polyhedron::set_sat_c_up_to_date() {
50650  status.set_sat_c_up_to_date();
50651}
50652
50653inline void
50654Polyhedron::set_sat_g_up_to_date() {
50655  status.set_sat_g_up_to_date();
50656}
50657
50658inline void
50659Polyhedron::clear_empty() {
50660  status.reset_empty();
50661}
50662
50663inline void
50664Polyhedron::clear_constraints_minimized() {
50665  status.reset_c_minimized();
50666}
50667
50668inline void
50669Polyhedron::clear_generators_minimized() {
50670  status.reset_g_minimized();
50671}
50672
50673inline void
50674Polyhedron::clear_pending_constraints() {
50675  status.reset_c_pending();
50676}
50677
50678inline void
50679Polyhedron::clear_pending_generators() {
50680  status.reset_g_pending();
50681}
50682
50683inline void
50684Polyhedron::clear_sat_c_up_to_date() {
50685  status.reset_sat_c_up_to_date();
50686  // Can get rid of sat_c here.
50687}
50688
50689inline void
50690Polyhedron::clear_sat_g_up_to_date() {
50691  status.reset_sat_g_up_to_date();
50692  // Can get rid of sat_g here.
50693}
50694
50695inline void
50696Polyhedron::clear_constraints_up_to_date() {
50697  clear_pending_constraints();
50698  clear_constraints_minimized();
50699  clear_sat_c_up_to_date();
50700  clear_sat_g_up_to_date();
50701  status.reset_c_up_to_date();
50702  // Can get rid of con_sys here.
50703}
50704
50705inline void
50706Polyhedron::clear_generators_up_to_date() {
50707  clear_pending_generators();
50708  clear_generators_minimized();
50709  clear_sat_c_up_to_date();
50710  clear_sat_g_up_to_date();
50711  status.reset_g_up_to_date();
50712  // Can get rid of gen_sys here.
50713}
50714
50715inline bool
50716Polyhedron::process_pending() const {
50717  PPL_ASSERT(space_dim > 0 && !marked_empty());
50718  PPL_ASSERT(has_something_pending());
50719
50720  if (has_pending_constraints()) {
50721    return process_pending_constraints();
50722  }
50723
50724  PPL_ASSERT(has_pending_generators());
50725  process_pending_generators();
50726  return true;
50727}
50728
50729inline bool
50730Polyhedron::bounds_from_above(const Linear_Expression& expr) const {
50731  return bounds(expr, true);
50732}
50733
50734inline bool
50735Polyhedron::bounds_from_below(const Linear_Expression& expr) const {
50736  return bounds(expr, false);
50737}
50738
50739inline bool
50740Polyhedron::maximize(const Linear_Expression& expr,
50741                     Coefficient& sup_n, Coefficient& sup_d,
50742                     bool& maximum) const {
50743  Generator g(point());
50744  return max_min(expr, true, sup_n, sup_d, maximum, g);
50745}
50746
50747inline bool
50748Polyhedron::maximize(const Linear_Expression& expr,
50749                     Coefficient& sup_n, Coefficient& sup_d, bool& maximum,
50750                     Generator& g) const {
50751  return max_min(expr, true, sup_n, sup_d, maximum, g);
50752}
50753
50754inline bool
50755Polyhedron::minimize(const Linear_Expression& expr,
50756                     Coefficient& inf_n, Coefficient& inf_d,
50757                     bool& minimum) const {
50758  Generator g(point());
50759  return max_min(expr, false, inf_n, inf_d, minimum, g);
50760}
50761
50762inline bool
50763Polyhedron::minimize(const Linear_Expression& expr,
50764                     Coefficient& inf_n, Coefficient& inf_d, bool& minimum,
50765                     Generator& g) const {
50766  return max_min(expr, false, inf_n, inf_d, minimum, g);
50767}
50768
50769inline Constraint_System
50770Polyhedron::simplified_constraints() const {
50771  PPL_ASSERT(constraints_are_up_to_date());
50772  Constraint_System cs(con_sys);
50773  if (cs.num_pending_rows() > 0) {
50774    cs.unset_pending_rows();
50775  }
50776  if (has_pending_constraints() || !constraints_are_minimized()) {
50777    cs.simplify();
50778  }
50779  return cs;
50780}
50781
50782inline Congruence_System
50783Polyhedron::congruences() const {
50784  return Congruence_System(minimized_constraints());
50785}
50786
50787inline Congruence_System
50788Polyhedron::minimized_congruences() const {
50789  return Congruence_System(minimized_constraints());
50790}
50791
50792inline void
50793Polyhedron::add_recycled_congruences(Congruence_System& cgs) {
50794  add_congruences(cgs);
50795}
50796
50797template <typename FP_Format, typename Interval_Info>
50798inline void
50799Polyhedron::generalized_refine_with_linear_form_inequality(
50800            const Linear_Form< Interval<FP_Format, Interval_Info> >& left,
50801            const Linear_Form< Interval<FP_Format, Interval_Info> >& right,
50802            const Relation_Symbol relsym) {
50803  switch (relsym) {
50804  case EQUAL:
50805    // TODO: see if we can handle this case more efficiently.
50806    refine_with_linear_form_inequality(left, right, false);
50807    refine_with_linear_form_inequality(right, left, false);
50808    break;
50809  case LESS_THAN:
50810    refine_with_linear_form_inequality(left, right, true);
50811    break;
50812  case LESS_OR_EQUAL:
50813    refine_with_linear_form_inequality(left, right, false);
50814    break;
50815  case GREATER_THAN:
50816    refine_with_linear_form_inequality(right, left, true);
50817    break;
50818  case GREATER_OR_EQUAL:
50819    refine_with_linear_form_inequality(right, left, false);
50820    break;
50821  case NOT_EQUAL:
50822    break;
50823  default:
50824    PPL_UNREACHABLE;
50825    break;
50826  }
50827}
50828
50829template <typename FP_Format, typename Interval_Info>
50830inline void
50831Polyhedron::
50832refine_fp_interval_abstract_store(
50833       Box< Interval<FP_Format, Interval_Info> >& store) const {
50834
50835  // Check that FP_Format is indeed a floating point type.
50836  PPL_COMPILE_TIME_CHECK(!std::numeric_limits<FP_Format>::is_exact,
50837                     "Polyhedron::refine_fp_interval_abstract_store:"
50838                     " T not a floating point type.");
50839
50840  typedef Interval<FP_Format, Interval_Info> FP_Interval_Type;
50841  store.intersection_assign(Box<FP_Interval_Type>(*this));
50842
50843}
50844
50845/*! \relates Polyhedron */
50846inline bool
50847operator!=(const Polyhedron& x, const Polyhedron& y) {
50848  return !(x == y);
50849}
50850
50851inline bool
50852Polyhedron::strictly_contains(const Polyhedron& y) const {
50853  const Polyhedron& x = *this;
50854  return x.contains(y) && !y.contains(x);
50855}
50856
50857inline void
50858Polyhedron::drop_some_non_integer_points(Complexity_Class complexity) {
50859  const Variables_Set* const p_vs = 0;
50860  drop_some_non_integer_points(p_vs, complexity);
50861}
50862
50863inline void
50864Polyhedron::drop_some_non_integer_points(const Variables_Set& vars,
50865                                         Complexity_Class complexity) {
50866  drop_some_non_integer_points(&vars, complexity);
50867}
50868
50869
50870namespace Interfaces {
50871
50872inline bool
50873is_necessarily_closed_for_interfaces(const Polyhedron& ph) {
50874  return ph.is_necessarily_closed();
50875}
50876
50877} // namespace Interfaces
50878
50879} // namespace Parma_Polyhedra_Library
50880
50881/* Automatically generated from PPL source file ../src/Polyhedron_templates.hh line 1. */
50882/* Polyhedron class implementation: non-inline template functions.
50883*/
50884
50885
50886/* Automatically generated from PPL source file ../src/MIP_Problem_defs.hh line 1. */
50887/* MIP_Problem class declaration.
50888*/
50889
50890
50891/* Automatically generated from PPL source file ../src/Matrix_defs.hh line 1. */
50892/* Matrix class declaration.
50893*/
50894
50895
50896/* Automatically generated from PPL source file ../src/Matrix_types.hh line 1. */
50897
50898
50899namespace Parma_Polyhedra_Library {
50900
50901template <typename Row>
50902class Matrix;
50903
50904} // namespace Parma_Polyhedra_Library
50905
50906/* Automatically generated from PPL source file ../src/Matrix_defs.hh line 31. */
50907#include <ostream>
50908
50909#ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
50910//! A sparse matrix of Coefficient.
50911#endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
50912template <typename Row>
50913class Parma_Polyhedra_Library::Matrix {
50914
50915public:
50916  typedef typename Swapping_Vector<Row>::iterator iterator;
50917  typedef typename Swapping_Vector<Row>::const_iterator const_iterator;
50918
50919  //! Returns the maximum number of rows of a Sparse_Matrix.
50920  static dimension_type max_num_rows();
50921
50922  //! Returns the maximum number of columns of a Sparse_Matrix.
50923  static dimension_type max_num_columns();
50924
50925  /*!
50926    \brief Constructs a square matrix with the given size, filled with
50927           unstored zeroes.
50928
50929    \param n
50930    The size of the new square matrix.
50931
50932    This method takes \f$O(n)\f$ time.
50933  */
50934  explicit Matrix(dimension_type n = 0);
50935
50936  /*!
50937    \brief Constructs a matrix with the given dimensions, filled with unstored
50938           zeroes.
50939
50940    \param num_rows
50941    The number of rows in the new matrix.
50942
50943    \param num_columns
50944    The number of columns in the new matrix.
50945
50946    This method takes \f$O(n)\f$ time, where n is \p num_rows.
50947  */
50948  Matrix(dimension_type num_rows, dimension_type num_columns);
50949
50950  //! Swaps (*this) with x.
50951  /*!
50952
50953    \param x
50954    The matrix that will be swapped with *this.
50955
50956    This method takes \f$O(1)\f$ time.
50957  */
50958  void m_swap(Matrix& x);
50959
50960  //! Returns the number of rows in the matrix.
50961  /*!
50962    This method takes \f$O(1)\f$ time.
50963  */
50964  dimension_type num_rows() const;
50965
50966  //! Returns the number of columns in the matrix.
50967  /*!
50968    This method takes \f$O(1)\f$ time.
50969  */
50970  dimension_type num_columns() const;
50971
50972  // TODO: Check if this can be removed.
50973  //! Returns the capacity of the row vector.
50974  dimension_type capacity() const;
50975
50976  //! Returns <CODE>true</CODE> if and only if \p *this has no rows.
50977  /*!
50978    \note
50979    The unusual naming for this method is \em intentional:
50980    we do not want it to be named \c empty because this would cause
50981    an error prone name clash with the corresponding methods in derived
50982    classes Constraint_System and Congruence_System (which have a
50983    different semantics).
50984  */
50985  bool has_no_rows() const;
50986
50987  //! Equivalent to resize(n, n).
50988  void resize(dimension_type n);
50989
50990  // TODO: Check if this can become private.
50991  //! Reserves space for at least \p n rows.
50992  void reserve_rows(dimension_type n);
50993
50994  //! Resizes this matrix to the specified dimensions.
50995  /*!
50996
50997    \param num_rows
50998    The desired numer of rows.
50999
51000    \param num_columns
51001    The desired numer of columns.
51002
51003    New rows and columns will contain non-stored zeroes.
51004
51005    This operation invalidates existing iterators.
51006
51007    Adding n rows takes \f$O(n)\f$ amortized time.
51008
51009    Adding n columns takes \f$O(r)\f$ time, where r is \p num_rows.
51010
51011    Removing n rows takes \f$O(n+k)\f$ amortized time, where k is the total
51012    number of elements stored in the removed rows.
51013
51014    Removing n columns takes \f$O(\sum_{j=1}^{r} (k_j*\log^2 n_j))\f$ time,
51015    where r is the number of rows, \f$k_j\f$ is the number of elements stored
51016    in the columns of the j-th row that must be removed and \f$n_j\f$ is the
51017    total number of elements stored in the j-th row.
51018    A weaker (but simpler) bound is \f$O(r+k*\log^2 c)\f$, where r is the
51019    number of rows, k is the number of elements that have to be removed and c
51020    is the number of columns.
51021  */
51022  void resize(dimension_type num_rows, dimension_type num_columns);
51023
51024  //! Adds \p n rows and \p m columns of zeroes to the matrix.
51025  /*!
51026    \param n
51027    The number of rows to be added: must be strictly positive.
51028
51029    \param m
51030    The number of columns to be added: must be strictly positive.
51031
51032    Turns the \f$r \times c\f$ matrix \f$M\f$ into
51033    the \f$(r+n) \times (c+m)\f$ matrix
51034    \f$\bigl(\genfrac{}{}{0pt}{}{M}{0} \genfrac{}{}{0pt}{}{0}{0}\bigr)\f$.
51035    The matrix is expanded avoiding reallocation whenever possible.
51036
51037    This method takes \f$O(r)\f$ time, where r is the number of the matrix's
51038    rows after the operation.
51039  */
51040  void add_zero_rows_and_columns(dimension_type n, dimension_type m);
51041
51042  //! Adds to the matrix \p n rows of zeroes.
51043  /*!
51044    \param n
51045    The number of rows to be added: must be strictly positive.
51046
51047    Turns the \f$r \times c\f$ matrix \f$M\f$ into
51048    the \f$(r+n) \times c\f$ matrix \f$\genfrac{(}{)}{0pt}{}{M}{0}\f$.
51049    The matrix is expanded avoiding reallocation whenever possible.
51050
51051    This method takes \f$O(k)\f$ amortized time, where k is the number of the
51052    new rows.
51053  */
51054  void add_zero_rows(dimension_type n);
51055
51056  //! Adds a copy of the row \p x at the end of the matrix.
51057  /*!
51058
51059    \param x
51060    The row that will be appended to the matrix.
51061
51062    This operation invalidates existing iterators.
51063
51064    This method takes \f$O(n)\f$ amortized time, where n is the numer of
51065    elements stored in \p x.
51066  */
51067  void add_row(const Row& x);
51068
51069  //! Adds the row \p y to the matrix.
51070  /*!
51071    \param y
51072    The row to be added: it must have the same size and capacity as
51073    \p *this. It is not declared <CODE>const</CODE> because its
51074    data-structures will recycled to build the new matrix row.
51075
51076    Turns the \f$r \times c\f$ matrix \f$M\f$ into
51077    the \f$(r+1) \times c\f$ matrix
51078    \f$\genfrac{(}{)}{0pt}{}{M}{y}\f$.
51079    The matrix is expanded avoiding reallocation whenever possible.
51080  */
51081  void add_recycled_row(Row& y);
51082
51083  /*! \brief
51084    Removes from the matrix the last \p n rows.
51085
51086    \param n
51087    The number of row that will be removed.
51088
51089    It is equivalent to num_rows() - n, num_columns()).
51090
51091    This method takes \f$O(n+k)\f$ amortized time, where k is the total number
51092    of elements stored in the removed rows and n is the number of removed
51093    rows.
51094  */
51095  void remove_trailing_rows(dimension_type n);
51096
51097  void remove_rows(iterator first, iterator last);
51098
51099  //! Permutes the columns of the matrix.
51100  /*!
51101    This method may be slow for some Row types, and should be avoided if
51102    possible.
51103
51104    \param cycles
51105    A vector representing the non-trivial cycles of the permutation
51106    according to which the columns must be rearranged.
51107
51108    The \p cycles vector contains, one after the other, the
51109    non-trivial cycles (i.e., the cycles of length greater than one)
51110    of a permutation of \e non-zero column indexes.  Each cycle is
51111    terminated by zero.  For example, assuming the matrix has 7
51112    columns, the permutation \f$ \{ 1 \mapsto 3, 2 \mapsto 4,
51113    3 \mapsto 6, 4 \mapsto 2, 5 \mapsto 5, 6 \mapsto 1 \}\f$ can be
51114    represented by the non-trivial cycles \f$(1 3 6)(2 4)\f$ that, in
51115    turn can be represented by a vector of 6 elements containing 1, 3,
51116    6, 0, 2, 4, 0.
51117
51118    This method takes \f$O(k*\sum_{j=1}^{r} \log^2 n_j)\f$ expected time,
51119    where k is the size of the \p cycles vector, r the number of rows and
51120    \f$n_j\f$ the number of elements stored in row j.
51121    A weaker (but simpler) bound is \f$O(k*r*\log^2 c)\f$, where k is the size
51122    of the \p cycles vector, r is the number of rows and c is the number of
51123    columns.
51124
51125    \note
51126    The first column of the matrix, having index zero, is never involved
51127    in a permutation.
51128  */
51129  void permute_columns(const std::vector<dimension_type>& cycles);
51130
51131  //! Swaps the columns having indexes \p i and \p j.
51132  void swap_columns(dimension_type i,  dimension_type j);
51133
51134  //! Adds \p n columns of zeroes to the matrix.
51135  /*!
51136    \param n
51137    The number of columns to be added: must be strictly positive.
51138
51139    Turns the \f$r \times c\f$ matrix \f$M\f$ into
51140    the \f$r \times (c+n)\f$ matrix \f$(M \, 0)\f$.
51141
51142    This method takes \f$O(r)\f$ amortized time, where r is the numer of the
51143    matrix's rows.
51144  */
51145  void add_zero_columns(dimension_type n);
51146
51147  //! Adds \p n columns of non-stored zeroes to the matrix before column i.
51148  /*!
51149
51150    \param n
51151    The numer of columns that will be added.
51152
51153    \param i
51154    The index of the column before which the new columns will be added.
51155
51156    This operation invalidates existing iterators.
51157
51158    This method takes \f$O(\sum_{j=1}^{r} (k_j+\log n_j))\f$ time, where r is
51159    the number of rows, \f$k_j\f$ is the number of elements stored in the
51160    columns of the j-th row that must be shifted and \f$n_j\f$ is the number
51161    of elements stored in the j-th row.
51162    A weaker (but simpler) bound is \f$O(k+r*\log c)\f$ time, where k is the
51163    number of elements that must be shifted, r is the number of the rows and c
51164    is the number of the columns.
51165  */
51166  void add_zero_columns(dimension_type n, dimension_type i);
51167
51168  //! Removes the i-th from the matrix, shifting other columns to the left.
51169  /*!
51170
51171    \param i
51172    The index of the column that will be removed.
51173
51174    This operation invalidates existing iterators on rows' elements.
51175
51176    This method takes \f$O(k + \sum_{j=1}^{r} (\log^2 n_j))\f$ amortized time,
51177    where k is the number of elements stored with column index greater than i,
51178    r the number of rows in this matrix and \f$n_j\f$ the number of elements
51179    stored in row j.
51180    A weaker (but simpler) bound is \f$O(r*(c-i+\log^2 c))\f$, where r is the
51181    number of rows, c is the number of columns and i is the parameter passed
51182    to this method.
51183  */
51184  void remove_column(dimension_type i);
51185
51186  //! Shrinks the matrix by removing its \p n trailing columns.
51187  /*!
51188
51189    \param n
51190    The number of trailing columns that will be removed.
51191
51192    This operation invalidates existing iterators.
51193
51194    This method takes \f$O(\sum_{j=1}^r (k_j*\log n_j))\f$ amortized time,
51195    where r is the number of rows, \f$k_j\f$ is the number of elements that
51196    have to be removed from row j and \f$n_j\f$ is the total number of
51197    elements stored in row j.
51198    A weaker (but simpler) bound is \f$O(r*n*\log c)\f$, where r is the number
51199    of rows, c the number of columns and n the parameter passed to this
51200    method.
51201  */
51202  void remove_trailing_columns(dimension_type n);
51203
51204  //! Equivalent to resize(0,0).
51205  void clear();
51206
51207  //! Returns an %iterator pointing to the first row.
51208  /*!
51209    This method takes \f$O(1)\f$ time.
51210  */
51211  iterator begin();
51212
51213  //! Returns an %iterator pointing after the last row.
51214  /*!
51215    This method takes \f$O(1)\f$ time.
51216  */
51217  iterator end();
51218
51219  //! Returns an %iterator pointing to the first row.
51220  /*!
51221    This method takes \f$O(1)\f$ time.
51222  */
51223  const_iterator begin() const;
51224
51225  //! Returns an %iterator pointing after the last row.
51226  /*!
51227    This method takes \f$O(1)\f$ time.
51228  */
51229  const_iterator end() const;
51230
51231  //! Returns a reference to the i-th row.
51232  /*!
51233    \param i
51234    The index of the desired row.
51235
51236    This method takes \f$O(1)\f$ time.
51237  */
51238  Row& operator[](dimension_type i);
51239
51240  //! Returns a const reference to the i-th row.
51241  /*!
51242    \param i
51243    The index of the desired row.
51244
51245    This method takes \f$O(1)\f$ time.
51246  */
51247  const Row& operator[](dimension_type i) const;
51248
51249  //! Loads the row from an ASCII representation generated using ascii_dump().
51250  /*!
51251    \param s
51252    The stream from which read the ASCII representation.
51253
51254    This method takes \f$O(n*\log n)\f$ time.
51255  */
51256  bool ascii_load(std::istream& s);
51257
51258  PPL_OUTPUT_DECLARATIONS
51259
51260  //! Returns the total size in bytes of the memory occupied by \p *this.
51261  /*!
51262    This method is \f$O(r+k)\f$, where r is the number of rows and k is the
51263    number of elements stored in the matrix.
51264  */
51265  memory_size_type total_memory_in_bytes() const;
51266
51267  //! Returns the size in bytes of the memory managed by \p *this.
51268  /*!
51269    This method is \f$O(r+k)\f$, where r is the number of rows and k is the
51270    number of elements stored in the matrix.
51271  */
51272  memory_size_type external_memory_in_bytes() const;
51273
51274  //! Checks if all the invariants are satisfied.
51275  bool OK() const;
51276
51277private:
51278  //! The vector that stores the matrix's elements.
51279  Swapping_Vector<Row> rows;
51280
51281  //! The number of columns in this matrix.
51282  dimension_type num_columns_;
51283};
51284
51285namespace Parma_Polyhedra_Library {
51286
51287#ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
51288/*! \relates Matrix */
51289#endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
51290template <typename Row>
51291void swap(Matrix<Row>& x, Matrix<Row>& y);
51292
51293#ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
51294//! Returns <CODE>true</CODE> if and only if \p x and \p y are identical.
51295/*! \relates Matrix */
51296#endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
51297template <typename Row>
51298bool operator==(const Matrix<Row>& x, const Matrix<Row>& y);
51299
51300#ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
51301//! Returns <CODE>true</CODE> if and only if \p x and \p y are different.
51302/*! \relates Matrix */
51303#endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
51304template <typename Row>
51305bool operator!=(const Matrix<Row>& x, const Matrix<Row>& y);
51306
51307} // namespace Parma_Polyhedra_Library
51308
51309
51310/* Automatically generated from PPL source file ../src/Matrix_inlines.hh line 1. */
51311/* Matrix class implementation: inline functions.
51312*/
51313
51314
51315namespace Parma_Polyhedra_Library {
51316
51317template <typename Row>
51318inline dimension_type
51319Matrix<Row>::max_num_rows() {
51320  return std::vector<Row>().max_size();
51321}
51322
51323template <typename Row>
51324inline dimension_type
51325Matrix<Row>::max_num_columns() {
51326  return Row::max_size();
51327}
51328
51329template <typename Row>
51330inline void
51331Matrix<Row>::m_swap(Matrix& x) {
51332  using std::swap;
51333  swap(rows, x.rows);
51334  swap(num_columns_, x.num_columns_);
51335}
51336
51337template <typename Row>
51338inline dimension_type
51339Matrix<Row>::num_rows() const {
51340  return rows.size();
51341}
51342
51343template <typename Row>
51344inline dimension_type
51345Matrix<Row>::num_columns() const {
51346  return num_columns_;
51347}
51348
51349template <typename Row>
51350inline dimension_type
51351Matrix<Row>::capacity() const {
51352  return rows.capacity();
51353}
51354
51355template <typename Row>
51356inline bool
51357Matrix<Row>::has_no_rows() const {
51358  return num_rows() == 0;
51359}
51360
51361template <typename Row>
51362inline void
51363Matrix<Row>::resize(dimension_type n) {
51364  resize(n, n);
51365}
51366
51367template <typename Row>
51368inline void
51369Matrix<Row>::reserve_rows(dimension_type requested_capacity) {
51370
51371  rows.reserve(requested_capacity);
51372}
51373
51374template <typename Row>
51375inline void
51376Matrix<Row>::add_zero_rows_and_columns(dimension_type n, dimension_type m) {
51377  resize(num_rows() + n, num_columns() + m);
51378}
51379
51380template <typename Row>
51381inline void
51382Matrix<Row>::add_zero_rows(dimension_type n) {
51383  resize(num_rows() + n, num_columns());
51384}
51385
51386template <typename Row>
51387inline void
51388Matrix<Row>::add_row(const Row& x) {
51389  // TODO: Optimize this.
51390  Row row(x);
51391  add_zero_rows(1);
51392  // Now x may have been invalidated, if it was a row of this matrix.
51393  swap(rows.back(), row);
51394  PPL_ASSERT(OK());
51395}
51396
51397template <typename Row>
51398inline void
51399Matrix<Row>::add_recycled_row(Row& x) {
51400  add_zero_rows(1);
51401  swap(rows.back(), x);
51402  PPL_ASSERT(OK());
51403}
51404
51405template <typename Row>
51406inline void
51407Matrix<Row>::remove_trailing_rows(dimension_type n) {
51408  resize(num_rows() - n, num_columns());
51409}
51410
51411template <typename Row>
51412inline void
51413Matrix<Row>::remove_rows(iterator first, iterator last) {
51414  rows.erase(first, last);
51415}
51416
51417template <typename Row>
51418inline void
51419Matrix<Row>::add_zero_columns(dimension_type n) {
51420  resize(num_rows(), num_columns() + n);
51421}
51422
51423template <typename Row>
51424inline void
51425Matrix<Row>::remove_trailing_columns(dimension_type n) {
51426  PPL_ASSERT(n <= num_columns());
51427  resize(num_rows(), num_columns() - n);
51428}
51429
51430template <typename Row>
51431inline void
51432Matrix<Row>::clear() {
51433  resize(0, 0);
51434}
51435
51436template <typename Row>
51437inline typename Matrix<Row>::iterator
51438Matrix<Row>::begin() {
51439  return rows.begin();
51440}
51441
51442template <typename Row>
51443inline typename Matrix<Row>::iterator
51444Matrix<Row>::end() {
51445  return rows.end();
51446}
51447
51448template <typename Row>
51449inline typename Matrix<Row>::const_iterator
51450Matrix<Row>::begin() const {
51451  return rows.begin();
51452}
51453
51454template <typename Row>
51455inline typename Matrix<Row>::const_iterator
51456Matrix<Row>::end() const {
51457  return rows.end();
51458}
51459
51460template <typename Row>
51461inline Row&
51462Matrix<Row>::operator[](dimension_type i) {
51463  PPL_ASSERT(i < rows.size());
51464  return rows[i];
51465}
51466
51467template <typename Row>
51468inline const Row&
51469Matrix<Row>::operator[](dimension_type i) const {
51470  PPL_ASSERT(i < rows.size());
51471  return rows[i];
51472}
51473
51474template <typename Row>
51475inline memory_size_type
51476Matrix<Row>::total_memory_in_bytes() const {
51477  return sizeof(*this) + external_memory_in_bytes();
51478}
51479
51480template <typename Row>
51481inline void
51482swap(Matrix<Row>& x, Matrix<Row>& y) {
51483  x.m_swap(y);
51484}
51485
51486} // namespace Parma_Polyhedra_Library
51487
51488/* Automatically generated from PPL source file ../src/Matrix_templates.hh line 1. */
51489/* Matrix class implementation: non-inline template functions.
51490*/
51491
51492
51493namespace Parma_Polyhedra_Library {
51494
51495template <typename Row>
51496Matrix<Row>::Matrix(dimension_type n)
51497  : rows(n), num_columns_(n) {
51498  for (dimension_type i = 0; i < rows.size(); ++i) {
51499    rows[i].resize(num_columns_);
51500  }
51501  PPL_ASSERT(OK());
51502}
51503
51504template <typename Row>
51505Matrix<Row>::Matrix(dimension_type num_rows, dimension_type num_columns)
51506  : rows(num_rows), num_columns_(num_columns) {
51507  for (dimension_type i = 0; i < rows.size(); ++i) {
51508    rows[i].resize(num_columns_);
51509  }
51510  PPL_ASSERT(OK());
51511}
51512
51513template <typename Row>
51514void
51515Matrix<Row>::resize(dimension_type num_rows, dimension_type num_columns) {
51516  const dimension_type old_num_rows = rows.size();
51517  rows.resize(num_rows);
51518  if (old_num_rows < num_rows) {
51519    for (dimension_type i = old_num_rows; i < num_rows; ++i) {
51520      rows[i].resize(num_columns);
51521    }
51522    if (num_columns_ != num_columns) {
51523      num_columns_ = num_columns;
51524      for (dimension_type i = 0; i < old_num_rows; ++i) {
51525        rows[i].resize(num_columns);
51526      }
51527    }
51528  }
51529  else
51530    if (num_columns_ != num_columns) {
51531      num_columns_ = num_columns;
51532      for (dimension_type i = 0; i < num_rows; ++i) {
51533        rows[i].resize(num_columns);
51534      }
51535    }
51536  PPL_ASSERT(OK());
51537}
51538
51539template <typename Row>
51540void
51541Matrix<Row>::permute_columns(const std::vector<dimension_type>& cycles) {
51542  PPL_DIRTY_TEMP_COEFFICIENT(tmp);
51543  const dimension_type n = cycles.size();
51544  PPL_ASSERT(cycles[n - 1] == 0);
51545  for (dimension_type k = num_rows(); k-- > 0; ) {
51546    Row& rows_k = (*this)[k];
51547    for (dimension_type i = 0, j = 0; i < n; i = ++j) {
51548      // Make `j' be the index of the next cycle terminator.
51549      while (cycles[j] != 0) {
51550        ++j;
51551      }
51552      // Cycles of length less than 2 are not allowed.
51553      PPL_ASSERT(j - i >= 2);
51554      if (j - i == 2) {
51555        // For cycles of length 2 no temporary is needed, just a swap.
51556        rows_k.swap_coefficients(cycles[i], cycles[i + 1]);
51557      }
51558      else {
51559        // Longer cycles need a temporary.
51560        tmp = rows_k.get(cycles[j - 1]);
51561        for (dimension_type l = (j - 1); l > i; --l) {
51562          rows_k.swap_coefficients(cycles[l-1], cycles[l]);
51563        }
51564        if (tmp == 0) {
51565          rows_k.reset(cycles[i]);
51566        }
51567        else {
51568          using std::swap;
51569          swap(tmp, rows_k[cycles[i]]);
51570        }
51571      }
51572    }
51573  }
51574}
51575
51576template <typename Row>
51577void
51578Matrix<Row>::swap_columns(dimension_type i, dimension_type j) {
51579  for (dimension_type k = num_rows(); k-- > 0; ) {
51580    (*this)[k].swap_coefficients(i, j);
51581  }
51582}
51583
51584template <typename Row>
51585void
51586Matrix<Row>::add_zero_columns(dimension_type n, dimension_type i) {
51587  for (dimension_type j = rows.size(); j-- > 0; ) {
51588    rows[j].add_zeroes_and_shift(n, i);
51589  }
51590  num_columns_ += n;
51591  PPL_ASSERT(OK());
51592}
51593
51594template <typename Row>
51595void
51596Matrix<Row>::remove_column(dimension_type i) {
51597  for (dimension_type j = rows.size(); j-- > 0; ) {
51598    rows[j].delete_element_and_shift(i);
51599  }
51600  --num_columns_;
51601  PPL_ASSERT(OK());
51602}
51603
51604template <typename Row>
51605void
51606Matrix<Row>::ascii_dump(std::ostream& s) const {
51607  s << num_rows() << " x ";
51608  s << num_columns() << "\n";
51609  for (const_iterator i = begin(), i_end = end(); i !=i_end; ++i) {
51610    i->ascii_dump(s);
51611  }
51612}
51613
51614PPL_OUTPUT_TEMPLATE_DEFINITIONS_ASCII_ONLY(Row, Matrix<Row>)
51615
51616template <typename Row>
51617bool
51618Matrix<Row>::ascii_load(std::istream& s) {
51619  std::string str;
51620  dimension_type new_num_rows;
51621  dimension_type new_num_cols;
51622  if (!(s >> new_num_rows)) {
51623    return false;
51624  }
51625  if (!(s >> str) || str != "x") {
51626    return false;
51627  }
51628  if (!(s >> new_num_cols)) {
51629    return false;
51630  }
51631
51632  for (iterator i = rows.begin(), i_end = rows.end();
51633       i != i_end; ++i) {
51634    i->clear();
51635  }
51636
51637  resize(new_num_rows, new_num_cols);
51638
51639  for (dimension_type row = 0; row < new_num_rows; ++row) {
51640    if (!rows[row].ascii_load(s)) {
51641      return false;
51642    }
51643  }
51644
51645  // Check invariants.
51646  PPL_ASSERT(OK());
51647  return true;
51648}
51649
51650template <typename Row>
51651memory_size_type
51652Matrix<Row>::external_memory_in_bytes() const {
51653  return rows.external_memory_in_bytes();
51654}
51655
51656template <typename Row>
51657bool
51658Matrix<Row>::OK() const {
51659  for (const_iterator i = begin(), i_end = end(); i != i_end; ++i) {
51660    if (i->size() != num_columns_) {
51661      return false;
51662    }
51663  }
51664  return true;
51665}
51666
51667/*! \relates Parma_Polyhedra_Library::Matrix */
51668template <typename Row>
51669bool
51670operator==(const Matrix<Row>& x, const Matrix<Row>& y) {
51671  if (x.num_rows() != y.num_rows()) {
51672    return false;
51673  }
51674  if (x.num_columns() != y.num_columns()) {
51675    return false;
51676  }
51677  for (dimension_type i = x.num_rows(); i-- > 0; ) {
51678    if (x[i] != y[i]) {
51679      return false;
51680    }
51681  }
51682  return true;
51683}
51684
51685/*! \relates Parma_Polyhedra_Library::Matrix */
51686template <typename Row>
51687bool
51688operator!=(const Matrix<Row>& x, const Matrix<Row>& y) {
51689  return !(x == y);
51690}
51691
51692} // namespace Parma_Polyhedra_Library
51693
51694/* Automatically generated from PPL source file ../src/Matrix_defs.hh line 436. */
51695
51696/* Automatically generated from PPL source file ../src/MIP_Problem_defs.hh line 37. */
51697#include <vector>
51698#include <deque>
51699#include <iterator>
51700#include <iosfwd>
51701
51702namespace Parma_Polyhedra_Library {
51703
51704namespace IO_Operators {
51705
51706//! Output operator.
51707/*! \relates Parma_Polyhedra_Library::MIP_Problem */
51708std::ostream&
51709operator<<(std::ostream& s, const MIP_Problem& mip);
51710
51711} // namespace IO_Operators
51712
51713//! Swaps \p x with \p y.
51714/*! \relates MIP_Problem */
51715void swap(MIP_Problem& x, MIP_Problem& y);
51716
51717} // namespace Parma_Polyhedra_Library
51718
51719//! A Mixed Integer (linear) Programming problem.
51720/*! \ingroup PPL_CXX_interface
51721  An object of this class encodes a mixed integer (linear) programming
51722  problem.
51723  The MIP problem is specified by providing:
51724   - the dimension of the vector space;
51725   - the feasible region, by means of a finite set of linear equality
51726     and non-strict inequality constraints;
51727   - the subset of the unknown variables that range over the integers
51728     (the other variables implicitly ranging over the reals);
51729   - the objective function, described by a Linear_Expression;
51730   - the optimization mode (either maximization or minimization).
51731
51732  The class provides support for the (incremental) solution of the
51733  MIP problem based on variations of the revised simplex method and
51734  on branch-and-bound techniques. The result of the resolution
51735  process is expressed in terms of an enumeration, encoding the
51736  feasibility and the unboundedness of the optimization problem.
51737  The class supports simple feasibility tests (i.e., no optimization),
51738  as well as the extraction of an optimal (resp., feasible) point,
51739  provided the MIP_Problem is optimizable (resp., feasible).
51740
51741  By exploiting the incremental nature of the solver, it is possible
51742  to reuse part of the computational work already done when solving
51743  variants of a given MIP_Problem: currently, incremental resolution
51744  supports the addition of space dimensions, the addition of constraints,
51745  the change of objective function and the change of optimization mode.
51746*/
51747class Parma_Polyhedra_Library::MIP_Problem {
51748public:
51749  //! Builds a trivial MIP problem.
51750  /*!
51751    A trivial MIP problem requires to maximize the objective function
51752    \f$0\f$ on a vector space under no constraints at all:
51753    the origin of the vector space is an optimal solution.
51754
51755    \param dim
51756    The dimension of the vector space enclosing \p *this
51757    (optional argument with default value \f$0\f$).
51758
51759    \exception std::length_error
51760    Thrown if \p dim exceeds <CODE>max_space_dimension()</CODE>.
51761  */
51762  explicit MIP_Problem(dimension_type dim = 0);
51763
51764  /*! \brief
51765    Builds an MIP problem having space dimension \p dim
51766    from the sequence of constraints in the range
51767    \f$[\mathrm{first}, \mathrm{last})\f$,
51768    the objective function \p obj and optimization mode \p mode;
51769    those dimensions whose indices occur in \p int_vars are
51770    constrained to take an integer value.
51771
51772    \param dim
51773    The dimension of the vector space enclosing \p *this.
51774
51775    \param first
51776    An input iterator to the start of the sequence of constraints.
51777
51778    \param last
51779    A past-the-end input iterator to the sequence of constraints.
51780
51781    \param int_vars
51782    The set of variables' indexes that are constrained to take integer values.
51783
51784    \param obj
51785    The objective function (optional argument with default value \f$0\f$).
51786
51787    \param mode
51788    The optimization mode (optional argument with default value
51789    <CODE>MAXIMIZATION</CODE>).
51790
51791    \exception std::length_error
51792    Thrown if \p dim exceeds <CODE>max_space_dimension()</CODE>.
51793
51794    \exception std::invalid_argument
51795    Thrown if a constraint in the sequence is a strict inequality,
51796    if the space dimension of a constraint (resp., of the
51797    objective function or of the integer variables) or the space dimension
51798    of the integer variable set is strictly greater than \p dim.
51799  */
51800  template <typename In>
51801  MIP_Problem(dimension_type dim,
51802              In first, In last,
51803              const Variables_Set& int_vars,
51804              const Linear_Expression& obj = Linear_Expression::zero(),
51805              Optimization_Mode mode = MAXIMIZATION);
51806
51807  /*! \brief
51808    Builds an MIP problem having space dimension \p dim
51809    from the sequence of constraints in the range
51810    \f$[\mathrm{first}, \mathrm{last})\f$,
51811    the objective function \p obj and optimization mode \p mode.
51812
51813    \param dim
51814    The dimension of the vector space enclosing \p *this.
51815
51816    \param first
51817    An input iterator to the start of the sequence of constraints.
51818
51819    \param last
51820    A past-the-end input iterator to the sequence of constraints.
51821
51822    \param obj
51823    The objective function (optional argument with default value \f$0\f$).
51824
51825    \param mode
51826    The optimization mode (optional argument with default value
51827    <CODE>MAXIMIZATION</CODE>).
51828
51829    \exception std::length_error
51830    Thrown if \p dim exceeds <CODE>max_space_dimension()</CODE>.
51831
51832    \exception std::invalid_argument
51833    Thrown if a constraint in the sequence is a strict inequality
51834    or if the space dimension of a constraint (resp., of the
51835    objective function or of the integer variables) is strictly
51836    greater than \p dim.
51837  */
51838  template <typename In>
51839  MIP_Problem(dimension_type dim,
51840              In first, In last,
51841              const Linear_Expression& obj = Linear_Expression::zero(),
51842              Optimization_Mode mode = MAXIMIZATION);
51843
51844  /*! \brief
51845    Builds an MIP problem having space dimension \p dim from the constraint
51846    system \p cs, the objective function \p obj and optimization mode \p mode.
51847
51848    \param dim
51849    The dimension of the vector space enclosing \p *this.
51850
51851    \param cs
51852    The constraint system defining the feasible region.
51853
51854    \param obj
51855    The objective function (optional argument with default value \f$0\f$).
51856
51857    \param mode
51858    The optimization mode (optional argument with default value
51859    <CODE>MAXIMIZATION</CODE>).
51860
51861    \exception std::length_error
51862    Thrown if \p dim exceeds <CODE>max_space_dimension()</CODE>.
51863
51864    \exception std::invalid_argument
51865    Thrown if the constraint system contains any strict inequality
51866    or if the space dimension of the constraint system (resp., the
51867    objective function) is strictly greater than \p dim.
51868  */
51869  MIP_Problem(dimension_type dim,
51870              const Constraint_System& cs,
51871              const Linear_Expression& obj = Linear_Expression::zero(),
51872              Optimization_Mode mode = MAXIMIZATION);
51873
51874  //! Ordinary copy constructor.
51875  MIP_Problem(const MIP_Problem& y);
51876
51877  //! Destructor.
51878  ~MIP_Problem();
51879
51880  //! Assignment operator.
51881  MIP_Problem& operator=(const MIP_Problem& y);
51882
51883  //! Returns the maximum space dimension an MIP_Problem can handle.
51884  static dimension_type max_space_dimension();
51885
51886  //! Returns the space dimension of the MIP problem.
51887  dimension_type space_dimension() const;
51888
51889  /*! \brief
51890    Returns a set containing all the variables' indexes constrained
51891    to be integral.
51892  */
51893  const Variables_Set& integer_space_dimensions() const;
51894
51895private:
51896  //! A type alias for a sequence of constraints.
51897  typedef std::vector<Constraint*> Constraint_Sequence;
51898
51899public:
51900  //! A read-only iterator on the constraints defining the feasible region.
51901  class const_iterator {
51902  private:
51903    typedef Constraint_Sequence::const_iterator Base;
51904    typedef std::iterator_traits<Base> Base_Traits;
51905
51906  public:
51907    typedef Base_Traits::iterator_category iterator_category;
51908    typedef Base_Traits::difference_type difference_type;
51909    typedef const Constraint value_type;
51910    typedef const Constraint* pointer;
51911    typedef const Constraint& reference;
51912
51913    //! Iterator difference: computes distances.
51914    difference_type operator-(const const_iterator& y) const;
51915
51916    //! Prefix increment.
51917    const_iterator& operator++();
51918
51919    //! Prefix decrement.
51920    const_iterator& operator--();
51921
51922    //! Postfix increment.
51923    const_iterator operator++(int);
51924
51925    //! Postfix decrement.
51926    const_iterator operator--(int);
51927
51928    //! Moves iterator forward of \p n positions.
51929    const_iterator& operator+=(difference_type n);
51930
51931    //! Moves iterator backward of \p n positions.
51932    const_iterator& operator-=(difference_type n);
51933
51934    //! Returns an iterator \p n positions forward.
51935    const_iterator operator+(difference_type n) const;
51936
51937    //! Returns an iterator \p n positions backward.
51938    const_iterator operator-(difference_type n) const;
51939
51940    //! Returns a reference to the "pointed" object.
51941    reference operator*() const;
51942
51943    //! Returns the address of the "pointed" object.
51944    pointer operator->() const;
51945
51946    //! Compares \p *this with y.
51947    /*!
51948      \param y
51949      The %iterator that will be compared with *this.
51950    */
51951    bool operator==(const const_iterator& y) const;
51952
51953    //! Compares \p *this with y.
51954    /*!
51955      \param y
51956      The %iterator that will be compared with *this.
51957    */
51958    bool operator!=(const const_iterator& y) const;
51959
51960  private:
51961    //! Constructor from a Base iterator.
51962    explicit const_iterator(Base b);
51963
51964    //! The Base iterator on the Constraint_Sequence.
51965    Base itr;
51966
51967    friend class MIP_Problem;
51968  };
51969
51970  /*! \brief
51971    Returns a read-only iterator to the first constraint defining
51972    the feasible region.
51973  */
51974  const_iterator constraints_begin() const;
51975
51976  /*! \brief
51977    Returns a past-the-end read-only iterator to the sequence of
51978    constraints defining the feasible region.
51979  */
51980  const_iterator constraints_end() const;
51981
51982  //! Returns the objective function.
51983  const Linear_Expression& objective_function() const;
51984
51985  //! Returns the optimization mode.
51986  Optimization_Mode optimization_mode() const;
51987
51988  //! Resets \p *this to be equal to the trivial MIP problem.
51989  /*!
51990    The space dimension is reset to \f$0\f$.
51991  */
51992  void clear();
51993
51994  /*! \brief
51995    Adds \p m new space dimensions and embeds the old MIP problem
51996    in the new vector space.
51997
51998    \param m
51999    The number of dimensions to add.
52000
52001    \exception std::length_error
52002    Thrown if adding \p m new space dimensions would cause the
52003    vector space to exceed dimension <CODE>max_space_dimension()</CODE>.
52004
52005    The new space dimensions will be those having the highest indexes
52006    in the new MIP problem; they are initially unconstrained.
52007  */
52008  void add_space_dimensions_and_embed(dimension_type m);
52009
52010  /*! \brief
52011    Sets the variables whose indexes are in set \p i_vars to be
52012    integer space dimensions.
52013
52014    \exception std::invalid_argument
52015    Thrown if some index in \p i_vars does not correspond to
52016    a space dimension in \p *this.
52017  */
52018  void add_to_integer_space_dimensions(const Variables_Set& i_vars);
52019
52020  /*! \brief
52021    Adds a copy of constraint \p c to the MIP problem.
52022
52023    \exception std::invalid_argument
52024    Thrown if the constraint \p c is a strict inequality or if its space
52025    dimension is strictly greater than the space dimension of \p *this.
52026  */
52027  void add_constraint(const Constraint& c);
52028
52029  /*! \brief
52030    Adds a copy of the constraints in \p cs to the MIP problem.
52031
52032    \exception std::invalid_argument
52033    Thrown if the constraint system \p cs contains any strict inequality
52034    or if its space dimension is strictly greater than the space dimension
52035    of \p *this.
52036  */
52037  void add_constraints(const Constraint_System& cs);
52038
52039  //! Sets the objective function to \p obj.
52040  /*!
52041    \exception std::invalid_argument
52042    Thrown if the space dimension of \p obj is strictly greater than
52043    the space dimension of \p *this.
52044  */
52045  void set_objective_function(const Linear_Expression& obj);
52046
52047  //! Sets the optimization mode to \p mode.
52048  void set_optimization_mode(Optimization_Mode mode);
52049
52050  //! Checks satisfiability of \p *this.
52051  /*!
52052    \return
52053    <CODE>true</CODE> if and only if the MIP problem is satisfiable.
52054  */
52055  bool is_satisfiable() const;
52056
52057  //! Optimizes the MIP problem.
52058  /*!
52059    \return
52060    An MIP_Problem_Status flag indicating the outcome of the optimization
52061    attempt (unfeasible, unbounded or optimized problem).
52062  */
52063  MIP_Problem_Status solve() const;
52064
52065  /*! \brief
52066    Sets \p num and \p denom so that
52067    \f$\frac{\mathtt{numer}}{\mathtt{denom}}\f$ is the result of
52068    evaluating the objective function on \p evaluating_point.
52069
52070    \param evaluating_point
52071    The point on which the objective function will be evaluated.
52072
52073    \param numer
52074    On exit will contain the numerator of the evaluated value.
52075
52076    \param denom
52077    On exit will contain the denominator of the evaluated value.
52078
52079    \exception std::invalid_argument
52080    Thrown if \p *this and \p evaluating_point are dimension-incompatible
52081    or if the generator \p evaluating_point is not a point.
52082  */
52083  void evaluate_objective_function(const Generator& evaluating_point,
52084                                   Coefficient& numer,
52085                                   Coefficient& denom) const;
52086
52087  //! Returns a feasible point for \p *this, if it exists.
52088  /*!
52089    \exception std::domain_error
52090    Thrown if the MIP problem is not satisfiable.
52091  */
52092  const Generator& feasible_point() const;
52093
52094  //! Returns an optimal point for \p *this, if it exists.
52095  /*!
52096    \exception std::domain_error
52097    Thrown if \p *this does not not have an optimizing point, i.e.,
52098    if the MIP problem is unbounded or not satisfiable.
52099  */
52100  const Generator& optimizing_point() const;
52101
52102  /*! \brief
52103    Sets \p numer and \p denom so that
52104    \f$\frac{\mathtt{numer}}{\mathtt{denom}}\f$ is the solution of the
52105    optimization problem.
52106
52107    \exception std::domain_error
52108    Thrown if \p *this does not not have an optimizing point, i.e.,
52109    if the MIP problem is unbounded or not satisfiable.
52110  */
52111  void optimal_value(Coefficient& numer, Coefficient& denom) const;
52112
52113  //! Checks if all the invariants are satisfied.
52114  bool OK() const;
52115
52116  PPL_OUTPUT_DECLARATIONS
52117
52118  /*! \brief
52119    Loads from \p s an ASCII representation (as produced by
52120    ascii_dump(std::ostream&) const) and sets \p *this accordingly.
52121    Returns <CODE>true</CODE> if successful, <CODE>false</CODE> otherwise.
52122  */
52123  bool ascii_load(std::istream& s);
52124
52125  //! Returns the total size in bytes of the memory occupied by \p *this.
52126  memory_size_type total_memory_in_bytes() const;
52127
52128  //! Returns the size in bytes of the memory managed by \p *this.
52129  memory_size_type external_memory_in_bytes() const;
52130
52131  //! Swaps \p *this with \p y.
52132  void m_swap(MIP_Problem& y);
52133
52134  //! Names of MIP problems' control parameters.
52135  enum Control_Parameter_Name {
52136    //! The pricing rule.
52137    PRICING
52138  };
52139
52140  //! Possible values for MIP problem's control parameters.
52141  enum Control_Parameter_Value {
52142    //! Steepest edge pricing method, using floating points (default).
52143    PRICING_STEEPEST_EDGE_FLOAT,
52144    //! Steepest edge pricing method, using Coefficient.
52145    PRICING_STEEPEST_EDGE_EXACT,
52146    //! Textbook pricing method.
52147    PRICING_TEXTBOOK
52148  };
52149
52150  //! Returns the value of the control parameter \p name.
52151  Control_Parameter_Value
52152  get_control_parameter(Control_Parameter_Name name) const;
52153
52154  //! Sets control parameter \p value.
52155  void set_control_parameter(Control_Parameter_Value value);
52156
52157private:
52158  //! The dimension of the vector space.
52159  dimension_type external_space_dim;
52160
52161  /*! \brief
52162    The space dimension of the current (partial) solution of the
52163    MIP problem; it may be smaller than \p external_space_dim.
52164  */
52165  dimension_type internal_space_dim;
52166
52167#if PPL_USE_SPARSE_MATRIX
52168  typedef Sparse_Row Row;
52169#else
52170  typedef Dense_Row Row;
52171#endif
52172
52173  //! The matrix encoding the current feasible region in tableau form.
52174  Matrix<Row> tableau;
52175
52176  typedef Row working_cost_type;
52177
52178  //! The working cost function.
52179  working_cost_type working_cost;
52180
52181  //! A map between the variables of `input_cs' and `tableau'.
52182  /*!
52183    Contains all the pairs (i, j) such that mapping[i].first encodes the index
52184    of the column in the tableau where input_cs[i] is stored; if
52185    mapping[i].second is not a zero, it encodes the split part of the tableau
52186    of input_cs[i].
52187    The "positive" one is represented by mapping[i].first and the "negative"
52188    one is represented by mapping[i].second.
52189  */
52190  std::vector<std::pair<dimension_type, dimension_type> > mapping;
52191
52192  //! The current basic solution.
52193  std::vector<dimension_type> base;
52194
52195  //! An enumerated type describing the internal status of the MIP problem.
52196  enum Status {
52197    //! The MIP problem is unsatisfiable.
52198    UNSATISFIABLE,
52199    //! The MIP problem is satisfiable; a feasible solution has been computed.
52200    SATISFIABLE,
52201    //! The MIP problem is unbounded; a feasible solution has been computed.
52202    UNBOUNDED,
52203    //! The MIP problem is optimized; an optimal solution has been computed.
52204    OPTIMIZED,
52205    /*! \brief
52206      The feasible region of the MIP problem has been changed by adding
52207      new space dimensions or new constraints; a feasible solution for
52208      the old feasible region is still available.
52209    */
52210    PARTIALLY_SATISFIABLE
52211  };
52212
52213  //! The internal state of the MIP problem.
52214  Status status;
52215
52216  // TODO: merge `status', `initialized', `pricing' and (maybe) `opt_mode'
52217  // into a single bitset status word, so as to save space and allow
52218  // for other control parameters.
52219
52220  //! The pricing method in use.
52221  Control_Parameter_Value pricing;
52222
52223  /*! \brief
52224    A Boolean encoding whether or not internal data structures have
52225    already been properly sized and populated: useful to allow for
52226    deeper checks in method OK().
52227  */
52228  bool initialized;
52229
52230  //! The sequence of constraints describing the feasible region.
52231  std::vector<Constraint*> input_cs;
52232
52233  /*! \brief
52234    The number of constraints that are inherited from our parent
52235    in the recursion tree built when solving via branch-and-bound.
52236
52237    The first \c inherited_constraints elements in \c input_cs point to
52238    the inherited constraints, whose resources are owned by our ancestors.
52239    The resources of the other elements in \c input_cs are owned by \c *this
52240    and should be appropriately released on destruction.
52241  */
52242  dimension_type inherited_constraints;
52243
52244  //! The first index of `input_cs' containing a pending constraint.
52245  dimension_type first_pending_constraint;
52246
52247  //! The objective function to be optimized.
52248  Linear_Expression input_obj_function;
52249
52250  //! The optimization mode requested.
52251  Optimization_Mode opt_mode;
52252
52253  //! The last successfully computed feasible or optimizing point.
52254  Generator last_generator;
52255
52256  /*! \brief
52257    A set containing all the indexes of variables that are constrained
52258    to have an integer value.
52259  */
52260  Variables_Set i_variables;
52261
52262  //! A helper class to temporarily relax a MIP problem using RAII.
52263  struct RAII_Temporary_Real_Relaxation {
52264    MIP_Problem& lp;
52265    Variables_Set i_vars;
52266
52267    RAII_Temporary_Real_Relaxation(MIP_Problem& mip)
52268      : lp(mip), i_vars() {
52269      // Turn mip into an LP problem (saving i_variables in i_vars).
52270      using std::swap;
52271      swap(i_vars, lp.i_variables);
52272    }
52273
52274    ~RAII_Temporary_Real_Relaxation() {
52275      // Restore the original set of integer variables.
52276      using std::swap;
52277      swap(i_vars, lp.i_variables);
52278    }
52279  };
52280  friend struct RAII_Temporary_Real_Relaxation;
52281
52282  //! A tag type to distinguish normal vs. inheriting copy constructor.
52283  struct Inherit_Constraints {};
52284
52285  //! Copy constructor inheriting constraints.
52286  MIP_Problem(const MIP_Problem& y, Inherit_Constraints);
52287
52288  //! Helper method: implements exception safe addition.
52289  void add_constraint_helper(const Constraint& c);
52290
52291  //! Processes the pending constraints of \p *this.
52292  void process_pending_constraints();
52293
52294  /*! \brief
52295    Optimizes the MIP problem using the second phase of the
52296    primal simplex algorithm.
52297  */
52298  void second_phase();
52299
52300  /*! \brief
52301    Assigns to \p this->tableau a simplex tableau representing the
52302    MIP problem, inserting into \p this->mapping the information
52303    that is required to recover the original MIP problem.
52304
52305    \return
52306    <CODE>UNFEASIBLE_MIP_PROBLEM</CODE> if the constraint system contains
52307    any trivially unfeasible constraint (tableau was not computed);
52308    <CODE>UNBOUNDED_MIP_PROBLEM</CODE> if the problem is trivially unbounded
52309    (the computed tableau contains no constraints);
52310    <CODE>OPTIMIZED_MIP_PROBLEM></CODE> if the problem is neither trivially
52311    unfeasible nor trivially unbounded (the tableau was computed
52312    successfully).
52313  */
52314  MIP_Problem_Status
52315  compute_tableau(std::vector<dimension_type>& worked_out_row);
52316
52317  /*! \brief
52318    Parses the pending constraints to gather information on
52319    how to resize the tableau.
52320
52321    \note
52322    All of the method parameters are output parameters; their value
52323    is only meaningful when the function exit returning value \c true.
52324
52325    \return
52326    \c false if a trivially false constraint is detected, \c true otherwise.
52327
52328    \param additional_tableau_rows
52329    On exit, this will store the number of rows that have to be added
52330    to the original tableau.
52331
52332    \param additional_slack_variables
52333    This will store the number of slack variables that have to be added
52334    to the original tableau.
52335
52336    \param is_tableau_constraint
52337    This container of Boolean flags is initially empty. On exit, it size
52338    will be equal to the number of pending constraints in \c input_cs.
52339    For each pending constraint index \c i, the corresponding element
52340    of this container (having index <CODE>i - first_pending_constraint</CODE>)
52341    will be set to \c true if and only if the constraint has to be included
52342    in the tableau.
52343
52344    \param is_satisfied_inequality
52345    This container of Boolean flags is initially empty. On exit, its size
52346    will be equal to the number of pending constraints in \c input_cs.
52347    For each pending constraint index \c i, the corresponding element
52348    of this container (having index <CODE>i - first_pending_constraint</CODE>)
52349    will be set to \c true if and only if it is an inequality and it
52350    is already satisfied by \c last_generator (hence it does not require
52351    the introduction of an artificial variable).
52352
52353    \param is_nonnegative_variable
52354    This container of Boolean flags is initially empty.
52355    On exit, it size is equal to \c external_space_dim.
52356    For each variable (index), the corresponding element of this container
52357    is \c true if the variable is known to be nonnegative (and hence should
52358    not be split into a positive and a negative part).
52359
52360    \param is_remergeable_variable
52361    This container of Boolean flags is initially empty.
52362    On exit, it size is equal to \c internal_space_dim.
52363    For each variable (index), the corresponding element of this container
52364    is \c true if the variable was previously split into positive and
52365    negative parts that can now be merged back, since it is known
52366    that the variable is nonnegative.
52367  */
52368  bool parse_constraints(dimension_type& additional_tableau_rows,
52369                         dimension_type& additional_slack_variables,
52370                         std::deque<bool>& is_tableau_constraint,
52371                         std::deque<bool>& is_satisfied_inequality,
52372                         std::deque<bool>& is_nonnegative_variable,
52373                         std::deque<bool>& is_remergeable_variable) const;
52374
52375  /*! \brief
52376    Computes the row index of the variable exiting the base
52377    of the MIP problem. Implemented with anti-cycling rule.
52378
52379    \return
52380    The row index of the variable exiting the base.
52381
52382    \param entering_var_index
52383    The column index of the variable entering the base.
52384  */
52385  dimension_type
52386  get_exiting_base_index(dimension_type entering_var_index) const;
52387
52388  //! Linearly combines \p x with \p y so that <CODE>*this[k]</CODE> is 0.
52389  /*!
52390    \param x
52391    The row that will be combined with \p y object.
52392
52393    \param y
52394    The row that will be combined with \p x object.
52395
52396    \param k
52397    The position of \p *this that have to be \f$0\f$.
52398
52399    Computes a linear combination of \p x and \p y having
52400    the element of index \p k equal to \f$0\f$. Then it assigns
52401    the resulting Row to \p x and normalizes it.
52402  */
52403  static void linear_combine(Row& x, const Row& y, const dimension_type k);
52404
52405  // TODO: Remove this when the sparse working cost has been tested enough.
52406#if PPL_USE_SPARSE_MATRIX
52407
52408  //! Linearly combines \p x with \p y so that <CODE>*this[k]</CODE> is 0.
52409  /*!
52410    \param x
52411    The row that will be combined with \p y object.
52412
52413    \param y
52414    The row that will be combined with \p x object.
52415
52416    \param k
52417    The position of \p *this that have to be \f$0\f$.
52418
52419    Computes a linear combination of \p x and \p y having
52420    the element of index \p k equal to \f$0\f$. Then it assigns
52421    the resulting Dense_Row to \p x and normalizes it.
52422  */
52423  static void linear_combine(Dense_Row& x, const Sparse_Row& y,
52424                             const dimension_type k);
52425
52426#endif // defined(PPL_USE_SPARSE_MATRIX)
52427
52428  static bool is_unbounded_obj_function(
52429    const Linear_Expression& obj_function,
52430    const std::vector<std::pair<dimension_type, dimension_type> >& mapping,
52431    Optimization_Mode optimization_mode);
52432
52433  /*! \brief
52434    Performs the pivoting operation on the tableau.
52435
52436    \param entering_var_index
52437    The index of the variable entering the base.
52438
52439    \param exiting_base_index
52440    The index of the row exiting the base.
52441  */
52442  void pivot(dimension_type entering_var_index,
52443             dimension_type exiting_base_index);
52444
52445  /*! \brief
52446    Computes the column index of the variable entering the base,
52447    using the textbook algorithm with anti-cycling rule.
52448
52449    \return
52450    The column index of the variable that enters the base.
52451    If no such variable exists, optimality was achieved
52452    and <CODE>0</CODE> is returned.
52453  */
52454  dimension_type textbook_entering_index() const;
52455
52456  /*! \brief
52457    Computes the column index of the variable entering the base,
52458    using an exact steepest-edge algorithm with anti-cycling rule.
52459
52460    \return
52461    The column index of the variable that enters the base.
52462    If no such variable exists, optimality was achieved
52463    and <CODE>0</CODE> is returned.
52464
52465    To compute the entering_index, the steepest edge algorithm chooses
52466    the index `j' such that \f$\frac{d_{j}}{\|\Delta x^{j} \|}\f$ is the
52467    largest in absolute value, where
52468    \f[
52469      \|\Delta x^{j} \|
52470        = \left(
52471            1+\sum_{i=1}^{m} \alpha_{ij}^2
52472          \right)^{\frac{1}{2}}.
52473    \f]
52474    Recall that, due to the exact integer implementation of the algorithm,
52475    our tableau does not contain the ``real'' \f$\alpha\f$ values, but these
52476    can be computed dividing the value of the coefficient by the value of
52477    the variable in base. Obviously the result may not be an integer, so
52478    we will proceed in another way: we compute the lcm of all the variables
52479    in base to get the good ``weight'' of each Coefficient of the tableau.
52480  */
52481  dimension_type steepest_edge_exact_entering_index() const;
52482
52483  /*! \brief
52484    Same as steepest_edge_exact_entering_index,
52485    but using floating points.
52486
52487    \note
52488    Due to rounding errors, the index of the variable entering the base
52489    of the MIP problem is not predictable across different architectures.
52490    Hence, the overall simplex computation may differ in the path taken
52491    to reach the optimum. Anyway, the exact final result will be computed
52492    for the MIP_Problem.
52493  */
52494  dimension_type steepest_edge_float_entering_index() const;
52495
52496  /*! \brief
52497    Returns <CODE>true</CODE> if and if only the algorithm successfully
52498    computed a feasible solution.
52499
52500    \note
52501    Uses an exact pricing method (either textbook or exact steepest edge),
52502    so that the result is deterministic across different architectures.
52503  */
52504  bool compute_simplex_using_exact_pricing();
52505
52506  /*! \brief
52507    Returns <CODE>true</CODE> if and if only the algorithm successfully
52508    computed a feasible solution.
52509
52510    \note
52511    Uses a floating point implementation of the steepest edge pricing
52512    method, so that the result is correct, but not deterministic across
52513    different architectures.
52514  */
52515  bool compute_simplex_using_steepest_edge_float();
52516
52517  /*! \brief
52518    Drop unnecessary artificial variables from the tableau and get ready
52519    for the second phase of the simplex algorithm.
52520
52521    \note
52522    The two parameters denote a STL-like half-open range.
52523    It is assumed that \p begin_artificials is strictly greater than 0
52524    and smaller than \p end_artificials.
52525
52526    \param begin_artificials
52527    The start of the tableau column index range for artificial variables.
52528
52529    \param end_artificials
52530    The end of the tableau column index range for artificial variables.
52531    Note that column index end_artificial is \e excluded from the range.
52532  */
52533  void erase_artificials(dimension_type begin_artificials,
52534                         dimension_type end_artificials);
52535
52536  bool is_in_base(dimension_type var_index,
52537                  dimension_type& row_index) const;
52538
52539  /*! \brief
52540    Computes a valid generator that satisfies all the constraints of the
52541    Linear Programming problem associated to \p *this.
52542  */
52543  void compute_generator() const;
52544
52545  /*! \brief
52546    Merges back the positive and negative part of a (previously split)
52547    variable after detecting a corresponding nonnegativity constraint.
52548
52549    \return
52550    If the negative part of \p var_index was in base, the index of
52551    the corresponding tableau row (which has become non-feasible);
52552    otherwise \c not_a_dimension().
52553
52554    \param var_index
52555    The index of the variable that has to be merged.
52556  */
52557  dimension_type merge_split_variable(dimension_type var_index);
52558
52559  //! Returns <CODE>true</CODE> if and only if \p c is satisfied by \p g.
52560  static bool is_satisfied(const Constraint& c, const Generator& g);
52561
52562  //! Returns <CODE>true</CODE> if and only if \p c is saturated by \p g.
52563  static bool is_saturated(const Constraint& c, const Generator& g);
52564
52565  /*! \brief
52566    Returns a status that encodes the solution of the MIP problem.
52567
52568    \param have_incumbent_solution
52569    It is used to store if the solving process has found a provisional
52570    optimum point.
52571
52572    \param incumbent_solution_value
52573    Encodes the evaluated value of the provisional optimum point found.
52574
52575    \param incumbent_solution_point
52576    If the method returns `OPTIMIZED', this will contain the optimality point.
52577
52578    \param mip
52579    The problem that has to be solved.
52580
52581    \param i_vars
52582    The variables that are constrained to take an integer value.
52583  */
52584  static MIP_Problem_Status solve_mip(bool& have_incumbent_solution,
52585                                      mpq_class& incumbent_solution_value,
52586                                      Generator& incumbent_solution_point,
52587                                      MIP_Problem& mip,
52588                                      const Variables_Set& i_vars);
52589
52590  /*! \brief
52591    Returns \c true if and if only the LP problem is satisfiable.
52592  */
52593  bool is_lp_satisfiable() const;
52594
52595  /*! \brief
52596    Returns \c true if and if only the MIP problem \p mip is satisfiable
52597    when variables in \p i_vars can only take integral values.
52598
52599    \param mip
52600    The MIP problem. This is assumed to have no integral space dimension
52601    (so that it is a pure LP problem).
52602
52603    \param i_vars
52604    The variables that are constrained to take integral values.
52605
52606    \param p
52607    If \c true is returned, it will encode a feasible point.
52608  */
52609  static bool is_mip_satisfiable(MIP_Problem& mip,
52610                                 const Variables_Set& i_vars,
52611                                 Generator& p);
52612
52613  /*! \brief
52614    Returns \c true if and if only \c mip.last_generator satisfies all the
52615    integrality conditions implicitly stated using by \p i_vars.
52616
52617    \param mip
52618    The MIP problem. This is assumed to have no integral space dimension
52619    (so that it is a pure LP problem).
52620
52621    \param i_vars
52622    The variables that are constrained to take an integer value.
52623
52624    \param branching_index
52625    If \c false is returned, this will encode the non-integral variable
52626    index on which the `branch and bound' algorithm should be applied.
52627  */
52628  static bool choose_branching_variable(const MIP_Problem& mip,
52629                                        const Variables_Set& i_vars,
52630                                        dimension_type& branching_index);
52631};
52632
52633/* Automatically generated from PPL source file ../src/MIP_Problem_inlines.hh line 1. */
52634/* MIP_Problem class implementation: inline functions.
52635*/
52636
52637
52638/* Automatically generated from PPL source file ../src/MIP_Problem_inlines.hh line 28. */
52639#include <stdexcept>
52640
52641namespace Parma_Polyhedra_Library {
52642
52643inline dimension_type
52644MIP_Problem::max_space_dimension() {
52645  return Constraint::max_space_dimension();
52646}
52647
52648inline dimension_type
52649MIP_Problem::space_dimension() const {
52650  return external_space_dim;
52651}
52652
52653
52654inline
52655MIP_Problem::MIP_Problem(const MIP_Problem& y)
52656  : external_space_dim(y.external_space_dim),
52657    internal_space_dim(y.internal_space_dim),
52658    tableau(y.tableau),
52659    working_cost(y.working_cost),
52660    mapping(y.mapping),
52661    base(y.base),
52662    status(y.status),
52663    pricing(y.pricing),
52664    initialized(y.initialized),
52665    input_cs(),
52666    inherited_constraints(0),
52667    first_pending_constraint(),
52668    input_obj_function(y.input_obj_function),
52669    opt_mode(y.opt_mode),
52670    last_generator(y.last_generator),
52671    i_variables(y.i_variables) {
52672  input_cs.reserve(y.input_cs.size());
52673  for (Constraint_Sequence::const_iterator i = y.input_cs.begin(),
52674         i_end = y.input_cs.end(); i != i_end; ++i) {
52675    add_constraint_helper(*(*i));
52676  }
52677  PPL_ASSERT(OK());
52678}
52679
52680inline
52681MIP_Problem::MIP_Problem(const MIP_Problem& y, Inherit_Constraints)
52682  : external_space_dim(y.external_space_dim),
52683    internal_space_dim(y.internal_space_dim),
52684    tableau(y.tableau),
52685    working_cost(y.working_cost),
52686    mapping(y.mapping),
52687    base(y.base),
52688    status(y.status),
52689    pricing(y.pricing),
52690    initialized(y.initialized),
52691    input_cs(y.input_cs),
52692    // NOTE: The constraints are inherited, NOT copied!
52693    inherited_constraints(y.input_cs.size()),
52694    first_pending_constraint(y.first_pending_constraint),
52695    input_obj_function(y.input_obj_function),
52696    opt_mode(y.opt_mode),
52697    last_generator(y.last_generator),
52698    i_variables(y.i_variables) {
52699  PPL_ASSERT(OK());
52700}
52701
52702inline void
52703MIP_Problem::add_constraint_helper(const Constraint& c) {
52704  // For exception safety, reserve space for the new element.
52705  const dimension_type size = input_cs.size();
52706  if (size == input_cs.capacity()) {
52707    const dimension_type max_size = input_cs.max_size();
52708    if (size == max_size) {
52709      throw std::length_error("MIP_Problem::add_constraint(): "
52710                              "too many constraints");
52711    }
52712    // Use an exponential grow policy to avoid too many reallocations.
52713    input_cs.reserve(compute_capacity(size + 1, max_size));
52714  }
52715
52716  // This operation does not throw, because the space for the new element
52717  // has already been reserved: hence the new-ed Constraint is safe.
52718  input_cs.push_back(new Constraint(c));
52719}
52720
52721inline
52722MIP_Problem::~MIP_Problem() {
52723  // NOTE: do NOT delete inherited constraints; they are owned
52724  // (and will eventually be deleted) by ancestors.
52725  for (Constraint_Sequence::const_iterator
52726         i = nth_iter(input_cs, inherited_constraints),
52727         i_end = input_cs.end(); i != i_end; ++i) {
52728    delete *i;
52729  }
52730}
52731
52732
52733inline void
52734MIP_Problem::set_optimization_mode(const Optimization_Mode mode) {
52735  if (opt_mode != mode) {
52736    opt_mode = mode;
52737    if (status == UNBOUNDED || status == OPTIMIZED) {
52738      status = SATISFIABLE;
52739    }
52740    PPL_ASSERT(OK());
52741  }
52742}
52743
52744inline const Linear_Expression&
52745MIP_Problem::objective_function() const {
52746  return input_obj_function;
52747}
52748
52749inline Optimization_Mode
52750MIP_Problem::optimization_mode() const {
52751  return opt_mode;
52752}
52753
52754inline void
52755MIP_Problem::optimal_value(Coefficient& numer, Coefficient& denom) const {
52756  const Generator& g = optimizing_point();
52757  evaluate_objective_function(g, numer, denom);
52758}
52759
52760inline MIP_Problem::const_iterator
52761MIP_Problem::constraints_begin() const {
52762  return const_iterator(input_cs.begin());
52763}
52764
52765inline MIP_Problem::const_iterator
52766MIP_Problem::constraints_end() const {
52767  return const_iterator(input_cs.end());
52768}
52769
52770inline const Variables_Set&
52771MIP_Problem::integer_space_dimensions() const {
52772  return i_variables;
52773}
52774
52775inline MIP_Problem::Control_Parameter_Value
52776MIP_Problem::get_control_parameter(Control_Parameter_Name name) const {
52777  PPL_USED(name);
52778  PPL_ASSERT(name == PRICING);
52779  return pricing;
52780}
52781
52782inline void
52783MIP_Problem::set_control_parameter(Control_Parameter_Value value) {
52784  pricing = value;
52785}
52786
52787inline void
52788MIP_Problem::m_swap(MIP_Problem& y) {
52789  using std::swap;
52790  swap(external_space_dim, y.external_space_dim);
52791  swap(internal_space_dim, y.internal_space_dim);
52792  swap(tableau, y.tableau);
52793  swap(working_cost, y.working_cost);
52794  swap(mapping, y.mapping);
52795  swap(initialized, y.initialized);
52796  swap(base, y.base);
52797  swap(status, y.status);
52798  swap(pricing, y.pricing);
52799  swap(input_cs, y.input_cs);
52800  swap(inherited_constraints, y.inherited_constraints);
52801  swap(first_pending_constraint, y.first_pending_constraint);
52802  swap(input_obj_function, y.input_obj_function);
52803  swap(opt_mode, y.opt_mode);
52804  swap(last_generator, y.last_generator);
52805  swap(i_variables, y.i_variables);
52806}
52807
52808inline MIP_Problem&
52809MIP_Problem::operator=(const MIP_Problem& y) {
52810  MIP_Problem tmp(y);
52811  m_swap(tmp);
52812  return *this;
52813}
52814
52815inline void
52816MIP_Problem::clear() {
52817  MIP_Problem tmp;
52818  m_swap(tmp);
52819}
52820
52821
52822inline memory_size_type
52823MIP_Problem::external_memory_in_bytes() const {
52824  memory_size_type n
52825    = working_cost.external_memory_in_bytes()
52826    + tableau.external_memory_in_bytes()
52827    + input_obj_function.external_memory_in_bytes()
52828    + last_generator.external_memory_in_bytes();
52829
52830  // Adding the external memory for `input_cs'.
52831  // NOTE: disregard inherited constraints, as they are owned by ancestors.
52832  n += input_cs.capacity() * sizeof(Constraint*);
52833  for (Constraint_Sequence::const_iterator
52834         i = nth_iter(input_cs, inherited_constraints),
52835         i_end = input_cs.end(); i != i_end; ++i) {
52836    n += ((*i)->total_memory_in_bytes());
52837  }
52838
52839  // Adding the external memory for `base'.
52840  n += base.capacity() * sizeof(dimension_type);
52841  // Adding the external memory for `mapping'.
52842  n += mapping.capacity() * sizeof(std::pair<dimension_type, dimension_type>);
52843  return n;
52844}
52845
52846inline memory_size_type
52847MIP_Problem::total_memory_in_bytes() const {
52848  return sizeof(*this) + external_memory_in_bytes();
52849}
52850
52851inline
52852MIP_Problem::const_iterator::const_iterator(Base b)
52853  : itr(b) {
52854}
52855
52856inline MIP_Problem::const_iterator::difference_type
52857MIP_Problem::const_iterator::operator-(const const_iterator& y) const {
52858  return itr - y.itr;
52859}
52860
52861inline MIP_Problem::const_iterator&
52862MIP_Problem::const_iterator::operator++() {
52863  ++itr;
52864  return *this;
52865}
52866
52867inline MIP_Problem::const_iterator&
52868MIP_Problem::const_iterator::operator--() {
52869  --itr;
52870  return *this;
52871}
52872
52873inline MIP_Problem::const_iterator
52874MIP_Problem::const_iterator::operator++(int) {
52875  const_iterator x = *this;
52876  operator++();
52877  return x;
52878}
52879
52880inline MIP_Problem::const_iterator
52881MIP_Problem::const_iterator::operator--(int) {
52882  const_iterator x = *this;
52883  operator--();
52884  return x;
52885}
52886
52887inline MIP_Problem::const_iterator
52888MIP_Problem::const_iterator::operator+(difference_type n) const {
52889  return const_iterator(itr + n);
52890}
52891
52892inline MIP_Problem::const_iterator
52893MIP_Problem::const_iterator::operator-(difference_type n) const {
52894  return const_iterator(itr - n);
52895}
52896
52897inline MIP_Problem::const_iterator&
52898MIP_Problem::const_iterator::operator+=(difference_type n) {
52899  itr += n;
52900  return *this;
52901}
52902
52903inline MIP_Problem::const_iterator&
52904MIP_Problem::const_iterator::operator-=(difference_type n) {
52905  itr -= n;
52906  return *this;
52907}
52908
52909inline MIP_Problem::const_iterator::reference
52910MIP_Problem::const_iterator::operator*() const {
52911  return *(*itr);
52912}
52913
52914inline MIP_Problem::const_iterator::pointer
52915MIP_Problem::const_iterator::operator->() const {
52916  return *itr;
52917}
52918
52919inline bool
52920MIP_Problem::const_iterator::operator==(const const_iterator& y) const {
52921  return itr == y.itr;
52922}
52923
52924inline bool
52925MIP_Problem::const_iterator::operator!=(const const_iterator& y) const {
52926  return itr != y.itr;
52927}
52928
52929/*! \relates MIP_Problem */
52930inline void
52931swap(MIP_Problem& x, MIP_Problem& y) {
52932  x.m_swap(y);
52933}
52934
52935} // namespace Parma_Polyhedra_Library
52936
52937/* Automatically generated from PPL source file ../src/MIP_Problem_templates.hh line 1. */
52938/* MIP_Problem class implementation: non-inline template functions.
52939*/
52940
52941
52942/* Automatically generated from PPL source file ../src/MIP_Problem_templates.hh line 28. */
52943
52944namespace Parma_Polyhedra_Library {
52945
52946template <typename In>
52947MIP_Problem::MIP_Problem(const dimension_type dim,
52948                         In first, In last,
52949                         const Variables_Set& int_vars,
52950                         const Linear_Expression& obj,
52951                         const Optimization_Mode mode)
52952  : external_space_dim(dim),
52953    internal_space_dim(0),
52954    tableau(),
52955    working_cost(0),
52956    mapping(),
52957    base(),
52958    status(PARTIALLY_SATISFIABLE),
52959    pricing(PRICING_STEEPEST_EDGE_FLOAT),
52960    initialized(false),
52961    input_cs(),
52962    inherited_constraints(0),
52963    first_pending_constraint(0),
52964    input_obj_function(obj),
52965    opt_mode(mode),
52966    last_generator(point()),
52967    i_variables(int_vars) {
52968  // Check that integer Variables_Set does not exceed the space dimension
52969  // of the problem.
52970  if (i_variables.space_dimension() > external_space_dim) {
52971    std::ostringstream s;
52972    s << "PPL::MIP_Problem::MIP_Problem"
52973      << "(dim, first, last, int_vars, obj, mode):\n"
52974      << "dim == "<< external_space_dim << " and int_vars.space_dimension() =="
52975      << " " << i_variables.space_dimension() << " are dimension"
52976      "incompatible.";
52977    throw std::invalid_argument(s.str());
52978  }
52979
52980  // Check for space dimension overflow.
52981  if (dim > max_space_dimension()) {
52982    throw std::length_error("PPL::MIP_Problem:: MIP_Problem(dim, first, "
52983                            "last, int_vars, obj, mode):\n"
52984                            "dim exceeds the maximum allowed"
52985                            "space dimension.");
52986  }
52987  // Check the objective function.
52988  if (obj.space_dimension() > dim) {
52989    std::ostringstream s;
52990    s << "PPL::MIP_Problem::MIP_Problem(dim, first, last,"
52991      << "int_vars, obj, mode):\n"
52992      << "obj.space_dimension() == "<< obj.space_dimension()
52993      << " exceeds d == "<< dim << ".";
52994    throw std::invalid_argument(s.str());
52995  }
52996  // Check the constraints.
52997  try {
52998    for (In i = first; i != last; ++i) {
52999      if (i->is_strict_inequality()) {
53000        throw std::invalid_argument("PPL::MIP_Problem::"
53001                                    "MIP_Problem(dim, first, last, int_vars,"
53002                                    "obj, mode):\nrange [first, last) contains"
53003                                    "a strict inequality constraint.");
53004      }
53005      if (i->space_dimension() > dim) {
53006        std::ostringstream s;
53007        s << "PPL::MIP_Problem::"
53008          << "MIP_Problem(dim, first, last, int_vars, obj, mode):\n"
53009          << "range [first, last) contains a constraint having space"
53010          << "dimension  == " << i->space_dimension() << " that exceeds"
53011          "this->space_dimension == " << dim << ".";
53012        throw std::invalid_argument(s.str());
53013      }
53014      add_constraint_helper(*i);
53015    }
53016  } catch (...) {
53017    // Delete the allocated constraints, to avoid memory leaks.
53018
53019    for (Constraint_Sequence::const_iterator
53020          i = input_cs.begin(), i_end = input_cs.end();
53021          i != i_end; ++i) {
53022      delete *i;
53023    }
53024
53025    throw;
53026  }
53027  PPL_ASSERT(OK());
53028}
53029
53030template <typename In>
53031MIP_Problem::MIP_Problem(dimension_type dim,
53032                         In first, In last,
53033                         const Linear_Expression& obj,
53034                         Optimization_Mode mode)
53035  : external_space_dim(dim),
53036    internal_space_dim(0),
53037    tableau(),
53038    working_cost(0),
53039    mapping(),
53040    base(),
53041    status(PARTIALLY_SATISFIABLE),
53042    pricing(PRICING_STEEPEST_EDGE_FLOAT),
53043    initialized(false),
53044    input_cs(),
53045    inherited_constraints(0),
53046    first_pending_constraint(0),
53047    input_obj_function(obj),
53048    opt_mode(mode),
53049    last_generator(point()),
53050    i_variables() {
53051  // Check for space dimension overflow.
53052  if (dim > max_space_dimension()) {
53053    throw std::length_error("PPL::MIP_Problem::"
53054                            "MIP_Problem(dim, first, last, obj, mode):\n"
53055                            "dim exceeds the maximum allowed space "
53056                            "dimension.");
53057  }
53058  // Check the objective function.
53059  if (obj.space_dimension() > dim) {
53060    std::ostringstream s;
53061    s << "PPL::MIP_Problem::MIP_Problem(dim, first, last,"
53062      << " obj, mode):\n"
53063      << "obj.space_dimension() == "<< obj.space_dimension()
53064      << " exceeds d == "<< dim << ".";
53065    throw std::invalid_argument(s.str());
53066  }
53067  // Check the constraints.
53068  try {
53069    for (In i = first; i != last; ++i) {
53070      if (i->is_strict_inequality()) {
53071        throw std::invalid_argument("PPL::MIP_Problem::"
53072                                    "MIP_Problem(dim, first, last, obj, mode):"
53073                                    "\n"
53074                                    "range [first, last) contains a strict "
53075                                    "inequality constraint.");
53076      }
53077      if (i->space_dimension() > dim) {
53078        std::ostringstream s;
53079        s << "PPL::MIP_Problem::"
53080          << "MIP_Problem(dim, first, last, obj, mode):\n"
53081          << "range [first, last) contains a constraint having space"
53082          << "dimension" << " == " << i->space_dimension() << " that exceeds"
53083          "this->space_dimension == " << dim << ".";
53084        throw std::invalid_argument(s.str());
53085      }
53086      add_constraint_helper(*i);
53087    }
53088  } catch (...) {
53089    // Delete the allocated constraints, to avoid memory leaks.
53090
53091    for (Constraint_Sequence::const_iterator
53092          i = input_cs.begin(), i_end = input_cs.end();
53093          i != i_end; ++i) {
53094      delete *i;
53095    }
53096
53097    throw;
53098  }
53099  PPL_ASSERT(OK());
53100}
53101
53102} // namespace Parma_Polyhedra_Library
53103
53104/* Automatically generated from PPL source file ../src/MIP_Problem_defs.hh line 975. */
53105
53106/* Automatically generated from PPL source file ../src/Polyhedron_templates.hh line 31. */
53107// For static method overflows.
53108/* Automatically generated from PPL source file ../src/Floating_Point_Expression_defs.hh line 1. */
53109/* Declarations for the Floating_Point_Expression class and its constituents.
53110*/
53111
53112
53113/* Automatically generated from PPL source file ../src/Floating_Point_Expression_types.hh line 1. */
53114
53115
53116namespace Parma_Polyhedra_Library {
53117
53118template <typename FP_Interval_Type, typename FP_Format>
53119class Floating_Point_Expression;
53120
53121} // namespace Parma_Polyhedra_Library
53122
53123/* Automatically generated from PPL source file ../src/Floating_Point_Expression_defs.hh line 31. */
53124#include <cmath>
53125#include <map>
53126
53127namespace Parma_Polyhedra_Library {
53128
53129/*! \ingroup PPL_CXX_Interface \brief
53130  A floating point expression on a given format.
53131
53132  This class represents a concrete <EM>floating point expression</EM>. This
53133  includes constants, floating point variables, binary and unary
53134  arithmetic operators.
53135
53136  \par Template type parameters
53137
53138  - The class template type parameter \p FP_Interval_Type represents the type
53139  of the intervals used in the abstract domain. The interval bounds
53140  should have a floating point type.
53141  - The class template type parameter \p FP_Format represents the floating
53142  point format used in the concrete domain.
53143  This parameter must be a struct similar to the ones defined in file
53144  Float_defs.hh, even though it is sufficient to define the three
53145  fields BASE, MANTISSA_BITS and EXPONENT_BIAS.
53146*/
53147template <typename FP_Interval_Type, typename FP_Format>
53148class Floating_Point_Expression {
53149
53150public:
53151
53152  //! Alias for a linear form with template argument \p FP_Interval_Type.
53153  typedef Linear_Form<FP_Interval_Type> FP_Linear_Form;
53154
53155  //! Alias for a map that associates a variable index to an interval.
53156  /*! \brief
53157    Alias for a Box storing lower and upper bounds for floating point
53158    variables.
53159
53160    The type a linear form abstract store associating each variable with an
53161    interval that correctly approximates its value.
53162  */
53163  typedef Box<FP_Interval_Type> FP_Interval_Abstract_Store;
53164
53165  //! Alias for a map that associates a variable index to a linear form.
53166  /*!
53167    The type a linear form abstract store associating each variable with a
53168    linear form that correctly approximates its value.
53169  */
53170  typedef std::map<dimension_type, FP_Linear_Form>
53171          FP_Linear_Form_Abstract_Store;
53172
53173  //! The floating point format used by the analyzer.
53174  typedef typename FP_Interval_Type::boundary_type boundary_type;
53175
53176  //! The interval policy used by \p FP_Interval_Type.
53177  typedef typename FP_Interval_Type::info_type info_type;
53178
53179  //! Destructor.
53180  virtual ~Floating_Point_Expression();
53181
53182  //! Linearizes a floating point expression.
53183  /*! \brief
53184    Makes \p result become a linear form that correctly approximates the
53185    value of the floating point expression in the given composite
53186    abstract store.
53187
53188    \param int_store The interval abstract store.
53189    \param lf_store The linear form abstract store.
53190    \param result Becomes the linearized expression.
53191
53192    \return <CODE>true</CODE> if the linearization succeeded,
53193    <CODE>false</CODE> otherwise.
53194
53195    Formally, if \p *this represents the expression \f$e\f$,
53196    \p int_store represents the interval abstract store \f$\rho^{\#}\f$ and
53197    \p lf_store represents the linear form abstract store \f$\rho^{\#}_l\f$,
53198    then \p result will become
53199    \f$\linexprenv{e}{\rho^{\#}}{\rho^{\#}_l}\f$
53200    if the linearization succeeds.
53201
53202    All variables occurring in the floating point expression MUST have
53203    an associated interval in \p int_store.
53204    If this precondition is not met, calling the method causes an
53205    undefined behavior.
53206  */
53207  virtual bool linearize(const FP_Interval_Abstract_Store& int_store,
53208                         const FP_Linear_Form_Abstract_Store& lf_store,
53209                         FP_Linear_Form& result) const = 0;
53210
53211  /*! \brief
53212    Absolute error.
53213
53214    Represents the interval \f$[-\omega, \omega]\f$ where \f$\omega\f$ is the
53215    smallest non-zero positive number in the less precise floating point
53216    format between the analyzer format and the analyzed format.
53217
53218  */
53219  static FP_Interval_Type absolute_error;
53220
53221  // FIXME: this may not be the best place for them.
53222  /*! \brief
53223    Verifies if a given linear form overflows.
53224    \param lf The linear form to verify.
53225    \return
53226    Returns <CODE>false</CODE> if all coefficients in \p lf are bounded,
53227    <CODE>true</CODE> otherwise.
53228  */
53229  static bool overflows(const FP_Linear_Form& lf);
53230
53231  /*! \brief
53232    Computes the relative error of a given linear form.
53233
53234    Static helper method that is used by <CODE>linearize</CODE>
53235    to account for the relative errors on \p lf.
53236    \param lf The linear form used to compute the relative error.
53237    \param result Becomes the linear form corresponding to a relative
53238    error committed on \p lf.
53239
53240    This method makes <CODE>result</CODE> become a linear form
53241    obtained by evaluating the function \f$\varepsilon_{\mathbf{f}}(l)\f$
53242    on the linear form \p lf. This function is defined
53243    such as:
53244    \f[
53245    \varepsilon_{\mathbf{f}}\left([a, b]+\sum_{v \in \cV}[a_{v}, b_{v}]v\right)
53246    \defeq
53247    (\textrm{max}(|a|, |b|) \amifp [-\beta^{-\textrm{p}}, \beta^{-\textrm{p}}])
53248    +
53249    \sum_{v \in \cV}(\textrm{max}(|a_{v}|,|b_{v}|)
53250    \amifp
53251    [-\beta^{-\textrm{p}}, \beta^{-\textrm{p}}])v
53252    \f]
53253    where p is the fraction size in bits for the format \f$\mathbf{f}\f$ and
53254    \f$\beta\f$ the base.
53255  */
53256  static void relative_error(const FP_Linear_Form& lf,
53257                             FP_Linear_Form& result);
53258
53259  /*! \brief
53260    Makes \p result become an interval that overapproximates all the
53261    possible values of \p lf in the interval abstract store \p store.
53262
53263    \param lf The linear form to aproximate.
53264    \param store The abstract store.
53265    \param result The linear form that will be modified.
53266
53267    This method makes <CODE>result</CODE> become
53268    \f$\iota(lf)\rho^{\#}\f$, that is an interval defined as:
53269    \f[
53270    \iota\left(i + \sum_{v \in \cV}i_{v}v\right)\rho^{\#}
53271    \defeq
53272    i \asifp \left(\bigoplus_{v \in \cV}{}^{\#}i_{v} \amifp
53273    \rho^{\#}(v)\right)
53274    \f]
53275  */
53276  static void intervalize(const FP_Linear_Form& lf,
53277                          const FP_Interval_Abstract_Store& store,
53278                          FP_Interval_Type& result);
53279
53280private:
53281
53282  /*! \brief
53283    Computes the absolute error.
53284
53285    Static helper method that is used to compute the value of the public
53286    static field <CODE>absolute_error</CODE>.
53287
53288    \return The interval \f$[-\omega, \omega]\f$ corresponding to the value
53289    of <CODE>absolute_error</CODE>
53290  */
53291  static FP_Interval_Type compute_absolute_error();
53292
53293}; // class Floating_Point_Expression
53294
53295
53296template <typename FP_Interval_Type, typename FP_Format>
53297FP_Interval_Type Floating_Point_Expression<FP_Interval_Type, FP_Format>
53298  ::absolute_error = compute_absolute_error();
53299
53300} // namespace Parma_Polyhedra_Library
53301
53302/* Automatically generated from PPL source file ../src/Floating_Point_Expression_inlines.hh line 1. */
53303/* Floating_Point_Expression class implementation: inline functions.
53304*/
53305
53306
53307/* Automatically generated from PPL source file ../src/Floating_Point_Expression_inlines.hh line 29. */
53308
53309namespace Parma_Polyhedra_Library {
53310
53311template <typename FP_Interval_Type, typename FP_Format>
53312inline
53313Floating_Point_Expression<FP_Interval_Type, FP_Format>
53314::~Floating_Point_Expression() {}
53315
53316template <typename FP_Interval_Type, typename FP_Format>
53317inline bool
53318Floating_Point_Expression<FP_Interval_Type, FP_Format>
53319::overflows(const FP_Linear_Form& lf) {
53320  if (!lf.inhomogeneous_term().is_bounded()) {
53321    return true;
53322  }
53323
53324  dimension_type dimension = lf.space_dimension();
53325  for (dimension_type i = 0; i < dimension; ++i) {
53326    if (!lf.coefficient(Variable(i)).is_bounded()) {
53327      return true;
53328    }
53329  }
53330
53331  return false;
53332}
53333
53334} // namespace Parma_Polyhedra_Library
53335
53336/* Automatically generated from PPL source file ../src/Floating_Point_Expression_templates.hh line 1. */
53337/* Floating_Point_Expression class implementation:
53338   non-inline template functions.
53339*/
53340
53341
53342/* Automatically generated from PPL source file ../src/Floating_Point_Expression_templates.hh line 29. */
53343#include <cmath>
53344
53345namespace Parma_Polyhedra_Library {
53346
53347template<typename FP_Interval_Type, typename FP_Format>
53348void
53349Floating_Point_Expression<FP_Interval_Type, FP_Format>
53350::relative_error(const FP_Linear_Form& lf, FP_Linear_Form& result) {
53351
53352  FP_Interval_Type error_propagator;
53353  boundary_type lb = -pow(FP_Format::BASE,
53354  -static_cast<typename Floating_Point_Expression<FP_Interval_Type, FP_Format>
53355  ::boundary_type>(FP_Format::MANTISSA_BITS));
53356  error_propagator.build(i_constraint(GREATER_OR_EQUAL, lb),
53357                         i_constraint(LESS_OR_EQUAL, -lb));
53358
53359  // Handle the inhomogeneous term.
53360  const FP_Interval_Type* current_term = &lf.inhomogeneous_term();
53361  assert(current_term->is_bounded());
53362
53363  FP_Interval_Type
53364    current_multiplier(std::max(std::abs(current_term->lower()),
53365                                std::abs(current_term->upper())));
53366  FP_Linear_Form current_result_term(current_multiplier);
53367  current_result_term *= error_propagator;
53368  result = FP_Linear_Form(current_result_term);
53369
53370  // Handle the other terms.
53371  dimension_type dimension = lf.space_dimension();
53372  for (dimension_type i = 0; i < dimension; ++i) {
53373    current_term = &lf.coefficient(Variable(i));
53374    assert(current_term->is_bounded());
53375    current_multiplier
53376      = FP_Interval_Type(std::max(std::abs(current_term->lower()),
53377                                  std::abs(current_term->upper())));
53378    current_result_term = FP_Linear_Form(Variable(i));
53379    current_result_term *= current_multiplier;
53380    current_result_term *= error_propagator;
53381    result += current_result_term;
53382  }
53383
53384  return;
53385}
53386
53387template<typename FP_Interval_Type, typename FP_Format>
53388void
53389Floating_Point_Expression<FP_Interval_Type, FP_Format>
53390::intervalize(const FP_Linear_Form& lf,
53391              const FP_Interval_Abstract_Store& store,
53392              FP_Interval_Type& result) {
53393  result = FP_Interval_Type(lf.inhomogeneous_term());
53394  dimension_type dimension = lf.space_dimension();
53395  assert(dimension <= store.space_dimension());
53396  for (dimension_type i = 0; i < dimension; ++i) {
53397    FP_Interval_Type current_addend = lf.coefficient(Variable(i));
53398    const FP_Interval_Type& curr_int = store.get_interval(Variable(i));
53399    current_addend *= curr_int;
53400    result += current_addend;
53401  }
53402
53403  return;
53404}
53405
53406template<typename FP_Interval_Type, typename FP_Format>
53407FP_Interval_Type
53408Floating_Point_Expression<FP_Interval_Type, FP_Format>
53409::compute_absolute_error() {
53410  typedef typename Floating_Point_Expression<FP_Interval_Type, FP_Format>
53411    ::boundary_type Boundary;
53412  boundary_type omega;
53413  omega = std::max(pow(static_cast<Boundary>(FP_Format::BASE),
53414                       static_cast<Boundary>(1 - FP_Format::EXPONENT_BIAS
53415                                             - FP_Format::MANTISSA_BITS)),
53416                   std::numeric_limits<Boundary>::denorm_min());
53417  FP_Interval_Type result;
53418  result.build(i_constraint(GREATER_OR_EQUAL, -omega),
53419               i_constraint(LESS_OR_EQUAL, omega));
53420  return result;
53421}
53422
53423} // namespace Parma_Polyhedra_Library
53424
53425/* Automatically generated from PPL source file ../src/Floating_Point_Expression_defs.hh line 211. */
53426
53427/* Automatically generated from PPL source file ../src/Polyhedron_templates.hh line 33. */
53428#include <algorithm>
53429#include <deque>
53430
53431namespace Parma_Polyhedra_Library {
53432
53433template <typename Interval>
53434Polyhedron::Polyhedron(Topology topol,
53435                       const Box<Interval>& box,
53436                       Complexity_Class)
53437  : con_sys(topol, default_con_sys_repr),
53438    gen_sys(topol, default_gen_sys_repr),
53439    sat_c(),
53440    sat_g() {
53441  // Initialize the space dimension as indicated by the box.
53442  space_dim = box.space_dimension();
53443
53444  // Check for emptiness.
53445  if (box.is_empty()) {
53446    set_empty();
53447    return;
53448  }
53449
53450  // Zero-dim universe polyhedron.
53451  if (space_dim == 0) {
53452    set_zero_dim_univ();
53453    return;
53454  }
53455
53456  // Properly set the space dimension of `con_sys'.
53457  con_sys.set_space_dimension(space_dim);
53458
53459  PPL_DIRTY_TEMP_COEFFICIENT(l_n);
53460  PPL_DIRTY_TEMP_COEFFICIENT(l_d);
53461  PPL_DIRTY_TEMP_COEFFICIENT(u_n);
53462  PPL_DIRTY_TEMP_COEFFICIENT(u_d);
53463
53464  if (topol == NECESSARILY_CLOSED) {
53465    for (dimension_type k = space_dim; k-- > 0; ) {
53466      const Variable v_k = Variable(k);
53467      // See if we have a valid lower bound.
53468      bool l_closed = false;
53469      bool l_bounded = box.has_lower_bound(v_k, l_n, l_d, l_closed);
53470      // See if we have a valid upper bound.
53471      bool u_closed = false;
53472      bool u_bounded = box.has_upper_bound(v_k, u_n, u_d, u_closed);
53473
53474      // See if we have an implicit equality constraint.
53475      if (l_bounded && u_bounded
53476          && l_closed && u_closed
53477          && l_n == u_n && l_d == u_d) {
53478        // Add the constraint `l_d*v_k == l_n'.
53479        con_sys.insert(l_d * v_k == l_n);
53480      }
53481      else {
53482        if (l_bounded) {
53483          // Add the constraint `l_d*v_k >= l_n'.
53484          con_sys.insert(l_d * v_k >= l_n);
53485        }
53486        if (u_bounded) {
53487          // Add the constraint `u_d*v_k <= u_n'.
53488          con_sys.insert(u_d * v_k <= u_n);
53489        }
53490      }
53491    }
53492  }
53493  else {
53494    // topol == NOT_NECESSARILY_CLOSED
53495    for (dimension_type k = space_dim; k-- > 0; ) {
53496      const Variable v_k = Variable(k);
53497      // See if we have a valid lower bound.
53498      bool l_closed = false;
53499      bool l_bounded = box.has_lower_bound(v_k, l_n, l_d, l_closed);
53500      // See if we have a valid upper bound.
53501      bool u_closed = false;
53502      bool u_bounded = box.has_upper_bound(v_k, u_n, u_d, u_closed);
53503
53504      // See if we have an implicit equality constraint.
53505      if (l_bounded && u_bounded
53506          && l_closed && u_closed
53507          && l_n == u_n && l_d == u_d) {
53508        // Add the constraint `l_d*v_k == l_n'.
53509        con_sys.insert(l_d * v_k == l_n);
53510      }
53511      else {
53512        // Check if a lower bound constraint is required.
53513        if (l_bounded) {
53514          if (l_closed) {
53515            // Add the constraint `l_d*v_k >= l_n'.
53516            con_sys.insert(l_d * v_k >= l_n);
53517          }
53518          else {
53519            // Add the constraint `l_d*v_k > l_n'.
53520            con_sys.insert(l_d * v_k > l_n);
53521          }
53522        }
53523        // Check if an upper bound constraint is required.
53524        if (u_bounded) {
53525          if (u_closed) {
53526            // Add the constraint `u_d*v_k <= u_n'.
53527            con_sys.insert(u_d * v_k <= u_n);
53528          }
53529          else {
53530            // Add the constraint `u_d*v_k < u_n'.
53531            con_sys.insert(u_d * v_k < u_n);
53532          }
53533        }
53534      }
53535    }
53536  }
53537
53538  // Adding the low-level constraints.
53539  con_sys.add_low_level_constraints();
53540
53541  // Constraints are up-to-date.
53542  set_constraints_up_to_date();
53543  PPL_ASSERT_HEAVY(OK());
53544}
53545
53546template <typename Partial_Function>
53547void
53548Polyhedron::map_space_dimensions(const Partial_Function& pfunc) {
53549  if (space_dim == 0) {
53550    return;
53551  }
53552  if (pfunc.has_empty_codomain()) {
53553    // All dimensions vanish: the polyhedron becomes zero_dimensional.
53554    if (marked_empty()
53555        || (has_pending_constraints()
53556            && !remove_pending_to_obtain_generators())
53557        || (!generators_are_up_to_date() && !update_generators())) {
53558      // Removing all dimensions from the empty polyhedron.
53559      space_dim = 0;
53560      con_sys.clear();
53561    }
53562    else {
53563      // Removing all dimensions from a non-empty polyhedron.
53564      set_zero_dim_univ();
53565    }
53566
53567    PPL_ASSERT_HEAVY(OK());
53568    return;
53569  }
53570
53571  const dimension_type new_space_dimension = pfunc.max_in_codomain() + 1;
53572
53573  if (new_space_dimension == space_dim) {
53574    // The partial function `pfunc' is indeed total and thus specifies
53575    // a permutation, that is, a renaming of the dimensions.  For
53576    // maximum efficiency, we will simply permute the columns of the
53577    // constraint system and/or the generator system.
53578
53579    std::vector<Variable> cycle;
53580    cycle.reserve(space_dim);
53581
53582    // Used to mark elements as soon as they are inserted in a cycle.
53583    std::deque<bool> visited(space_dim);
53584
53585    for (dimension_type i = space_dim; i-- > 0; ) {
53586      if (visited[i]) {
53587        continue;
53588      }
53589
53590      dimension_type j = i;
53591      do {
53592        visited[j] = true;
53593        // The following initialization is only to make the compiler happy.
53594        dimension_type k = 0;
53595        if (!pfunc.maps(j, k)) {
53596          throw_invalid_argument("map_space_dimensions(pfunc)",
53597                                 " pfunc is inconsistent");
53598        }
53599        if (k == j) {
53600          break;
53601        }
53602
53603        cycle.push_back(Variable(j));
53604        // Go along the cycle.
53605        j = k;
53606      } while (!visited[j]);
53607
53608      // End of cycle.
53609
53610      // Permute all that is up-to-date.  Notice that the contents of
53611      // the saturation matrices is unaffected by the permutation of
53612      // columns: they remain valid, if they were so.
53613      if (constraints_are_up_to_date()) {
53614        con_sys.permute_space_dimensions(cycle);
53615      }
53616
53617      if (generators_are_up_to_date()) {
53618        gen_sys.permute_space_dimensions(cycle);
53619      }
53620
53621      cycle.clear();
53622    }
53623
53624    PPL_ASSERT_HEAVY(OK());
53625    return;
53626  }
53627
53628  // If control gets here, then `pfunc' is not a permutation and some
53629  // dimensions must be projected away.
53630
53631  // If there are pending constraints, using `generators()' we process them.
53632  const Generator_System& old_gensys = generators();
53633
53634  if (old_gensys.has_no_rows()) {
53635    // The polyhedron is empty.
53636    Polyhedron new_polyhedron(topology(), new_space_dimension, EMPTY);
53637    m_swap(new_polyhedron);
53638    PPL_ASSERT_HEAVY(OK());
53639    return;
53640  }
53641
53642  // Make a local copy of the partial function.
53643  std::vector<dimension_type> pfunc_maps(space_dim, not_a_dimension());
53644  for (dimension_type j = space_dim; j-- > 0; ) {
53645    dimension_type pfunc_j;
53646    if (pfunc.maps(j, pfunc_j)) {
53647      pfunc_maps[j] = pfunc_j;
53648    }
53649  }
53650
53651  Generator_System new_gensys;
53652  for (Generator_System::const_iterator i = old_gensys.begin(),
53653         old_gensys_end = old_gensys.end(); i != old_gensys_end; ++i) {
53654    const Generator& old_g = *i;
53655    const Generator::expr_type old_e = old_g.expression();
53656    Linear_Expression expr;
53657    expr.set_space_dimension(new_space_dimension);
53658    bool all_zeroes = true;
53659    for (Generator::expr_type::const_iterator j = old_e.begin(),
53660          j_end = old_e.end(); j != j_end; ++j) {
53661      const dimension_type mapped_id = pfunc_maps[j.variable().id()];
53662      if (mapped_id != not_a_dimension()) {
53663        add_mul_assign(expr, *j, Variable(mapped_id));
53664        all_zeroes = false;
53665      }
53666    }
53667    switch (old_g.type()) {
53668    case Generator::LINE:
53669      if (!all_zeroes) {
53670        new_gensys.insert(line(expr));
53671      }
53672      break;
53673    case Generator::RAY:
53674      if (!all_zeroes) {
53675        new_gensys.insert(ray(expr));
53676      }
53677      break;
53678    case Generator::POINT:
53679      // A point in the origin has all zero homogeneous coefficients.
53680      new_gensys.insert(point(expr, old_g.divisor()));
53681      break;
53682    case Generator::CLOSURE_POINT:
53683      // A closure point in the origin has all zero homogeneous coefficients.
53684      new_gensys.insert(closure_point(expr, old_g.divisor()));
53685      break;
53686    }
53687  }
53688  Polyhedron new_polyhedron(topology(), new_gensys);
53689  m_swap(new_polyhedron);
53690  PPL_ASSERT_HEAVY(OK(true));
53691}
53692
53693template <typename FP_Format, typename Interval_Info>
53694void
53695Polyhedron::refine_with_linear_form_inequality(
53696  const Linear_Form< Interval<FP_Format, Interval_Info> >& left,
53697  const Linear_Form< Interval<FP_Format, Interval_Info> >& right,
53698  const bool is_strict) {
53699
53700  // Check that FP_Format is indeed a floating point type.
53701  PPL_COMPILE_TIME_CHECK(!std::numeric_limits<FP_Format>::is_exact,
53702                         "Polyhedron::refine_with_linear_form_inequality:"
53703                         " FP_Format not a floating point type.");
53704
53705  // Dimension compatibility checks.
53706  // The dimensions of left and right should not be greater than the
53707  // dimension of *this.
53708  const dimension_type left_space_dim = left.space_dimension();
53709  if (space_dim < left_space_dim) {
53710    throw_dimension_incompatible(
53711          "refine_with_linear_form_inequality(l1, l2, s)", "l1", left);
53712  }
53713
53714  const dimension_type right_space_dim = right.space_dimension();
53715  if (space_dim < right_space_dim) {
53716    throw_dimension_incompatible(
53717          "refine_with_linear_form_inequality(l1, l2, s)", "l2", right);
53718  }
53719
53720  // We assume that the analyzer will not refine an unreachable test.
53721  PPL_ASSERT(!marked_empty());
53722
53723  typedef Interval<FP_Format, Interval_Info> FP_Interval_Type;
53724  typedef Linear_Form<FP_Interval_Type> FP_Linear_Form;
53725
53726  if (Floating_Point_Expression<FP_Interval_Type, float_ieee754_single>::
53727      overflows(left)) {
53728    return;
53729  }
53730
53731  if (Floating_Point_Expression<FP_Interval_Type, float_ieee754_single>::
53732      overflows(right)) {
53733    return;
53734  }
53735
53736  // Overapproximate left - right.
53737  FP_Linear_Form left_minus_right(left);
53738  left_minus_right -= right;
53739  if (Floating_Point_Expression<FP_Interval_Type, float_ieee754_single>::
53740      overflows(left_minus_right)) {
53741    return;
53742  }
53743
53744  dimension_type lf_space_dim = left_minus_right.space_dimension();
53745  FP_Linear_Form lf_approx;
53746  overapproximate_linear_form(left_minus_right, lf_space_dim, lf_approx);
53747  if (Floating_Point_Expression<FP_Interval_Type, float_ieee754_single>::
53748      overflows(lf_approx)) {
53749    return;
53750  }
53751
53752  // Normalize left - right.
53753  Linear_Expression lf_approx_le;
53754  convert_to_integer_expression(lf_approx, lf_space_dim, lf_approx_le);
53755
53756  // Finally, do the refinement.
53757  if (!is_strict || is_necessarily_closed()) {
53758    refine_with_constraint(lf_approx_le <= 0);
53759  }
53760  else {
53761    refine_with_constraint(lf_approx_le < 0);
53762  }
53763}
53764
53765template <typename FP_Format, typename Interval_Info>
53766void
53767Polyhedron::affine_form_image(const Variable var,
53768const Linear_Form<Interval <FP_Format, Interval_Info> >& lf) {
53769
53770  // Check that FP_Format is indeed a floating point type.
53771  PPL_COMPILE_TIME_CHECK(!std::numeric_limits<FP_Format>::is_exact,
53772                         "Polyhedron::affine_form_image:"
53773                         " FP_Format not a floating point type.");
53774
53775  // Dimension compatibility checks.
53776  // The dimension of lf should not be greater than the dimension of *this.
53777  const dimension_type lf_space_dim = lf.space_dimension();
53778  if (space_dim < lf_space_dim) {
53779    throw_dimension_incompatible("affine_form_image(v, l, s)", "l", lf);
53780  }
53781
53782  // `var' should be one of the dimensions of the polyhedron.
53783  const dimension_type var_id = var.id();
53784  if (space_dim < var_id + 1) {
53785    throw_dimension_incompatible("affine_form_image(v, l, s)", "v", var);
53786  }
53787
53788  // We assume that the analyzer will not perform an unreachable assignment.
53789  PPL_ASSERT(!marked_empty());
53790
53791  typedef Interval<FP_Format, Interval_Info> FP_Interval_Type;
53792  typedef Linear_Form<FP_Interval_Type> FP_Linear_Form;
53793
53794  if (Floating_Point_Expression<FP_Interval_Type, float_ieee754_single>::
53795      overflows(lf)) {
53796    *this = Polyhedron(topology(), space_dim, UNIVERSE);
53797    return;
53798  }
53799
53800  // Overapproximate lf.
53801  FP_Linear_Form lf_approx;
53802  overapproximate_linear_form(lf, lf_space_dim, lf_approx);
53803
53804  if (Floating_Point_Expression<FP_Interval_Type, float_ieee754_single>::
53805      overflows(lf_approx)) {
53806    *this = Polyhedron(topology(), space_dim, UNIVERSE);
53807    return;
53808  }
53809
53810  // Normalize lf.
53811  Linear_Expression lf_approx_le;
53812  PPL_DIRTY_TEMP_COEFFICIENT(lo_coeff);
53813  PPL_DIRTY_TEMP_COEFFICIENT(hi_coeff);
53814  PPL_DIRTY_TEMP_COEFFICIENT(denominator);
53815  convert_to_integer_expressions(lf_approx, lf_space_dim, lf_approx_le,
53816                                 lo_coeff, hi_coeff, denominator);
53817
53818  // Finally, do the assignment.
53819  bounded_affine_image(var, lf_approx_le + lo_coeff, lf_approx_le + hi_coeff,
53820                       denominator);
53821}
53822
53823template <typename FP_Format, typename Interval_Info>
53824void
53825Polyhedron
53826::overapproximate_linear_form(const Linear_Form<Interval <FP_Format, Interval_Info> >& lf,
53827                              const dimension_type lf_dimension,
53828                              Linear_Form<Interval <FP_Format, Interval_Info> >& result) {
53829
53830  // Check that FP_Format is indeed a floating point type.
53831  PPL_COMPILE_TIME_CHECK(!std::numeric_limits<FP_Format>::is_exact,
53832                         "Polyhedron::overapproximate_linear_form:"
53833                         " FP_Format not a floating point type.");
53834
53835  typedef Interval<FP_Format, Interval_Info> FP_Interval_Type;
53836  typedef Linear_Form<FP_Interval_Type> FP_Linear_Form;
53837
53838  // Build a Box from the Polyhedron so that we can extract upper and
53839  // lower bounds of variables easily.
53840  Box<FP_Interval_Type> box(*this);
53841
53842  result = FP_Linear_Form(lf.inhomogeneous_term());
53843  // FIXME: this may not be policy-neutral.
53844  const FP_Interval_Type aux_divisor1(static_cast<FP_Format>(0.5));
53845  FP_Interval_Type aux_divisor2(aux_divisor1);
53846  aux_divisor2.lower() = static_cast<FP_Format>(-0.5);
53847
53848  for (dimension_type i = 0; i < lf_dimension; ++i) {
53849    Variable curr_var(i);
53850    const FP_Interval_Type& curr_coeff = lf.coefficient(curr_var);
53851    PPL_ASSERT(curr_coeff.is_bounded());
53852    FP_Format curr_lb = curr_coeff.lower();
53853    FP_Format curr_ub = curr_coeff.upper();
53854    if (curr_lb != 0 || curr_ub != 0) {
53855      const FP_Interval_Type& curr_int = box.get_interval(curr_var);
53856      FP_Interval_Type curr_addend(curr_ub - curr_lb);
53857      curr_addend *= aux_divisor2;
53858      curr_addend *= curr_int;
53859      result += curr_addend;
53860      curr_addend = FP_Interval_Type(curr_lb + curr_ub);
53861      curr_addend *= aux_divisor1;
53862      FP_Linear_Form curr_addend_lf(curr_var);
53863      curr_addend_lf *= curr_addend;
53864      result += curr_addend_lf;
53865    }
53866  }
53867}
53868
53869template <typename FP_Format, typename Interval_Info>
53870void
53871Polyhedron::convert_to_integer_expression(
53872                const Linear_Form<Interval <FP_Format, Interval_Info> >& lf,
53873                const dimension_type lf_dimension,
53874                Linear_Expression& result) {
53875  result = Linear_Expression();
53876
53877  typedef Interval<FP_Format, Interval_Info> FP_Interval_Type;
53878  std::vector<Coefficient> numerators(lf_dimension+1);
53879  std::vector<Coefficient> denominators(lf_dimension+1);
53880
53881  // Convert each floating point number to a pair <numerator, denominator>
53882  // and compute the lcm of all denominators.
53883  PPL_DIRTY_TEMP_COEFFICIENT(lcm);
53884  lcm = 1;
53885  const FP_Interval_Type& b = lf.inhomogeneous_term();
53886  // FIXME: are these checks numerator[i] != 0 really necessary?
53887  numer_denom(b.lower(), numerators[lf_dimension],
53888                         denominators[lf_dimension]);
53889  if (numerators[lf_dimension] != 0) {
53890      lcm_assign(lcm, lcm, denominators[lf_dimension]);
53891  }
53892
53893  for (dimension_type i = 0; i < lf_dimension; ++i) {
53894    const FP_Interval_Type& curr_int = lf.coefficient(Variable(i));
53895    numer_denom(curr_int.lower(), numerators[i], denominators[i]);
53896    if (numerators[i] != 0) {
53897      lcm_assign(lcm, lcm, denominators[i]);
53898    }
53899  }
53900
53901  for (dimension_type i = 0; i < lf_dimension; ++i) {
53902    if (numerators[i] != 0) {
53903      exact_div_assign(denominators[i], lcm, denominators[i]);
53904      numerators[i] *= denominators[i];
53905      result += numerators[i] * Variable(i);
53906    }
53907  }
53908
53909  if (numerators[lf_dimension] != 0) {
53910    exact_div_assign(denominators[lf_dimension],
53911                     lcm, denominators[lf_dimension]);
53912    numerators[lf_dimension] *= denominators[lf_dimension];
53913    result += numerators[lf_dimension];
53914  }
53915}
53916
53917template <typename FP_Format, typename Interval_Info>
53918void
53919Polyhedron::convert_to_integer_expressions(
53920                const Linear_Form<Interval <FP_Format, Interval_Info> >& lf,
53921                const dimension_type lf_dimension, Linear_Expression& res,
53922                Coefficient& res_low_coeff, Coefficient& res_hi_coeff,
53923                Coefficient& denominator) {
53924  res = Linear_Expression();
53925
53926  typedef Interval<FP_Format, Interval_Info> FP_Interval_Type;
53927  std::vector<Coefficient> numerators(lf_dimension+2);
53928  std::vector<Coefficient> denominators(lf_dimension+2);
53929
53930  // Convert each floating point number to a pair <numerator, denominator>
53931  // and compute the lcm of all denominators.
53932  Coefficient& lcm = denominator;
53933  lcm = 1;
53934  const FP_Interval_Type& b = lf.inhomogeneous_term();
53935  numer_denom(b.lower(), numerators[lf_dimension], denominators[lf_dimension]);
53936  // FIXME: are these checks numerator[i] != 0 really necessary?
53937  if (numerators[lf_dimension] != 0) {
53938      lcm_assign(lcm, lcm, denominators[lf_dimension]);
53939  }
53940
53941  numer_denom(b.upper(), numerators[lf_dimension+1],
53942                         denominators[lf_dimension+1]);
53943  if (numerators[lf_dimension+1] != 0) {
53944      lcm_assign(lcm, lcm, denominators[lf_dimension+1]);
53945  }
53946
53947  for (dimension_type i = 0; i < lf_dimension; ++i) {
53948    const FP_Interval_Type& curr_int = lf.coefficient(Variable(i));
53949    numer_denom(curr_int.lower(), numerators[i], denominators[i]);
53950    if (numerators[i] != 0) {
53951      lcm_assign(lcm, lcm, denominators[i]);
53952    }
53953  }
53954
53955  for (dimension_type i = 0; i < lf_dimension; ++i) {
53956    if (numerators[i] != 0) {
53957      exact_div_assign(denominators[i], lcm, denominators[i]);
53958      numerators[i] *= denominators[i];
53959      res += numerators[i] * Variable(i);
53960    }
53961  }
53962
53963  if (numerators[lf_dimension] != 0) {
53964    exact_div_assign(denominators[lf_dimension],
53965                     lcm, denominators[lf_dimension]);
53966    numerators[lf_dimension] *= denominators[lf_dimension];
53967    res_low_coeff = numerators[lf_dimension];
53968  }
53969  else {
53970    res_low_coeff = 0;
53971  }
53972
53973  if (numerators[lf_dimension+1] != 0) {
53974    exact_div_assign(denominators[lf_dimension+1],
53975                     lcm, denominators[lf_dimension+1]);
53976    numerators[lf_dimension+1] *= denominators[lf_dimension+1];
53977    res_hi_coeff = numerators[lf_dimension+1];
53978  }
53979  else {
53980    res_hi_coeff = 0;
53981  }
53982}
53983
53984template <typename C>
53985void
53986Polyhedron::throw_dimension_incompatible(const char* method,
53987                                         const char* lf_name,
53988                                         const Linear_Form<C>& lf) const {
53989  throw_dimension_incompatible(method, lf_name, lf.space_dimension());
53990}
53991
53992template <typename Input>
53993Input&
53994Polyhedron::check_obj_space_dimension_overflow(Input& input,
53995                                               const Topology topol,
53996                                               const char* method,
53997                                               const char* reason) {
53998  check_space_dimension_overflow(input.space_dimension(),
53999                                 max_space_dimension(),
54000                                 topol, method, reason);
54001  return input;
54002}
54003
54004} // namespace Parma_Polyhedra_Library
54005
54006/* Automatically generated from PPL source file ../src/Polyhedron_chdims_templates.hh line 1. */
54007/* Polyhedron class implementation (non-inline template operators that
54008   may change the dimension of the vector space).
54009*/
54010
54011
54012namespace Parma_Polyhedra_Library {
54013
54014template <typename Linear_System1, typename Linear_System2>
54015void
54016Polyhedron::add_space_dimensions(Linear_System1& sys1,
54017                                 Linear_System2& sys2,
54018                                 Bit_Matrix& sat1,
54019                                 Bit_Matrix& sat2,
54020                                 dimension_type add_dim) {
54021  PPL_ASSERT(sys1.topology() == sys2.topology());
54022  PPL_ASSERT(sys1.space_dimension() == sys2.space_dimension());
54023  PPL_ASSERT(add_dim != 0);
54024
54025  sys1.set_space_dimension(sys1.space_dimension() + add_dim);
54026  sys2.add_universe_rows_and_space_dimensions(add_dim);
54027
54028  // The resulting saturation matrix will be as follows:
54029  // from row    0    to      add_dim-1       : only zeroes
54030  //          add_dim     add_dim+num_rows-1  : old saturation matrix
54031
54032  // In fact all the old generators saturate all the new constraints
54033  // because the polyhedron has not been embedded in the new space.
54034  sat1.resize(sat1.num_rows() + add_dim, sat1.num_columns());
54035  // The old matrix is moved to the end of the new matrix.
54036  for (dimension_type i = sat1.num_rows() - add_dim; i-- > 0; ) {
54037    swap(sat1[i], sat1[i+add_dim]);
54038  }
54039  // Computes the "sat_c", too.
54040  sat2.transpose_assign(sat1);
54041}
54042
54043} // namespace Parma_Polyhedra_Library
54044
54045/* Automatically generated from PPL source file ../src/Polyhedron_conversion_templates.hh line 1. */
54046/* Polyhedron class implementation: conversion().
54047*/
54048
54049
54050/* Automatically generated from PPL source file ../src/Polyhedron_conversion_templates.hh line 34. */
54051
54052#include <cstddef>
54053#include <climits>
54054
54055// This flag turns on the quick non-adjacency test;
54056// the performance impact of this test was evaluated by H. Le Verge (1994);
54057// see also Corollary 4.2 in B. Genov's PhD thesis (2014).
54058#ifndef PPL_QUICK_NON_ADJ_TEST
54059#define PPL_QUICK_NON_ADJ_TEST 1
54060#endif
54061
54062// This flag turns on the quick adjacency test;
54063// for a justification, see Corollary 4.3 in B. Genov's PhD thesis (2014),
54064// where it is also said that the test was implemented in cddlib.
54065#ifndef PPL_QUICK_ADJ_TEST
54066#define PPL_QUICK_ADJ_TEST 1
54067#endif
54068
54069namespace Parma_Polyhedra_Library {
54070
54071/*!
54072  \return
54073  The number of lines of the polyhedron or the number of equality
54074  constraints in the result of conversion.
54075
54076  \param source
54077  The system to use to convert \p dest: it may be modified;
54078
54079  \param start
54080  The index of \p source row from which conversion begin;
54081
54082  \param dest
54083  The result of the conversion;
54084
54085  \param sat
54086  The saturation matrix telling us, for each row in \p source, which
54087  are the rows of \p dest that satisfy but do not saturate it;
54088
54089  \param num_lines_or_equalities
54090  The number of rows in the system \p dest that are either lines of
54091  the polyhedron (when \p dest is a system of generators) or equality
54092  constraints (when \p dest is a system of constraints).
54093
54094  \if Include_Implementation_Details
54095
54096  For simplicity, all the following comments assume we are converting a
54097  constraint system \p source to a generator system \p dest;
54098  the comments for the symmetric case can be obtained by duality.
54099
54100  If some of the constraints in \p source are redundant, they will be removed.
54101  This is why the \p source is not declared to be a constant parameter.
54102
54103  If \p start is 0, then \p source is a sorted system; also, \p dest is
54104  a generator system corresponding to an empty constraint system.
54105  If otherwise \p start is greater than 0, then the two sub-systems of
54106  \p source made by the non-pending rows and the pending rows, respectively,
54107  are both sorted; also, \p dest is the generator system corresponding to
54108  the non-pending constraints of \p source.
54109
54110  Independently from the value of \p start, \p dest has lines from index 0
54111  to index \p num_lines_or_equalities - 1 and rays/points from index
54112  \p num_lines_or_equalities to the last of its rows.
54113
54114  Note that here the rows of \p sat are indexed by rows of \p dest
54115  and its columns are indexed by rows of \p source.
54116
54117  We know that polyhedra can be represented by both a system of
54118  constraints or a system of generators (points, rays and lines)
54119  (see Section \ref representation).
54120  When we have both descriptions for a polyhedron \f$P\f$
54121  we have what is called a <EM>double description</EM>
54122  (or <EM>DD pair</EM>) for \f$P\f$.
54123
54124  Here, the <EM>representation system</EM> refers to the system \f$C\f$
54125  whose rows represent the constraints that characterize \f$P\f$
54126  and the <EM>generating system</EM>, the system \f$G\f$ whose rows
54127  represent the generators of \f$P\f$.
54128  We say that a pair \f$(C, G)\f$ of (real) systems is
54129  a <EM>double description pair</EM> if
54130  \f[
54131    C\vect{x} \geq \vect{0}
54132      \quad\iff\quad
54133        \exists \vect{\lambda} \geq \vect{0} \mathrel{.}
54134        \vect{x} = G\vect{\lambda}.
54135  \f]
54136
54137  The term "double description" is quite natural in the sense that
54138  such a pair contains two different description of the same object.
54139  In fact, if we refer to the cone representation of a polyhedron \f$P\f$
54140  and we call \f$C\f$ and \f$G\f$ the systems of constraints and
54141  rays respectively, we have
54142  \f[
54143    P = \{\, \vect{x} \in \Rset^n \mid C\vect{x} \geq \vect{0}\, \}
54144      = \{\, \vect{x} \in \Rset^n \mid \vect{x} = G\vect{\lambda}
54145      \text{ for some } \vect{\lambda} \geq \vect{0}\, \}.
54146  \f]
54147
54148  Because of the theorem of Minkowski (see Section \ref prelims),
54149  we can say that, given a \f$m \times n\f$ representation system
54150  \f$C\f$ such that
54151  \f$\mathop{\mathrm{rank}}(C) = n = \mathit{dimension of the whole space}\f$
54152  for a non-empty polyhedron \f$P\f$,
54153  it is always possible to find a generating system \f$G\f$ for \f$P\f$
54154  such that \f$(C, G)\f$ is a DD pair.
54155  Conversely, Weyl's theorem ensures that, for each generating system
54156  \f$G\f$, it is possible to find a representation system \f$C\f$
54157  such that \f$(C, G)\f$ is a DD pair.
54158
54159  For efficiency reasons, our representation of polyhedra makes use
54160  of a double description.
54161  We are thus left with two problems:
54162    -# given \f$C\f$ find \f$G\f$ such that \f$(C, G)\f$ is a DD pair;
54163    -# given \f$G\f$ find \f$C\f$ such that \f$(C, G)\f$ is a DD pair.
54164
54165  Using Farkas' Lemma we can prove that these two problems are
54166  computationally equivalent (i.e., linear-time reducible to each other).
54167  Farkas' Lemma establishes a fundamental property of vectors in
54168  \f$\Rset^n\f$ that, in a sense, captures the essence of duality.
54169  Consider a matrix \f$A \in \Rset^{m \times n}\f$ and let
54170  \f$\{ \vect{a}_1, \ldots, \vect{a}_m \}\f$ be its set of row vectors.
54171  Consider also another vector \f$\vect{c} \in \Rset^n\f$ such that,
54172  whenever a vector \f$\vect{y} \in \Rset^n\f$ has a non-negative projection
54173  on the \f$\vect{a}_i\f$'s, it also has a non-negative projection
54174  on \f$\vect{c}\f$.
54175  The lemma states that \f$\vect{c}\f$ has this property if and only if
54176  it is in the cone generated by the \f$\vect{a}_i\f$'s.
54177  Formally, the lemma states the equivalence of the two following
54178  assertions:
54179    -# \f$
54180         \forall \vect{y}
54181           \mathrel{:} (A\vect{y} \geq 0 \implies
54182           \langle \vect{y},\vect{c} \rangle \geq 0)
54183       \f$;
54184    -# \f$
54185         \exists \vect{\lambda} \geq \vect{0}
54186           \mathrel{.} \vect{c}^\mathrm{T} = \vect{\lambda}^\mathrm{T}A
54187       \f$.
54188
54189  With this result we can prove that \f$(C, G)\f$ is a DD pair
54190  if and only if \f$(G^\mathrm{T}, C^\mathrm{T})\f$ is a DD pair.
54191
54192  Suppose \f$(C, G)\f$ is a DD pair.
54193  Thus, for each \f$x\f$ of the appropriate dimension,
54194  \f$C\vect{x} \geq \vect{0}\f$ if and only if
54195  \f$\exists \lambda \geq 0 \mathrel{.} \vect{x} = G\vect{\lambda}\f$,
54196  which is of course equivalent to
54197  \f$
54198    \exists \vect{\lambda} \geq \vect{0}
54199      \mathrel{.} \vect{x}^\mathrm{T} = \vect{\lambda}^\mathrm{T}G^\mathrm{T}
54200  \f$.
54201
54202  First, we assume that \f$\vect{z}\f$ is such that
54203  \f$G^\mathrm{T}\vect{z} \geq \vect{0}\f$
54204  and we will show that
54205  \f$\exists \vect{\mu} \geq \vect{0} \mathrel{.}
54206  \vect{z} = C^\mathrm{T}\vect{\mu}\f$.
54207  Let \f$\vect{x}\f$ be such that \f$C\vect{x} \geq \vect{0}\f$.
54208  Since \f$(C, G)\f$ is a DD pair, this is equivalent to
54209  \f$
54210    \exists \vect{\lambda} \geq \vect{0}
54211      \mathrel{.} \vect{x}^\mathrm{T} = \vect{\lambda}^\mathrm{T}G^\mathrm{T}
54212  \f$,
54213  which, by Farkas' Lemma is equivalent to
54214  \f$
54215    \forall \vect{y} \mathrel{:} (G^\mathrm{T}\vect{y} \geq \vect{0} \implies
54216                                 \langle \vect{y}, \vect{x} \rangle \geq 0)
54217  \f$.
54218  Taking \f$\vect{y} = \vect{z}\f$ and recalling our assumption that
54219  \f$G^\mathrm{T}\vect{z} \geq \vect{0}\f$
54220  we can conclude that \f$\langle \vect{z}, \vect{x} \rangle \geq 0\f$,
54221  that is equivalent to \f$\langle \vect{x}, \vect{z} \rangle \geq 0\f$.
54222  We have thus established that
54223  \f$
54224    \forall \vect{x} \mathrel{:} (C\vect{x} \geq \vect{0} \implies
54225    \langle \vect{x}, \vect{z} \rangle \geq 0)
54226  \f$.
54227  By Farkas' Lemma, this is equivalent to
54228  \f$\exists \vect{\mu} \geq \vect{0} \mathrel{.}
54229  \vect{z}^\mathrm{T} = \vect{\mu}^\mathrm{T} C\f$,
54230  which is equivalent to what we wanted to prove, that is,
54231  \f$\exists \vect{\mu} \geq \vect{0} \mathrel{.}
54232  \vect{z} = C^\mathrm{T}\vect{\mu}\f$.
54233
54234  In order to prove the reverse implication, the following observation
54235  turns out to be useful:
54236  when \f$(C, G)\f$ is a DD pair, \f$CG \geq 0\f$.
54237  In fact,
54238  let \f$\vect{e}_j\f$ be the vector whose components are all \f$0\f$
54239  apart from the \f$j\f$-th one, which is \f$1\f$.
54240  Clearly \f$\vect{e}_j \geq \vect{0}\f$ and, taking
54241  \f$\vect{\lambda} = \vect{e}_j\f$ and
54242  \f$\vect{x} = G\vect{\lambda} = G \vect{e}_j\f$, we have
54243  \f$C\vect{x} = C(G \vect{e}_j) = (CG)\vect{e}_j \geq \vect{0}\f$,
54244  since \f$(C, G)\f$ is a DD pair.
54245  Thus, as \f$(CG)\vect{e}_j\f$ is the \f$j\f$-th column of \f$CG\f$
54246  and since the choice of \f$j\f$ was arbitrary, \f$CG \geq \vect{0}\f$.
54247
54248  We now assume that \f$\vect{z}\f$ is such that
54249  \f$\exists \vect{\mu} \geq \vect{0} \mathrel{.}
54250  \vect{z} = C^\mathrm{T}\vect{\mu}\f$
54251  and we will prove that \f$G^\mathrm{T}\vect{z} \geq \vect{0}\f$.
54252  By Farkas' Lemma, the assumption
54253  \f$\exists \vect{\mu} \geq \vect{0} \mathrel{.}
54254  \vect{z}^\mathrm{T} = \vect{\mu}^\mathrm{T}C\f$,
54255  is equivalent to
54256  \f$\forall \vect{y} \mathrel{:} (C\vect{y} \geq \vect{0}
54257  \implies \langle \vect{y}, \vect{z} \rangle \geq 0)\f$.
54258  If we take \f$\vect{y} = G\vect{e}_j\f$ then \f$C\vect{y}
54259                 = CG\vect{e}_j \geq 0\f$,
54260  since \f$CG \geq \vect{0}\f$.
54261  So
54262  \f$
54263    \langle \vect{y}, \vect{z} \rangle
54264      = (\vect{e}_j^\mathrm{T}G^\mathrm{T}) \vect{z}
54265      = \vect{e}_j^\mathrm{T}(G^\mathrm{T} \vect{z})
54266      \geq 0
54267  \f$,
54268  that is, the \f$j\f$-th component of \f$G^\mathrm{T}\vect{z}\f$
54269  is non-negative. The arbitrary choice of \f$j\f$ allows us to conclude
54270  that \f$G^\mathrm{T}\vect{z} \geq \vect{0}\f$, as required.
54271
54272  In view of this result, the following exposition assumes, for clarity,
54273  that the conversion being performed is from constraints to generators.
54274  Thus, even if the roles of \p source and \p dest can be interchanged,
54275  in the sequel we assume the \p source system will contain the constraints
54276  that represent the polyhedron and the \p dest system will contain
54277  the generator that generates it.
54278
54279  There are some observations that are useful to understand this function:
54280
54281  Observation 1: Let \f$A\f$ be a system of constraints that generate
54282  the polyhedron \f$P\f$ and \f$\vect{c}\f$ a new constraint that must
54283  be added. Suppose that there is a line \f$\vect{z}\f$ that does not
54284  saturate the constraint \f$\vect{c}\f$. If we combine the old lines
54285  and rays that do not saturate \f$\vect{c}\f$ (except \f$\vect{z}\f$)
54286  with \f$\vect{z}\f$ such that the new ones saturate \f$\vect{c}\f$,
54287  the new lines and rays also saturate the constraints  saturated by
54288  the old lines and rays.
54289
54290  In fact, if \f$\vect{y}_1\f$ is the old generator that does not saturate
54291  \f$\vect{c}\f$, \f$\vect{y}_2\f$ is the new one such that
54292  \f[
54293    \vect{y}_2 = \lambda \vect{y}_1 + \mu \vect{z}
54294  \f]
54295  and \f$\vect{c}_1\f$ is a previous constraint that \f$\vect{y}_1\f$
54296  and \f$\vect{z}\f$ saturates, we can see
54297  \f[
54298    \langle \vect{c}_1, \vect{y}_2 \rangle
54299    = \langle \vect{c}_1, (\lambda \vect{y}_1 + \mu \vect{z}) \rangle
54300    = \lambda \langle \vect{c}_1, \vect{y}_1 \rangle
54301       + \mu \langle \vect{c}_1, \vect{z} \rangle
54302       = 0 + \mu \langle \vect{c}_1, \vect{z} \rangle
54303       = \mu \langle \vect{c}_1, \vect{z} \rangle
54304  \f]
54305  and
54306  \f[
54307    \mu \langle \vect{c}_1, \vect{z} \rangle = 0.
54308  \f]
54309
54310  Proposition 1: Let \f$\vect{r}_1\f$ and \f$\vect{r}_2\f$ be distinct
54311  rays of \f$P\f$.
54312  Then the following statements are equivalent:
54313  a) \f$\vect{r}_1\f$ and \f$\vect{r}_2\f$ are adjacent extreme rays
54314     (see Section \ref prelims);
54315  b) \f$\vect{r}_1\f$ and \f$\vect{r}_2\f$ are extreme rays and the
54316     rank of the system composed by the constraints saturated by both
54317     \f$\vect{r}_1\f$ and \f$\vect{r}_2\f$ is equal to
54318     \f$d - 2\f$, where \f$d\f$ is the rank of the system of constraints.
54319
54320  In fact, let \f$F\f$ be the system of generators that saturate the
54321  constraints saturated by both \f$\vect{r}_1\f$ and \f$\vect{r}_2\f$.
54322  If b) holds, the set \f$F\f$ is 2-dimensional and \f$\vect{r}_1\f$ and
54323  \f$\vect{r}_2\f$ generate this set. So, every generator
54324  \f$\vect{x}\f$ of \f$F\f$ can be built as a combination of
54325  \f$\vect{r}_1\f$ and \f$\vect{r}_2\f$, i.e.
54326  \f[
54327    \vect{x} = \lambda \vect{r}_1 + \mu \vect{r}_2.
54328  \f]
54329  This combination is non-negative because there exists at least a
54330  constraint \f$c\f$ saturated by \f$\vect{r}_1\f$ and not
54331  \f$\vect{r}_2\f$ (or vice versa) (because they are distinct) for which
54332  \f[
54333    \langle \vect{c}, \vect{x} \rangle \geq 0
54334  \f]
54335  and
54336  \f[
54337    \langle \vect{c}, \vect{x} \rangle
54338    = \lambda \langle \vect{c}, \vect{r}_1 \rangle
54339                           (or = \mu \langle \vect{c}, \vect{r}_2 \rangle).
54340  \f]
54341  So, there is no other extreme ray in \f$F\f$ and a) holds.
54342  Otherwise, if b) does not hold, the rank of the system generated by
54343  the constraints saturated by both \f$\vect{r}_1\f$ and \f$\vect{r}_2\f$
54344  is equal to \f$d - k\f$, with \p k \>= 3, the set \f$F\f$ is
54345  \p k -dimensional and at least \p k extreme rays are necessary
54346  to generate \f$F\f$.
54347  So, \f$\vect{r}_1\f$ and \f$\vect{r}_2\f$ are not adjacent and
54348  a) does not hold.
54349
54350  Proposition 2: When we build the new system of generators starting from
54351  a system \f$A\f$ of constraints of \f$P\f$, if \f$\vect{c}\f$ is the
54352  constraint to add to \f$A\f$ and all lines of \f$P\f$ saturate
54353  \f$\vect{c}\f$, the new set of rays is the union of those rays that
54354  saturate, of those that satisfy and of a set \f$\overline Q\f$ of
54355  rays such that each of them
54356  -# lies on the hyper-plane represented by the k-th constraint,
54357  -# is a positive combination of two adjacent rays \f$\vect{r}_1\f$ and
54358     \f$\vect{r}_2\f$ such that the first one satisfies the constraint and
54359     the other does not satisfy it.
54360  If the adjacency property is not taken in account, the new set of
54361  rays is not irredundant, in general.
54362
54363  In fact, if \f$\vect{r}_1\f$ and \f$\vect{r}_2\f$ are not adjacent,
54364  the rank of the system composed by the constraints saturated by both
54365  \f$\vect{r}_1\f$ and \f$\vect{r}_2\f$ is different from \f$d - 2\f$
54366  (see the previous proposition) or neither \f$\vect{r}_1\f$ nor
54367  \f$\vect{r}_2\f$ are extreme rays. Since the new ray \f$\vect{r}\f$
54368  is a combination of \f$\vect{r}_1\f$ and \f$\vect{r}_2\f$,
54369  it saturates the same constraints saturated by both \f$\vect{r}_1\f$ and
54370  \f$\vect{r}_2\f$.
54371  If the rank is less than \f$d - 2\f$, the rank of
54372  the system composed by \f$\vect{c}\f$ (that is saturated by \f$\vect{r}\f$)
54373  and by the constraints of \f$A\f$ saturated by \f$\vect{r}\f$  is less
54374  than \f$d - 1\f$. It means that \f$r\f$ is redundant (see
54375  Section \ref prelims).
54376  If neither \f$\vect{r}_1\f$ nor \f$\vect{r}_2\f$ are extreme rays,
54377  they belong to a 2-dimensional face containing exactly two extreme rays
54378  of \f$P\f$.
54379  These two adjacent rays build a ray equal to \f$\vect{r}\f$ and so
54380  \f$\vect{r}\f$ is redundant.
54381
54382  \endif
54383*/
54384template <typename Source_Linear_System, typename Dest_Linear_System>
54385dimension_type
54386Polyhedron::conversion(Source_Linear_System& source,
54387                       const dimension_type start,
54388                       Dest_Linear_System& dest,
54389                       Bit_Matrix& sat,
54390                       dimension_type num_lines_or_equalities) {
54391  typedef typename Dest_Linear_System::row_type dest_row_type;
54392  typedef typename Source_Linear_System::row_type source_row_type;
54393
54394  // Constraints and generators must have the same dimension,
54395  // otherwise the scalar products below will bomb.
54396  PPL_ASSERT(source.space_dimension() == dest.space_dimension());
54397  const dimension_type source_space_dim = source.space_dimension();
54398  const dimension_type source_num_rows = source.num_rows();
54399  const dimension_type source_num_columns = source_space_dim
54400    + (source.is_necessarily_closed() ? 1U : 2U);
54401
54402
54403  dimension_type dest_num_rows = dest.num_rows();
54404  // The rows removed from `dest' will be placed in this vector, so they
54405  // can be recycled if needed.
54406  std::vector<dest_row_type> recyclable_dest_rows;
54407
54408  using std::swap;
54409
54410  // By construction, the number of columns of `sat' is the same as
54411  // the number of rows of `source'; also, the number of rows of `sat'
54412  // is the same as the number of rows of `dest'.
54413  PPL_ASSERT(source_num_rows == sat.num_columns());
54414  PPL_ASSERT(dest_num_rows == sat.num_rows());
54415
54416  // If `start > 0', then we are converting the pending constraints.
54417  PPL_ASSERT(start == 0 || start == source.first_pending_row());
54418
54419  PPL_DIRTY_TEMP_COEFFICIENT(normalized_sp_i);
54420  PPL_DIRTY_TEMP_COEFFICIENT(normalized_sp_o);
54421
54422  bool dest_sorted = dest.is_sorted();
54423  const dimension_type dest_first_pending_row = dest.first_pending_row();
54424
54425  // This will contain the row indexes of the redundant rows of `source'.
54426  std::vector<dimension_type> redundant_source_rows;
54427
54428#if PPL_QUICK_ADJ_TEST
54429  // This will contain the number of ones in each row of `sat'.
54430  PPL_DIRTY_TEMP(std::vector<dimension_type>, sat_num_ones);
54431  sat_num_ones.resize(dest_num_rows, 0);
54432  for (dimension_type i = dest_num_rows; i-- > 0; ) {
54433    sat_num_ones[i] = sat[i].count_ones();
54434  }
54435#endif // PPL_QUICK_ADJ_TEST
54436
54437  // Converting the sub-system of `source' having rows with indexes
54438  // from `start' to the last one (i.e., `source_num_rows' - 1).
54439  for (dimension_type k = start; k < source_num_rows; ++k) {
54440    const source_row_type& source_k = source[k];
54441
54442#ifndef NDEBUG
54443#if PPL_QUICK_ADJ_TEST
54444    for (dimension_type i = dest_num_rows; i-- > 0; ) {
54445      PPL_ASSERT(sat_num_ones[i] == sat[i].count_ones());
54446    }
54447#endif // PPL_QUICK_ADJ_TEST
54448#endif // NDEBUG
54449
54450    // `scalar_prod[i]' will contain the scalar product of the
54451    // constraint `source_k' and the generator `dest_rows[i]'.  This
54452    // product is 0 if and only if the generator saturates the
54453    // constraint.
54454    PPL_DIRTY_TEMP(std::vector<Coefficient>, scalar_prod);
54455    if (dest_num_rows > scalar_prod.size()) {
54456      scalar_prod.insert(scalar_prod.end(),
54457                         dest_num_rows - scalar_prod.size(),
54458                         Coefficient_zero());
54459    }
54460    // `index_non_zero' will indicate the first generator in `dest_rows'
54461    // that does not saturate the constraint `source_k'.
54462    dimension_type index_non_zero = 0;
54463    for ( ; index_non_zero < dest_num_rows; ++index_non_zero) {
54464      WEIGHT_BEGIN();
54465      Scalar_Products::assign(scalar_prod[index_non_zero],
54466                              source_k,
54467                              dest.sys.rows[index_non_zero]);
54468      WEIGHT_ADD_MUL(17, source_space_dim);
54469      if (scalar_prod[index_non_zero] != 0) {
54470        // The generator does not saturate the constraint.
54471        break;
54472      }
54473      // Check if the client has requested abandoning all expensive
54474      // computations.  If so, the exception specified by the client
54475      // is thrown now.
54476      maybe_abandon();
54477    }
54478    for (dimension_type i = index_non_zero + 1; i < dest_num_rows; ++i) {
54479      WEIGHT_BEGIN();
54480      Scalar_Products::assign(scalar_prod[i], source_k, dest.sys.rows[i]);
54481      WEIGHT_ADD_MUL(25, source_space_dim);
54482      // Check if the client has requested abandoning all expensive
54483      // computations.  If so, the exception specified by the client
54484      // is thrown now.
54485      maybe_abandon();
54486    }
54487
54488    // We first treat the case when `index_non_zero' is less than
54489    // `num_lines_or_equalities', i.e., when the generator that
54490    // does not saturate the constraint `source_k' is a line.
54491    // The other case (described later) is when all the lines
54492    // in `dest_rows' (i.e., all the rows having indexes less than
54493    // `num_lines_or_equalities') do saturate the constraint.
54494
54495    if (index_non_zero < num_lines_or_equalities) {
54496      // Since the generator `dest_rows[index_non_zero]' does not saturate
54497      // the constraint `source_k', it can no longer be a line
54498      // (see saturation rule in Section \ref prelims).
54499      // Therefore, we first transform it to a ray.
54500      dest.sys.rows[index_non_zero].set_is_ray_or_point_or_inequality();
54501      // Of the two possible choices, we select the ray satisfying
54502      // the constraint (namely, the ray whose scalar product
54503      // with the constraint gives a positive result).
54504      if (scalar_prod[index_non_zero] < 0) {
54505        // The ray `dest_rows[index_non_zero]' lies on the wrong half-space:
54506        // we change it to have the opposite direction.
54507        neg_assign(scalar_prod[index_non_zero]);
54508        neg_assign(dest.sys.rows[index_non_zero].expr);
54509        // The modified row may still not be OK(), so don't assert OK here.
54510        // They are all checked at the end of this function.
54511      }
54512      // Having changed a line to a ray, we set `dest_rows' to be a
54513      // non-sorted system, we decrement the number of lines of `dest_rows'
54514      // and, if necessary, we move the new ray below all the remaining lines.
54515      dest_sorted = false;
54516      --num_lines_or_equalities;
54517      if (index_non_zero != num_lines_or_equalities) {
54518        swap(dest.sys.rows[index_non_zero],
54519             dest.sys.rows[num_lines_or_equalities]);
54520        swap(scalar_prod[index_non_zero],
54521             scalar_prod[num_lines_or_equalities]);
54522      }
54523      const dest_row_type& dest_nle = dest.sys.rows[num_lines_or_equalities];
54524
54525      // Computing the new lineality space.
54526      // Since each line must lie on the hyper-plane corresponding to
54527      // the constraint `source_k', the scalar product between
54528      // the line and the constraint must be 0.
54529      // This property already holds for the lines having indexes
54530      // between 0 and `index_non_zero' - 1.
54531      // We have to consider the remaining lines, having indexes
54532      // between `index_non_zero' and `num_lines_or_equalities' - 1.
54533      // Each line that does not saturate the constraint has to be
54534      // linearly combined with generator `dest_nle' so that the
54535      // resulting new line saturates the constraint.
54536      // Note that, by Observation 1 above, the resulting new line
54537      // will still saturate all the constraints that were saturated by
54538      // the old line.
54539
54540      Coefficient& scalar_prod_nle = scalar_prod[num_lines_or_equalities];
54541      PPL_ASSERT(scalar_prod_nle != 0);
54542      for (dimension_type
54543             i = index_non_zero; i < num_lines_or_equalities; ++i) {
54544        if (scalar_prod[i] != 0) {
54545          // The following fragment optimizes the computation of
54546          //
54547          // <CODE>
54548          //   Coefficient scale = scalar_prod[i];
54549          //   scale.gcd_assign(scalar_prod_nle);
54550          //   Coefficient normalized_sp_i = scalar_prod[i] / scale;
54551          //   Coefficient normalized_sp_n = scalar_prod_nle / scale;
54552          //   for (dimension_type c = dest_num_columns; c-- > 0; ) {
54553          //     dest[i][c] *= normalized_sp_n;
54554          //     dest[i][c] -= normalized_sp_i * dest_nle[c];
54555          //   }
54556          // </CODE>
54557          normalize2(scalar_prod[i],
54558                     scalar_prod_nle,
54559                     normalized_sp_i,
54560                     normalized_sp_o);
54561          dest_row_type& dest_i = dest.sys.rows[i];
54562          neg_assign(normalized_sp_i);
54563          dest_i.expr.linear_combine(dest_nle.expr,
54564                                     normalized_sp_o, normalized_sp_i);
54565          dest_i.strong_normalize();
54566          // The modified row may still not be OK(), so don't assert OK here.
54567          // They are all checked at the end of this function.
54568          scalar_prod[i] = 0;
54569          // dest_sorted has already been set to false.
54570        }
54571      }
54572
54573      // Computing the new pointed cone.
54574      // Similarly to what we have done during the computation of
54575      // the lineality space, we consider all the remaining rays
54576      // (having indexes strictly greater than `num_lines_or_equalities')
54577      // that do not saturate the constraint `source_k'. These rays
54578      // are positively combined with the ray `dest_nle' so that the
54579      // resulting new rays saturate the constraint.
54580      for (dimension_type
54581             i = num_lines_or_equalities + 1; i < dest_num_rows; ++i) {
54582        if (scalar_prod[i] != 0) {
54583          // The following fragment optimizes the computation of
54584          //
54585          // <CODE>
54586          //   Coefficient scale = scalar_prod[i];
54587          //   scale.gcd_assign(scalar_prod_nle);
54588          //   Coefficient normalized_sp_i = scalar_prod[i] / scale;
54589          //   Coefficient normalized_sp_n = scalar_prod_nle / scale;
54590          //   for (dimension_type c = dest_num_columns; c-- > 0; ) {
54591          //     dest[i][c] *= normalized_sp_n;
54592          //     dest[i][c] -= normalized_sp_i * dest_nle[c];
54593          //   }
54594          // </CODE>
54595          normalize2(scalar_prod[i],
54596                     scalar_prod_nle,
54597                     normalized_sp_i,
54598                     normalized_sp_o);
54599          dest_row_type& dest_i = dest.sys.rows[i];
54600          WEIGHT_BEGIN();
54601          neg_assign(normalized_sp_i);
54602          dest_i.expr.linear_combine(dest_nle.expr,
54603                                     normalized_sp_o, normalized_sp_i);
54604          dest_i.strong_normalize();
54605          // The modified row may still not be OK(), so don't assert OK here.
54606          // They are all checked at the end of this function.
54607          scalar_prod[i] = 0;
54608          // `dest_sorted' has already been set to false.
54609          WEIGHT_ADD_MUL(41, source_space_dim);
54610        }
54611        // Check if the client has requested abandoning all expensive
54612        // computations.  If so, the exception specified by the client
54613        // is thrown now.
54614        maybe_abandon();
54615      }
54616      // Since the `scalar_prod_nle' is positive (by construction), it
54617      // does not saturate the constraint `source_k'.  Therefore, if
54618      // the constraint is an inequality, we set to 1 the
54619      // corresponding element of `sat' ...
54620      Bit_Row& sat_nle = sat[num_lines_or_equalities];
54621      if (source_k.is_ray_or_point_or_inequality()) {
54622        sat_nle.set(k - redundant_source_rows.size());
54623#if PPL_QUICK_ADJ_TEST
54624        ++sat_num_ones[num_lines_or_equalities];
54625#endif // PPL_QUICK_ADJ_TEST
54626      }
54627      else {
54628        // ... otherwise, the constraint is an equality which is
54629        // violated by the generator `dest_nle': the generator has to be
54630        // removed from `dest_rows'.
54631        --dest_num_rows;
54632        swap(dest.sys.rows[num_lines_or_equalities],
54633             dest.sys.rows[dest_num_rows]);
54634        recyclable_dest_rows.resize(recyclable_dest_rows.size() + 1);
54635        swap(dest.sys.rows.back(), recyclable_dest_rows.back());
54636        dest.sys.rows.pop_back();
54637        PPL_ASSERT(dest_num_rows == dest.sys.rows.size());
54638
54639        swap(scalar_prod_nle, scalar_prod[dest_num_rows]);
54640        swap(sat_nle, sat[dest_num_rows]);
54641#if PPL_QUICK_ADJ_TEST
54642        swap(sat_num_ones[num_lines_or_equalities],
54643             sat_num_ones[dest_num_rows]);
54644#endif // PPL_QUICK_ADJ_TEST
54645        // dest_sorted has already been set to false.
54646      }
54647      // Finished handling the line or equality case:
54648      // continue with next `k'.
54649      continue;
54650    }
54651
54652    // Here all the lines in `dest_rows' saturate the constraint `source_k'.
54653    PPL_ASSERT(index_non_zero >= num_lines_or_equalities);
54654    // First, we reorder the generators in `dest_rows' as follows:
54655    // -# all the lines should have indexes between 0 and
54656    //    `num_lines_or_equalities' - 1 (this already holds);
54657    // -# all the rays that saturate the constraint should have
54658    //    indexes between `num_lines_or_equalities' and
54659    //    `lines_or_equal_bound' - 1; these rays form the set Q=.
54660    // -# all the rays that have a positive scalar product with the
54661    //    constraint should have indexes between `lines_or_equal_bound'
54662    //    and `sup_bound' - 1; these rays form the set Q+.
54663    // -# all the rays that have a negative scalar product with the
54664    //    constraint should have indexes between `sup_bound' and
54665    //    `dest_num_rows' - 1; these rays form the set Q-.
54666    dimension_type lines_or_equal_bound = num_lines_or_equalities;
54667    dimension_type inf_bound = dest_num_rows;
54668    // While we find saturating generators, we simply increment
54669    // `lines_or_equal_bound'.
54670    while (inf_bound > lines_or_equal_bound
54671           && scalar_prod[lines_or_equal_bound] == 0) {
54672      ++lines_or_equal_bound;
54673    }
54674    dimension_type sup_bound = lines_or_equal_bound;
54675    while (inf_bound > sup_bound) {
54676      const int sp_sign = sgn(scalar_prod[sup_bound]);
54677      if (sp_sign == 0) {
54678        // This generator has to be moved in Q=.
54679        swap(dest.sys.rows[sup_bound], dest.sys.rows[lines_or_equal_bound]);
54680        swap(scalar_prod[sup_bound], scalar_prod[lines_or_equal_bound]);
54681        swap(sat[sup_bound], sat[lines_or_equal_bound]);
54682#if PPL_QUICK_ADJ_TEST
54683        swap(sat_num_ones[sup_bound], sat_num_ones[lines_or_equal_bound]);
54684#endif // PPL_QUICK_ADJ_TEST
54685        ++lines_or_equal_bound;
54686        ++sup_bound;
54687        dest_sorted = false;
54688      }
54689      else if (sp_sign < 0) {
54690        // This generator has to be moved in Q-.
54691        --inf_bound;
54692        swap(dest.sys.rows[sup_bound], dest.sys.rows[inf_bound]);
54693        swap(sat[sup_bound], sat[inf_bound]);
54694        swap(scalar_prod[sup_bound], scalar_prod[inf_bound]);
54695#if PPL_QUICK_ADJ_TEST
54696        swap(sat_num_ones[sup_bound], sat_num_ones[inf_bound]);
54697#endif // PPL_QUICK_ADJ_TEST
54698        dest_sorted = false;
54699      }
54700      else {
54701        // sp_sign > 0: this generator has to be moved in Q+.
54702        ++sup_bound;
54703      }
54704    }
54705
54706    if (sup_bound == dest_num_rows) {
54707      // Here the set Q- is empty.
54708      // If the constraint is an inequality, then all the generators
54709      // in Q= and Q+ satisfy the constraint. The constraint is redundant
54710      // and it can be safely removed from the constraint system.
54711      // This is why the `source' parameter is not declared `const'.
54712      if (source_k.is_ray_or_point_or_inequality()) {
54713        redundant_source_rows.push_back(k);
54714      }
54715      else {
54716        // The constraint is an equality, so that all the generators
54717        // in Q+ violate it. Since the set Q- is empty, we can simply
54718        // remove from `dest_rows' all the generators of Q+.
54719        PPL_ASSERT(dest_num_rows >= lines_or_equal_bound);
54720        while (dest_num_rows != lines_or_equal_bound) {
54721          recyclable_dest_rows.resize(recyclable_dest_rows.size() + 1);
54722          swap(dest.sys.rows.back(), recyclable_dest_rows.back());
54723          dest.sys.rows.pop_back();
54724          --dest_num_rows;
54725          }
54726        PPL_ASSERT(dest_num_rows == dest.sys.rows.size());
54727      }
54728      // Finished handling the case when Q- is empty:
54729      // continue with next `k'.
54730      continue;
54731    }
54732
54733    // The set Q- is not empty, i.e., at least one generator
54734    // violates the constraint `source_k'.
54735    if (sup_bound == num_lines_or_equalities) {
54736      // The set Q+ is empty, so that all generators that satisfy
54737      // the constraint also saturate it.
54738      // We can simply remove from `dest_rows' all the generators in Q-.
54739      PPL_ASSERT(dest_num_rows >= sup_bound);
54740      while (dest_num_rows != sup_bound) {
54741        recyclable_dest_rows.resize(recyclable_dest_rows.size() + 1);
54742        swap(dest.sys.rows.back(), recyclable_dest_rows.back());
54743        dest.sys.rows.pop_back();
54744        --dest_num_rows;
54745      }
54746      PPL_ASSERT(dest_num_rows == dest.sys.rows.size());
54747      // Finished handling the case when Q+ is empty:
54748      // continue with next `k'.
54749      continue;
54750    }
54751
54752    // The sets Q+ and Q- are both non-empty.
54753    // The generators of the new pointed cone are all those satisfying
54754    // the constraint `source_k' plus a set of new rays enjoying
54755    // the following properties:
54756    // -# they lie on the hyper-plane represented by the constraint
54757    // -# they are obtained as a positive combination of two
54758    //    adjacent rays, the first taken from Q+ and the second
54759    //    taken from Q-.
54760
54761    const dimension_type bound = dest_num_rows;
54762
54763#if PPL_QUICK_NON_ADJ_TEST
54764    // For the quick non-adjacency test, we refer to the definition
54765    // of a minimal proper face (see comments in Polyhedron_defs.hh):
54766    // an extremal ray saturates at least `n' - `t' - 1 constraints,
54767    // where `n' is the dimension of the space and `t' is the dimension
54768    // of the lineality space. Since `n == source_num_columns - 1' and
54769    // `t == num_lines_or_equalities', we obtain that an extremal ray
54770    // saturates at least `source_num_columns - num_lines_or_equalities - 2'
54771    // constraints.
54772    const dimension_type min_saturators
54773      = source_num_columns - num_lines_or_equalities - 2;
54774    // NOTE: we are treating the `k'-th constraint.
54775    const dimension_type max_saturators = k - redundant_source_rows.size();
54776#endif // PPL_QUICK_NON_ADJ_TEST
54777
54778    // In the following loop,
54779    // `i' runs through the generators in the set Q+ and
54780    // `j' runs through the generators in the set Q-.
54781    for (dimension_type i = lines_or_equal_bound; i < sup_bound; ++i) {
54782      for (dimension_type j = sup_bound; j < bound; ++j) {
54783        // Checking if generators `dest_rows[i]' and `dest_rows[j]' are
54784        // adjacent.
54785        // If there exist another generator that saturates
54786        // all the constraints saturated by both `dest_rows[i]' and
54787        // `dest_rows[j]', then they are NOT adjacent.
54788        PPL_ASSERT(sat[i].last() == C_Integer<unsigned long>::max
54789                   || sat[i].last() < k);
54790        PPL_ASSERT(sat[j].last() == C_Integer<unsigned long>::max
54791                   || sat[j].last() < k);
54792
54793        // Being the union of `sat[i]' and `sat[j]',
54794        // `new_satrow' corresponds to a ray that saturates all the
54795        // constraints saturated by both `dest_rows[i]' and
54796        // `dest_rows[j]'.
54797        Bit_Row new_satrow(sat[i], sat[j]);
54798
54799        // Even before actually creating the new ray as a
54800        // positive combination of `dest_rows[i]' and `dest_rows[j]',
54801        // we exploit saturation information to perform:
54802        //  - a quick non-adjacency test;
54803        //  - a quick adjacency test.
54804
54805#if (PPL_QUICK_NON_ADJ_TEST || PPL_QUICK_ADJ_TEST)
54806        // Compute the number of common saturators.
54807        dimension_type new_satrow_ones = new_satrow.count_ones();
54808#endif // (PPL_QUICK_NON_ADJ_TEST || PPL_QUICK_ADJ_TEST)
54809
54810#if PPL_QUICK_NON_ADJ_TEST
54811        const dimension_type num_common_satur
54812          = max_saturators - new_satrow_ones;
54813        if (num_common_satur < min_saturators) {
54814          // Quick non-adjacency test succeded: consider next `j'.
54815          continue;
54816        }
54817#endif // PPL_QUICK_NON_ADJ_TEST
54818
54819#if PPL_QUICK_ADJ_TEST
54820        // If either `sat[i]' or `sat[j]' has exactly one more zeroes
54821        // than `new_satrow', then `dest_rows[i]' and `dest_rows[j]'
54822        // are adjacent. Equivalently, adjacency holds if `new_satrow_ones'
54823        // is equal to 1 plus the maximum of `sat_num_ones[i]' and
54824        // `sat_num_ones[j]'.
54825        const dimension_type max_ones_i_j
54826          = std::max(sat_num_ones[i], sat_num_ones[j]);
54827        if (max_ones_i_j + 1 == new_satrow_ones) {
54828          // Quick adjacency test succeded: skip the full test.
54829          goto are_adjacent;
54830        }
54831#endif // PPL_QUICK_ADJ_TEST
54832
54833        // Perform the full (combinatorial) adjacency test.
54834        {
54835          bool redundant = false;
54836          WEIGHT_BEGIN();
54837          for (dimension_type l = num_lines_or_equalities; l < bound; ++l) {
54838            if (l != i && l != j
54839                && subset_or_equal(sat[l], new_satrow)) {
54840              // Found another generator saturating all the constraints
54841              // saturated by both `dest_rows[i]' and `dest_rows[j]'.
54842              redundant = true;
54843              break;
54844            }
54845          }
54846          PPL_ASSERT(bound >= num_lines_or_equalities);
54847          WEIGHT_ADD_MUL(15, bound - num_lines_or_equalities);
54848          if (redundant) {
54849            // Full non-adjacency test succeded: consider next `j'.
54850            continue;
54851          }
54852        }
54853
54854#if PPL_QUICK_ADJ_TEST
54855      are_adjacent:
54856#endif // PPL_QUICK_ADJ_TEST
54857        // Adding the new ray to `dest_rows' and the corresponding
54858        // saturation row to `sat'.
54859        dest_row_type new_row;
54860        if (recyclable_dest_rows.empty()) {
54861          sat.add_recycled_row(new_satrow);
54862#if PPL_QUICK_ADJ_TEST
54863          sat_num_ones.push_back(new_satrow_ones);
54864#endif // PPL_QUICK_ADJ_TEST
54865        }
54866        else {
54867          swap(new_row, recyclable_dest_rows.back());
54868          recyclable_dest_rows.pop_back();
54869          new_row.set_space_dimension_no_ok(source_space_dim);
54870          swap(sat[dest_num_rows], new_satrow);
54871#if PPL_QUICK_ADJ_TEST
54872          swap(sat_num_ones[dest_num_rows], new_satrow_ones);
54873#endif // PPL_QUICK_ADJ_TEST
54874        }
54875
54876        // The following fragment optimizes the computation of
54877        //
54878        // <CODE>
54879        //   Coefficient scale = scalar_prod[i];
54880        //   scale.gcd_assign(scalar_prod[j]);
54881        //   Coefficient normalized_sp_i = scalar_prod[i] / scale;
54882        //   Coefficient normalized_sp_j = scalar_prod[j] / scale;
54883        //   for (dimension_type c = dest_num_columns; c-- > 0; ) {
54884        //     new_row[c] = normalized_sp_i * dest[j][c];
54885        //     new_row[c] -= normalized_sp_j * dest[i][c];
54886        //   }
54887        // </CODE>
54888        normalize2(scalar_prod[i],
54889                   scalar_prod[j],
54890                   normalized_sp_i,
54891                   normalized_sp_o);
54892        WEIGHT_BEGIN();
54893
54894        neg_assign(normalized_sp_o);
54895        new_row = dest.sys.rows[j];
54896        // TODO: Check if the following assertions hold.
54897        PPL_ASSERT(normalized_sp_i != 0);
54898        PPL_ASSERT(normalized_sp_o != 0);
54899        new_row.expr.linear_combine(dest.sys.rows[i].expr,
54900                                    normalized_sp_i, normalized_sp_o);
54901
54902        WEIGHT_ADD_MUL(86, source_space_dim);
54903        new_row.strong_normalize();
54904        // Don't assert new_row.OK() here, because it may fail if
54905        // the parameter `dest' contained a row that wasn't ok.
54906        // Since we added a new generator to `dest_rows',
54907        // we also add a new element to `scalar_prod';
54908        // by construction, the new ray lies on the hyper-plane
54909        // represented by the constraint `source_k'.
54910        // Thus, the added scalar product is 0.
54911        PPL_ASSERT(scalar_prod.size() >= dest_num_rows);
54912        if (scalar_prod.size() <= dest_num_rows) {
54913          scalar_prod.push_back(Coefficient_zero());
54914        }
54915        else {
54916          scalar_prod[dest_num_rows] = Coefficient_zero();
54917        }
54918        dest.sys.rows.resize(dest.sys.rows.size() + 1);
54919        swap(dest.sys.rows.back(), new_row);
54920        // Increment the number of generators.
54921        ++dest_num_rows;
54922      } // End of loop on `j'.
54923      // Check if the client has requested abandoning all expensive
54924      // computations.  If so, the exception specified by the client
54925      // is thrown now.
54926      maybe_abandon();
54927    } // End of loop on `i'.
54928    // Now we substitute the rays in Q- (i.e., the rays violating
54929    // the constraint) with the newly added rays.
54930    dimension_type j;
54931    if (source_k.is_ray_or_point_or_inequality()) {
54932      // The constraint is an inequality:
54933      // the violating generators are those in Q-.
54934      j = sup_bound;
54935      // For all the generators in Q+, set to 1 the corresponding
54936      // entry for the constraint `source_k' in the saturation matrix.
54937
54938      // After the removal of redundant rows in `source', the k-th
54939      // row will have index `new_k'.
54940      const dimension_type new_k = k - redundant_source_rows.size();
54941      for (dimension_type l = lines_or_equal_bound;
54942           l < sup_bound; ++l) {
54943        sat[l].set(new_k);
54944#if PPL_QUICK_ADJ_TEST
54945        ++sat_num_ones[l];
54946#endif // PPL_PPL_QUICK_ADJ_TEST
54947      }
54948    }
54949    else {
54950      // The constraint is an equality:
54951      // the violating generators are those in the union of Q+ and Q-.
54952      j = lines_or_equal_bound;
54953    }
54954    // Swapping the newly added rays
54955    // (index `i' running through `dest_num_rows - 1' down-to `bound')
54956    // with the generators violating the constraint
54957    // (index `j' running through `j' up-to `bound - 1').
54958    dimension_type i = dest_num_rows;
54959    while (j < bound && i > bound) {
54960      --i;
54961      swap(dest.sys.rows[i], dest.sys.rows[j]);
54962      swap(scalar_prod[i], scalar_prod[j]);
54963      swap(sat[i], sat[j]);
54964#if PPL_QUICK_ADJ_TEST
54965      swap(sat_num_ones[i], sat_num_ones[j]);
54966#endif // PPL_QUICK_ADJ_TEST
54967      ++j;
54968      dest_sorted = false;
54969    }
54970    // Setting the number of generators in `dest':
54971    // - if the number of generators violating the constraint
54972    //   is less than or equal to the number of the newly added
54973    //   generators, we assign `i' to `dest_num_rows' because
54974    //   all generators above this index are significant;
54975    // - otherwise, we assign `j' to `dest_num_rows' because
54976    //   all generators below index `j-1' violates the constraint.
54977    const dimension_type new_num_rows = (j == bound) ? i : j;
54978    PPL_ASSERT(dest_num_rows >= new_num_rows);
54979    while (dest_num_rows != new_num_rows) {
54980      recyclable_dest_rows.resize(recyclable_dest_rows.size() + 1);
54981      swap(dest.sys.rows.back(), recyclable_dest_rows.back());
54982      dest.sys.rows.pop_back();
54983      --dest_num_rows;
54984    }
54985    PPL_ASSERT(dest_num_rows == dest.sys.rows.size());
54986  } // End of loop on `k'.
54987
54988  // We may have identified some redundant constraints in `source',
54989  // which have been swapped at the end of the system.
54990  if (redundant_source_rows.size() > 0) {
54991    source.remove_rows(redundant_source_rows);
54992    sat.remove_trailing_columns(redundant_source_rows.size());
54993  }
54994
54995  // If `start == 0', then `source' was sorted and remained so.
54996  // If otherwise `start > 0', then the two sub-system made by the
54997  // non-pending rows and the pending rows, respectively, were both sorted.
54998  // Thus, the overall system is sorted if and only if either
54999  // `start == source_num_rows' (i.e., the second sub-system is empty)
55000  // or the row ordering holds for the two rows at the boundary between
55001  // the two sub-systems.
55002  if (start > 0 && start < source.num_rows()) {
55003    source.set_sorted(compare(source[start - 1], source[start]) <= 0);
55004  }
55005  // There are no longer pending constraints in `source'.
55006  source.unset_pending_rows();
55007
55008  // We may have identified some redundant rays in `dest_rows',
55009  // which have been swapped into recyclable_dest_rows.
55010  if (!recyclable_dest_rows.empty()) {
55011    const dimension_type num_removed_rows = recyclable_dest_rows.size();
55012    sat.remove_trailing_rows(num_removed_rows);
55013  }
55014  if (dest_sorted) {
55015    // If the non-pending generators in `dest' are still declared to be
55016    // sorted, then we have to also check for the sortedness of the
55017    // pending generators.
55018    for (dimension_type i = dest_first_pending_row;
55019         i < dest_num_rows; ++i) {
55020      if (compare(dest.sys.rows[i - 1], dest.sys.rows[i]) > 0) {
55021        dest_sorted = false;
55022        break;
55023      }
55024    }
55025  }
55026#ifndef NDEBUG
55027  // The previous code can modify the rows' fields, exploiting the friendness.
55028  // Check that all rows are OK now.
55029  for (dimension_type i = dest.num_rows(); i-- > 0; ) {
55030    PPL_ASSERT(dest.sys.rows[i].OK());
55031  }
55032#endif
55033
55034  dest.sys.index_first_pending = dest.num_rows();
55035  dest.set_sorted(dest_sorted);
55036  PPL_ASSERT(dest.sys.OK());
55037
55038  return num_lines_or_equalities;
55039}
55040
55041} // namespace Parma_Polyhedra_Library
55042
55043/* Automatically generated from PPL source file ../src/Polyhedron_minimize_templates.hh line 1. */
55044/* Polyhedron class implementation: minimize() and add_and_minimize().
55045*/
55046
55047
55048/* Automatically generated from PPL source file ../src/Polyhedron_minimize_templates.hh line 29. */
55049#include <stdexcept>
55050
55051namespace Parma_Polyhedra_Library {
55052
55053/*!
55054  \return
55055  <CODE>true</CODE> if the polyhedron is empty, <CODE>false</CODE>
55056  otherwise.
55057
55058  \param con_to_gen
55059  <CODE>true</CODE> if \p source represents the constraints,
55060  <CODE>false</CODE> otherwise;
55061
55062  \param source
55063  The given system, which is not empty;
55064
55065  \param dest
55066  The system to build and minimize;
55067
55068  \param sat
55069  The saturation matrix.
55070
55071  \p dest is not <CODE>const</CODE> because it will be built (and then
55072  modified) during minimize(). Also, \p sat and \p source are
55073  not <CODE>const</CODE> because the former will be built during
55074  \p dest creation and the latter will maybe be sorted and modified by
55075  <CODE>conversion()</CODE> and <CODE>simplify()</CODE>.
55076
55077  \p sat has the generators on its columns and the constraints on its rows
55078  if \p con_to_gen is <CODE>true</CODE>, otherwise it has the generators on
55079  its rows and the constraints on its columns.
55080
55081  Given \p source, this function builds (by means of
55082  <CODE>conversion()</CODE>) \p dest and then simplifies (invoking
55083  <CODE>simplify()</CODE>) \p source, erasing redundant rows.
55084  For the sequel we assume that \p source is the system of constraints
55085  and \p dest is the system of generators.
55086  This will simplify the description of the function; the dual case is
55087  similar.
55088*/
55089template <typename Source_Linear_System, typename Dest_Linear_System>
55090bool
55091Polyhedron::minimize(const bool con_to_gen,
55092                     Source_Linear_System& source,
55093                     Dest_Linear_System& dest,
55094                     Bit_Matrix& sat) {
55095
55096  typedef typename Dest_Linear_System::row_type dest_row_type;
55097
55098  // Topologies have to agree.
55099  PPL_ASSERT(source.topology() == dest.topology());
55100  // `source' cannot be empty: even if it is an empty constraint system,
55101  // representing the universe polyhedron, homogenization has added
55102  // the positive constraint. It also cannot be an empty generator system,
55103  // since this function is always called starting from a non-empty
55104  // polyhedron.
55105  PPL_ASSERT(!source.has_no_rows());
55106
55107  // Sort the source system, if necessary.
55108  if (!source.is_sorted()) {
55109    source.sort_rows();
55110  }
55111  // Initialization of the system of generators `dest'.
55112  // The algorithm works incrementally and we haven't seen any
55113  // constraint yet: as a consequence, `dest' should describe
55114  // the universe polyhedron of the appropriate dimension.
55115  // To this end, we initialize it to the identity matrix of dimension
55116  // `source.num_columns()': the rows represent the lines corresponding
55117  // to the canonical basis of the vector space.
55118  dimension_type dest_num_rows
55119    = source.topology() == NECESSARILY_CLOSED ? source.space_dimension() + 1
55120                                              : source.space_dimension() + 2;
55121
55122  dest.clear();
55123  dest.set_space_dimension(source.space_dimension());
55124
55125  // Initialize `dest' to the identity matrix.
55126  for (dimension_type i = 0; i < dest_num_rows; ++i) {
55127    Linear_Expression expr;
55128    expr.set_space_dimension(dest_num_rows - 1);
55129    if (i == 0) {
55130      expr += 1;
55131    }
55132    else {
55133      expr += Variable(i - 1);
55134    }
55135    dest_row_type dest_i(expr, dest_row_type::LINE_OR_EQUALITY, NECESSARILY_CLOSED);
55136    if (dest.topology() == NOT_NECESSARILY_CLOSED) {
55137      dest_i.mark_as_not_necessarily_closed();
55138    }
55139    dest.sys.insert_no_ok(dest_i, Recycle_Input());
55140  }
55141  // The identity matrix `dest' is not sorted (see the sorting rules
55142  // in Constrant.cc and Generator.cc).
55143  dest.set_sorted(false);
55144
55145  // NOTE: the system `dest', as it is now, is not a _legal_ system of
55146  //       generators, because in the first row we have a line with a
55147  //       non-zero divisor (which should only happen for
55148  //       points). However, this is NOT a problem, because `source'
55149  //       necessarily contains the positivity constraint (or a
55150  //       combination of it with another constraint) which will
55151  //       restore things as they should be.
55152
55153
55154  // Building a saturation matrix and initializing it by setting
55155  // all of its elements to zero. This matrix will be modified together
55156  // with `dest' during the conversion.
55157  // NOTE: since we haven't seen any constraint yet, the relevant
55158  //       portion of `tmp_sat' is the sub-matrix consisting of
55159  //       the first 0 columns: thus the relevant portion correctly
55160  //       characterizes the initial saturation information.
55161  Bit_Matrix tmp_sat(dest_num_rows, source.num_rows());
55162
55163  // By invoking the function conversion(), we populate `dest' with
55164  // the generators characterizing the polyhedron described by all
55165  // the constraints in `source'.
55166  // The `start' parameter is zero (we haven't seen any constraint yet)
55167  // and the 5th parameter (representing the number of lines in `dest'),
55168  // by construction, is equal to `dest_num_rows'.
55169  const dimension_type num_lines_or_equalities
55170    = conversion(source, 0U, dest, tmp_sat, dest_num_rows);
55171  // conversion() may have modified the number of rows in `dest'.
55172  dest_num_rows = dest.num_rows();
55173
55174#ifndef NDEBUG
55175  for (dimension_type i = dest.num_rows(); i-- > 0; ) {
55176    PPL_ASSERT(dest[i].OK());
55177  }
55178#endif
55179
55180  // Checking if the generators in `dest' represent an empty polyhedron:
55181  // the polyhedron is empty if there are no points
55182  // (because rays, lines and closure points need a supporting point).
55183  // Points can be detected by looking at:
55184  // - the divisor, for necessarily closed polyhedra;
55185  // - the epsilon coordinate, for NNC polyhedra.
55186  dimension_type first_point;
55187  if (dest.is_necessarily_closed()) {
55188    for (first_point = num_lines_or_equalities;
55189        first_point < dest_num_rows;
55190        ++first_point) {
55191      if (dest[first_point].expr.inhomogeneous_term() > 0) {
55192        break;
55193      }
55194    }
55195  }
55196  else {
55197    for (first_point = num_lines_or_equalities;
55198        first_point < dest_num_rows;
55199        ++first_point) {
55200      if (dest[first_point].expr.get(Variable(dest.space_dimension())) > 0) {
55201        break;
55202      }
55203    }
55204  }
55205
55206  if (first_point == dest_num_rows) {
55207    if (con_to_gen) {
55208      // No point has been found: the polyhedron is empty.
55209      return true;
55210    }
55211    else {
55212      // Here `con_to_gen' is false: `dest' is a system of constraints.
55213      // In this case the condition `first_point == dest_num_rows'
55214      // actually means that all the constraints in `dest' have their
55215      // inhomogeneous term equal to 0.
55216      // This is an ILLEGAL situation, because it implies that
55217      // the constraint system `dest' lacks the positivity constraint
55218      // and no linear combination of the constraints in `dest'
55219      // can reintroduce the positivity constraint.
55220      PPL_UNREACHABLE;
55221      return false;
55222    }
55223  }
55224  else {
55225    // A point has been found: the polyhedron is not empty.
55226    // Now invoking simplify() to remove all the redundant constraints
55227    // from the system `source'.
55228    // Since the saturation matrix `tmp_sat' returned by conversion()
55229    // has rows indexed by generators (the rows of `dest') and columns
55230    // indexed by constraints (the rows of `source'), we have to
55231    // transpose it to obtain the saturation matrix needed by simplify().
55232    sat.transpose_assign(tmp_sat);
55233    simplify(source, sat);
55234    return false;
55235  }
55236}
55237
55238
55239/*!
55240  \return
55241  <CODE>true</CODE> if the obtained polyhedron is empty,
55242  <CODE>false</CODE> otherwise.
55243
55244  \param con_to_gen
55245  <CODE>true</CODE> if \p source1 and \p source2 are system of
55246  constraints, <CODE>false</CODE> otherwise;
55247
55248  \param source1
55249  The first element of the given DD pair;
55250
55251  \param dest
55252  The second element of the given DD pair;
55253
55254  \param sat
55255  The saturation matrix that bind \p source1 to \p dest;
55256
55257  \param source2
55258  The new system of generators or constraints.
55259
55260  It is assumed that \p source1 and \p source2 are sorted and have
55261  no pending rows. It is also assumed that \p dest has no pending rows.
55262  On entry, the rows of \p sat are indexed by the rows of \p dest
55263  and its columns are indexed by the rows of \p source1.
55264  On exit, the rows of \p sat are indexed by the rows of \p dest
55265  and its columns are indexed by the rows of the system obtained
55266  by merging \p source1 and \p source2.
55267
55268  Let us suppose we want to add some constraints to a given system of
55269  constraints \p source1. This method, given a minimized double description
55270  pair (\p source1, \p dest) and a system of new constraints \p source2,
55271  modifies \p source1 by adding to it the constraints of \p source2 that
55272  are not in \p source1. Then, by invoking
55273  <CODE>add_and_minimize(bool, Linear_System_Class&, Linear_System_Class&, Bit_Matrix&)</CODE>,
55274  processes the added constraints obtaining a new DD pair.
55275
55276  This method treats also the dual case, i.e., adding new generators to
55277  a previous system of generators. In this case \p source1 contains the
55278  old generators, \p source2 the new ones and \p dest is the system
55279  of constraints in the given minimized DD pair.
55280
55281  Since \p source2 contains the constraints (or the generators) that
55282  will be added to \p source1, it is constant: it will not be modified.
55283*/
55284template <typename Source_Linear_System1, typename Source_Linear_System2,
55285          typename Dest_Linear_System>
55286bool
55287Polyhedron::add_and_minimize(const bool con_to_gen,
55288                             Source_Linear_System1& source1,
55289                             Dest_Linear_System& dest,
55290                             Bit_Matrix& sat,
55291                             const Source_Linear_System2& source2) {
55292  // `source1' and `source2' cannot be empty.
55293  PPL_ASSERT(!source1.has_no_rows() && !source2.has_no_rows());
55294  // `source1' and `source2' must have the same number of columns
55295  // to be merged.
55296  PPL_ASSERT(source1.num_columns() == source2.num_columns());
55297  // `source1' and `source2' are fully sorted.
55298  PPL_ASSERT(source1.is_sorted() && source1.num_pending_rows() == 0);
55299  PPL_ASSERT(source2.is_sorted() && source2.num_pending_rows() == 0);
55300  PPL_ASSERT(dest.num_pending_rows() == 0);
55301
55302  const dimension_type old_source1_num_rows = source1.num_rows();
55303  // `k1' and `k2' run through the rows of `source1' and `source2', resp.
55304  dimension_type k1 = 0;
55305  dimension_type k2 = 0;
55306  dimension_type source2_num_rows = source2.num_rows();
55307  while (k1 < old_source1_num_rows && k2 < source2_num_rows) {
55308    // Add to `source1' the constraints from `source2', as pending rows.
55309    // We exploit the property that initially both `source1' and `source2'
55310    // are sorted and index `k1' only scans the non-pending rows of `source1',
55311    // so that it is not influenced by the pending rows appended to it.
55312    // This way no duplicate (i.e., trivially redundant) constraint
55313    // is introduced in `source1'.
55314    const int cmp = compare(source1[k1], source2[k2]);
55315    if (cmp == 0) {
55316      // We found the same row: there is no need to add `source2[k2]'.
55317      ++k2;
55318      // By sortedness, since `k1 < old_source1_num_rows',
55319      // we can increment index `k1' too.
55320      ++k1;
55321    }
55322    else if (cmp < 0) {
55323      // By sortedness, we can increment `k1'.
55324      ++k1;
55325    }
55326    else {
55327      // Here `cmp > 0'.
55328      // By sortedness, `source2[k2]' cannot be in `source1'.
55329      // We add it as a pending row of `source1' (sortedness unaffected).
55330      source1.add_pending_row(source2[k2]);
55331      // We can increment `k2'.
55332      ++k2;
55333    }
55334  }
55335  // Have we scanned all the rows in `source2'?
55336  if (k2 < source2_num_rows) {
55337    // By sortedness, all the rows in `source2' having indexes
55338    // greater than or equal to `k2' were not in `source1'.
55339    // We add them as pending rows of 'source1' (sortedness not affected).
55340    for ( ; k2 < source2_num_rows; ++k2) {
55341      source1.add_pending_row(source2[k2]);
55342    }
55343  }
55344
55345  if (source1.num_pending_rows() == 0) {
55346    // No row was appended to `source1', because all the constraints
55347    // in `source2' were already in `source1'.
55348    // There is nothing left to do ...
55349    return false;
55350  }
55351  return add_and_minimize(con_to_gen, source1, dest, sat);
55352}
55353
55354/*!
55355  \return
55356  <CODE>true</CODE> if the obtained polyhedron is empty,
55357  <CODE>false</CODE> otherwise.
55358
55359  \param con_to_gen
55360  <CODE>true</CODE> if \p source is a system of constraints,
55361  <CODE>false</CODE> otherwise;
55362
55363  \param source
55364  The first element of the given DD pair. It also contains the pending
55365  rows to be processed;
55366
55367  \param dest
55368  The second element of the given DD pair. It cannot have pending rows;
55369
55370  \param sat
55371  The saturation matrix that bind the upper part of \p source to \p dest.
55372
55373  On entry, the rows of \p sat are indexed by the rows of \p dest
55374  and its columns are indexed by the non-pending rows of \p source.
55375  On exit, the rows of \p sat are indexed by the rows of \p dest
55376  and its columns are indexed by the rows of \p source.
55377
55378  Let us suppose that \p source is a system of constraints.
55379  This method assumes that the non-pending part of \p source and
55380  system \p dest form a double description pair in minimal form and
55381  will build a new DD pair in minimal form by processing the pending
55382  constraints in \p source. To this end, it will call
55383  <CODE>conversion()</CODE>) and <CODE>simplify</CODE>.
55384
55385  This method treats also the dual case, i.e., processing pending
55386  generators. In this case \p source contains generators and \p dest
55387  is the system of constraints corresponding to the non-pending part
55388  of \p source.
55389*/
55390template <typename Source_Linear_System, typename Dest_Linear_System>
55391bool
55392Polyhedron::add_and_minimize(const bool con_to_gen,
55393                             Source_Linear_System& source,
55394                             Dest_Linear_System& dest,
55395                             Bit_Matrix& sat) {
55396  PPL_ASSERT(source.num_pending_rows() > 0);
55397  PPL_ASSERT(source.space_dimension() == dest.space_dimension());
55398  PPL_ASSERT(source.is_sorted());
55399
55400  // First, pad the saturation matrix with new columns (of zeroes)
55401  // to accommodate for the pending rows of `source'.
55402  sat.resize(dest.num_rows(), source.num_rows());
55403
55404  // Incrementally compute the new system of generators.
55405  // Parameter `start' is set to the index of the first pending constraint.
55406  const dimension_type num_lines_or_equalities
55407    = conversion(source, source.first_pending_row(),
55408                 dest, sat,
55409                 dest.num_lines_or_equalities());
55410
55411  // conversion() may have modified the number of rows in `dest'.
55412  const dimension_type dest_num_rows = dest.num_rows();
55413
55414  // Checking if the generators in `dest' represent an empty polyhedron:
55415  // the polyhedron is empty if there are no points
55416  // (because rays, lines and closure points need a supporting point).
55417  // Points can be detected by looking at:
55418  // - the divisor, for necessarily closed polyhedra;
55419  // - the epsilon coordinate, for NNC polyhedra.
55420  dimension_type first_point;
55421  if (dest.is_necessarily_closed()) {
55422    for (first_point = num_lines_or_equalities;
55423        first_point < dest_num_rows;
55424        ++first_point) {
55425      if (dest[first_point].expr.inhomogeneous_term() > 0) {
55426        break;
55427      }
55428    }
55429  }
55430  else {
55431    for (first_point = num_lines_or_equalities;
55432        first_point < dest_num_rows;
55433        ++first_point) {
55434      if (dest[first_point].expr.get(Variable(dest.space_dimension())) > 0) {
55435        break;
55436      }
55437    }
55438  }
55439
55440  if (first_point == dest_num_rows) {
55441    if (con_to_gen) {
55442      // No point has been found: the polyhedron is empty.
55443      return true;
55444    }
55445    else {
55446      // Here `con_to_gen' is false: `dest' is a system of constraints.
55447      // In this case the condition `first_point == dest_num_rows'
55448      // actually means that all the constraints in `dest' have their
55449      // inhomogeneous term equal to 0.
55450      // This is an ILLEGAL situation, because it implies that
55451      // the constraint system `dest' lacks the positivity constraint
55452      // and no linear combination of the constraints in `dest'
55453      // can reintroduce the positivity constraint.
55454      PPL_UNREACHABLE;
55455      return false;
55456    }
55457  }
55458  else {
55459    // A point has been found: the polyhedron is not empty.
55460    // Now invoking `simplify()' to remove all the redundant constraints
55461    // from the system `source'.
55462    // Since the saturation matrix `sat' returned by `conversion()'
55463    // has rows indexed by generators (the rows of `dest') and columns
55464    // indexed by constraints (the rows of `source'), we have to
55465    // transpose it to obtain the saturation matrix needed by `simplify()'.
55466    sat.transpose();
55467    simplify(source, sat);
55468    // Transposing back.
55469    sat.transpose();
55470    return false;
55471  }
55472}
55473
55474} // namespace Parma_Polyhedra_Library
55475
55476/* Automatically generated from PPL source file ../src/Polyhedron_simplify_templates.hh line 1. */
55477/* Polyhedron class implementation: simplify().
55478*/
55479
55480
55481/* Automatically generated from PPL source file ../src/Polyhedron_simplify_templates.hh line 29. */
55482#include <cstddef>
55483#include <limits>
55484
55485namespace Parma_Polyhedra_Library {
55486
55487/*!
55488  \return
55489  The rank of \p sys.
55490
55491  \param sys
55492  The system to simplify: it will be modified;
55493
55494  \param sat
55495  The saturation matrix corresponding to \p sys.
55496
55497  \p sys may be modified by swapping some of its rows and by possibly
55498  removing some of them, if they turn out to be redundant.
55499
55500  If \p sys is a system of constraints, then the rows of \p sat are
55501  indexed by constraints and its columns are indexed by generators;
55502  otherwise, if \p sys is a system of generators, then the rows of
55503  \p sat are indexed by generators and its columns by constraints.
55504
55505  Given a system of constraints or a system of generators, this function
55506  simplifies it using Gauss' elimination method (to remove redundant
55507  equalities/lines), deleting redundant inequalities/rays/points and
55508  making back-substitution.
55509  The explanation that follows assumes that \p sys is a system of
55510  constraints. For the case when \p sys is a system of generators,
55511  a similar explanation can be obtain by applying duality.
55512
55513  The explanation relies on the notion of <EM>redundancy</EM>.
55514  (See the Introduction.)
55515
55516  First we make some observations that can help the reader
55517  in understanding the function:
55518
55519  Proposition: An inequality that is saturated by all the generators
55520  can be transformed to an equality.
55521
55522  In fact, by combining any number of generators that saturate the
55523  constraints, we obtain a generator that saturates the constraints too:
55524  \f[
55525    \langle \vect{c}, \vect{r}_1 \rangle = 0 \land
55526    \langle \vect{c}, \vect{r}_2 \rangle = 0
55527    \Rightarrow
55528    \langle \vect{c}, (\lambda_1 \vect{r}_1 + \lambda_2 \vect{r}_2) \rangle =
55529    \lambda_1 \langle \vect{c}, \vect{r}_1 \rangle
55530    + \lambda_2 \langle \vect{c}, \vect{r}_2 \rangle
55531    = 0,
55532  \f]
55533  where \f$\lambda_1, \lambda_2\f$ can be any real number.
55534*/
55535template <typename Linear_System1>
55536dimension_type
55537Polyhedron::simplify(Linear_System1& sys, Bit_Matrix& sat) {
55538  dimension_type num_rows = sys.num_rows();
55539  const dimension_type num_cols_sat = sat.num_columns();
55540
55541  using std::swap;
55542
55543  // Looking for the first inequality in `sys'.
55544  dimension_type num_lines_or_equalities = 0;
55545  while (num_lines_or_equalities < num_rows
55546         && sys[num_lines_or_equalities].is_line_or_equality()) {
55547    ++num_lines_or_equalities;
55548  }
55549
55550  // `num_saturators[i]' will contain the number of generators
55551  // that saturate the constraint `sys[i]'.
55552  if (num_rows > simplify_num_saturators_size) {
55553    delete [] simplify_num_saturators_p;
55554    simplify_num_saturators_p = 0;
55555    simplify_num_saturators_size = 0;
55556    const size_t max_size
55557      = std::numeric_limits<size_t>::max() / sizeof(dimension_type);
55558    const size_t new_size = compute_capacity(num_rows, max_size);
55559    simplify_num_saturators_p = new dimension_type[new_size];
55560    simplify_num_saturators_size = new_size;
55561  }
55562  dimension_type* const num_saturators = simplify_num_saturators_p;
55563
55564  bool sys_sorted = sys.is_sorted();
55565
55566  // Computing the number of saturators for each inequality,
55567  // possibly identifying and swapping those that happen to be
55568  // equalities (see Proposition above).
55569  for (dimension_type i = num_lines_or_equalities; i < num_rows; ++i) {
55570    if (sat[i].empty()) {
55571      // The constraint `sys_rows[i]' is saturated by all the generators.
55572      // Thus, either it is already an equality or it can be transformed
55573      // to an equality (see Proposition above).
55574      sys.sys.rows[i].set_is_line_or_equality();
55575      // Note: simple normalization already holds.
55576      sys.sys.rows[i].sign_normalize();
55577      // We also move it just after all the other equalities,
55578      // so that system `sys_rows' keeps its partial sortedness.
55579      if (i != num_lines_or_equalities) {
55580        sys.sys.rows[i].m_swap(sys.sys.rows[num_lines_or_equalities]);
55581        swap(sat[i], sat[num_lines_or_equalities]);
55582        swap(num_saturators[i], num_saturators[num_lines_or_equalities]);
55583      }
55584      ++num_lines_or_equalities;
55585      // `sys' is no longer sorted.
55586      sys_sorted = false;
55587    }
55588    else {
55589      // There exists a generator which does not saturate `sys[i]',
55590      // so that `sys[i]' is indeed an inequality.
55591      // We store the number of its saturators.
55592      num_saturators[i] = num_cols_sat - sat[i].count_ones();
55593    }
55594  }
55595
55596  sys.set_sorted(sys_sorted);
55597  PPL_ASSERT(sys.OK());
55598
55599  // At this point, all the equalities of `sys' (included those
55600  // inequalities that we just transformed to equalities) have
55601  // indexes between 0 and `num_lines_or_equalities' - 1,
55602  // which is the property needed by method gauss().
55603  // We can simplify the system of equalities, obtaining the rank
55604  // of `sys' as result.
55605  const dimension_type rank = sys.gauss(num_lines_or_equalities);
55606
55607  // Now the irredundant equalities of `sys' have indexes from 0
55608  // to `rank' - 1, whereas the equalities having indexes from `rank'
55609  // to `num_lines_or_equalities' - 1 are all redundant.
55610  // (The inequalities in `sys' have been left untouched.)
55611  // The rows containing equalities are not sorted.
55612
55613  if (rank < num_lines_or_equalities) {
55614    // We identified some redundant equalities.
55615    // Moving them at the bottom of `sys':
55616    // - index `redundant' runs through the redundant equalities
55617    // - index `erasing' identifies the first row that should
55618    //   be erased after this loop.
55619    // Note that we exit the loop either because we have removed all
55620    // redundant equalities or because we have moved all the
55621    // inequalities.
55622    for (dimension_type redundant = rank,
55623           erasing = num_rows;
55624         redundant < num_lines_or_equalities
55625           && erasing > num_lines_or_equalities;
55626         ) {
55627      --erasing;
55628      sys.remove_row(redundant);
55629      swap(sat[redundant], sat[erasing]);
55630      swap(num_saturators[redundant], num_saturators[erasing]);
55631      ++redundant;
55632    }
55633    // Adjusting the value of `num_rows' to the number of meaningful
55634    // rows of `sys': `num_lines_or_equalities' - `rank' is the number of
55635    // redundant equalities moved to the bottom of `sys', which are
55636    // no longer meaningful.
55637    num_rows -= num_lines_or_equalities - rank;
55638
55639    // If the above loop exited because it moved all inequalities, it may not
55640    // have removed all the rendundant rows.
55641    sys.remove_trailing_rows(sys.num_rows() - num_rows);
55642
55643    PPL_ASSERT(sys.num_rows() == num_rows);
55644
55645    sat.remove_trailing_rows(num_lines_or_equalities - rank);
55646
55647    // Adjusting the value of `num_lines_or_equalities'.
55648    num_lines_or_equalities = rank;
55649  }
55650
55651  const dimension_type old_num_rows = sys.num_rows();
55652
55653  // Now we use the definition of redundancy (given in the Introduction)
55654  // to remove redundant inequalities.
55655
55656  // First we check the saturation rule, which provides a necessary
55657  // condition for an inequality to be irredundant (i.e., it provides
55658  // a sufficient condition for identifying redundant inequalities).
55659  // Let
55660  //
55661  //   num_saturators[i] = num_sat_lines[i] + num_sat_rays_or_points[i],
55662  //   dim_lin_space = num_irredundant_lines,
55663  //   dim_ray_space
55664  //     = dim_vector_space - num_irredundant_equalities - dim_lin_space
55665  //     = num_columns - 1 - num_lines_or_equalities - dim_lin_space,
55666  //   min_sat_rays_or_points = dim_ray_space.
55667  //
55668  // An inequality saturated by less than `dim_ray_space' _rays/points_
55669  // is redundant. Thus we have the implication
55670  //
55671  //   (num_saturators[i] - num_sat_lines[i] < dim_ray_space)
55672  //      ==>
55673  //        redundant(sys[i]).
55674  //
55675  // Moreover, since every line saturates all inequalities, we also have
55676  //     dim_lin_space = num_sat_lines[i]
55677  // so that we can rewrite the condition above as follows:
55678  //
55679  //   (num_saturators[i] < num_columns - num_lines_or_equalities - 1)
55680  //      ==>
55681  //        redundant(sys[i]).
55682  //
55683  const dimension_type sys_num_columns
55684    = sys.topology() == NECESSARILY_CLOSED ? sys.space_dimension() + 1
55685                                           : sys.space_dimension() + 2;
55686  const dimension_type min_saturators
55687    = sys_num_columns - num_lines_or_equalities - 1;
55688  for (dimension_type i = num_lines_or_equalities; i < num_rows; ) {
55689    if (num_saturators[i] < min_saturators) {
55690      // The inequality `sys[i]' is redundant.
55691      --num_rows;
55692      sys.remove_row(i);
55693      swap(sat[i], sat[num_rows]);
55694      swap(num_saturators[i], num_saturators[num_rows]);
55695    }
55696    else {
55697      ++i;
55698    }
55699  }
55700
55701  // Now we check the independence rule.
55702  for (dimension_type i = num_lines_or_equalities; i < num_rows; ) {
55703    bool redundant = false;
55704    // NOTE: in the inner loop, index `j' runs through _all_ the
55705    // inequalities and we do not test if `sat[i]' is strictly
55706    // contained into `sat[j]'.  Experimentation has shown that this
55707    // is faster than having `j' only run through the indexes greater
55708    // than `i' and also doing the test `strict_subset(sat[i],
55709    // sat[k])'.
55710    for (dimension_type j = num_lines_or_equalities; j < num_rows; ) {
55711      if (i == j) {
55712        // We want to compare different rows of `sys'.
55713        ++j;
55714      }
55715      else {
55716        // Let us recall that each generator lies on a facet of the
55717        // polyhedron (see the Introduction).
55718        // Given two constraints `c_1' and `c_2', if there are `m'
55719        // generators lying on the hyper-plane corresponding to `c_1',
55720        // the same `m' generators lie on the hyper-plane
55721        // corresponding to `c_2', too, and there is another one lying
55722        // on the latter but not on the former, then `c_2' is more
55723        // restrictive than `c_1', i.e., `c_1' is redundant.
55724        bool strict_subset;
55725        if (subset_or_equal(sat[j], sat[i], strict_subset)) {
55726          if (strict_subset) {
55727            // All the saturators of the inequality `sys[i]' are
55728            // saturators of the inequality `sys[j]' too,
55729            // and there exists at least one saturator of `sys[j]'
55730            // which is not a saturator of `sys[i]'.
55731            // It follows that inequality `sys[i]' is redundant.
55732            redundant = true;
55733            break;
55734          }
55735          else {
55736            // We have `sat[j] == sat[i]'.  Hence inequalities
55737            // `sys[i]' and `sys[j]' are saturated by the same set of
55738            // generators. Then we can remove either one of the two
55739            // inequalities: we remove `sys[j]'.
55740            --num_rows;
55741            sys.remove_row(j);
55742            PPL_ASSERT(sys.num_rows() == num_rows);
55743            swap(sat[j], sat[num_rows]);
55744            swap(num_saturators[j], num_saturators[num_rows]);
55745          }
55746        }
55747        else {
55748          // If we reach this point then we know that `sat[i]' does
55749          // not contain (and is different from) `sat[j]', so that
55750          // `sys[i]' is not made redundant by inequality `sys[j]'.
55751          ++j;
55752        }
55753      }
55754    }
55755    if (redundant) {
55756      // The inequality `sys[i]' is redundant.
55757      --num_rows;
55758      sys.remove_row(i);
55759      PPL_ASSERT(sys.num_rows() == num_rows);
55760      swap(sat[i], sat[num_rows]);
55761      swap(num_saturators[i], num_saturators[num_rows]);
55762    }
55763    else {
55764      // The inequality `sys[i]' is not redundant.
55765      ++i;
55766    }
55767  }
55768
55769  // Here we physically remove the `sat' rows corresponding to the redundant
55770  // inequalities previously removed from `sys'.
55771  sat.remove_trailing_rows(old_num_rows - num_rows);
55772
55773  // At this point the first `num_lines_or_equalities' rows of 'sys'
55774  // represent the irredundant equalities, while the remaining rows
55775  // (i.e., those having indexes from `num_lines_or_equalities' to
55776  // `num_rows' - 1) represent the irredundant inequalities.
55777#ifndef NDEBUG
55778  // Check if the flag is set (that of the equalities is already set).
55779  for (dimension_type i = num_lines_or_equalities; i < num_rows; ++i) {
55780    PPL_ASSERT(sys[i].is_ray_or_point_or_inequality());
55781  }
55782#endif
55783
55784  // Finally, since now the sub-system (of `sys') of the irredundant
55785  // equalities is in triangular form, we back substitute each
55786  // variables with the expression obtained considering the equalities
55787  // starting from the last one.
55788  sys.back_substitute(num_lines_or_equalities);
55789
55790  // The returned value is the number of irredundant equalities i.e.,
55791  // the rank of the sub-system of `sys' containing only equalities.
55792  // (See the Introduction for definition of lineality space dimension.)
55793  return num_lines_or_equalities;
55794}
55795
55796} // namespace Parma_Polyhedra_Library
55797
55798/* Automatically generated from PPL source file ../src/Polyhedron_defs.hh line 2862. */
55799
55800/* Automatically generated from PPL source file ../src/Grid_defs.hh line 1. */
55801/* Grid class declaration.
55802*/
55803
55804
55805/* Automatically generated from PPL source file ../src/Grid_Generator_System_defs.hh line 1. */
55806/* Grid_Generator_System class declaration.
55807*/
55808
55809
55810/* Automatically generated from PPL source file ../src/Grid_Generator_System_defs.hh line 28. */
55811
55812/* Automatically generated from PPL source file ../src/Grid_Generator_System_defs.hh line 33. */
55813#include <iosfwd>
55814#include <cstddef>
55815
55816namespace Parma_Polyhedra_Library {
55817
55818namespace IO_Operators {
55819
55820//! Output operator.
55821/*!
55822  \relates Parma_Polyhedra_Library::Grid_Generator_System
55823  Writes <CODE>false</CODE> if \p gs is empty.  Otherwise, writes on
55824  \p s the generators of \p gs, all in one row and separated by ", ".
55825*/
55826std::ostream& operator<<(std::ostream& s, const Grid_Generator_System& gs);
55827
55828} // namespace IO_Operators
55829
55830//! Swaps \p x with \p y.
55831/*! \relates Grid_Generator_System */
55832void swap(Grid_Generator_System& x, Grid_Generator_System& y);
55833
55834//! Returns <CODE>true</CODE> if and only if \p x and \p y are identical.
55835/*! \relates Grid_Generator_System */
55836bool operator==(const Grid_Generator_System& x,
55837                const Grid_Generator_System& y);
55838
55839} // namespace Parma_Polyhedra_Library
55840
55841//! A system of grid generators.
55842/*! \ingroup PPL_CXX_interface
55843    An object of the class Grid_Generator_System is a system of
55844    grid generators, i.e., a multiset of objects of the class
55845    Grid_Generator (lines, parameters and points).
55846    When inserting generators in a system, space dimensions are
55847    automatically adjusted so that all the generators in the system
55848    are defined on the same vector space.
55849    A system of grid generators which is meant to define a non-empty
55850    grid must include at least one point: the reason is that
55851    lines and parameters need a supporting point
55852    (lines only specify directions while parameters only
55853    specify direction and distance.
55854
55855    \par
55856     In all the examples it is assumed that variables
55857    <CODE>x</CODE> and <CODE>y</CODE> are defined as follows:
55858    \code
55859  Variable x(0);
55860  Variable y(1);
55861    \endcode
55862
55863    \par Example 1
55864    The following code defines the line having the same direction
55865    as the \f$x\f$ axis (i.e., the first Cartesian axis)
55866    in \f$\Rset^2\f$:
55867    \code
55868  Grid_Generator_System gs;
55869  gs.insert(grid_line(x + 0*y));
55870    \endcode
55871    As said above, this system of generators corresponds to
55872    an empty grid, because the line has no supporting point.
55873    To define a system of generators that does correspond to
55874    the \f$x\f$ axis, we can add the following code which
55875    inserts the origin of the space as a point:
55876    \code
55877  gs.insert(grid_point(0*x + 0*y));
55878    \endcode
55879    Since space dimensions are automatically adjusted, the following
55880    code obtains the same effect:
55881    \code
55882  gs.insert(grid_point(0*x));
55883    \endcode
55884    In contrast, if we had added the following code, we would have
55885    defined a line parallel to the \f$x\f$ axis through
55886    the point \f$(0, 1)^\transpose \in \Rset^2\f$.
55887    \code
55888  gs.insert(grid_point(0*x + 1*y));
55889    \endcode
55890
55891    \par Example 2
55892    The following code builds a system of generators corresponding
55893    to the grid consisting of all the integral points on the \f$x\f$ axes;
55894    that is, all points satisfying the congruence relation
55895    \f[
55896      \bigl\{\,
55897        (x, 0)^\transpose \in \Rset^2
55898      \bigm|
55899        x \pmod{1}\ 0
55900      \,\bigr\},
55901    \f]
55902    \code
55903  Grid_Generator_System gs;
55904  gs.insert(parameter(x + 0*y));
55905  gs.insert(grid_point(0*x + 0*y));
55906    \endcode
55907
55908    \par Example 3
55909    The following code builds a system of generators having three points
55910    corresponding to a non-relational grid consisting of all points
55911    whose coordinates are integer multiple of 3.
55912    \code
55913  Grid_Generator_System gs;
55914  gs.insert(grid_point(0*x + 0*y));
55915  gs.insert(grid_point(0*x + 3*y));
55916  gs.insert(grid_point(3*x + 0*y));
55917    \endcode
55918
55919    \par Example 4
55920    By using parameters instead of two of the points we
55921    can define the same grid as that defined in the previous example.
55922    Note that there has to be at least one point and, for this purpose,
55923    any point in the grid could be considered.
55924    Thus the following code builds two identical grids from the
55925    grid generator systems \p gs and \p gs1.
55926    \code
55927  Grid_Generator_System gs;
55928  gs.insert(grid_point(0*x + 0*y));
55929  gs.insert(parameter(0*x + 3*y));
55930  gs.insert(parameter(3*x + 0*y));
55931  Grid_Generator_System gs1;
55932  gs1.insert(grid_point(3*x + 3*y));
55933  gs1.insert(parameter(0*x + 3*y));
55934  gs1.insert(parameter(3*x + 0*y));
55935    \endcode
55936
55937    \par Example 5
55938    The following code builds a system of generators having one point and
55939    a parameter corresponding to all the integral points that
55940    lie on \f$x + y = 2\f$ in \f$\Rset^2\f$
55941    \code
55942  Grid_Generator_System gs;
55943  gs.insert(grid_point(1*x + 1*y));
55944  gs.insert(parameter(1*x - 1*y));
55945    \endcode
55946
55947    \note
55948    After inserting a multiset of generators in a grid generator system,
55949    there are no guarantees that an <EM>exact</EM> copy of them
55950    can be retrieved:
55951    in general, only an <EM>equivalent</EM> grid generator system
55952    will be available, where original generators may have been
55953    reordered, removed (if they are duplicate or redundant), etc.
55954*/
55955class Parma_Polyhedra_Library::Grid_Generator_System {
55956public:
55957  typedef Grid_Generator row_type;
55958
55959  static const Representation default_representation = SPARSE;
55960
55961  //! Default constructor: builds an empty system of generators.
55962  explicit Grid_Generator_System(Representation r = default_representation);
55963
55964  //! Builds the singleton system containing only generator \p g.
55965  explicit Grid_Generator_System(const Grid_Generator& g,
55966                                 Representation r = default_representation);
55967
55968  //! Builds an empty system of generators of dimension \p dim.
55969  explicit Grid_Generator_System(dimension_type dim,
55970                                 Representation r = default_representation);
55971
55972  //! Ordinary copy constructor.
55973  //! The new Grid_Generator_System will have the same representation as `gs'.
55974  Grid_Generator_System(const Grid_Generator_System& gs);
55975
55976  //! Copy constructor with specified representation.
55977  Grid_Generator_System(const Grid_Generator_System& gs, Representation r);
55978
55979  //! Destructor.
55980  ~Grid_Generator_System();
55981
55982  //! Assignment operator.
55983  Grid_Generator_System& operator=(const Grid_Generator_System& y);
55984
55985  //! Returns the current representation of *this.
55986  Representation representation() const;
55987
55988  //! Converts *this to the specified representation.
55989  void set_representation(Representation r);
55990
55991  //! Returns the maximum space dimension a Grid_Generator_System can handle.
55992  static dimension_type max_space_dimension();
55993
55994  //! Returns the dimension of the vector space enclosing \p *this.
55995  dimension_type space_dimension() const;
55996
55997  /*! \brief
55998    Removes all the generators from the generator system and sets its
55999    space dimension to 0.
56000  */
56001  void clear();
56002
56003  /*! \brief
56004    Inserts into \p *this a copy of the generator \p g, increasing the
56005    number of space dimensions if needed.
56006
56007    If \p g is an all-zero parameter then the only action is to ensure
56008    that the space dimension of \p *this is at least the space
56009    dimension of \p g.
56010  */
56011  void insert(const Grid_Generator& g);
56012
56013  /*! \brief
56014    Inserts into \p *this the generator \p g, increasing the number of
56015    space dimensions if needed.
56016  */
56017  void insert(Grid_Generator& g, Recycle_Input);
56018
56019  /*! \brief
56020    Inserts into \p *this the generators in \p gs, increasing the
56021    number of space dimensions if needed.
56022  */
56023  void insert(Grid_Generator_System& gs, Recycle_Input);
56024
56025  //! Initializes the class.
56026  static void initialize();
56027
56028  //! Finalizes the class.
56029  static void finalize();
56030
56031  /*! \brief
56032    Returns the singleton system containing only
56033    Grid_Generator::zero_dim_point().
56034  */
56035  static const Grid_Generator_System& zero_dim_univ();
56036
56037  //! An iterator over a system of grid generators
56038  /*! \ingroup PPL_CXX_interface
56039    A const_iterator is used to provide read-only access
56040    to each generator contained in an object of Grid_Generator_System.
56041
56042    \par Example
56043    The following code prints the system of generators
56044    of the grid <CODE>gr</CODE>:
56045    \code
56046  const Grid_Generator_System& ggs = gr.generators();
56047  for (Grid_Generator_System::const_iterator i = ggs.begin(),
56048        ggs_end = ggs.end(); i != ggs_end; ++i)
56049    cout << *i << endl;
56050    \endcode
56051    The same effect can be obtained more concisely by using
56052    more features of the STL:
56053    \code
56054  const Grid_Generator_System& ggs = gr.generators();
56055  copy(ggs.begin(), ggs.end(), ostream_iterator<Grid_Generator>(cout, "\n"));
56056    \endcode
56057  */
56058  class const_iterator
56059    : public std::iterator<std::forward_iterator_tag,
56060                           Grid_Generator,
56061                           std::ptrdiff_t,
56062                           const Grid_Generator*,
56063                           const Grid_Generator&> {
56064  public:
56065    //! Default constructor.
56066    const_iterator();
56067
56068    //! Ordinary copy constructor.
56069    const_iterator(const const_iterator& y);
56070
56071    //! Destructor.
56072    ~const_iterator();
56073
56074    //! Assignment operator.
56075    const_iterator& operator=(const const_iterator& y);
56076
56077    //! Dereference operator.
56078    const Grid_Generator& operator*() const;
56079
56080    //! Indirect member selector.
56081    const Grid_Generator* operator->() const;
56082
56083    //! Prefix increment operator.
56084    const_iterator& operator++();
56085
56086    //! Postfix increment operator.
56087    const_iterator operator++(int);
56088
56089    /*! \brief
56090      Returns <CODE>true</CODE> if and only if \p *this and \p y are
56091      identical.
56092    */
56093    bool operator==(const const_iterator& y) const;
56094
56095    /*! \brief
56096      Returns <CODE>true</CODE> if and only if \p *this and \p y are
56097      different.
56098    */
56099    bool operator!=(const const_iterator& y) const;
56100
56101  private:
56102    friend class Grid_Generator_System;
56103
56104    Linear_System<Grid_Generator>::const_iterator i;
56105
56106    //! Copy constructor from Linear_System< Grid_Generator>::const_iterator.
56107    const_iterator(const Linear_System<Grid_Generator>::const_iterator& y);
56108  };
56109
56110  //! Returns <CODE>true</CODE> if and only if \p *this has no generators.
56111  bool empty() const;
56112
56113  /*! \brief
56114    Returns the const_iterator pointing to the first generator, if \p
56115    *this is not empty; otherwise, returns the past-the-end
56116    const_iterator.
56117  */
56118  const_iterator begin() const;
56119
56120  //! Returns the past-the-end const_iterator.
56121  const_iterator end() const;
56122
56123  //! Returns the number of rows (generators) in the system.
56124  dimension_type num_rows() const;
56125
56126  //! Returns the number of parameters in the system.
56127  dimension_type num_parameters() const;
56128
56129  //! Returns the number of lines in the system.
56130  dimension_type num_lines() const;
56131
56132  /*! \brief
56133    Returns <CODE>true</CODE> if and only if \p *this contains one or
56134    more points.
56135  */
56136  bool has_points() const;
56137
56138  //! Returns <CODE>true</CODE> if \p *this is identical to \p y.
56139  bool is_equal_to(const Grid_Generator_System& y) const;
56140
56141  //! Checks if all the invariants are satisfied.
56142  bool OK() const;
56143
56144  PPL_OUTPUT_DECLARATIONS
56145
56146  /*! \brief
56147    Loads from \p s an ASCII representation (as produced by
56148    ascii_dump(std::ostream&) const) and sets \p *this accordingly.
56149    Returns <CODE>true</CODE> if successful, <CODE>false</CODE> otherwise.
56150
56151    Resizes the matrix of generators using the numbers of rows and columns
56152    read from \p s, then initializes the coordinates of each generator
56153    and its type reading the contents from \p s.
56154  */
56155  bool ascii_load(std::istream& s);
56156
56157  //! Returns the total size in bytes of the memory occupied by \p *this.
56158  memory_size_type total_memory_in_bytes() const;
56159
56160  //! Returns the size in bytes of the memory managed by \p *this.
56161  memory_size_type external_memory_in_bytes() const;
56162
56163  //! Swaps \p *this with \p y.
56164  void m_swap(Grid_Generator_System& y);
56165
56166private:
56167  //! Returns a constant reference to the \p k- th generator of the system.
56168  const Grid_Generator& operator[](dimension_type k) const;
56169
56170  //! Assigns to a given variable an affine expression.
56171  /*!
56172    \param v
56173    The variable to which the affine transformation is assigned;
56174
56175    \param expr
56176    The numerator of the affine transformation:
56177    \f$\sum_{i = 0}^{n - 1} a_i x_i + b\f$;
56178
56179    \param denominator
56180    The denominator of the affine transformation;
56181
56182    We allow affine transformations (see the Section \ref
56183    rational_grid_operations)to have rational
56184    coefficients. Since the coefficients of linear expressions are
56185    integers we also provide an integer \p denominator that will
56186    be used as denominator of the affine transformation.  The
56187    denominator is required to be a positive integer and its
56188    default value is 1.
56189
56190    The affine transformation assigns to every variable \p v, in every
56191    column, the follow expression:
56192    \f[
56193      \frac{\sum_{i = 0}^{n - 1} a_i x_i + b}
56194           {\mathrm{denominator}}.
56195    \f]
56196
56197    \p expr is a constant parameter and unaltered by this computation.
56198  */
56199  void affine_image(Variable v,
56200                    const Linear_Expression& expr,
56201                    Coefficient_traits::const_reference denominator);
56202
56203  //! Sets the sortedness flag of the system to \p b.
56204  void set_sorted(bool b);
56205
56206  /*! \brief
56207    Adds \p dims rows and \p dims columns of zeroes to the matrix,
56208    initializing the added rows as in the universe system.
56209
56210    \param dims
56211    The number of rows and columns to be added: must be strictly
56212    positive.
56213
56214    Turns the \f$r \times c\f$ matrix \f$A\f$ into the \f$(r+dims)
56215    \times (c+dims)\f$ matrix
56216    \f$\bigl(\genfrac{}{}{0pt}{}{A}{0} \genfrac{}{}{0pt}{}{0}{B}\bigr)\f$
56217    where \f$B\f$ is the \f$dims \times dims\f$ unit matrix of the form
56218    \f$\bigl(\genfrac{}{}{0pt}{}{1}{0} \genfrac{}{}{0pt}{}{0}{1}\bigr)\f$.
56219    The matrix is expanded avoiding reallocation whenever possible.
56220  */
56221  void add_universe_rows_and_columns(dimension_type dims);
56222
56223  //! Resizes the system to the specified space dimension.
56224  void set_space_dimension(dimension_type space_dim);
56225
56226  //! Removes all the specified dimensions from the generator system.
56227  /*!
56228    The space dimension of the variable with the highest space
56229    dimension in \p vars must be at most the space dimension
56230    of \p this.
56231  */
56232  void remove_space_dimensions(const Variables_Set& vars);
56233
56234  //! Shift by \p n positions the coefficients of variables, starting from
56235  //! the coefficient of \p v. This increases the space dimension by \p n.
56236  void shift_space_dimensions(Variable v, dimension_type n);
56237
56238  //! Sets the index to indicate that the system has no pending rows.
56239  void unset_pending_rows();
56240
56241  //! Permutes the space dimensions of the matrix.
56242  /*
56243    \param cycle
56244    A vector representing a cycle of the permutation according to which the
56245    columns must be rearranged.
56246
56247    The \p cycle vector represents a cycle of a permutation of space
56248    dimensions.
56249    For example, the permutation
56250    \f$ \{ x_1 \mapsto x_2, x_2 \mapsto x_3, x_3 \mapsto x_1 \}\f$ can be
56251    represented by the vector containing \f$ x_1, x_2, x_3 \f$.
56252  */
56253  void permute_space_dimensions(const std::vector<Variable>& cycle);
56254
56255  bool has_no_rows() const;
56256
56257  //! Makes the system shrink by removing its \p n trailing rows.
56258  void remove_trailing_rows(dimension_type n);
56259
56260  void insert_verbatim(const Grid_Generator& g);
56261
56262  //! Returns the system topology.
56263  Topology topology() const;
56264
56265  //! Returns the index of the first pending row.
56266  dimension_type first_pending_row() const;
56267
56268  Linear_System<Grid_Generator> sys;
56269
56270  /*! \brief
56271    Holds (between class initialization and finalization) a pointer to
56272    the singleton system containing only Grid_Generator::zero_dim_point().
56273  */
56274  static const Grid_Generator_System* zero_dim_univ_p;
56275
56276  friend bool
56277  operator==(const Grid_Generator_System& x, const Grid_Generator_System& y);
56278
56279  //! Sets the index of the first pending row to \p i.
56280  void set_index_first_pending_row(dimension_type i);
56281
56282  //! Removes all the invalid lines and parameters.
56283  /*!
56284    The invalid lines and parameters are those with all
56285    the homogeneous terms set to zero.
56286  */
56287  void remove_invalid_lines_and_parameters();
56288
56289  friend class Polyhedron;
56290  friend class Grid;
56291};
56292
56293// Grid_Generator_System_inlines.hh is not included here on purpose.
56294
56295/* Automatically generated from PPL source file ../src/Grid_Generator_System_inlines.hh line 1. */
56296/* Grid_Generator_System class implementation: inline functions.
56297*/
56298
56299
56300/* Automatically generated from PPL source file ../src/Grid_Generator_System_inlines.hh line 28. */
56301
56302namespace Parma_Polyhedra_Library {
56303
56304inline void
56305Grid_Generator_System::set_sorted(bool b) {
56306  sys.set_sorted(b);
56307}
56308
56309inline void
56310Grid_Generator_System::unset_pending_rows() {
56311  sys.unset_pending_rows();
56312}
56313
56314inline void
56315Grid_Generator_System::set_index_first_pending_row(const dimension_type i) {
56316  sys.set_index_first_pending_row(i);
56317}
56318
56319inline void
56320Grid_Generator_System
56321::permute_space_dimensions(const std::vector<Variable>& cycle) {
56322  return sys.permute_space_dimensions(cycle);
56323}
56324
56325inline bool
56326Grid_Generator_System::is_equal_to(const Grid_Generator_System& y) const {
56327  return (sys == y.sys);
56328}
56329
56330inline
56331Grid_Generator_System::Grid_Generator_System(Representation r)
56332  : sys(NECESSARILY_CLOSED, r) {
56333  sys.set_sorted(false);
56334  PPL_ASSERT(space_dimension() == 0);
56335}
56336
56337inline
56338Grid_Generator_System::Grid_Generator_System(const Grid_Generator_System& gs)
56339  : sys(gs.sys) {
56340}
56341
56342inline
56343Grid_Generator_System::Grid_Generator_System(const Grid_Generator_System& gs,
56344                                             Representation r)
56345  : sys(gs.sys, r) {
56346}
56347
56348inline
56349Grid_Generator_System::Grid_Generator_System(dimension_type dim,
56350                                             Representation r)
56351  : sys(NECESSARILY_CLOSED, r) {
56352  sys.set_space_dimension(dim);
56353  sys.set_sorted(false);
56354  PPL_ASSERT(space_dimension() == dim);
56355}
56356
56357inline
56358Grid_Generator_System::Grid_Generator_System(const Grid_Generator& g,
56359                                             Representation r)
56360  : sys(NECESSARILY_CLOSED, r) {
56361  sys.insert(g);
56362  sys.set_sorted(false);
56363}
56364
56365inline
56366Grid_Generator_System::~Grid_Generator_System() {
56367}
56368
56369inline Grid_Generator_System&
56370Grid_Generator_System::operator=(const Grid_Generator_System& y) {
56371  Grid_Generator_System tmp = y;
56372  swap(*this, tmp);
56373  return *this;
56374}
56375
56376inline Representation
56377Grid_Generator_System::representation() const {
56378  return sys.representation();
56379}
56380
56381inline void
56382Grid_Generator_System::set_representation(Representation r) {
56383  sys.set_representation(r);
56384}
56385
56386inline dimension_type
56387Grid_Generator_System::max_space_dimension() {
56388  // Grid generators use an extra column for the parameter divisor.
56389  return Linear_System<Grid_Generator>::max_space_dimension() - 1;
56390}
56391
56392inline dimension_type
56393Grid_Generator_System::space_dimension() const {
56394  return sys.space_dimension();
56395}
56396
56397inline const Grid_Generator_System&
56398Grid_Generator_System::zero_dim_univ() {
56399  PPL_ASSERT(zero_dim_univ_p != 0);
56400  return *zero_dim_univ_p;
56401}
56402
56403inline void
56404Grid_Generator_System::clear() {
56405  sys.clear();
56406  sys.set_sorted(false);
56407  sys.unset_pending_rows();
56408  PPL_ASSERT(space_dimension() == 0);
56409}
56410
56411inline void
56412Grid_Generator_System::m_swap(Grid_Generator_System& y) {
56413  swap(sys, y.sys);
56414}
56415
56416inline memory_size_type
56417Grid_Generator_System::external_memory_in_bytes() const {
56418  return sys.external_memory_in_bytes();
56419}
56420
56421inline memory_size_type
56422Grid_Generator_System::total_memory_in_bytes() const {
56423  return external_memory_in_bytes() + sizeof(*this);
56424}
56425
56426inline dimension_type
56427Grid_Generator_System::num_rows() const {
56428  return sys.num_rows();
56429}
56430
56431inline
56432Grid_Generator_System::const_iterator::const_iterator()
56433  : i() {
56434}
56435
56436inline
56437Grid_Generator_System::const_iterator::const_iterator(const const_iterator& y)
56438  : i(y.i) {
56439}
56440
56441inline
56442Grid_Generator_System::const_iterator::~const_iterator() {
56443}
56444
56445inline Grid_Generator_System::const_iterator&
56446Grid_Generator_System::const_iterator::operator=(const const_iterator& y) {
56447  i = y.i;
56448  return *this;
56449}
56450
56451inline const Grid_Generator&
56452Grid_Generator_System::const_iterator::operator*() const {
56453  return *i;
56454}
56455
56456inline const Grid_Generator*
56457Grid_Generator_System::const_iterator::operator->() const {
56458  return i.operator->();
56459}
56460
56461inline Grid_Generator_System::const_iterator&
56462Grid_Generator_System::const_iterator::operator++() {
56463  ++i;
56464  return *this;
56465}
56466
56467inline Grid_Generator_System::const_iterator
56468Grid_Generator_System::const_iterator::operator++(int) {
56469  const const_iterator tmp = *this;
56470  operator++();
56471  return tmp;
56472}
56473
56474inline bool
56475Grid_Generator_System
56476::const_iterator::operator==(const const_iterator& y) const {
56477  return i == y.i;
56478}
56479
56480inline bool
56481Grid_Generator_System
56482::const_iterator::operator!=(const const_iterator& y) const {
56483  return i != y.i;
56484}
56485
56486inline bool
56487Grid_Generator_System::empty() const {
56488  return sys.has_no_rows();
56489}
56490
56491inline
56492Grid_Generator_System::const_iterator
56493::const_iterator(const Linear_System<Grid_Generator>::const_iterator& y)
56494  : i(y) {
56495}
56496
56497inline Grid_Generator_System::const_iterator
56498Grid_Generator_System::begin() const {
56499  return static_cast<Grid_Generator_System::const_iterator>(sys.begin());
56500}
56501
56502inline Grid_Generator_System::const_iterator
56503Grid_Generator_System::end() const {
56504  return static_cast<Grid_Generator_System::const_iterator>(sys.end());
56505}
56506
56507inline const Grid_Generator&
56508Grid_Generator_System::operator[](const dimension_type k) const {
56509  return sys[k];
56510}
56511
56512inline bool
56513Grid_Generator_System::has_no_rows() const {
56514  return sys.has_no_rows();
56515}
56516
56517inline void
56518Grid_Generator_System::remove_trailing_rows(dimension_type n) {
56519  sys.remove_trailing_rows(n);
56520}
56521
56522inline void
56523Grid_Generator_System::insert_verbatim(const Grid_Generator& g) {
56524  sys.insert(g);
56525}
56526
56527inline Topology
56528Grid_Generator_System::topology() const {
56529  return sys.topology();
56530}
56531
56532inline dimension_type
56533Grid_Generator_System::first_pending_row() const {
56534  return sys.first_pending_row();
56535}
56536
56537/*! \relates Grid_Generator_System */
56538inline bool
56539operator==(const Grid_Generator_System& x,
56540           const Grid_Generator_System& y) {
56541  return x.is_equal_to(y);
56542}
56543
56544/*! \relates Grid_Generator_System */
56545inline void
56546swap(Grid_Generator_System& x, Grid_Generator_System& y) {
56547  x.m_swap(y);
56548}
56549
56550} // namespace Parma_Polyhedra_Library
56551
56552/* Automatically generated from PPL source file ../src/Grid_Certificate_types.hh line 1. */
56553
56554
56555namespace Parma_Polyhedra_Library {
56556
56557class Grid_Certificate;
56558
56559}
56560
56561/* Automatically generated from PPL source file ../src/Grid_defs.hh line 47. */
56562#include <vector>
56563#include <iosfwd>
56564
56565namespace Parma_Polyhedra_Library {
56566
56567namespace IO_Operators {
56568
56569//! Output operator.
56570/*!
56571  \relates Parma_Polyhedra_Library::Grid
56572  Writes a textual representation of \p gr on \p s: <CODE>false</CODE>
56573  is written if \p gr is an empty grid; <CODE>true</CODE> is written
56574  if \p gr is a universe grid; a minimized system of congruences
56575  defining \p gr is written otherwise, all congruences in one row
56576  separated by ", "s.
56577*/
56578std::ostream&
56579operator<<(std::ostream& s, const Grid& gr);
56580
56581} // namespace IO_Operators
56582
56583//! Swaps \p x with \p y.
56584/*! \relates Grid */
56585void swap(Grid& x, Grid& y);
56586
56587/*! \brief
56588  Returns <CODE>true</CODE> if and only if \p x and \p y are the same
56589  grid.
56590
56591  \relates Grid
56592  Note that \p x and \p y may be dimension-incompatible grids: in
56593  those cases, the value <CODE>false</CODE> is returned.
56594*/
56595bool operator==(const Grid& x, const Grid& y);
56596
56597/*! \brief
56598  Returns <CODE>true</CODE> if and only if \p x and \p y are different
56599  grids.
56600
56601  \relates Grid
56602  Note that \p x and \p y may be dimension-incompatible grids: in
56603  those cases, the value <CODE>true</CODE> is returned.
56604*/
56605bool operator!=(const Grid& x, const Grid& y);
56606
56607} // namespace Parma_Polyhedra_Library
56608
56609
56610//! A grid.
56611/*! \ingroup PPL_CXX_interface
56612  An object of the class Grid represents a rational grid.
56613
56614  The domain of grids <EM>optimally supports</EM>:
56615    - all (proper and non-proper) congruences;
56616    - tautological and inconsistent constraints;
56617    - linear equality constraints (i.e., non-proper congruences).
56618
56619  Depending on the method, using a constraint that is not optimally
56620  supported by the domain will either raise an exception or
56621  result in a (possibly non-optimal) upward approximation.
56622
56623  The domain of grids support a concept of double description similar
56624  to the one developed for polyhedra: hence, a grid can be specified
56625  as either a finite system of congruences or a finite system of
56626  generators (see Section \ref sect_rational_grids) and it is always
56627  possible to obtain either representation.
56628  That is, if we know the system of congruences, we can obtain
56629  from this a system of generators that define the same grid
56630  and vice versa.
56631  These systems can contain redundant members, or they can be in the
56632  minimal form.
56633
56634  A key attribute of any grid is its space dimension (the dimension
56635  \f$n \in \Nset\f$ of the enclosing vector space):
56636
56637  - all grids, the empty ones included, are endowed with a space
56638    dimension;
56639  - most operations working on a grid and another object (another
56640    grid, a congruence, a generator, a set of variables, etc.) will
56641    throw an exception if the grid and the object are not
56642    dimension-compatible (see Section \ref Grid_Space_Dimensions);
56643  - the only ways in which the space dimension of a grid can be
56644    changed are with <EM>explicit</EM> calls to operators provided for
56645    that purpose, and with standard copy, assignment and swap
56646    operators.
56647
56648  Note that two different grids can be defined on the zero-dimension
56649  space: the empty grid and the universe grid \f$R^0\f$.
56650
56651  \par
56652  In all the examples it is assumed that variables
56653  <CODE>x</CODE> and <CODE>y</CODE> are defined (where they are
56654  used) as follows:
56655  \code
56656  Variable x(0);
56657  Variable y(1);
56658  \endcode
56659
56660  \par Example 1
56661  The following code builds a grid corresponding to the even integer
56662  pairs in \f$\Rset^2\f$, given as a system of congruences:
56663  \code
56664  Congruence_System cgs;
56665  cgs.insert((x %= 0) / 2);
56666  cgs.insert((y %= 0) / 2);
56667  Grid gr(cgs);
56668  \endcode
56669  The following code builds the same grid as above, but starting
56670  from a system of generators specifying three of the points:
56671  \code
56672  Grid_Generator_System gs;
56673  gs.insert(grid_point(0*x + 0*y));
56674  gs.insert(grid_point(0*x + 2*y));
56675  gs.insert(grid_point(2*x + 0*y));
56676  Grid gr(gs);
56677  \endcode
56678
56679  \par Example 2
56680  The following code builds a grid corresponding to a line in
56681  \f$\Rset^2\f$ by adding a single congruence to the universe grid:
56682  \code
56683  Congruence_System cgs;
56684  cgs.insert(x - y == 0);
56685  Grid gr(cgs);
56686  \endcode
56687  The following code builds the same grid as above, but starting
56688  from a system of generators specifying a point and a line:
56689  \code
56690  Grid_Generator_System gs;
56691  gs.insert(grid_point(0*x + 0*y));
56692  gs.insert(grid_line(x + y));
56693  Grid gr(gs);
56694  \endcode
56695
56696  \par Example 3
56697  The following code builds a grid corresponding to the integral
56698  points on the line \f$x = y\f$ in \f$\Rset^2\f$ constructed
56699  by adding an equality and congruence to the universe grid:
56700  \code
56701  Congruence_System cgs;
56702  cgs.insert(x - y == 0);
56703  cgs.insert(x %= 0);
56704  Grid gr(cgs);
56705  \endcode
56706  The following code builds the same grid as above, but starting
56707  from a system of generators specifying a point and a parameter:
56708  \code
56709  Grid_Generator_System gs;
56710  gs.insert(grid_point(0*x + 0*y));
56711  gs.insert(parameter(x + y));
56712  Grid gr(gs);
56713  \endcode
56714
56715  \par Example 4
56716  The following code builds the grid corresponding to a plane by
56717  creating the universe grid in \f$\Rset^2\f$:
56718  \code
56719  Grid gr(2);
56720  \endcode
56721  The following code builds the same grid as above, but starting
56722  from the empty grid in \f$\Rset^2\f$ and inserting the appropriate
56723  generators (a point, and two lines).
56724  \code
56725  Grid gr(2, EMPTY);
56726  gr.add_grid_generator(grid_point(0*x + 0*y));
56727  gr.add_grid_generator(grid_line(x));
56728  gr.add_grid_generator(grid_line(y));
56729  \endcode
56730  Note that a generator system must contain a point when describing
56731  a grid.  To ensure that this is always the case it is required
56732  that the first generator inserted in an empty grid is a point
56733  (otherwise, an exception is thrown).
56734
56735  \par Example 5
56736  The following code shows the use of the function
56737  <CODE>add_space_dimensions_and_embed</CODE>:
56738  \code
56739  Grid gr(1);
56740  gr.add_congruence(x == 2);
56741  gr.add_space_dimensions_and_embed(1);
56742  \endcode
56743  We build the universe grid in the 1-dimension space \f$\Rset\f$.
56744  Then we add a single equality congruence,
56745  thus obtaining the grid corresponding to the singleton set
56746  \f$\{ 2 \} \sseq \Rset\f$.
56747  After the last line of code, the resulting grid is
56748  \f[
56749  \bigl\{\,
56750  (2, y)^\transpose \in \Rset^2
56751  \bigm|
56752  y \in \Rset
56753  \,\bigr\}.
56754  \f]
56755
56756  \par Example 6
56757  The following code shows the use of the function
56758  <CODE>add_space_dimensions_and_project</CODE>:
56759  \code
56760  Grid gr(1);
56761  gr.add_congruence(x == 2);
56762  gr.add_space_dimensions_and_project(1);
56763  \endcode
56764  The first two lines of code are the same as in Example 4 for
56765  <CODE>add_space_dimensions_and_embed</CODE>.
56766  After the last line of code, the resulting grid is
56767  the singleton set
56768  \f$\bigl\{ (2, 0)^\transpose \bigr\} \sseq \Rset^2\f$.
56769
56770  \par Example 7
56771  The following code shows the use of the function
56772  <CODE>affine_image</CODE>:
56773  \code
56774  Grid gr(2, EMPTY);
56775  gr.add_grid_generator(grid_point(0*x + 0*y));
56776  gr.add_grid_generator(grid_point(4*x + 0*y));
56777  gr.add_grid_generator(grid_point(0*x + 2*y));
56778  Linear_Expression expr = x + 3;
56779  gr.affine_image(x, expr);
56780  \endcode
56781  In this example the starting grid is all the pairs of \f$x\f$ and
56782  \f$y\f$ in \f$\Rset^2\f$ where \f$x\f$ is an integer multiple of 4
56783  and \f$y\f$ is an integer multiple of 2.  The considered variable
56784  is \f$x\f$ and the affine expression is \f$x+3\f$.  The resulting
56785  grid is the given grid translated 3 integers to the right (all the
56786  pairs \f$(x, y)\f$ where \f$x\f$ is -1 plus an integer multiple of 4
56787  and \f$y\f$ is an integer multiple of 2).
56788  Moreover, if the affine transformation for the same variable \p x
56789  is instead \f$x+y\f$:
56790  \code
56791  Linear_Expression expr = x + y;
56792  \endcode
56793  the resulting grid is every second integral point along the \f$x=y\f$
56794  line, with this line of points repeated at every fourth integral value
56795  along the \f$x\f$ axis.
56796  Instead, if we do not use an invertible transformation for the
56797  same variable; for example, the affine expression \f$y\f$:
56798  \code
56799  Linear_Expression expr = y;
56800  \endcode
56801  the resulting grid is every second point along the \f$x=y\f$ line.
56802
56803  \par Example 8
56804  The following code shows the use of the function
56805  <CODE>affine_preimage</CODE>:
56806  \code
56807  Grid gr(2, EMPTY);
56808  gr.add_grid_generator(grid_point(0*x + 0*y));
56809  gr.add_grid_generator(grid_point(4*x + 0*y));
56810  gr.add_grid_generator(grid_point(0*x + 2*y));
56811  Linear_Expression expr = x + 3;
56812  gr.affine_preimage(x, expr);
56813  \endcode
56814  In this example the starting grid, \p var and the affine
56815  expression and the denominator are the same as in Example 6, while
56816  the resulting grid is similar but translated 3 integers to the
56817  left (all the pairs \f$(x, y)\f$
56818  where \f$x\f$ is -3 plus an integer multiple of 4 and
56819  \f$y\f$ is an integer multiple of 2)..
56820  Moreover, if the affine transformation for \p x is \f$x+y\f$
56821  \code
56822  Linear_Expression expr = x + y;
56823  \endcode
56824  the resulting grid is a similar grid to the result in Example 6,
56825  only the grid is slanted along \f$x=-y\f$.
56826  Instead, if we do not use an invertible transformation for the same
56827  variable \p x, for example, the affine expression \f$y\f$:
56828  \code
56829  Linear_Expression expr = y;
56830  \endcode
56831  the resulting grid is every fourth line parallel to the \f$x\f$
56832  axis.
56833
56834  \par Example 9
56835  For this example we also use the variables:
56836  \code
56837  Variable z(2);
56838  Variable w(3);
56839  \endcode
56840  The following code shows the use of the function
56841  <CODE>remove_space_dimensions</CODE>:
56842  \code
56843  Grid_Generator_System gs;
56844  gs.insert(grid_point(3*x + y +0*z + 2*w));
56845  Grid gr(gs);
56846  Variables_Set vars;
56847  vars.insert(y);
56848  vars.insert(z);
56849  gr.remove_space_dimensions(vars);
56850  \endcode
56851  The starting grid is the singleton set
56852  \f$\bigl\{ (3, 1, 0, 2)^\transpose \bigr\} \sseq \Rset^4\f$, while
56853  the resulting grid is
56854  \f$\bigl\{ (3, 2)^\transpose \bigr\} \sseq \Rset^2\f$.
56855  Be careful when removing space dimensions <EM>incrementally</EM>:
56856  since dimensions are automatically renamed after each application
56857  of the <CODE>remove_space_dimensions</CODE> operator, unexpected
56858  results can be obtained.
56859  For instance, by using the following code we would obtain
56860  a different result:
56861  \code
56862  set<Variable> vars1;
56863  vars1.insert(y);
56864  gr.remove_space_dimensions(vars1);
56865  set<Variable> vars2;
56866  vars2.insert(z);
56867  gr.remove_space_dimensions(vars2);
56868  \endcode
56869  In this case, the result is the grid
56870  \f$\bigl\{(3, 0)^\transpose \bigr\} \sseq \Rset^2\f$:
56871  when removing the set of dimensions \p vars2
56872  we are actually removing variable \f$w\f$ of the original grid.
56873  For the same reason, the operator \p remove_space_dimensions
56874  is not idempotent: removing twice the same non-empty set of dimensions
56875  is never the same as removing them just once.
56876*/
56877
56878class Parma_Polyhedra_Library::Grid {
56879public:
56880  //! The numeric type of coefficients.
56881  typedef Coefficient coefficient_type;
56882
56883  //! Returns the maximum space dimension all kinds of Grid can handle.
56884  static dimension_type max_space_dimension();
56885
56886  /*! \brief
56887    Returns true indicating that this domain has methods that
56888    can recycle congruences.
56889  */
56890  static bool can_recycle_congruence_systems();
56891
56892  /*! \brief
56893    Returns true indicating that this domain has methods that
56894    can recycle constraints.
56895  */
56896  static bool can_recycle_constraint_systems();
56897
56898  //! Builds a grid having the specified properties.
56899  /*!
56900    \param num_dimensions
56901    The number of dimensions of the vector space enclosing the grid;
56902
56903    \param kind
56904    Specifies whether the universe or the empty grid has to be built.
56905
56906    \exception std::length_error
56907    Thrown if \p num_dimensions exceeds the maximum allowed space
56908    dimension.
56909  */
56910  explicit Grid(dimension_type num_dimensions = 0,
56911                Degenerate_Element kind = UNIVERSE);
56912
56913  //! Builds a grid, copying a system of congruences.
56914  /*!
56915    The grid inherits the space dimension of the congruence system.
56916
56917    \param cgs
56918    The system of congruences defining the grid.
56919
56920    \exception std::length_error
56921    Thrown if \p num_dimensions exceeds the maximum allowed space
56922    dimension.
56923  */
56924  explicit Grid(const Congruence_System& cgs);
56925
56926  //! Builds a grid, recycling a system of congruences.
56927  /*!
56928    The grid inherits the space dimension of the congruence system.
56929
56930    \param cgs
56931    The system of congruences defining the grid.  Its data-structures
56932    may be recycled to build the grid.
56933
56934    \param dummy
56935    A dummy tag to syntactically differentiate this one
56936    from the other constructors.
56937
56938    \exception std::length_error
56939    Thrown if \p num_dimensions exceeds the maximum allowed space
56940    dimension.
56941  */
56942  Grid(Congruence_System& cgs, Recycle_Input dummy);
56943
56944  //! Builds a grid, copying a system of constraints.
56945  /*!
56946    The grid inherits the space dimension of the constraint system.
56947
56948    \param cs
56949    The system of constraints defining the grid.
56950
56951    \exception std::invalid_argument
56952    Thrown if the constraint system \p cs contains inequality constraints.
56953
56954    \exception std::length_error
56955    Thrown if \p num_dimensions exceeds the maximum allowed space
56956    dimension.
56957  */
56958  explicit Grid(const Constraint_System& cs);
56959
56960  //! Builds a grid, recycling a system of constraints.
56961  /*!
56962    The grid inherits the space dimension of the constraint system.
56963
56964    \param cs
56965    The system of constraints defining the grid.  Its data-structures
56966    may be recycled to build the grid.
56967
56968    \param dummy
56969    A dummy tag to syntactically differentiate this one
56970    from the other constructors.
56971
56972    \exception std::invalid_argument
56973    Thrown if the constraint system \p cs contains inequality constraints.
56974
56975    \exception std::length_error
56976    Thrown if \p num_dimensions exceeds the maximum allowed space
56977    dimension.
56978  */
56979  Grid(Constraint_System& cs, Recycle_Input dummy);
56980
56981  //! Builds a grid, copying a system of grid generators.
56982  /*!
56983    The grid inherits the space dimension of the generator system.
56984
56985    \param ggs
56986    The system of generators defining the grid.
56987
56988    \exception std::invalid_argument
56989    Thrown if the system of generators is not empty but has no points.
56990
56991    \exception std::length_error
56992    Thrown if \p num_dimensions exceeds the maximum allowed space
56993    dimension.
56994  */
56995  explicit Grid(const Grid_Generator_System& ggs);
56996
56997  //! Builds a grid, recycling a system of grid generators.
56998  /*!
56999    The grid inherits the space dimension of the generator system.
57000
57001    \param ggs
57002    The system of generators defining the grid.  Its data-structures
57003    may be recycled to build the grid.
57004
57005    \param dummy
57006    A dummy tag to syntactically differentiate this one
57007    from the other constructors.
57008
57009    \exception std::invalid_argument
57010    Thrown if the system of generators is not empty but has no points.
57011
57012    \exception std::length_error
57013    Thrown if \p num_dimensions exceeds the maximum allowed space dimension.
57014  */
57015  Grid(Grid_Generator_System& ggs, Recycle_Input dummy);
57016
57017  //! Builds a grid out of a box.
57018  /*!
57019    The grid inherits the space dimension of the box.
57020    The built grid is the most precise grid that includes the box.
57021
57022    \param box
57023    The box representing the grid to be built.
57024
57025    \param complexity
57026    This argument is ignored as the algorithm used has
57027    polynomial complexity.
57028
57029    \exception std::length_error
57030    Thrown if the space dimension of \p box exceeds the maximum
57031    allowed space dimension.
57032  */
57033  template <typename Interval>
57034  explicit Grid(const Box<Interval>& box,
57035                Complexity_Class complexity = ANY_COMPLEXITY);
57036
57037  //! Builds a grid out of a bounded-difference shape.
57038  /*!
57039    The grid inherits the space dimension of the BDS.
57040    The built grid is the most precise grid that includes the BDS.
57041
57042    \param bd
57043    The BDS representing the grid to be built.
57044
57045    \param complexity
57046    This argument is ignored as the algorithm used has
57047    polynomial complexity.
57048
57049    \exception std::length_error
57050    Thrown if the space dimension of \p bd exceeds the maximum
57051    allowed space dimension.
57052  */
57053  template <typename U>
57054  explicit Grid(const BD_Shape<U>& bd,
57055                Complexity_Class complexity = ANY_COMPLEXITY);
57056
57057  //! Builds a grid out of an octagonal shape.
57058  /*!
57059    The grid inherits the space dimension of the octagonal shape.
57060    The built grid is the most precise grid that includes the octagonal shape.
57061
57062    \param os
57063    The octagonal shape representing the grid to be built.
57064
57065    \param complexity
57066    This argument is ignored as the algorithm used has
57067    polynomial complexity.
57068
57069    \exception std::length_error
57070    Thrown if the space dimension of \p os exceeds the maximum
57071    allowed space dimension.
57072  */
57073  template <typename U>
57074  explicit Grid(const Octagonal_Shape<U>& os,
57075                Complexity_Class complexity = ANY_COMPLEXITY);
57076
57077  /*! \brief
57078    Builds a grid from a polyhedron using algorithms whose complexity
57079    does not exceed the one specified by \p complexity.
57080    If \p complexity is \p ANY_COMPLEXITY, then the grid built is the
57081    smallest one containing \p ph.
57082
57083    The grid inherits the space dimension of polyhedron.
57084
57085    \param ph
57086    The polyhedron.
57087
57088    \param complexity
57089    The complexity class.
57090
57091    \exception std::length_error
57092    Thrown if \p num_dimensions exceeds the maximum allowed space
57093    dimension.
57094  */
57095  explicit Grid(const Polyhedron& ph,
57096                Complexity_Class complexity = ANY_COMPLEXITY);
57097
57098  //! Ordinary copy constructor.
57099  /*!
57100    The complexity argument is ignored.
57101  */
57102  Grid(const Grid& y,
57103       Complexity_Class complexity = ANY_COMPLEXITY);
57104
57105  /*! \brief
57106    The assignment operator.  (\p *this and \p y can be
57107    dimension-incompatible.)
57108  */
57109  Grid& operator=(const Grid& y);
57110
57111  //! \name Member Functions that Do Not Modify the Grid
57112  //@{
57113
57114  //! Returns the dimension of the vector space enclosing \p *this.
57115  dimension_type space_dimension() const;
57116
57117  /*! \brief
57118    Returns \f$0\f$, if \p *this is empty; otherwise, returns
57119    the \ref Grid_Affine_Dimension "affine dimension" of \p *this.
57120  */
57121  dimension_type affine_dimension() const;
57122
57123  /*! \brief
57124    Returns a system of equality constraints satisfied by \p *this
57125    with the same affine dimension as \p *this.
57126  */
57127  Constraint_System constraints() const;
57128
57129  /*! \brief
57130    Returns a minimal system of equality constraints satisfied by
57131    \p *this with the same affine dimension as \p *this.
57132  */
57133  Constraint_System minimized_constraints() const;
57134
57135  //! Returns the system of congruences.
57136  const Congruence_System& congruences() const;
57137
57138  //! Returns the system of congruences in minimal form.
57139  const Congruence_System& minimized_congruences() const;
57140
57141  //! Returns the system of generators.
57142  const Grid_Generator_System& grid_generators() const;
57143
57144  //! Returns the minimized system of generators.
57145  const Grid_Generator_System& minimized_grid_generators() const;
57146
57147  //! Returns the relations holding between \p *this and \p cg.
57148  /*
57149    \exception std::invalid_argument
57150    Thrown if \p *this and congruence \p cg are dimension-incompatible.
57151  */
57152  // FIXME: Poly_Con_Relation seems to encode exactly what we want
57153  // here.  We must find a new name for that class.  Temporarily,
57154  // we keep using it without changing the name.
57155  Poly_Con_Relation relation_with(const Congruence& cg) const;
57156
57157  //! Returns the relations holding between \p *this and \p g.
57158  /*
57159    \exception std::invalid_argument
57160    Thrown if \p *this and generator \p g are dimension-incompatible.
57161  */
57162  // FIXME: see the comment for Poly_Con_Relation above.
57163  Poly_Gen_Relation
57164  relation_with(const Grid_Generator& g) const;
57165
57166  //! Returns the relations holding between \p *this and \p g.
57167  /*
57168    \exception std::invalid_argument
57169    Thrown if \p *this and generator \p g are dimension-incompatible.
57170  */
57171  // FIXME: see the comment for Poly_Con_Relation above.
57172  Poly_Gen_Relation
57173  relation_with(const Generator& g) const;
57174
57175  //! Returns the relations holding between \p *this and \p c.
57176  /*
57177    \exception std::invalid_argument
57178    Thrown if \p *this and constraint \p c are dimension-incompatible.
57179  */
57180  // FIXME: Poly_Con_Relation seems to encode exactly what we want
57181  // here.  We must find a new name for that class.  Temporarily,
57182  // we keep using it without changing the name.
57183  Poly_Con_Relation relation_with(const Constraint& c) const;
57184
57185  //! Returns \c true if and only if \p *this is an empty grid.
57186  bool is_empty() const;
57187
57188  //! Returns \c true if and only if \p *this is a universe grid.
57189  bool is_universe() const;
57190
57191  /*! \brief
57192    Returns <CODE>true</CODE> if and only if \p *this is a
57193    topologically closed subset of the vector space.
57194
57195    A grid is always topologically closed.
57196  */
57197  bool is_topologically_closed() const;
57198
57199  /*! \brief
57200    Returns <CODE>true</CODE> if and only if \p *this and \p y are
57201    disjoint.
57202
57203    \exception std::invalid_argument
57204    Thrown if \p x and \p y are dimension-incompatible.
57205  */
57206  bool is_disjoint_from(const Grid& y) const;
57207
57208  //! Returns <CODE>true</CODE> if and only if \p *this is discrete.
57209  /*!
57210    A grid is discrete if it can be defined by a generator system which
57211    contains only points and parameters.  This includes the empty grid
57212    and any grid in dimension zero.
57213  */
57214  bool is_discrete() const;
57215
57216  //! Returns <CODE>true</CODE> if and only if \p *this is bounded.
57217  bool is_bounded() const;
57218
57219  /*! \brief
57220    Returns <CODE>true</CODE> if and only if \p *this
57221    contains at least one integer point.
57222  */
57223  bool contains_integer_point() const;
57224
57225  /*! \brief
57226    Returns <CODE>true</CODE> if and only if \p var is constrained in
57227    \p *this.
57228
57229    \exception std::invalid_argument
57230    Thrown if \p var is not a space dimension of \p *this.
57231  */
57232  bool constrains(Variable var) const;
57233
57234  //! Returns <CODE>true</CODE> if and only if \p expr is bounded in \p *this.
57235  /*!
57236    This method is the same as bounds_from_below.
57237
57238    \exception std::invalid_argument
57239    Thrown if \p expr and \p *this are dimension-incompatible.
57240  */
57241  bool bounds_from_above(const Linear_Expression& expr) const;
57242
57243  //! Returns <CODE>true</CODE> if and only if \p expr is bounded in \p *this.
57244  /*!
57245    This method is the same as bounds_from_above.
57246
57247    \exception std::invalid_argument
57248    Thrown if \p expr and \p *this are dimension-incompatible.
57249  */
57250  bool bounds_from_below(const Linear_Expression& expr) const;
57251
57252  /*! \brief
57253    Returns <CODE>true</CODE> if and only if \p *this is not empty and
57254    \p expr is bounded from above in \p *this, in which case the
57255    supremum value is computed.
57256
57257    \param expr
57258    The linear expression to be maximized subject to \p *this;
57259
57260    \param sup_n
57261    The numerator of the supremum value;
57262
57263    \param sup_d
57264    The denominator of the supremum value;
57265
57266    \param maximum
57267    <CODE>true</CODE> if the supremum value can be reached in \p this.
57268    Always <CODE>true</CODE> when \p this bounds \p expr.  Present for
57269    interface compatibility with class Polyhedron, where closure
57270    points can result in a value of false.
57271
57272    \exception std::invalid_argument
57273    Thrown if \p expr and \p *this are dimension-incompatible.
57274
57275    If \p *this is empty or \p expr is not bounded by \p *this,
57276    <CODE>false</CODE> is returned and \p sup_n, \p sup_d and \p
57277    maximum are left untouched.
57278  */
57279  bool maximize(const Linear_Expression& expr,
57280                Coefficient& sup_n, Coefficient& sup_d, bool& maximum) const;
57281
57282  /*! \brief
57283    Returns <CODE>true</CODE> if and only if \p *this is not empty and
57284    \p expr is bounded from above in \p *this, in which case the
57285    supremum value and a point where \p expr reaches it are computed.
57286
57287    \param expr
57288    The linear expression to be maximized subject to \p *this;
57289
57290    \param sup_n
57291    The numerator of the supremum value;
57292
57293    \param sup_d
57294    The denominator of the supremum value;
57295
57296    \param maximum
57297    <CODE>true</CODE> if the supremum value can be reached in \p this.
57298    Always <CODE>true</CODE> when \p this bounds \p expr.  Present for
57299    interface compatibility with class Polyhedron, where closure
57300    points can result in a value of false;
57301
57302    \param point
57303    When maximization succeeds, will be assigned a point where \p expr
57304    reaches its supremum value.
57305
57306    \exception std::invalid_argument
57307    Thrown if \p expr and \p *this are dimension-incompatible.
57308
57309    If \p *this is empty or \p expr is not bounded by \p *this,
57310    <CODE>false</CODE> is returned and \p sup_n, \p sup_d, \p maximum
57311    and \p point are left untouched.
57312  */
57313  bool maximize(const Linear_Expression& expr,
57314                Coefficient& sup_n, Coefficient& sup_d, bool& maximum,
57315                Generator& point) const;
57316
57317  /*! \brief
57318    Returns <CODE>true</CODE> if and only if \p *this is not empty and
57319    \p expr is bounded from below in \p *this, in which case the
57320    infimum value is computed.
57321
57322    \param expr
57323    The linear expression to be minimized subject to \p *this;
57324
57325    \param inf_n
57326    The numerator of the infimum value;
57327
57328    \param inf_d
57329    The denominator of the infimum value;
57330
57331    \param minimum
57332    <CODE>true</CODE> if the is the infimum value can be reached in \p
57333    this.  Always <CODE>true</CODE> when \p this bounds \p expr.
57334    Present for interface compatibility with class Polyhedron, where
57335    closure points can result in a value of false.
57336
57337    \exception std::invalid_argument
57338    Thrown if \p expr and \p *this are dimension-incompatible.
57339
57340    If \p *this is empty or \p expr is not bounded from below,
57341    <CODE>false</CODE> is returned and \p inf_n, \p inf_d
57342    and \p minimum are left untouched.
57343  */
57344  bool minimize(const Linear_Expression& expr,
57345                Coefficient& inf_n, Coefficient& inf_d, bool& minimum) const;
57346
57347  /*! \brief
57348    Returns <CODE>true</CODE> if and only if \p *this is not empty and
57349    \p expr is bounded from below in \p *this, in which case the
57350    infimum value and a point where \p expr reaches it are computed.
57351
57352    \param expr
57353    The linear expression to be minimized subject to \p *this;
57354
57355    \param inf_n
57356    The numerator of the infimum value;
57357
57358    \param inf_d
57359    The denominator of the infimum value;
57360
57361    \param minimum
57362    <CODE>true</CODE> if the is the infimum value can be reached in \p
57363    this.  Always <CODE>true</CODE> when \p this bounds \p expr.
57364    Present for interface compatibility with class Polyhedron, where
57365    closure points can result in a value of false;
57366
57367    \param point
57368    When minimization succeeds, will be assigned a point where \p expr
57369    reaches its infimum value.
57370
57371    \exception std::invalid_argument
57372    Thrown if \p expr and \p *this are dimension-incompatible.
57373
57374    If \p *this is empty or \p expr is not bounded from below,
57375    <CODE>false</CODE> is returned and \p inf_n, \p inf_d, \p minimum
57376    and \p point are left untouched.
57377  */
57378  bool minimize(const Linear_Expression& expr,
57379                Coefficient& inf_n, Coefficient& inf_d, bool& minimum,
57380                Generator& point) const;
57381
57382  /*! \brief
57383    Returns <CODE>true</CODE> if and only if \p *this is not empty and
57384    \ref Grid_Frequency "frequency" for \p *this with respect to \p expr
57385    is defined, in which case the frequency and the value for \p expr
57386    that is closest to zero are computed.
57387
57388    \param expr
57389    The linear expression for which the frequency is needed;
57390
57391    \param freq_n
57392    The numerator of the maximum frequency of \p expr;
57393
57394    \param freq_d
57395    The denominator of the maximum frequency of \p expr;
57396
57397    \param val_n
57398    The numerator of them value of \p expr at a point in the grid
57399    that is closest to zero;
57400
57401    \param val_d
57402    The denominator of a value of \p expr at a point in the grid
57403    that is closest to zero;
57404
57405    \exception std::invalid_argument
57406    Thrown if \p expr and \p *this are dimension-incompatible.
57407
57408    If \p *this is empty or frequency is undefined with respect to \p expr,
57409    then <CODE>false</CODE> is returned and \p freq_n, \p freq_d,
57410    \p val_n and \p val_d are left untouched.
57411  */
57412  bool frequency(const Linear_Expression& expr,
57413                 Coefficient& freq_n, Coefficient& freq_d,
57414                 Coefficient& val_n, Coefficient& val_d) const;
57415
57416  //! Returns <CODE>true</CODE> if and only if \p *this contains \p y.
57417  /*!
57418    \exception std::invalid_argument
57419    Thrown if \p *this and \p y are dimension-incompatible.
57420  */
57421  bool contains(const Grid& y) const;
57422
57423  /*! \brief
57424    Returns <CODE>true</CODE> if and only if \p *this strictly
57425    contains \p y.
57426
57427    \exception std::invalid_argument
57428    Thrown if \p *this and \p y are dimension-incompatible.
57429  */
57430  bool strictly_contains(const Grid& y) const;
57431
57432  //! Checks if all the invariants are satisfied.
57433  /*!
57434    \return
57435    <CODE>true</CODE> if and only if \p *this satisfies all the
57436    invariants and either \p check_not_empty is <CODE>false</CODE> or
57437    \p *this is not empty.
57438
57439    \param check_not_empty
57440    <CODE>true</CODE> if and only if, in addition to checking the
57441    invariants, \p *this must be checked to be not empty.
57442
57443    The check is performed so as to intrude as little as possible.  If
57444    the library has been compiled with run-time assertions enabled,
57445    error messages are written on <CODE>std::cerr</CODE> in case
57446    invariants are violated. This is useful for the purpose of
57447    debugging the library.
57448  */
57449  bool OK(bool check_not_empty = false) const;
57450
57451  //@} // Member Functions that Do Not Modify the Grid
57452
57453  //! \name Space Dimension Preserving Member Functions that May Modify the Grid
57454  //@{
57455
57456  //! Adds a copy of congruence \p cg to \p *this.
57457  /*!
57458    \exception std::invalid_argument
57459    Thrown if \p *this and congruence \p cg are
57460    dimension-incompatible.
57461  */
57462  void add_congruence(const Congruence& cg);
57463
57464  /*! \brief
57465    Adds a copy of grid generator \p g to the system of generators of
57466    \p *this.
57467
57468    \exception std::invalid_argument
57469    Thrown if \p *this and generator \p g are dimension-incompatible,
57470    or if \p *this is an empty grid and \p g is not a point.
57471  */
57472  void add_grid_generator(const Grid_Generator& g);
57473
57474  //! Adds a copy of each congruence in \p cgs to \p *this.
57475  /*!
57476    \param cgs
57477    Contains the congruences that will be added to the system of
57478    congruences of \p *this.
57479
57480    \exception std::invalid_argument
57481    Thrown if \p *this and \p cgs are dimension-incompatible.
57482  */
57483  void add_congruences(const Congruence_System& cgs);
57484
57485  //! Adds the congruences in \p cgs to *this.
57486  /*!
57487    \param cgs
57488    The congruence system to be added to \p *this.  The congruences in
57489    \p cgs may be recycled.
57490
57491    \exception std::invalid_argument
57492    Thrown if \p *this and \p cgs are dimension-incompatible.
57493
57494    \warning
57495    The only assumption that can be made about \p cgs upon successful
57496    or exceptional return is that it can be safely destroyed.
57497  */
57498  void add_recycled_congruences(Congruence_System& cgs);
57499
57500  /*! \brief
57501    Adds to \p *this a congruence equivalent to constraint \p c.
57502
57503    \param c
57504    The constraint to be added.
57505
57506    \exception std::invalid_argument
57507    Thrown if \p *this and \p c are dimension-incompatible
57508    or if constraint \p c is not optimally supported by the grid domain.
57509  */
57510  void add_constraint(const Constraint& c);
57511
57512  /*! \brief
57513    Adds to \p *this congruences equivalent to the constraints in \p cs.
57514
57515    \param cs
57516    The constraints to be added.
57517
57518    \exception std::invalid_argument
57519    Thrown if \p *this and \p cs are dimension-incompatible
57520    or if \p cs contains a constraint which is not optimally supported
57521    by the grid domain.
57522  */
57523  void add_constraints(const Constraint_System& cs);
57524
57525  /*! \brief
57526    Adds to \p *this congruences equivalent to the constraints in \p cs.
57527
57528    \param cs
57529    The constraints to be added. They may be recycled.
57530
57531    \exception std::invalid_argument
57532    Thrown if \p *this and \p cs are dimension-incompatible
57533    or if \p cs contains a constraint which is not optimally supported
57534    by the grid domain.
57535
57536    \warning
57537    The only assumption that can be made about \p cs upon successful
57538    or exceptional return is that it can be safely destroyed.
57539  */
57540  void add_recycled_constraints(Constraint_System& cs);
57541
57542  //! Uses a copy of the congruence \p cg to refine \p *this.
57543  /*!
57544    \param cg
57545    The congruence used.
57546
57547    \exception std::invalid_argument
57548    Thrown if \p *this and congruence \p cg are dimension-incompatible.
57549  */
57550  void refine_with_congruence(const Congruence& cg);
57551
57552 //! Uses a copy of the congruences in \p cgs to refine \p *this.
57553  /*!
57554    \param cgs
57555    The congruences used.
57556
57557    \exception std::invalid_argument
57558    Thrown if \p *this and \p cgs are dimension-incompatible.
57559  */
57560  void refine_with_congruences(const Congruence_System& cgs);
57561
57562  //! Uses a copy of the constraint \p c to refine \p *this.
57563  /*!
57564
57565    \param c
57566    The constraint used. If it is not an equality, it will be ignored
57567
57568    \exception std::invalid_argument
57569    Thrown if \p *this and \p c are dimension-incompatible.
57570  */
57571  void refine_with_constraint(const Constraint& c);
57572
57573  //! Uses a copy of the constraints in \p cs to refine \p *this.
57574  /*!
57575    \param cs
57576    The constraints used. Constraints that are not equalities are ignored.
57577
57578    \exception std::invalid_argument
57579    Thrown if \p *this and \p cs are dimension-incompatible.
57580  */
57581  void refine_with_constraints(const Constraint_System& cs);
57582
57583  /*! \brief
57584    Adds a copy of the generators in \p gs to the system of generators
57585    of \p *this.
57586
57587    \param gs
57588    Contains the generators that will be added to the system of
57589    generators of \p *this.
57590
57591    \exception std::invalid_argument
57592    Thrown if \p *this and \p gs are dimension-incompatible, or if
57593    \p *this is empty and the system of generators \p gs is not empty,
57594    but has no points.
57595  */
57596  void add_grid_generators(const Grid_Generator_System& gs);
57597
57598  /*! \brief
57599    Adds the generators in \p gs to the system of generators of \p
57600    *this.
57601
57602    \param gs
57603    The generator system to be added to \p *this.  The generators in
57604    \p gs may be recycled.
57605
57606    \exception std::invalid_argument
57607    Thrown if \p *this and \p gs are dimension-incompatible.
57608
57609    \warning
57610    The only assumption that can be made about \p gs upon successful
57611    or exceptional return is that it can be safely destroyed.
57612  */
57613  void add_recycled_grid_generators(Grid_Generator_System& gs);
57614
57615  /*! \brief
57616    Computes the \ref Cylindrification "cylindrification" of \p *this with
57617    respect to space dimension \p var, assigning the result to \p *this.
57618
57619    \param var
57620    The space dimension that will be unconstrained.
57621
57622    \exception std::invalid_argument
57623    Thrown if \p var is not a space dimension of \p *this.
57624  */
57625  void unconstrain(Variable var);
57626
57627  /*! \brief
57628    Computes the \ref Cylindrification "cylindrification" of \p *this with
57629    respect to the set of space dimensions \p vars,
57630    assigning the result to \p *this.
57631
57632    \param vars
57633    The set of space dimension that will be unconstrained.
57634
57635    \exception std::invalid_argument
57636    Thrown if \p *this is dimension-incompatible with one of the
57637    Variable objects contained in \p vars.
57638  */
57639  void unconstrain(const Variables_Set& vars);
57640
57641  /*! \brief
57642    Assigns to \p *this the intersection of \p *this and \p y.
57643
57644    \exception std::invalid_argument
57645    Thrown if \p *this and \p y are dimension-incompatible.
57646  */
57647  void intersection_assign(const Grid& y);
57648
57649  /*! \brief
57650    Assigns to \p *this the least upper bound of \p *this and \p y.
57651
57652    \exception std::invalid_argument
57653    Thrown if \p *this and \p y are dimension-incompatible.
57654  */
57655  void upper_bound_assign(const Grid& y);
57656
57657  /*! \brief
57658    If the upper bound of \p *this and \p y is exact it is assigned to \p
57659    *this and <CODE>true</CODE> is returned, otherwise
57660    <CODE>false</CODE> is returned.
57661
57662    \exception std::invalid_argument
57663    Thrown if \p *this and \p y are dimension-incompatible.
57664  */
57665  bool upper_bound_assign_if_exact(const Grid& y);
57666
57667  /*! \brief
57668    Assigns to \p *this the \ref Convex_Polyhedral_Difference "grid-difference"
57669    of \p *this and \p y.
57670
57671    The grid difference between grids x and y is the smallest grid
57672    containing all the points from x and y that are only in x.
57673
57674    \exception std::invalid_argument
57675    Thrown if \p *this and \p y are dimension-incompatible.
57676  */
57677  void difference_assign(const Grid& y);
57678
57679  /*! \brief
57680    Assigns to \p *this a \ref Meet_Preserving_Simplification
57681    "meet-preserving simplification" of \p *this with respect to \p y.
57682    If \c false is returned, then the intersection is empty.
57683
57684    \exception std::invalid_argument
57685    Thrown if \p *this and \p y are topology-incompatible or
57686    dimension-incompatible.
57687  */
57688  bool simplify_using_context_assign(const Grid& y);
57689
57690  /*! \brief
57691    Assigns to \p *this the \ref Grid_Affine_Transformation
57692    "affine image" of \p
57693    *this under the function mapping variable \p var to the affine
57694    expression specified by \p expr and \p denominator.
57695
57696    \param var
57697    The variable to which the affine expression is assigned;
57698
57699    \param expr
57700    The numerator of the affine expression;
57701
57702    \param denominator
57703    The denominator of the affine expression (optional argument with
57704    default value 1).
57705
57706    \exception std::invalid_argument
57707    Thrown if \p denominator is zero or if \p expr and \p *this are
57708    dimension-incompatible or if \p var is not a space dimension of
57709    \p *this.
57710
57711    \if Include_Implementation_Details
57712
57713    When considering the generators of a grid, the
57714    affine transformation
57715    \f[
57716      \frac{\sum_{i=0}^{n-1} a_i x_i + b}{\mathrm{denominator}}
57717    \f]
57718    is assigned to \p var where \p expr is
57719    \f$\sum_{i=0}^{n-1} a_i x_i + b\f$
57720    (\f$b\f$ is the inhomogeneous term).
57721
57722    If congruences are up-to-date, it uses the specialized function
57723    affine_preimage() (for the system of congruences)
57724    and inverse transformation to reach the same result.
57725    To obtain the inverse transformation we use the following observation.
57726
57727    Observation:
57728    -# The affine transformation is invertible if the coefficient
57729       of \p var in this transformation (i.e., \f$a_\mathrm{var}\f$)
57730       is different from zero.
57731    -# If the transformation is invertible, then we can write
57732       \f[
57733         \mathrm{denominator} * {x'}_\mathrm{var}
57734           = \sum_{i = 0}^{n - 1} a_i x_i + b
57735           = a_\mathrm{var} x_\mathrm{var}
57736             + \sum_{i \neq var} a_i x_i + b,
57737       \f]
57738       so that the inverse transformation is
57739       \f[
57740         a_\mathrm{var} x_\mathrm{var}
57741           = \mathrm{denominator} * {x'}_\mathrm{var}
57742             - \sum_{i \neq j} a_i x_i - b.
57743       \f]
57744
57745    Then, if the transformation is invertible, all the entities that
57746    were up-to-date remain up-to-date. Otherwise only generators remain
57747    up-to-date.
57748
57749    \endif
57750  */
57751  void affine_image(Variable var,
57752                    const Linear_Expression& expr,
57753                    Coefficient_traits::const_reference denominator
57754                    = Coefficient_one());
57755
57756  /*! \brief
57757    Assigns to \p *this the \ref Grid_Affine_Transformation
57758    "affine preimage" of
57759    \p *this under the function mapping variable \p var to the affine
57760    expression specified by \p expr and \p denominator.
57761
57762    \param var
57763    The variable to which the affine expression is substituted;
57764
57765    \param expr
57766    The numerator of the affine expression;
57767
57768    \param denominator
57769    The denominator of the affine expression (optional argument with
57770    default value 1).
57771
57772    \exception std::invalid_argument
57773    Thrown if \p denominator is zero or if \p expr and \p *this are
57774    dimension-incompatible or if \p var is not a space dimension of \p *this.
57775
57776    \if Include_Implementation_Details
57777
57778    When considering congruences of a grid, the affine transformation
57779    \f[
57780      \frac{\sum_{i=0}^{n-1} a_i x_i + b}{denominator},
57781    \f]
57782    is assigned to \p var where \p expr is
57783    \f$\sum_{i=0}^{n-1} a_i x_i + b\f$
57784    (\f$b\f$ is the inhomogeneous term).
57785
57786    If generators are up-to-date, then the specialized function
57787    affine_image() is used (for the system of generators)
57788    and inverse transformation to reach the same result.
57789    To obtain the inverse transformation, we use the following observation.
57790
57791    Observation:
57792    -# The affine transformation is invertible if the coefficient
57793       of \p var in this transformation (i.e. \f$a_\mathrm{var}\f$)
57794       is different from zero.
57795    -# If the transformation is invertible, then we can write
57796       \f[
57797         \mathrm{denominator} * {x'}_\mathrm{var}
57798           = \sum_{i = 0}^{n - 1} a_i x_i + b
57799           = a_\mathrm{var} x_\mathrm{var}
57800               + \sum_{i \neq \mathrm{var}} a_i x_i + b,
57801       \f],
57802       the inverse transformation is
57803       \f[
57804         a_\mathrm{var} x_\mathrm{var}
57805           = \mathrm{denominator} * {x'}_\mathrm{var}
57806               - \sum_{i \neq j} a_i x_i - b.
57807       \f].
57808
57809    Then, if the transformation is invertible, all the entities that
57810    were up-to-date remain up-to-date. Otherwise only congruences remain
57811    up-to-date.
57812
57813    \endif
57814  */
57815  void affine_preimage(Variable var,
57816                       const Linear_Expression& expr,
57817                       Coefficient_traits::const_reference denominator
57818                         = Coefficient_one());
57819
57820  /*! \brief
57821    Assigns to \p *this the image of \p *this with respect to
57822    the \ref Grid_Generalized_Image "generalized affine relation"
57823    \f$\mathrm{var}' = \frac{\mathrm{expr}}{\mathrm{denominator}}
57824    \pmod{\mathrm{modulus}}\f$.
57825
57826    \param var
57827    The left hand side variable of the generalized affine relation;
57828
57829    \param relsym
57830    The relation symbol where EQUAL is the symbol for a congruence
57831    relation;
57832
57833    \param expr
57834    The numerator of the right hand side affine expression;
57835
57836    \param denominator
57837    The denominator of the right hand side affine expression.
57838    Optional argument with an automatic value of one;
57839
57840    \param modulus
57841    The modulus of the congruence lhs %= rhs.  A modulus of zero
57842    indicates lhs == rhs.  Optional argument with an automatic value
57843    of zero.
57844
57845    \exception std::invalid_argument
57846    Thrown if \p denominator is zero or if \p expr and \p *this are
57847    dimension-incompatible or if \p var is not a space dimension of \p
57848    *this.
57849  */
57850  void
57851  generalized_affine_image(Variable var,
57852                           Relation_Symbol relsym,
57853                           const Linear_Expression& expr,
57854                           Coefficient_traits::const_reference denominator
57855                           = Coefficient_one(),
57856                           Coefficient_traits::const_reference modulus
57857                           = Coefficient_zero());
57858
57859  /*! \brief
57860    Assigns to \p *this the preimage of \p *this with respect to the
57861    \ref Grid_Generalized_Image "generalized affine relation"
57862    \f$\mathrm{var}' = \frac{\mathrm{expr}}{\mathrm{denominator}}
57863    \pmod{\mathrm{modulus}}\f$.
57864
57865    \param var
57866    The left hand side variable of the generalized affine relation;
57867
57868    \param relsym
57869    The relation symbol where EQUAL is the symbol for a congruence
57870    relation;
57871
57872    \param expr
57873    The numerator of the right hand side affine expression;
57874
57875    \param denominator
57876    The denominator of the right hand side affine expression.
57877    Optional argument with an automatic value of one;
57878
57879    \param modulus
57880    The modulus of the congruence lhs %= rhs.  A modulus of zero
57881    indicates lhs == rhs.  Optional argument with an automatic value
57882    of zero.
57883
57884    \exception std::invalid_argument
57885    Thrown if \p denominator is zero or if \p expr and \p *this are
57886    dimension-incompatible or if \p var is not a space dimension of \p
57887    *this.
57888  */
57889  void
57890  generalized_affine_preimage(Variable var,
57891                              Relation_Symbol relsym,
57892                              const Linear_Expression& expr,
57893                              Coefficient_traits::const_reference denominator
57894                              = Coefficient_one(),
57895                              Coefficient_traits::const_reference modulus
57896                              = Coefficient_zero());
57897
57898  /*! \brief
57899    Assigns to \p *this the image of \p *this with respect to
57900    the \ref Grid_Generalized_Image "generalized affine relation"
57901    \f$\mathrm{lhs}' = \mathrm{rhs} \pmod{\mathrm{modulus}}\f$.
57902
57903    \param lhs
57904    The left hand side affine expression.
57905
57906    \param relsym
57907    The relation symbol where EQUAL is the symbol for a congruence
57908    relation;
57909
57910    \param rhs
57911    The right hand side affine expression.
57912
57913    \param modulus
57914    The modulus of the congruence lhs %= rhs.  A modulus of zero
57915    indicates lhs == rhs.  Optional argument with an automatic value
57916    of zero.
57917
57918    \exception std::invalid_argument
57919    Thrown if \p *this is dimension-incompatible with \p lhs or \p
57920    rhs.
57921  */
57922  void
57923  generalized_affine_image(const Linear_Expression& lhs,
57924                           Relation_Symbol relsym,
57925                           const Linear_Expression& rhs,
57926                           Coefficient_traits::const_reference modulus
57927                           = Coefficient_zero());
57928
57929  /*! \brief
57930    Assigns to \p *this the preimage of \p *this with respect to the
57931    \ref Grid_Generalized_Image "generalized affine relation"
57932    \f$\mathrm{lhs}' = \mathrm{rhs} \pmod{\mathrm{modulus}}\f$.
57933
57934    \param lhs
57935    The left hand side affine expression;
57936
57937    \param relsym
57938    The relation symbol where EQUAL is the symbol for a congruence
57939    relation;
57940
57941    \param rhs
57942    The right hand side affine expression;
57943
57944    \param modulus
57945    The modulus of the congruence lhs %= rhs.  A modulus of zero
57946    indicates lhs == rhs.  Optional argument with an automatic value
57947    of zero.
57948
57949    \exception std::invalid_argument
57950    Thrown if \p *this is dimension-incompatible with \p lhs or \p
57951    rhs.
57952  */
57953  void
57954  generalized_affine_preimage(const Linear_Expression& lhs,
57955                              Relation_Symbol relsym,
57956                              const Linear_Expression& rhs,
57957                              Coefficient_traits::const_reference modulus
57958                              = Coefficient_zero());
57959
57960  /*!
57961    \brief
57962    Assigns to \p *this the image of \p *this with respect to the
57963    \ref Single_Update_Bounded_Affine_Relations "bounded affine relation"
57964    \f$\frac{\mathrm{lb\_expr}}{\mathrm{denominator}}
57965         \leq \mathrm{var}'
57966           \leq \frac{\mathrm{ub\_expr}}{\mathrm{denominator}}\f$.
57967
57968    \param var
57969    The variable updated by the affine relation;
57970
57971    \param lb_expr
57972    The numerator of the lower bounding affine expression;
57973
57974    \param ub_expr
57975    The numerator of the upper bounding affine expression;
57976
57977    \param denominator
57978    The (common) denominator for the lower and upper bounding
57979    affine expressions (optional argument with default value 1).
57980
57981    \exception std::invalid_argument
57982    Thrown if \p denominator is zero or if \p lb_expr (resp., \p ub_expr)
57983    and \p *this are dimension-incompatible or if \p var is not a space
57984    dimension of \p *this.
57985  */
57986  void bounded_affine_image(Variable var,
57987                            const Linear_Expression& lb_expr,
57988                            const Linear_Expression& ub_expr,
57989                            Coefficient_traits::const_reference denominator
57990                            = Coefficient_one());
57991
57992  /*!
57993    \brief
57994    Assigns to \p *this the preimage of \p *this with respect to the
57995    \ref Single_Update_Bounded_Affine_Relations "bounded affine relation"
57996    \f$\frac{\mathrm{lb\_expr}}{\mathrm{denominator}}
57997         \leq \mathrm{var}'
57998           \leq \frac{\mathrm{ub\_expr}}{\mathrm{denominator}}\f$.
57999
58000    \param var
58001    The variable updated by the affine relation;
58002
58003    \param lb_expr
58004    The numerator of the lower bounding affine expression;
58005
58006    \param ub_expr
58007    The numerator of the upper bounding affine expression;
58008
58009    \param denominator
58010    The (common) denominator for the lower and upper bounding
58011    affine expressions (optional argument with default value 1).
58012
58013    \exception std::invalid_argument
58014    Thrown if \p denominator is zero or if \p lb_expr (resp., \p ub_expr)
58015    and \p *this are dimension-incompatible or if \p var is not a space
58016    dimension of \p *this.
58017  */
58018  void bounded_affine_preimage(Variable var,
58019                               const Linear_Expression& lb_expr,
58020                               const Linear_Expression& ub_expr,
58021                               Coefficient_traits::const_reference denominator
58022                               = Coefficient_one());
58023
58024  /*! \brief
58025    Assigns to \p *this the result of computing the \ref Grid_Time_Elapse
58026    "time-elapse" between \p *this and \p y.
58027
58028    \exception std::invalid_argument
58029    Thrown if \p *this and \p y are dimension-incompatible.
58030  */
58031  void time_elapse_assign(const Grid& y);
58032
58033  /*! \brief
58034    \ref Wrapping_Operator "Wraps" the specified dimensions of the
58035    vector space.
58036
58037    \param vars
58038    The set of Variable objects corresponding to the space dimensions
58039    to be wrapped.
58040
58041    \param w
58042    The width of the bounded integer type corresponding to
58043    all the dimensions to be wrapped.
58044
58045    \param r
58046    The representation of the bounded integer type corresponding to
58047    all the dimensions to be wrapped.
58048
58049    \param o
58050    The overflow behavior of the bounded integer type corresponding to
58051    all the dimensions to be wrapped.
58052
58053    \param cs_p
58054    Possibly null pointer to a constraint system.
58055    This argument is for compatibility with wrap_assign()
58056    for the other domains and only checked for dimension-compatibility.
58057
58058    \param complexity_threshold
58059    A precision parameter of the \ref Wrapping_Operator "wrapping operator".
58060    This argument is for compatibility with wrap_assign()
58061    for the other domains and is ignored.
58062
58063    \param wrap_individually
58064    <CODE>true</CODE> if the dimensions should be wrapped individually.
58065    As wrapping dimensions collectively does not improve the precision,
58066    this argument is ignored.
58067
58068    \exception std::invalid_argument
58069    Thrown if \p *this is dimension-incompatible with one of the
58070    Variable objects contained in \p vars or with <CODE>*cs_p</CODE>.
58071
58072    \warning
58073    It is assumed that variables in \p Vars represent integers.  Thus,
58074    where the extra cost is negligible, the integrality of these
58075    variables is enforced; possibly causing a non-integral grid to
58076    become empty.
58077  */
58078  void wrap_assign(const Variables_Set& vars,
58079                   Bounded_Integer_Type_Width w,
58080                   Bounded_Integer_Type_Representation r,
58081                   Bounded_Integer_Type_Overflow o,
58082                   const Constraint_System* cs_p = 0,
58083                   unsigned complexity_threshold = 16,
58084                   bool wrap_individually = true);
58085
58086  /*! \brief
58087    Possibly tightens \p *this by dropping all points with non-integer
58088    coordinates.
58089
58090    \param complexity
58091    This argument is ignored as the algorithm used has polynomial
58092    complexity.
58093  */
58094  void drop_some_non_integer_points(Complexity_Class complexity
58095                                    = ANY_COMPLEXITY);
58096
58097  /*! \brief
58098    Possibly tightens \p *this by dropping all points with non-integer
58099    coordinates for the space dimensions corresponding to \p vars.
58100
58101    \param vars
58102    Points with non-integer coordinates for these variables/space-dimensions
58103    can be discarded.
58104
58105    \param complexity
58106    This argument is ignored as the algorithm used has polynomial
58107    complexity.
58108  */
58109  void drop_some_non_integer_points(const Variables_Set& vars,
58110                                    Complexity_Class complexity
58111                                    = ANY_COMPLEXITY);
58112
58113  //! Assigns to \p *this its topological closure.
58114  void topological_closure_assign();
58115
58116  /*! \brief
58117    Assigns to \p *this the result of computing the \ref Grid_Widening
58118    "Grid widening" between \p *this and \p y using congruence systems.
58119
58120    \param y
58121    A grid that <EM>must</EM> be contained in \p *this;
58122
58123    \param tp
58124    An optional pointer to an unsigned variable storing the number of
58125    available tokens (to be used when applying the
58126    \ref Grid_Widening_with_Tokens "widening with tokens" delay technique).
58127
58128    \exception std::invalid_argument
58129    Thrown if \p *this and \p y are dimension-incompatible.
58130  */
58131  void congruence_widening_assign(const Grid& y, unsigned* tp = NULL);
58132
58133  /*! \brief
58134    Assigns to \p *this the result of computing the \ref Grid_Widening
58135    "Grid widening" between \p *this and \p y using generator systems.
58136
58137    \param y
58138    A grid that <EM>must</EM> be contained in \p *this;
58139
58140    \param tp
58141    An optional pointer to an unsigned variable storing the number of
58142    available tokens (to be used when applying the
58143    \ref Grid_Widening_with_Tokens "widening with tokens" delay technique).
58144
58145    \exception std::invalid_argument
58146    Thrown if \p *this and \p y are dimension-incompatible.
58147  */
58148  void generator_widening_assign(const Grid& y, unsigned* tp = NULL);
58149
58150  /*! \brief
58151    Assigns to \p *this the result of computing the \ref Grid_Widening
58152    "Grid widening" between \p *this and \p y.
58153
58154    This widening uses either the congruence or generator systems
58155    depending on which of the systems describing x and y
58156    are up to date and minimized.
58157
58158    \param y
58159    A grid that <EM>must</EM> be contained in \p *this;
58160
58161    \param tp
58162    An optional pointer to an unsigned variable storing the number of
58163    available tokens (to be used when applying the
58164    \ref Grid_Widening_with_Tokens "widening with tokens" delay technique).
58165
58166    \exception std::invalid_argument
58167    Thrown if \p *this and \p y are dimension-incompatible.
58168  */
58169  void widening_assign(const Grid& y, unsigned* tp = NULL);
58170
58171  /*! \brief
58172    Improves the result of the congruence variant of
58173    \ref Grid_Widening "Grid widening" computation by also enforcing
58174    those congruences in \p cgs that are satisfied by all the points
58175    of \p *this.
58176
58177    \param y
58178    A grid that <EM>must</EM> be contained in \p *this;
58179
58180    \param cgs
58181    The system of congruences used to improve the widened grid;
58182
58183    \param tp
58184    An optional pointer to an unsigned variable storing the number of
58185    available tokens (to be used when applying the
58186    \ref Grid_Widening_with_Tokens "widening with tokens" delay technique).
58187
58188    \exception std::invalid_argument
58189    Thrown if \p *this, \p y and \p cgs are dimension-incompatible.
58190  */
58191  void limited_congruence_extrapolation_assign(const Grid& y,
58192                                               const Congruence_System& cgs,
58193                                               unsigned* tp = NULL);
58194
58195  /*! \brief
58196    Improves the result of the generator variant of the
58197    \ref Grid_Widening "Grid widening"
58198    computation by also enforcing those congruences in \p cgs that are
58199    satisfied by all the points of \p *this.
58200
58201    \param y
58202    A grid that <EM>must</EM> be contained in \p *this;
58203
58204    \param cgs
58205    The system of congruences used to improve the widened grid;
58206
58207    \param tp
58208    An optional pointer to an unsigned variable storing the number of
58209    available tokens (to be used when applying the
58210    \ref Grid_Widening_with_Tokens "widening with tokens" delay technique).
58211
58212    \exception std::invalid_argument
58213    Thrown if \p *this, \p y and \p cgs are dimension-incompatible.
58214  */
58215  void limited_generator_extrapolation_assign(const Grid& y,
58216                                              const Congruence_System& cgs,
58217                                              unsigned* tp = NULL);
58218
58219  /*! \brief
58220    Improves the result of the \ref Grid_Widening "Grid widening"
58221    computation by also enforcing those congruences in \p cgs that are
58222    satisfied by all the points of \p *this.
58223
58224    \param y
58225    A grid that <EM>must</EM> be contained in \p *this;
58226
58227    \param cgs
58228    The system of congruences used to improve the widened grid;
58229
58230    \param tp
58231    An optional pointer to an unsigned variable storing the number of
58232    available tokens (to be used when applying the
58233    \ref Grid_Widening_with_Tokens "widening with tokens" delay technique).
58234
58235    \exception std::invalid_argument
58236    Thrown if \p *this, \p y and \p cgs are dimension-incompatible.
58237  */
58238  void limited_extrapolation_assign(const Grid& y,
58239                                    const Congruence_System& cgs,
58240                                    unsigned* tp = NULL);
58241
58242  //@} // Space Dimension Preserving Member Functions that May Modify [...]
58243
58244  //! \name Member Functions that May Modify the Dimension of the Vector Space
58245  //@{
58246
58247  /*! \brief
58248    \ref Adding_New_Dimensions_to_the_Vector_Space "Adds"
58249    \p m new space dimensions and embeds the old grid in the new
58250    vector space.
58251
58252    \param m
58253    The number of dimensions to add.
58254
58255    \exception std::length_error
58256    Thrown if adding \p m new space dimensions would cause the vector
58257    space to exceed dimension <CODE>max_space_dimension()</CODE>.
58258
58259    The new space dimensions will be those having the highest indexes
58260    in the new grid, which is characterized by a system of congruences
58261    in which the variables which are the new dimensions can have any
58262    value.  For instance, when starting from the grid \f$\cL \sseq
58263    \Rset^2\f$ and adding a third space dimension, the result will be
58264    the grid
58265    \f[
58266      \bigl\{\,
58267        (x, y, z)^\transpose \in \Rset^3
58268      \bigm|
58269        (x, y)^\transpose \in \cL
58270      \,\bigr\}.
58271    \f]
58272  */
58273  void add_space_dimensions_and_embed(dimension_type m);
58274
58275  /*! \brief
58276    \ref Adding_New_Dimensions_to_the_Vector_Space "Adds"
58277    \p m new space dimensions to the grid and does not embed it
58278    in the new vector space.
58279
58280    \param m
58281    The number of space dimensions to add.
58282
58283    \exception std::length_error
58284    Thrown if adding \p m new space dimensions would cause the
58285    vector space to exceed dimension <CODE>max_space_dimension()</CODE>.
58286
58287    The new space dimensions will be those having the highest indexes
58288    in the new grid, which is characterized by a system of congruences
58289    in which the variables running through the new dimensions are all
58290    constrained to be equal to 0.  For instance, when starting from
58291    the grid \f$\cL \sseq \Rset^2\f$ and adding a third space
58292    dimension, the result will be the grid
58293    \f[
58294      \bigl\{\,
58295        (x, y, 0)^\transpose \in \Rset^3
58296      \bigm|
58297        (x, y)^\transpose \in \cL
58298      \,\bigr\}.
58299    \f]
58300  */
58301  void add_space_dimensions_and_project(dimension_type m);
58302
58303  /*! \brief
58304    Assigns to \p *this the \ref Concatenating_Polyhedra "concatenation" of
58305    \p *this and \p y, taken in this order.
58306
58307    \exception std::length_error
58308    Thrown if the concatenation would cause the vector space
58309    to exceed dimension <CODE>max_space_dimension()</CODE>.
58310  */
58311  void concatenate_assign(const Grid& y);
58312
58313  //! Removes all the specified dimensions from the vector space.
58314  /*!
58315    \param vars
58316    The set of Variable objects corresponding to the space dimensions
58317    to be removed.
58318
58319    \exception std::invalid_argument
58320    Thrown if \p *this is dimension-incompatible with one of the
58321    Variable objects contained in \p vars.
58322  */
58323  void remove_space_dimensions(const Variables_Set& vars);
58324
58325  /*! \brief
58326    Removes the higher dimensions of the vector space so that the
58327    resulting space will have \ref Removing_Dimensions_from_the_Vector_Space
58328    "dimension \p new_dimension."
58329
58330    \exception std::invalid_argument
58331    Thrown if \p new_dimensions is greater than the space dimension of
58332    \p *this.
58333  */
58334  void remove_higher_space_dimensions(dimension_type new_dimension);
58335
58336  /*! \brief
58337    Remaps the dimensions of the vector space according to
58338    a \ref Mapping_the_Dimensions_of_the_Vector_Space "partial function".
58339
58340    If \p pfunc maps only some of the dimensions of \p *this then the
58341    rest will be projected away.
58342
58343    If the highest dimension mapped to by \p pfunc is higher than the
58344    highest dimension in \p *this then the number of dimensions in \p
58345    *this will be increased to the highest dimension mapped to by \p
58346    pfunc.
58347
58348    \param pfunc
58349    The partial function specifying the destiny of each space
58350    dimension.
58351
58352    The template type parameter Partial_Function must provide
58353    the following methods.
58354    \code
58355      bool has_empty_codomain() const
58356    \endcode
58357    returns <CODE>true</CODE> if and only if the represented partial
58358    function has an empty codomain (i.e., it is always undefined).
58359    The <CODE>has_empty_codomain()</CODE> method will always be called
58360    before the methods below.  However, if
58361    <CODE>has_empty_codomain()</CODE> returns <CODE>true</CODE>, none
58362    of the functions below will be called.
58363    \code
58364      dimension_type max_in_codomain() const
58365    \endcode
58366    returns the maximum value that belongs to the codomain of the
58367    partial function.
58368    The <CODE>max_in_codomain()</CODE> method is called at most once.
58369    \code
58370      bool maps(dimension_type i, dimension_type& j) const
58371    \endcode
58372    Let \f$f\f$ be the represented function and \f$k\f$ be the value
58373    of \p i.  If \f$f\f$ is defined in \f$k\f$, then \f$f(k)\f$ is
58374    assigned to \p j and <CODE>true</CODE> is returned.  If \f$f\f$ is
58375    undefined in \f$k\f$, then <CODE>false</CODE> is returned.
58376    This method is called at most \f$n\f$ times, where \f$n\f$ is the
58377    dimension of the vector space enclosing the grid.
58378
58379    The result is undefined if \p pfunc does not encode a partial
58380    function with the properties described in the
58381    \ref Mapping_the_Dimensions_of_the_Vector_Space "specification of the mapping operator".
58382  */
58383  template <typename Partial_Function>
58384  void map_space_dimensions(const Partial_Function& pfunc);
58385
58386  //! Creates \p m copies of the space dimension corresponding to \p var.
58387  /*!
58388    \param var
58389    The variable corresponding to the space dimension to be replicated;
58390
58391    \param m
58392    The number of replicas to be created.
58393
58394    \exception std::invalid_argument
58395    Thrown if \p var does not correspond to a dimension of the vector
58396    space.
58397
58398    \exception std::length_error
58399    Thrown if adding \p m new space dimensions would cause the vector
58400    space to exceed dimension <CODE>max_space_dimension()</CODE>.
58401
58402    If \p *this has space dimension \f$n\f$, with \f$n > 0\f$,
58403    and <CODE>var</CODE> has space dimension \f$k \leq n\f$,
58404    then the \f$k\f$-th space dimension is
58405    \ref Expanding_One_Dimension_of_the_Vector_Space_to_Multiple_Dimensions
58406    "expanded" to \p m new space dimensions
58407    \f$n\f$, \f$n+1\f$, \f$\dots\f$, \f$n+m-1\f$.
58408  */
58409  void expand_space_dimension(Variable var, dimension_type m);
58410
58411  //! Folds the space dimensions in \p vars into \p dest.
58412  /*!
58413    \param vars
58414    The set of Variable objects corresponding to the space dimensions
58415    to be folded;
58416
58417    \param dest
58418    The variable corresponding to the space dimension that is the
58419    destination of the folding operation.
58420
58421    \exception std::invalid_argument
58422    Thrown if \p *this is dimension-incompatible with \p dest or with
58423    one of the Variable objects contained in \p vars.  Also
58424    thrown if \p dest is contained in \p vars.
58425
58426    If \p *this has space dimension \f$n\f$, with \f$n > 0\f$,
58427    <CODE>dest</CODE> has space dimension \f$k \leq n\f$,
58428    \p vars is a set of variables whose maximum space dimension
58429    is also less than or equal to \f$n\f$, and \p dest is not a member
58430    of \p vars, then the space dimensions corresponding to
58431    variables in \p vars are
58432    \ref Folding_Multiple_Dimensions_of_the_Vector_Space_into_One_Dimension "folded"
58433    into the \f$k\f$-th space dimension.
58434  */
58435  void fold_space_dimensions(const Variables_Set& vars, Variable dest);
58436
58437  //@} // Member Functions that May Modify the Dimension of the Vector Space
58438
58439  friend bool operator==(const Grid& x, const Grid& y);
58440
58441  friend class Parma_Polyhedra_Library::Grid_Certificate;
58442
58443  template <typename Interval> friend class Parma_Polyhedra_Library::Box;
58444
58445  //! \name Miscellaneous Member Functions
58446  //@{
58447
58448  //! Destructor.
58449  ~Grid();
58450
58451  /*! \brief
58452    Swaps \p *this with grid \p y.  (\p *this and \p y can be
58453    dimension-incompatible.)
58454  */
58455  void m_swap(Grid& y);
58456
58457  PPL_OUTPUT_DECLARATIONS
58458
58459  /*! \brief
58460    Loads from \p s an ASCII representation (as produced by
58461    ascii_dump(std::ostream&) const) and sets \p *this accordingly.
58462    Returns <CODE>true</CODE> if successful, <CODE>false</CODE> otherwise.
58463  */
58464  bool ascii_load(std::istream& s);
58465
58466  //! Returns the total size in bytes of the memory occupied by \p *this.
58467  memory_size_type total_memory_in_bytes() const;
58468
58469  //! Returns the size in bytes of the memory managed by \p *this.
58470  memory_size_type external_memory_in_bytes() const;
58471
58472  /*! \brief
58473    Returns a 32-bit hash code for \p *this.
58474
58475    If \p x and \p y are such that <CODE>x == y</CODE>,
58476    then <CODE>x.hash_code() == y.hash_code()</CODE>.
58477  */
58478  int32_t hash_code() const;
58479
58480  //@} // Miscellaneous Member Functions
58481
58482private:
58483
58484  //! The system of congruences.
58485  Congruence_System con_sys;
58486
58487  //! The system of generators.
58488  Grid_Generator_System gen_sys;
58489
58490#define PPL_IN_Grid_CLASS
58491/* Automatically generated from PPL source file ../src/Grid_Status_idefs.hh line 1. */
58492/* Grid::Status class declaration.
58493*/
58494
58495
58496#ifndef PPL_IN_Grid_CLASS
58497#error "Do not include Grid_Status_idefs.hh directly; use Grid_defs.hh instead"
58498#endif
58499
58500//! A conjunctive assertion about a grid.
58501/*!
58502  The assertions supported that are in use are:
58503  - <EM>zero-dim universe</EM>: the grid is the zero-dimension
58504    vector space \f$\Rset^0 = \{\cdot\}\f$;
58505  - <EM>empty</EM>: the grid is the empty set;
58506  - <EM>congruences up-to-date</EM>: the grid is correctly
58507    characterized by the attached system of congruences, modulo the
58508    processing of pending generators;
58509  - <EM>generators up-to-date</EM>: the grid is correctly
58510    characterized by the attached system of generators, modulo the
58511    processing of pending congruences;
58512  - <EM>congruences minimized</EM>: the non-pending part of the system
58513    of congruences attached to the grid is in minimal form;
58514  - <EM>generators minimized</EM>: the non-pending part of the system
58515    of generators attached to the grid is in minimal form.
58516
58517  Other supported assertions are:
58518  - <EM>congruences pending</EM>
58519  - <EM>generators pending</EM>
58520  - <EM>congruences' saturation matrix up-to-date</EM>
58521  - <EM>generators' saturation matrix up-to-date</EM>.
58522
58523  Not all the conjunctions of these elementary assertions constitute
58524  a legal Status.  In fact:
58525  - <EM>zero-dim universe</EM> excludes any other assertion;
58526  - <EM>empty</EM>: excludes any other assertion;
58527  - <EM>congruences pending</EM> and <EM>generators pending</EM>
58528    are mutually exclusive;
58529  - <EM>congruences pending</EM> implies both <EM>congruences minimized</EM>
58530    and <EM>generators minimized</EM>;
58531  - <EM>generators pending</EM> implies both <EM>congruences minimized</EM>
58532    and <EM>generators minimized</EM>;
58533  - <EM>congruences minimized</EM> implies <EM>congruences up-to-date</EM>;
58534  - <EM>generators minimized</EM> implies <EM>generators up-to-date</EM>;
58535  - <EM>congruences' saturation matrix up-to-date</EM> implies both
58536    <EM>congruences up-to-date</EM> and <EM>generators up-to-date</EM>;
58537  - <EM>generators' saturation matrix up-to-date</EM> implies both
58538    <EM>congruences up-to-date</EM> and <EM>generators up-to-date</EM>.
58539*/
58540class Status {
58541public:
58542  //! By default Status is the <EM>zero-dim universe</EM> assertion.
58543  Status();
58544
58545  //! \name Test, remove or add an individual assertion from the conjunction
58546  //@{
58547  bool test_zero_dim_univ() const;
58548  void reset_zero_dim_univ();
58549  void set_zero_dim_univ();
58550
58551  bool test_empty() const;
58552  void reset_empty();
58553  void set_empty();
58554
58555  bool test_c_up_to_date() const;
58556  void reset_c_up_to_date();
58557  void set_c_up_to_date();
58558
58559  bool test_g_up_to_date() const;
58560  void reset_g_up_to_date();
58561  void set_g_up_to_date();
58562
58563  bool test_c_minimized() const;
58564  void reset_c_minimized();
58565  void set_c_minimized();
58566
58567  bool test_g_minimized() const;
58568  void reset_g_minimized();
58569  void set_g_minimized();
58570
58571  bool test_sat_c_up_to_date() const;
58572  void reset_sat_c_up_to_date();
58573  void set_sat_c_up_to_date();
58574
58575  bool test_sat_g_up_to_date() const;
58576  void reset_sat_g_up_to_date();
58577  void set_sat_g_up_to_date();
58578
58579  bool test_c_pending() const;
58580  void reset_c_pending();
58581  void set_c_pending();
58582
58583  bool test_g_pending() const;
58584  void reset_g_pending();
58585  void set_g_pending();
58586  //@} // Test, remove or add an individual assertion from the conjunction
58587
58588  //! Checks if all the invariants are satisfied.
58589  bool OK() const;
58590
58591  PPL_OUTPUT_DECLARATIONS
58592
58593  /*! \brief
58594    Loads from \p s an ASCII representation (as produced by
58595    ascii_dump(std::ostream&) const) and sets \p *this accordingly.
58596    Returns <CODE>true</CODE> if successful, <CODE>false</CODE> otherwise.
58597  */
58598  bool ascii_load(std::istream& s);
58599
58600private:
58601  //! Status is implemented by means of a finite bitset.
58602  typedef unsigned int flags_t;
58603
58604  //! \name Bitmasks for the individual assertions
58605  //@{
58606  static const flags_t ZERO_DIM_UNIV    = 0U;
58607  static const flags_t EMPTY            = 1U << 0;
58608  static const flags_t C_UP_TO_DATE     = 1U << 1;
58609  static const flags_t G_UP_TO_DATE     = 1U << 2;
58610  static const flags_t C_MINIMIZED      = 1U << 3;
58611  static const flags_t G_MINIMIZED      = 1U << 4;
58612  static const flags_t SAT_C_UP_TO_DATE = 1U << 5;
58613  static const flags_t SAT_G_UP_TO_DATE = 1U << 6;
58614  static const flags_t CS_PENDING       = 1U << 7;
58615  static const flags_t GS_PENDING       = 1U << 8;
58616  //@} // Bitmasks for the individual assertions
58617
58618  //! This holds the current bitset.
58619  flags_t flags;
58620
58621  //! Construct from a bitmask.
58622  Status(flags_t mask);
58623
58624  //! Check whether <EM>all</EM> bits in \p mask are set.
58625  bool test_all(flags_t mask) const;
58626
58627  //! Check whether <EM>at least one</EM> bit in \p mask is set.
58628  bool test_any(flags_t mask) const;
58629
58630  //! Set the bits in \p mask.
58631  void set(flags_t mask);
58632
58633  //! Reset the bits in \p mask.
58634  void reset(flags_t mask);
58635};
58636
58637/* Automatically generated from PPL source file ../src/Grid_defs.hh line 1977. */
58638#undef PPL_IN_Grid_CLASS
58639
58640  //! The status flags to keep track of the grid's internal state.
58641  Status status;
58642
58643  //! The number of dimensions of the enclosing vector space.
58644  dimension_type space_dim;
58645
58646  enum Dimension_Kind {
58647    PARAMETER = 0,
58648    LINE = 1,
58649    GEN_VIRTUAL = 2,
58650    PROPER_CONGRUENCE = PARAMETER,
58651    CON_VIRTUAL = LINE,
58652    EQUALITY = GEN_VIRTUAL
58653  };
58654
58655  typedef std::vector<Dimension_Kind> Dimension_Kinds;
58656
58657  // The type of row associated with each dimension.  If the virtual
58658  // rows existed then the reduced systems would be square and upper
58659  // or lower triangular, and the rows in each would have the types
58660  // given in this vector.  As the congruence system is reduced to an
58661  // upside-down lower triangular form the ordering of the congruence
58662  // types is last to first.
58663  Dimension_Kinds dim_kinds;
58664
58665  //! Builds a grid universe or empty grid.
58666  /*!
58667    \param num_dimensions
58668    The number of dimensions of the vector space enclosing the grid;
58669
58670    \param kind
58671    specifies whether the universe or the empty grid has to be built.
58672  */
58673  void construct(dimension_type num_dimensions, Degenerate_Element kind);
58674
58675  //! Builds a grid from a system of congruences.
58676  /*!
58677    The grid inherits the space dimension of the congruence system.
58678
58679    \param cgs
58680    The system of congruences defining the grid. Its data-structures
58681    may be recycled to build the grid.
58682  */
58683  void construct(Congruence_System& cgs);
58684
58685  //! Builds a grid from a system of grid generators.
58686  /*!
58687    The grid inherits the space dimension of the generator system.
58688
58689    \param ggs
58690    The system of grid generators defining the grid.  Its data-structures
58691    may be recycled to build the grid.
58692  */
58693  void construct(Grid_Generator_System& ggs);
58694
58695  //! \name Private Verifiers: Verify if Individual Flags are Set
58696  //@{
58697
58698  //! Returns <CODE>true</CODE> if the grid is known to be empty.
58699  /*!
58700    The return value <CODE>false</CODE> does not necessarily
58701    implies that \p *this is non-empty.
58702  */
58703  bool marked_empty() const;
58704
58705  //! Returns <CODE>true</CODE> if the system of congruences is up-to-date.
58706  bool congruences_are_up_to_date() const;
58707
58708  //! Returns <CODE>true</CODE> if the system of generators is up-to-date.
58709  bool generators_are_up_to_date() const;
58710
58711  //! Returns <CODE>true</CODE> if the system of congruences is minimized.
58712  bool congruences_are_minimized() const;
58713
58714  //! Returns <CODE>true</CODE> if the system of generators is minimized.
58715  bool generators_are_minimized() const;
58716
58717  //@} // Private Verifiers: Verify if Individual Flags are Set
58718
58719  //! \name State Flag Setters: Set Only the Specified Flags
58720  //@{
58721
58722  /*! \brief
58723    Sets \p status to express that the grid is the universe
58724    0-dimension vector space, clearing all corresponding matrices.
58725  */
58726  void set_zero_dim_univ();
58727
58728  /*! \brief
58729    Sets \p status to express that the grid is empty, clearing all
58730    corresponding matrices.
58731  */
58732  void set_empty();
58733
58734  //! Sets \p status to express that congruences are up-to-date.
58735  void set_congruences_up_to_date();
58736
58737  //! Sets \p status to express that generators are up-to-date.
58738  void set_generators_up_to_date();
58739
58740  //! Sets \p status to express that congruences are minimized.
58741  void set_congruences_minimized();
58742
58743  //! Sets \p status to express that generators are minimized.
58744  void set_generators_minimized();
58745
58746  //@} // State Flag Setters: Set Only the Specified Flags
58747
58748  //! \name State Flag Cleaners: Clear Only the Specified Flag
58749  //@{
58750
58751  //! Clears the \p status flag indicating that the grid is empty.
58752  void clear_empty();
58753
58754  //! Sets \p status to express that congruences are out of date.
58755  void clear_congruences_up_to_date();
58756
58757  //! Sets \p status to express that generators are out of date.
58758  void clear_generators_up_to_date();
58759
58760  //! Sets \p status to express that congruences are no longer minimized.
58761  void clear_congruences_minimized();
58762
58763  //! Sets \p status to express that generators are no longer minimized.
58764  void clear_generators_minimized();
58765
58766  //@} // State Flag Cleaners: Clear Only the Specified Flag
58767
58768  //! \name Updating Matrices
58769  //@{
58770
58771  //! Updates and minimizes the congruences from the generators.
58772  void update_congruences() const;
58773
58774  //! Updates and minimizes the generators from the congruences.
58775  /*!
58776    \return
58777    <CODE>false</CODE> if and only if \p *this turns out to be an
58778    empty grid.
58779
58780    It is illegal to call this method when the Status field already
58781    declares the grid to be empty.
58782  */
58783  bool update_generators() const;
58784
58785  //@} // Updating Matrices
58786
58787  //! \name Minimization of Descriptions
58788  //@{
58789
58790  //! Minimizes both the congruences and the generators.
58791  /*!
58792    \return
58793    <CODE>false</CODE> if and only if \p *this turns out to be an
58794    empty grid.
58795
58796    Minimization is performed on each system only if the minimized
58797    Status field is clear.
58798  */
58799  bool minimize() const;
58800
58801  //@} // Minimization of Descriptions
58802
58803  enum Three_Valued_Boolean {
58804    TVB_TRUE,
58805    TVB_FALSE,
58806    TVB_DONT_KNOW
58807  };
58808
58809  //! Polynomial but incomplete equivalence test between grids.
58810  Three_Valued_Boolean quick_equivalence_test(const Grid& y) const;
58811
58812  //! Returns <CODE>true</CODE> if and only if \p *this is included in \p y.
58813  bool is_included_in(const Grid& y) const;
58814
58815  //! Checks if and how \p expr is bounded in \p *this.
58816  /*!
58817    Returns <CODE>true</CODE> if and only if \p from_above is
58818    <CODE>true</CODE> and \p expr is bounded from above in \p *this,
58819    or \p from_above is <CODE>false</CODE> and \p expr is bounded
58820    from below in \p *this.
58821
58822    \param expr
58823    The linear expression to test;
58824
58825    \param method_call
58826    The call description of the public parent method, for example
58827    "bounded_from_above(e)".  Passed to throw_dimension_incompatible,
58828    as the first argument.
58829
58830    \exception std::invalid_argument
58831    Thrown if \p expr and \p *this are dimension-incompatible.
58832  */
58833  bool bounds(const Linear_Expression& expr, const char* method_call) const;
58834
58835  //! Maximizes or minimizes \p expr subject to \p *this.
58836  /*!
58837    \param expr
58838    The linear expression to be maximized or minimized subject to \p
58839    *this;
58840
58841    \param method_call
58842    The call description of the public parent method, for example
58843    "maximize(e)".  Passed to throw_dimension_incompatible, as the
58844    first argument;
58845
58846    \param ext_n
58847    The numerator of the extremum value;
58848
58849    \param ext_d
58850    The denominator of the extremum value;
58851
58852    \param included
58853    <CODE>true</CODE> if and only if the extremum of \p expr in \p
58854    *this can actually be reached (which is always the case);
58855
58856    \param point
58857    When maximization or minimization succeeds, will be assigned the
58858    point where \p expr reaches the extremum value.
58859
58860    \exception std::invalid_argument
58861    Thrown if \p expr and \p *this are dimension-incompatible.
58862
58863    If \p *this is empty or \p expr is not bounded in the appropriate
58864    direction, <CODE>false</CODE> is returned and \p ext_n, \p ext_d,
58865    \p included and \p point are left untouched.
58866  */
58867  bool max_min(const Linear_Expression& expr,
58868               const char* method_call,
58869               Coefficient& ext_n, Coefficient& ext_d, bool& included,
58870               Generator* point = NULL) const;
58871
58872  /*! \brief
58873    Returns <CODE>true</CODE> if and only if \p *this is not empty and
58874    \ref Grid_Frequency "frequency" for \p *this with respect to \p expr
58875    is defined, in which case the frequency and the value for \p expr
58876    that is closest to zero are computed.
58877
58878    \param expr
58879    The linear expression for which the frequency is needed;
58880
58881    \param freq_n
58882    The numerator of the maximum frequency of \p expr;
58883
58884    \param freq_d
58885    The denominator of the maximum frequency of \p expr;
58886
58887    \param val_n
58888    The numerator of a value of \p expr at a point in the grid
58889    that is closest to zero;
58890
58891    \param val_d
58892    The denominator of a value of \p expr at a point in the grid
58893    that is closest to zero;
58894
58895    If \p *this is empty or frequency is undefined with respect to \p expr,
58896    then <CODE>false</CODE> is returned and \p freq_n, \p freq_d,
58897    \p val_n and \p val_d are left untouched.
58898
58899    \warning
58900    If \p expr and \p *this are dimension-incompatible,
58901    the grid generator system is not minimized or \p *this is
58902    empty, then the behavior is undefined.
58903  */
58904  bool frequency_no_check(const Linear_Expression& expr,
58905                Coefficient& freq_n, Coefficient& freq_d,
58906                Coefficient& val_n, Coefficient& val_d) const;
58907
58908  //! Checks if and how \p expr is bounded in \p *this.
58909  /*!
58910    Returns <CODE>true</CODE> if and only if \p from_above is
58911    <CODE>true</CODE> and \p expr is bounded from above in \p *this,
58912    or \p from_above is <CODE>false</CODE> and \p expr is bounded
58913    from below in \p *this.
58914
58915    \param expr
58916    The linear expression to test;
58917  */
58918  bool bounds_no_check(const Linear_Expression& expr) const;
58919
58920  /*! \brief
58921    Adds the congruence \p cg to \p *this.
58922
58923    \warning
58924    If \p cg and \p *this are dimension-incompatible,
58925    the grid generator system is not minimized or \p *this is
58926    empty, then the behavior is undefined.
58927  */
58928  void add_congruence_no_check(const Congruence& cg);
58929
58930  /*! \brief
58931    Uses the constraint \p c to refine \p *this.
58932
58933    \param c
58934    The constraint to be added.
58935
58936    \exception std::invalid_argument
58937    Thrown if c is a non-trivial inequality constraint.
58938
58939    \warning
58940    If \p c and \p *this are dimension-incompatible,
58941    the behavior is undefined.
58942  */
58943  void add_constraint_no_check(const Constraint& c);
58944
58945  /*! \brief
58946    Uses the constraint \p c to refine \p *this.
58947
58948    \param c
58949    The constraint to be added.
58950    Non-trivial inequalities are ignored.
58951
58952    \warning
58953    If \p c and \p *this are dimension-incompatible,
58954    the behavior is undefined.
58955  */
58956  void refine_no_check(const Constraint& c);
58957
58958  //! \name Widening- and Extrapolation-Related Functions
58959  //@{
58960
58961  //! Copies a widened selection of congruences from \p y to \p selected_cgs.
58962  void select_wider_congruences(const Grid& y,
58963                                Congruence_System& selected_cgs) const;
58964
58965  //! Copies widened generators from \p y to \p widened_ggs.
58966  void select_wider_generators(const Grid& y,
58967                               Grid_Generator_System& widened_ggs) const;
58968
58969  //@} // Widening- and Extrapolation-Related Functions
58970
58971  //! Adds new space dimensions to the given systems.
58972  /*!
58973    \param cgs
58974    A congruence system, to which columns are added;
58975
58976    \param gs
58977    A generator system, to which rows and columns are added;
58978
58979    \param dims
58980    The number of space dimensions to add.
58981
58982    This method is invoked only by
58983    <CODE>add_space_dimensions_and_embed()</CODE>.
58984  */
58985  void add_space_dimensions(Congruence_System& cgs,
58986                            Grid_Generator_System& gs,
58987                            dimension_type dims);
58988
58989  //! Adds new space dimensions to the given systems.
58990  /*!
58991    \param gs
58992    A generator system, to which columns are added;
58993
58994    \param cgs
58995    A congruence system, to which rows and columns are added;
58996
58997    \param dims
58998    The number of space dimensions to add.
58999
59000    This method is invoked only by
59001    <CODE>add_space_dimensions_and_project()</CODE>.
59002  */
59003  void add_space_dimensions(Grid_Generator_System& gs,
59004                            Congruence_System& cgs,
59005                            dimension_type dims);
59006
59007  //! \name Minimization-related Static Member Functions
59008  //@{
59009
59010  //! Normalizes the divisors in \p sys.
59011  /*!
59012    Converts \p sys to an equivalent system in which the divisors are
59013    of equal value.
59014
59015    \param sys
59016    The generator system to be normalized.  It must have at least one
59017    row.
59018
59019    \param divisor
59020    A reference to the initial value of the divisor.  The resulting
59021    value of this object is the new system divisor.
59022
59023    \param first_point
59024    If \p first_point has a value other than NULL then it is taken as
59025    the first point in \p sys, and it is assumed that any following
59026    points have the same divisor as \p first_point.
59027  */
59028  static void
59029  normalize_divisors(Grid_Generator_System& sys,
59030                     Coefficient& divisor,
59031                     const Grid_Generator* first_point = NULL);
59032
59033  //! Normalizes the divisors in \p sys.
59034  /*!
59035    Converts \p sys to an equivalent system in which the divisors are
59036    of equal value.
59037
59038    \param sys
59039    The generator system to be normalized.  It must have at least one
59040    row.
59041  */
59042  static void
59043  normalize_divisors(Grid_Generator_System& sys);
59044
59045  //! Normalize all the divisors in \p sys and \p gen_sys.
59046  /*!
59047    Modify \p sys and \p gen_sys to use the same single divisor value
59048    for all generators, leaving each system representing the grid it
59049    represented originally.
59050
59051    \param sys
59052    The first of the generator systems to be normalized.
59053
59054    \param gen_sys
59055    The second of the generator systems to be normalized.  This system
59056    must have at least one row and the divisors of the generators in
59057    this system must be equal.
59058
59059    \exception std::runtime_error
59060    Thrown if all rows in \p gen_sys are lines and/or parameters.
59061  */
59062  static void normalize_divisors(Grid_Generator_System& sys,
59063                                 Grid_Generator_System& gen_sys);
59064
59065  /*! \brief
59066    Converts generator system \p dest to be equivalent to congruence
59067    system \p source.
59068  */
59069  static void conversion(Congruence_System& source,
59070                         Grid_Generator_System& dest,
59071                         Dimension_Kinds& dim_kinds);
59072
59073  /*! \brief
59074    Converts congruence system \p dest to be equivalent to generator
59075    system \p source.
59076  */
59077  static void conversion(Grid_Generator_System& source,
59078                         Congruence_System& dest,
59079                         Dimension_Kinds& dim_kinds);
59080
59081  //! Converts \p cgs to upper triangular (i.e. minimized) form.
59082  /*!
59083    Returns <CODE>true</CODE> if \p cgs represents the empty set,
59084    otherwise returns <CODE>false</CODE>.
59085  */
59086  static bool simplify(Congruence_System& cgs,
59087                       Dimension_Kinds& dim_kinds);
59088
59089  //! Converts \p gs to lower triangular (i.e. minimized) form.
59090  /*!
59091    Expects \p gs to contain at least one point.
59092  */
59093  static void simplify(Grid_Generator_System& ggs,
59094                       Dimension_Kinds& dim_kinds);
59095
59096  //! Reduces the line \p row using the line \p pivot.
59097  /*!
59098    Uses the line \p pivot to change the representation of the line
59099    \p row so that the element at index \p column of \p row is zero.
59100  */
59101  // A member of Grid for access to Matrix<Dense_Row>::rows.
59102  static void reduce_line_with_line(Grid_Generator& row,
59103                                    Grid_Generator& pivot,
59104                                    dimension_type column);
59105
59106  //! Reduces the equality \p row using the equality \p pivot.
59107  /*!
59108    Uses the equality \p pivot to change the representation of the
59109    equality \p row so that the element at index \p column of \p row
59110    is zero.
59111  */
59112  // A member of Grid for access to Matrix<Dense_Row>::rows.
59113  static void reduce_equality_with_equality(Congruence& row,
59114                                            const Congruence& pivot,
59115                                            dimension_type column);
59116
59117  //! Reduces \p row using \p pivot.
59118  /*!
59119    Uses the point, parameter or proper congruence at \p pivot to
59120    change the representation of the point, parameter or proper
59121    congruence at \p row so that the element at index \p column of \p row
59122    is zero.  Only elements from index \p start to index \p end are
59123    modified (i.e. it is assumed that all other elements are zero).
59124    This means that \p col must be in [start,end).
59125
59126    NOTE: This may invalidate the rows, since it messes with the divisors.
59127    Client code has to fix that (if needed) and assert OK().
59128  */
59129  // Part of Grid for access to Matrix<Dense_Row>::rows.
59130  template <typename R>
59131  static void reduce_pc_with_pc(R& row,
59132                                R& pivot,
59133                                dimension_type column,
59134                                dimension_type start,
59135                                dimension_type end);
59136
59137  //! Reduce \p row using \p pivot.
59138  /*!
59139    Use the line \p pivot to change the representation of the
59140    parameter \p row such that the element at index \p column of \p row
59141    is zero.
59142  */
59143  // This takes a parameter with type Swapping_Vector<Grid_Generator> (instead
59144  // of Grid_Generator_System) to simplify the implementation of `simplify()'.
59145  // NOTE: This may invalidate `row' and the rows in `sys'. Client code must
59146  // fix/check this.
59147  static void reduce_parameter_with_line(Grid_Generator& row,
59148                                         const Grid_Generator& pivot,
59149                                         dimension_type column,
59150                                         Swapping_Vector<Grid_Generator>& sys,
59151                                         dimension_type num_columns);
59152
59153  //! Reduce \p row using \p pivot.
59154  /*!
59155    Use the equality \p pivot to change the representation of the
59156    congruence \p row such that element at index \p column of \p row
59157    is zero.
59158  */
59159  // A member of Grid for access to Matrix<Dense_Row>::rows.
59160  // This takes a parameter with type Swapping_Vector<Congruence> (instead of
59161  // Congruence_System) to simplify the implementation of `conversion()'.
59162  static void reduce_congruence_with_equality(Congruence& row,
59163                                              const Congruence& pivot,
59164                                              dimension_type column,
59165                                              Swapping_Vector<Congruence>& sys);
59166
59167  //! Reduce column \p dim in rows preceding \p pivot_index in \p sys.
59168  /*!
59169    Required when converting (or simplifying) a congruence or generator
59170    system to "strong minimal form"; informally, strong minimal form means
59171    that, not only is the system in minimal form (ie a triangular matrix),
59172    but also the absolute values of the coefficients of the proper congruences
59173    and parameters are minimal. As a simple example, the set of congruences
59174    \f$\{3x \equiv_3 0, 4x + y \equiv_3 1\}\f$,
59175    (which is in minimal form) is equivalent to the set
59176    \f$\{3x \equiv_3 0, x + y \equiv_3 1\}\f$
59177    (which is in strong minimal form).
59178
59179    \param sys
59180    The generator or congruence system to be reduced to strong minimal form.
59181
59182    \param dim
59183    Column to be reduced.
59184
59185    \param pivot_index
59186    Index of last row to be reduced.
59187
59188    \param start
59189    Index of first column to be changed.
59190
59191    \param end
59192    Index of last column to be changed.
59193
59194    \param sys_dim_kinds
59195    Dimension kinds of the elements of \p sys.
59196
59197    \param generators
59198    Flag indicating whether \p sys is a congruence or generator system
59199  */
59200  template <typename M>
59201  // This takes a parameter with type `Swapping_Vector<M::row_type>'
59202  // instead of `M' to simplify the implementation of simplify().
59203  // NOTE: This may invalidate the rows in `sys'. Client code must
59204  // fix/check this.
59205  static void reduce_reduced(Swapping_Vector<typename M::row_type>& sys,
59206                             dimension_type dim,
59207                             dimension_type pivot_index,
59208                             dimension_type start, dimension_type end,
59209                             const Dimension_Kinds& sys_dim_kinds,
59210                             bool generators = true);
59211
59212  //! Multiply the elements of \p dest by \p multiplier.
59213  // A member of Grid for access to Matrix<Dense_Row>::rows and cgs::operator[].
59214  // The type of `dest' is Swapping_Vector<Congruence> instead of
59215  // Congruence_System to simplify the implementation of conversion().
59216  static void multiply_grid(const Coefficient& multiplier,
59217                            Congruence& cg,
59218                            Swapping_Vector<Congruence>& dest,
59219                            dimension_type num_rows);
59220
59221  //! Multiply the elements of \p dest by \p multiplier.
59222  // A member of Grid for access to Grid_Generator::operator[].
59223  // The type of `dest' is Swapping_Vector<Grid_Generator> instead of
59224  // Grid_Generator_System to simplify the implementation of conversion().
59225  // NOTE: This does not check whether the rows are OK(). Client code
59226  // should do that.
59227  static void multiply_grid(const Coefficient& multiplier,
59228                            Grid_Generator& gen,
59229                            Swapping_Vector<Grid_Generator>& dest,
59230                            dimension_type num_rows);
59231
59232  /*! \brief
59233    If \p sys is lower triangular return <CODE>true</CODE>, else
59234    return <CODE>false</CODE>.
59235  */
59236  static bool lower_triangular(const Congruence_System& sys,
59237                               const Dimension_Kinds& dim_kinds);
59238
59239  /*! \brief
59240    If \p sys is upper triangular return <CODE>true</CODE>, else
59241    return <CODE>false</CODE>.
59242  */
59243  static bool upper_triangular(const Grid_Generator_System& sys,
59244                               const Dimension_Kinds& dim_kinds);
59245
59246#ifndef NDEBUG
59247  //! Checks that trailing rows contain only zero terms.
59248  /*!
59249    If all columns contain zero in the rows of \p system from row
59250    index \p first to row index \p last then return <code>true</code>,
59251    else return <code>false</code>.  \p row_size gives the number of
59252    columns in each row.
59253
59254    This method is only used in assertions in the simplify methods.
59255  */
59256  template <typename M, typename R>
59257  static bool rows_are_zero(M& system,
59258                            dimension_type first,
59259                            dimension_type last,
59260                            dimension_type row_size);
59261#endif
59262
59263  //@} // Minimization-Related Static Member Functions
59264
59265#ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
59266  //! \name Exception Throwers
59267  //@{
59268#endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
59269protected:
59270  void throw_dimension_incompatible(const char* method,
59271                                    const char* other_name,
59272                                    dimension_type other_dim) const;
59273  void throw_dimension_incompatible(const char* method,
59274                                    const char* gr_name,
59275                                    const Grid& gr) const;
59276  void throw_dimension_incompatible(const char* method,
59277                                    const char* le_name,
59278                                    const Linear_Expression& le) const;
59279  void throw_dimension_incompatible(const char* method,
59280                                    const char* cg_name,
59281                                    const Congruence& cg) const;
59282  void throw_dimension_incompatible(const char* method,
59283                                    const char* c_name,
59284                                    const Constraint& c) const;
59285  void throw_dimension_incompatible(const char* method,
59286                                    const char* g_name,
59287                                    const Grid_Generator& g) const;
59288  void throw_dimension_incompatible(const char* method,
59289                                    const char* g_name,
59290                                    const Generator& g) const;
59291  void throw_dimension_incompatible(const char* method,
59292                                    const char* cgs_name,
59293                                    const Congruence_System& cgs) const;
59294  void throw_dimension_incompatible(const char* method,
59295                                    const char* cs_name,
59296                                    const Constraint_System& cs) const;
59297  void throw_dimension_incompatible(const char* method,
59298                                    const char* gs_name,
59299                                    const Grid_Generator_System& gs) const;
59300  void throw_dimension_incompatible(const char* method,
59301                                    const char* var_name,
59302                                    Variable var) const;
59303  void throw_dimension_incompatible(const char* method,
59304                                    dimension_type required_space_dim) const;
59305
59306  static void throw_invalid_argument(const char* method,
59307                                     const char* reason);
59308  static void throw_invalid_constraint(const char* method,
59309                                       const char* c_name);
59310  static void throw_invalid_constraints(const char* method,
59311                                        const char* cs_name);
59312  static void throw_invalid_generator(const char* method,
59313                                      const char* g_name);
59314  static void throw_invalid_generators(const char* method,
59315                                       const char* gs_name);
59316#ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
59317  //@} // Exception Throwers
59318#endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
59319
59320};
59321
59322/* Automatically generated from PPL source file ../src/Grid_Status_inlines.hh line 1. */
59323/* Grid::Status class implementation: inline functions.
59324*/
59325
59326
59327namespace Parma_Polyhedra_Library {
59328
59329inline
59330Grid::Status::Status(flags_t mask)
59331  : flags(mask) {
59332}
59333
59334inline
59335Grid::Status::Status()
59336  : flags(ZERO_DIM_UNIV) {
59337}
59338
59339inline bool
59340Grid::Status::test_all(flags_t mask) const {
59341  return (flags & mask) == mask;
59342}
59343
59344inline bool
59345Grid::Status::test_any(flags_t mask) const {
59346  return (flags & mask) != 0;
59347}
59348
59349inline void
59350Grid::Status::set(flags_t mask) {
59351  flags |= mask;
59352}
59353
59354inline void
59355Grid::Status::reset(flags_t mask) {
59356  flags &= ~mask;
59357}
59358
59359inline bool
59360Grid::Status::test_zero_dim_univ() const {
59361  return flags == ZERO_DIM_UNIV;
59362}
59363
59364inline void
59365Grid::Status::reset_zero_dim_univ() {
59366  // This is a no-op if the current status is not zero-dim.
59367  if (flags == ZERO_DIM_UNIV) {
59368    // In the zero-dim space, if it is not the universe it is empty.
59369    flags = EMPTY;
59370  }
59371}
59372
59373inline void
59374Grid::Status::set_zero_dim_univ() {
59375  // Zero-dim universe is incompatible with anything else.
59376  flags = ZERO_DIM_UNIV;
59377}
59378
59379inline bool
59380Grid::Status::test_empty() const {
59381  return test_any(EMPTY);
59382}
59383
59384inline void
59385Grid::Status::reset_empty() {
59386  reset(EMPTY);
59387}
59388
59389inline void
59390Grid::Status::set_empty() {
59391  flags = EMPTY;
59392}
59393
59394inline bool
59395Grid::Status::test_c_up_to_date() const {
59396  return test_any(C_UP_TO_DATE);
59397}
59398
59399inline void
59400Grid::Status::reset_c_up_to_date() {
59401  reset(C_UP_TO_DATE);
59402}
59403
59404inline void
59405Grid::Status::set_c_up_to_date() {
59406  set(C_UP_TO_DATE);
59407}
59408
59409inline bool
59410Grid::Status::test_g_up_to_date() const {
59411  return test_any(G_UP_TO_DATE);
59412}
59413
59414inline void
59415Grid::Status::reset_g_up_to_date() {
59416  reset(G_UP_TO_DATE);
59417}
59418
59419inline void
59420Grid::Status::set_g_up_to_date() {
59421  set(G_UP_TO_DATE);
59422}
59423
59424inline bool
59425Grid::Status::test_c_minimized() const {
59426  return test_any(C_MINIMIZED);
59427}
59428
59429inline void
59430Grid::Status::reset_c_minimized() {
59431  reset(C_MINIMIZED);
59432}
59433
59434inline void
59435Grid::Status::set_c_minimized() {
59436  set(C_MINIMIZED);
59437}
59438
59439inline bool
59440Grid::Status::test_g_minimized() const {
59441  return test_any(G_MINIMIZED);
59442}
59443
59444inline void
59445Grid::Status::reset_g_minimized() {
59446  reset(G_MINIMIZED);
59447}
59448
59449inline void
59450Grid::Status::set_g_minimized() {
59451  set(G_MINIMIZED);
59452}
59453
59454
59455inline bool
59456Grid::Status::test_c_pending() const {
59457  return test_any(CS_PENDING);
59458}
59459
59460inline void
59461Grid::Status::reset_c_pending() {
59462  reset(CS_PENDING);
59463}
59464
59465inline void
59466Grid::Status::set_c_pending() {
59467  set(CS_PENDING);
59468}
59469
59470inline bool
59471Grid::Status::test_g_pending() const {
59472  return test_any(GS_PENDING);
59473}
59474
59475inline void
59476Grid::Status::reset_g_pending() {
59477  reset(GS_PENDING);
59478}
59479
59480inline void
59481Grid::Status::set_g_pending() {
59482  set(GS_PENDING);
59483}
59484
59485
59486inline bool
59487Grid::Status::test_sat_c_up_to_date() const {
59488  return test_any(SAT_C_UP_TO_DATE);
59489}
59490
59491inline void
59492Grid::Status::reset_sat_c_up_to_date() {
59493  reset(SAT_C_UP_TO_DATE);
59494}
59495
59496inline void
59497Grid::Status::set_sat_c_up_to_date() {
59498  set(SAT_C_UP_TO_DATE);
59499}
59500
59501inline bool
59502Grid::Status::test_sat_g_up_to_date() const {
59503  return test_any(SAT_G_UP_TO_DATE);
59504}
59505
59506inline void
59507Grid::Status::reset_sat_g_up_to_date() {
59508  reset(SAT_G_UP_TO_DATE);
59509}
59510
59511inline void
59512Grid::Status::set_sat_g_up_to_date() {
59513  set(SAT_G_UP_TO_DATE);
59514}
59515
59516} // namespace Parma_Polyhedra_Library
59517
59518/* Automatically generated from PPL source file ../src/Grid_inlines.hh line 1. */
59519/* Grid class implementation: inline functions.
59520*/
59521
59522
59523/* Automatically generated from PPL source file ../src/Grid_inlines.hh line 30. */
59524#include <algorithm>
59525
59526namespace Parma_Polyhedra_Library {
59527
59528inline bool
59529Grid::marked_empty() const {
59530  return status.test_empty();
59531}
59532
59533inline bool
59534Grid::congruences_are_up_to_date() const {
59535  return status.test_c_up_to_date();
59536}
59537
59538inline bool
59539Grid::generators_are_up_to_date() const {
59540  return status.test_g_up_to_date();
59541}
59542
59543inline bool
59544Grid::congruences_are_minimized() const {
59545  return status.test_c_minimized();
59546}
59547
59548inline bool
59549Grid::generators_are_minimized() const {
59550  return status.test_g_minimized();
59551}
59552
59553inline void
59554Grid::set_generators_up_to_date() {
59555  status.set_g_up_to_date();
59556}
59557
59558inline void
59559Grid::set_congruences_up_to_date() {
59560  status.set_c_up_to_date();
59561}
59562
59563inline void
59564Grid::set_congruences_minimized() {
59565  set_congruences_up_to_date();
59566  status.set_c_minimized();
59567}
59568
59569inline void
59570Grid::set_generators_minimized() {
59571  set_generators_up_to_date();
59572  status.set_g_minimized();
59573}
59574
59575inline void
59576Grid::clear_empty() {
59577  status.reset_empty();
59578}
59579
59580inline void
59581Grid::clear_congruences_minimized() {
59582  status.reset_c_minimized();
59583}
59584
59585inline void
59586Grid::clear_generators_minimized() {
59587  status.reset_g_minimized();
59588}
59589
59590inline void
59591Grid::clear_congruences_up_to_date() {
59592  clear_congruences_minimized();
59593  status.reset_c_up_to_date();
59594  // Can get rid of con_sys here.
59595}
59596
59597inline void
59598Grid::clear_generators_up_to_date() {
59599  clear_generators_minimized();
59600  status.reset_g_up_to_date();
59601  // Can get rid of gen_sys here.
59602}
59603
59604inline dimension_type
59605Grid::max_space_dimension() {
59606  // One dimension is reserved to have a value of type dimension_type
59607  // that does not represent a legal dimension.
59608  return std::min(std::numeric_limits<dimension_type>::max() - 1,
59609                  std::min(Congruence_System::max_space_dimension(),
59610                           Grid_Generator_System::max_space_dimension()
59611                           )
59612                  );
59613}
59614
59615inline
59616Grid::Grid(dimension_type num_dimensions,
59617           const Degenerate_Element kind)
59618  : con_sys(),
59619    gen_sys(check_space_dimension_overflow(num_dimensions,
59620                                           max_space_dimension(),
59621                                           "PPL::Grid::",
59622                                           "Grid(n, k)",
59623                                           "n exceeds the maximum "
59624                                           "allowed space dimension")) {
59625  construct(num_dimensions, kind);
59626  PPL_ASSERT(OK());
59627}
59628
59629inline
59630Grid::Grid(const Congruence_System& cgs)
59631  : con_sys(check_space_dimension_overflow(cgs.space_dimension(),
59632                                           max_space_dimension(),
59633                                           "PPL::Grid::",
59634                                           "Grid(cgs)",
59635                                           "the space dimension of cgs "
59636                                           "exceeds the maximum allowed "
59637                                           "space dimension")),
59638    gen_sys(cgs.space_dimension()) {
59639  Congruence_System cgs_copy(cgs);
59640  construct(cgs_copy);
59641}
59642
59643inline
59644Grid::Grid(Congruence_System& cgs, Recycle_Input)
59645  : con_sys(check_space_dimension_overflow(cgs.space_dimension(),
59646                                           max_space_dimension(),
59647                                           "PPL::Grid::",
59648                                           "Grid(cgs, recycle)",
59649                                           "the space dimension of cgs "
59650                                           "exceeds the maximum allowed "
59651                                           "space dimension")),
59652    gen_sys(cgs.space_dimension()) {
59653  construct(cgs);
59654}
59655
59656inline
59657Grid::Grid(const Grid_Generator_System& ggs)
59658  : con_sys(check_space_dimension_overflow(ggs.space_dimension(),
59659                                           max_space_dimension(),
59660                                           "PPL::Grid::",
59661                                           "Grid(ggs)",
59662                                           "the space dimension of ggs "
59663                                           "exceeds the maximum allowed "
59664                                           "space dimension")),
59665    gen_sys(ggs.space_dimension()) {
59666  Grid_Generator_System ggs_copy(ggs);
59667  construct(ggs_copy);
59668}
59669
59670inline
59671Grid::Grid(Grid_Generator_System& ggs, Recycle_Input)
59672  : con_sys(check_space_dimension_overflow(ggs.space_dimension(),
59673                                           max_space_dimension(),
59674                                           "PPL::Grid::",
59675                                           "Grid(ggs, recycle)",
59676                                           "the space dimension of ggs "
59677                                           "exceeds the maximum allowed "
59678                                           "space dimension")),
59679    gen_sys(ggs.space_dimension()) {
59680  construct(ggs);
59681}
59682
59683template <typename U>
59684inline
59685Grid::Grid(const BD_Shape<U>& bd, Complexity_Class)
59686  : con_sys(check_space_dimension_overflow(bd.space_dimension(),
59687                                           max_space_dimension(),
59688                                           "PPL::Grid::",
59689                                           "Grid(bd)",
59690                                           "the space dimension of bd "
59691                                           "exceeds the maximum allowed "
59692                                           "space dimension")),
59693    gen_sys(bd.space_dimension()) {
59694  Congruence_System cgs = bd.congruences();
59695  construct(cgs);
59696}
59697
59698template <typename U>
59699inline
59700Grid::Grid(const Octagonal_Shape<U>& os, Complexity_Class)
59701  : con_sys(check_space_dimension_overflow(os.space_dimension(),
59702                                           max_space_dimension(),
59703                                           "PPL::Grid::",
59704                                           "Grid(os)",
59705                                           "the space dimension of os "
59706                                           "exceeds the maximum allowed "
59707                                           "space dimension")),
59708    gen_sys(os.space_dimension()) {
59709  Congruence_System cgs = os.congruences();
59710  construct(cgs);
59711}
59712
59713inline
59714Grid::~Grid() {
59715}
59716
59717inline dimension_type
59718Grid::space_dimension() const {
59719  return space_dim;
59720}
59721
59722inline memory_size_type
59723Grid::total_memory_in_bytes() const {
59724  return sizeof(*this) + external_memory_in_bytes();
59725}
59726
59727inline int32_t
59728Grid::hash_code() const {
59729  return hash_code_from_dimension(space_dimension());
59730}
59731
59732inline Constraint_System
59733Grid::constraints() const {
59734  return Constraint_System(congruences());
59735}
59736
59737inline Constraint_System
59738Grid::minimized_constraints() const {
59739  return Constraint_System(minimized_congruences());
59740}
59741
59742inline void
59743Grid::m_swap(Grid& y) {
59744  using std::swap;
59745  swap(con_sys, y.con_sys);
59746  swap(gen_sys, y.gen_sys);
59747  swap(status, y.status);
59748  swap(space_dim, y.space_dim);
59749  swap(dim_kinds, y.dim_kinds);
59750}
59751
59752inline void
59753Grid::add_congruence(const Congruence& cg) {
59754  // Dimension-compatibility check.
59755  if (space_dim < cg.space_dimension()) {
59756    throw_dimension_incompatible("add_congruence(cg)", "cg", cg);
59757  }
59758
59759  if (!marked_empty()) {
59760    add_congruence_no_check(cg);
59761  }
59762}
59763
59764inline void
59765Grid::add_congruences(const Congruence_System& cgs) {
59766  // TODO: this is just an executable specification.
59767  // Space dimension compatibility check.
59768  if (space_dim < cgs.space_dimension()) {
59769    throw_dimension_incompatible("add_congruences(cgs)", "cgs", cgs);
59770  }
59771
59772  if (!marked_empty()) {
59773    Congruence_System cgs_copy = cgs;
59774    add_recycled_congruences(cgs_copy);
59775  }
59776}
59777
59778inline void
59779Grid::refine_with_congruence(const Congruence& cg) {
59780  add_congruence(cg);
59781}
59782
59783inline void
59784Grid::refine_with_congruences(const Congruence_System& cgs) {
59785  add_congruences(cgs);
59786}
59787
59788inline bool
59789Grid::can_recycle_constraint_systems() {
59790  return true;
59791}
59792
59793inline bool
59794Grid::can_recycle_congruence_systems() {
59795  return true;
59796}
59797
59798inline void
59799Grid::add_constraint(const Constraint& c) {
59800  // Space dimension compatibility check.
59801  if (space_dim < c.space_dimension()) {
59802    throw_dimension_incompatible("add_constraint(c)", "c", c);
59803  }
59804  if (!marked_empty()) {
59805    add_constraint_no_check(c);
59806  }
59807}
59808
59809inline void
59810Grid::add_recycled_constraints(Constraint_System& cs) {
59811  // TODO: really recycle the constraints.
59812  add_constraints(cs);
59813}
59814
59815inline bool
59816Grid::bounds_from_above(const Linear_Expression& expr) const {
59817  return bounds(expr, "bounds_from_above(e)");
59818}
59819
59820inline bool
59821Grid::bounds_from_below(const Linear_Expression& expr) const {
59822  return bounds(expr, "bounds_from_below(e)");
59823}
59824
59825inline bool
59826Grid::maximize(const Linear_Expression& expr,
59827               Coefficient& sup_n, Coefficient& sup_d, bool& maximum) const {
59828  return max_min(expr, "maximize(e, ...)", sup_n, sup_d, maximum);
59829}
59830
59831inline bool
59832Grid::maximize(const Linear_Expression& expr,
59833               Coefficient& sup_n, Coefficient& sup_d, bool& maximum,
59834               Generator& point) const {
59835  return max_min(expr, "maximize(e, ...)", sup_n, sup_d, maximum, &point);
59836}
59837
59838inline bool
59839Grid::minimize(const Linear_Expression& expr,
59840               Coefficient& inf_n, Coefficient& inf_d, bool& minimum) const {
59841  return max_min(expr, "minimize(e, ...)", inf_n, inf_d, minimum);
59842}
59843
59844inline bool
59845Grid::minimize(const Linear_Expression& expr,
59846               Coefficient& inf_n, Coefficient& inf_d, bool& minimum,
59847               Generator& point) const {
59848  return max_min(expr, "minimize(e, ...)", inf_n, inf_d, minimum, &point);
59849}
59850
59851inline void
59852Grid::normalize_divisors(Grid_Generator_System& sys) {
59853  PPL_DIRTY_TEMP_COEFFICIENT(divisor);
59854  divisor = 1;
59855  normalize_divisors(sys, divisor);
59856}
59857
59858/*! \relates Grid */
59859inline bool
59860operator!=(const Grid& x, const Grid& y) {
59861  return !(x == y);
59862}
59863
59864inline bool
59865Grid::strictly_contains(const Grid& y) const {
59866  const Grid& x = *this;
59867  return x.contains(y) && !y.contains(x);
59868}
59869
59870inline void
59871Grid::topological_closure_assign() {
59872}
59873
59874/*! \relates Grid */
59875inline void
59876swap(Grid& x, Grid& y) {
59877  x.m_swap(y);
59878}
59879
59880} // namespace Parma_Polyhedra_Library
59881
59882/* Automatically generated from PPL source file ../src/Grid_templates.hh line 1. */
59883/* Grid class implementation: inline functions.
59884*/
59885
59886
59887/* Automatically generated from PPL source file ../src/Grid_templates.hh line 30. */
59888#include <algorithm>
59889#include <deque>
59890
59891namespace Parma_Polyhedra_Library {
59892
59893template <typename Interval>
59894Grid::Grid(const Box<Interval>& box, Complexity_Class)
59895  : con_sys(),
59896    gen_sys() {
59897  space_dim = check_space_dimension_overflow(box.space_dimension(),
59898                                             max_space_dimension(),
59899                                             "PPL::Grid::",
59900                                             "Grid(box, from_bounding_box)",
59901                                             "the space dimension of box "
59902                                             "exceeds the maximum allowed "
59903                                             "space dimension");
59904
59905  if (box.is_empty()) {
59906    // Empty grid.
59907    set_empty();
59908    PPL_ASSERT(OK());
59909    return;
59910  }
59911
59912  if (space_dim == 0) {
59913    set_zero_dim_univ();
59914  }
59915  else {
59916    // Initialize the space dimension as indicated by the box.
59917    con_sys.set_space_dimension(space_dim);
59918    gen_sys.set_space_dimension(space_dim);
59919    // Add congruences and generators according to `box'.
59920    PPL_DIRTY_TEMP_COEFFICIENT(l_n);
59921    PPL_DIRTY_TEMP_COEFFICIENT(l_d);
59922    PPL_DIRTY_TEMP_COEFFICIENT(u_n);
59923    PPL_DIRTY_TEMP_COEFFICIENT(u_d);
59924    gen_sys.insert(grid_point());
59925    for (dimension_type k = space_dim; k-- > 0; ) {
59926      const Variable v_k = Variable(k);
59927      bool closed = false;
59928      // TODO: Consider producing the system(s) in minimized form.
59929      if (box.has_lower_bound(v_k, l_n, l_d, closed)) {
59930        if (box.has_upper_bound(v_k, u_n, u_d, closed)) {
59931          if (l_n * u_d == u_n * l_d) {
59932            // A point interval sets dimension k of every point to a
59933            // single value.
59934            con_sys.insert(l_d * v_k == l_n);
59935
59936            // This is declared here because it may be invalidated
59937            // by the call to gen_sys.insert() at the end of the loop.
59938            Grid_Generator& point = gen_sys.sys.rows[0];
59939
59940            // Scale the point to use as divisor the lcm of the
59941            // divisors of the existing point and the lower bound.
59942            const Coefficient& point_divisor = point.divisor();
59943            gcd_assign(u_n, l_d, point_divisor);
59944            // `u_n' now holds the gcd.
59945            exact_div_assign(u_n, point_divisor, u_n);
59946            if (l_d < 0) {
59947              neg_assign(u_n);
59948            }
59949            // l_d * u_n == abs(l_d * (point_divisor / gcd(l_d, point_divisor)))
59950            point.scale_to_divisor(l_d * u_n);
59951            // Set dimension k of the point to the lower bound.
59952            if (l_d < 0) {
59953              neg_assign(u_n);
59954            }
59955            // point[k + 1] = l_n * point_divisor / gcd(l_d, point_divisor)
59956            point.expr.set(Variable(k), l_n * u_n);
59957            PPL_ASSERT(point.OK());
59958
59959            PPL_ASSERT(gen_sys.sys.OK());
59960
59961            continue;
59962          }
59963        }
59964      }
59965      // A universe interval allows any value in dimension k.
59966      gen_sys.insert(grid_line(v_k));
59967    }
59968    set_congruences_up_to_date();
59969    set_generators_up_to_date();
59970  }
59971
59972  PPL_ASSERT(OK());
59973}
59974
59975template <typename Partial_Function>
59976void
59977Grid::map_space_dimensions(const Partial_Function& pfunc) {
59978  if (space_dim == 0) {
59979    return;
59980  }
59981
59982  if (pfunc.has_empty_codomain()) {
59983    // All dimensions vanish: the grid becomes zero_dimensional.
59984    if (marked_empty()
59985        || (!generators_are_up_to_date() && !update_generators())) {
59986      // Removing all dimensions from the empty grid.
59987      space_dim = 0;
59988      set_empty();
59989    }
59990    else {
59991      // Removing all dimensions from a non-empty grid.
59992      set_zero_dim_univ();
59993    }
59994
59995    PPL_ASSERT(OK());
59996    return;
59997  }
59998
59999  dimension_type new_space_dimension = pfunc.max_in_codomain() + 1;
60000
60001  if (new_space_dimension == space_dim) {
60002    // The partial function `pfunc' is indeed total and thus specifies
60003    // a permutation, that is, a renaming of the dimensions.  For
60004    // maximum efficiency, we will simply permute the columns of the
60005    // constraint system and/or the generator system.
60006
60007    std::vector<Variable> cycle;
60008    cycle.reserve(space_dim);
60009
60010    // Used to mark elements as soon as they are inserted in a cycle.
60011    std::deque<bool> visited(space_dim);
60012
60013    for (dimension_type i = space_dim; i-- > 0; ) {
60014      if (!visited[i]) {
60015        dimension_type j = i;
60016        do {
60017          visited[j] = true;
60018          // The following initialization is only to make the compiler happy.
60019          dimension_type k = 0;
60020          if (!pfunc.maps(j, k)) {
60021            throw_invalid_argument("map_space_dimensions(pfunc)",
60022                                   " pfunc is inconsistent");
60023          }
60024          if (k == j) {
60025            break;
60026          }
60027
60028          cycle.push_back(Variable(j));
60029          // Go along the cycle.
60030          j = k;
60031        } while (!visited[j]);
60032
60033        // End of cycle.
60034
60035        // Avoid calling clear_*_minimized() if cycle.size() is less than 2,
60036        // to improve efficiency.
60037        if (cycle.size() >= 2) {
60038          // Permute all that is up-to-date.
60039          if (congruences_are_up_to_date()) {
60040            con_sys.permute_space_dimensions(cycle);
60041            clear_congruences_minimized();
60042          }
60043
60044          if (generators_are_up_to_date()) {
60045            gen_sys.permute_space_dimensions(cycle);
60046            clear_generators_minimized();
60047          }
60048        }
60049
60050        cycle.clear();
60051      }
60052    }
60053
60054    PPL_ASSERT(OK());
60055    return;
60056  }
60057
60058  // If control gets here, then `pfunc' is not a permutation and some
60059  // dimensions must be projected away.
60060
60061  const Grid_Generator_System& old_gensys = grid_generators();
60062
60063  if (old_gensys.has_no_rows()) {
60064    // The grid is empty.
60065    Grid new_grid(new_space_dimension, EMPTY);
60066    m_swap(new_grid);
60067    PPL_ASSERT(OK());
60068    return;
60069  }
60070
60071  // Make a local copy of the partial function.
60072  std::vector<dimension_type> pfunc_maps(space_dim, not_a_dimension());
60073  for (dimension_type j = space_dim; j-- > 0; ) {
60074    dimension_type pfunc_j;
60075    if (pfunc.maps(j, pfunc_j)) {
60076      pfunc_maps[j] = pfunc_j;
60077    }
60078  }
60079
60080  Grid_Generator_System new_gensys;
60081  // Set sortedness, for the assertion met via gs::insert.
60082  new_gensys.set_sorted(false);
60083  // Get the divisor of the first point.
60084  Grid_Generator_System::const_iterator i;
60085  Grid_Generator_System::const_iterator old_gensys_end = old_gensys.end();
60086  for (i = old_gensys.begin(); i != old_gensys_end; ++i) {
60087    if (i->is_point()) {
60088      break;
60089    }
60090  }
60091  PPL_ASSERT(i != old_gensys_end);
60092  const Coefficient& system_divisor = i->divisor();
60093  for (i = old_gensys.begin(); i != old_gensys_end; ++i) {
60094    const Grid_Generator& old_g = *i;
60095    const Grid_Generator::expr_type old_g_e = old_g.expression();
60096    Linear_Expression expr;
60097    expr.set_space_dimension(new_space_dimension);
60098    bool all_zeroes = true;
60099    for (Grid_Generator::expr_type::const_iterator j = old_g_e.begin(),
60100          j_end = old_g_e.end(); j != j_end; ++j) {
60101      const dimension_type mapped_id = pfunc_maps[j.variable().id()];
60102      if (mapped_id != not_a_dimension()) {
60103        add_mul_assign(expr, *j, Variable(mapped_id));
60104        all_zeroes = false;
60105      }
60106    }
60107    switch (old_g.type()) {
60108    case Grid_Generator::LINE:
60109      if (!all_zeroes) {
60110        new_gensys.insert(grid_line(expr));
60111      }
60112      break;
60113    case Grid_Generator::PARAMETER:
60114      if (!all_zeroes) {
60115        new_gensys.insert(parameter(expr, system_divisor));
60116      }
60117      break;
60118    case Grid_Generator::POINT:
60119      new_gensys.insert(grid_point(expr, old_g.divisor()));
60120      break;
60121    }
60122  }
60123
60124  Grid new_grid(new_gensys);
60125  m_swap(new_grid);
60126
60127  PPL_ASSERT(OK(true));
60128}
60129
60130// Needed for converting the congruence or grid_generator system
60131// to "strong minimal form".
60132template <typename M>
60133void
60134Grid::reduce_reduced(Swapping_Vector<typename M::row_type>& rows,
60135                     const dimension_type dim,
60136                     const dimension_type pivot_index,
60137                     const dimension_type start,
60138                     const dimension_type end,
60139                     const Dimension_Kinds& sys_dim_kinds,
60140                     const bool generators) {
60141  // TODO: Remove this.
60142  typedef typename M::row_type M_row_type;
60143
60144  const M_row_type& pivot = rows[pivot_index];
60145  const Coefficient& pivot_dim = pivot.expr.get(dim);
60146
60147  if (pivot_dim == 0) {
60148    return;
60149  }
60150
60151  PPL_DIRTY_TEMP_COEFFICIENT(pivot_dim_half);
60152  pivot_dim_half = (pivot_dim + 1) / 2;
60153  const Dimension_Kind row_kind = sys_dim_kinds[dim];
60154  const bool row_is_line_or_equality
60155    = (row_kind == (generators ? LINE : EQUALITY));
60156
60157  PPL_DIRTY_TEMP_COEFFICIENT(num_rows_to_subtract);
60158  PPL_DIRTY_TEMP_COEFFICIENT(row_dim_remainder);
60159  for (dimension_type kinds_index = dim,
60160         row_index = pivot_index; row_index-- > 0; ) {
60161    if (generators) {
60162      --kinds_index;
60163      // Move over any virtual rows.
60164      while (sys_dim_kinds[kinds_index] == GEN_VIRTUAL) {
60165        --kinds_index;
60166      }
60167    }
60168    else {
60169      ++kinds_index;
60170      // Move over any virtual rows.
60171      while (sys_dim_kinds[kinds_index] == CON_VIRTUAL) {
60172        ++kinds_index;
60173      }
60174    }
60175
60176    // row_kind CONGRUENCE is included as PARAMETER
60177    if (row_is_line_or_equality
60178        || (row_kind == PARAMETER
60179            && sys_dim_kinds[kinds_index] == PARAMETER)) {
60180      M_row_type& row = rows[row_index];
60181
60182      const Coefficient& row_dim = row.expr.get(dim);
60183      // num_rows_to_subtract may be positive or negative.
60184      num_rows_to_subtract = row_dim / pivot_dim;
60185
60186      // Ensure that after subtracting num_rows_to_subtract * r_dim
60187      // from row_dim, -pivot_dim_half < row_dim <= pivot_dim_half.
60188      // E.g., if pivot[dim] = 9, then after this reduction
60189      // -5 < row_dim <= 5.
60190      row_dim_remainder = row_dim % pivot_dim;
60191      if (row_dim_remainder < 0) {
60192        if (row_dim_remainder <= -pivot_dim_half) {
60193          --num_rows_to_subtract;
60194        }
60195      }
60196      else if (row_dim_remainder > 0 && row_dim_remainder > pivot_dim_half) {
60197        ++num_rows_to_subtract;
60198      }
60199      // Subtract num_rows_to_subtract copies of pivot from row i.  Only the
60200      // entries from dim need to be subtracted, as the preceding
60201      // entries are all zero.
60202      // If num_rows_to_subtract is negative, these copies of pivot are
60203      // added to row i.
60204      if (num_rows_to_subtract != 0) {
60205        row.expr.linear_combine(pivot.expr,
60206                                Coefficient_one(), -num_rows_to_subtract,
60207                                start, end + 1);
60208      }
60209    }
60210  }
60211}
60212
60213} // namespace Parma_Polyhedra_Library
60214
60215/* Automatically generated from PPL source file ../src/Grid_defs.hh line 2664. */
60216
60217/* Automatically generated from PPL source file ../src/BD_Shape_defs.hh line 1. */
60218/* BD_Shape class declaration.
60219*/
60220
60221
60222/* Automatically generated from PPL source file ../src/DB_Matrix_defs.hh line 1. */
60223/* DB_Matrix class declaration.
60224*/
60225
60226
60227/* Automatically generated from PPL source file ../src/DB_Matrix_types.hh line 1. */
60228
60229
60230namespace Parma_Polyhedra_Library {
60231
60232template <typename T>
60233class DB_Matrix;
60234
60235} // namespace Parma_Polyhedra_Library
60236
60237/* Automatically generated from PPL source file ../src/DB_Row_defs.hh line 1. */
60238/* DB_Row class declaration.
60239*/
60240
60241
60242/* Automatically generated from PPL source file ../src/DB_Row_types.hh line 1. */
60243
60244
60245namespace Parma_Polyhedra_Library {
60246
60247template <typename T>
60248class DB_Row_Impl_Handler;
60249
60250template <typename T>
60251class DB_Row;
60252
60253} // namespace Parma_Polyhedra_Library
60254
60255/* Automatically generated from PPL source file ../src/Ptr_Iterator_defs.hh line 1. */
60256/* Ptr_Iterator class declaration.
60257*/
60258
60259
60260/* Automatically generated from PPL source file ../src/Ptr_Iterator_types.hh line 1. */
60261
60262
60263namespace Parma_Polyhedra_Library {
60264
60265namespace Implementation {
60266
60267template <typename P>
60268class Ptr_Iterator;
60269
60270} // namespace Implementation
60271
60272} // namespace Parma_Polyhedra_Library
60273
60274/* Automatically generated from PPL source file ../src/Ptr_Iterator_defs.hh line 28. */
60275#include <iterator>
60276
60277namespace Parma_Polyhedra_Library {
60278
60279namespace Implementation {
60280
60281template<typename P, typename Q>
60282bool operator==(const Ptr_Iterator<P>& x, const Ptr_Iterator<Q>& y);
60283
60284template<typename P, typename Q>
60285bool operator!=(const Ptr_Iterator<P>& x, const Ptr_Iterator<Q>& y);
60286
60287template<typename P, typename Q>
60288bool operator<(const Ptr_Iterator<P>& x, const Ptr_Iterator<Q>& y);
60289
60290template<typename P, typename Q>
60291bool operator<=(const Ptr_Iterator<P>& x, const Ptr_Iterator<Q>& y);
60292
60293template<typename P, typename Q>
60294bool operator>(const Ptr_Iterator<P>& x, const Ptr_Iterator<Q>& y);
60295
60296template<typename P, typename Q>
60297bool operator>=(const Ptr_Iterator<P>& x, const Ptr_Iterator<Q>& y);
60298
60299template<typename P, typename Q>
60300typename Ptr_Iterator<P>::difference_type
60301operator-(const Ptr_Iterator<P>& x, const Ptr_Iterator<Q>& y);
60302
60303template<typename P>
60304Ptr_Iterator<P> operator+(typename Ptr_Iterator<P>::difference_type m,
60305                          const Ptr_Iterator<P>& y);
60306
60307} // namespace Implementation
60308
60309} // namespace Parma_Polyhedra_Library
60310
60311#ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
60312//! A class to define STL const and non-const iterators from pointer types.
60313#endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
60314template <typename P>
60315class Parma_Polyhedra_Library::Implementation::Ptr_Iterator
60316  : public std::iterator<typename std::iterator_traits<P>::iterator_category,
60317                         typename std::iterator_traits<P>::value_type,
60318                         typename std::iterator_traits<P>::difference_type,
60319                         typename std::iterator_traits<P>::pointer,
60320                         typename std::iterator_traits<P>::reference> {
60321public:
60322  typedef typename std::iterator_traits<P>::difference_type difference_type;
60323  typedef typename std::iterator_traits<P>::reference reference;
60324  typedef typename std::iterator_traits<P>::pointer pointer;
60325
60326  //! Default constructor: no guarantees.
60327  Ptr_Iterator();
60328
60329  //! Construct an iterator pointing at \p q.
60330  explicit Ptr_Iterator(const P& q);
60331
60332  /*! \brief
60333    Copy constructor allowing the construction of a const_iterator
60334    from a non-const iterator.
60335  */
60336  template<typename Q>
60337  Ptr_Iterator(const Ptr_Iterator<Q>& q);
60338
60339  //! Dereference operator.
60340  reference operator*() const;
60341
60342  //! Indirect member selector.
60343  pointer operator->() const;
60344
60345  //! Subscript operator.
60346  reference operator[](const difference_type m) const;
60347
60348  //! Prefix increment operator.
60349  Ptr_Iterator& operator++();
60350
60351  //! Postfix increment operator.
60352  Ptr_Iterator operator++(int);
60353
60354  //! Prefix decrement operator
60355  Ptr_Iterator& operator--();
60356
60357  //! Postfix decrement operator.
60358  Ptr_Iterator operator--(int);
60359
60360  //! Assignment-increment operator.
60361  Ptr_Iterator& operator+=(const difference_type m);
60362
60363  //! Assignment-decrement operator.
60364  Ptr_Iterator& operator-=(const difference_type m);
60365
60366  //! Returns the difference between \p *this and \p y.
60367  difference_type operator-(const Ptr_Iterator& y) const;
60368
60369  //! Returns the sum of \p *this and \p m.
60370  Ptr_Iterator operator+(const difference_type m) const;
60371
60372  //! Returns the difference of \p *this and \p m.
60373  Ptr_Iterator operator-(const difference_type m) const;
60374
60375private:
60376  //! The base pointer implementing the iterator.
60377  P p;
60378
60379  //! Returns the hidden pointer.
60380  const P& base() const;
60381
60382  template <typename Q, typename R>
60383  friend bool Parma_Polyhedra_Library::Implementation::
60384  operator==(const Ptr_Iterator<Q>& x, const Ptr_Iterator<R>& y);
60385
60386  template <typename Q, typename R>
60387  friend bool Parma_Polyhedra_Library::Implementation::
60388  operator!=(const Ptr_Iterator<Q>& x, const Ptr_Iterator<R>& y);
60389
60390  template<typename Q, typename R>
60391  friend bool Parma_Polyhedra_Library::Implementation::
60392  operator<(const Ptr_Iterator<Q>& x, const Ptr_Iterator<R>& y);
60393
60394  template<typename Q, typename R>
60395  friend bool Parma_Polyhedra_Library::Implementation::
60396  operator<=(const Ptr_Iterator<Q>& x, const Ptr_Iterator<R>& y);
60397
60398  template<typename Q, typename R>
60399  friend bool Parma_Polyhedra_Library::Implementation::
60400  operator>(const Ptr_Iterator<Q>& x, const Ptr_Iterator<R>& y);
60401
60402  template<typename Q, typename R>
60403  friend bool Parma_Polyhedra_Library::Implementation::
60404  operator>=(const Ptr_Iterator<Q>& x, const Ptr_Iterator<R>& y);
60405
60406  template<typename Q, typename R>
60407  friend typename Ptr_Iterator<Q>::difference_type
60408  Parma_Polyhedra_Library::Implementation::
60409  operator-(const Ptr_Iterator<Q>& x, const Ptr_Iterator<R>& y);
60410
60411  friend Ptr_Iterator<P>
60412  Parma_Polyhedra_Library::Implementation::
60413  operator+<>(typename Ptr_Iterator<P>::difference_type m,
60414              const Ptr_Iterator<P>& y);
60415};
60416
60417/* Automatically generated from PPL source file ../src/Ptr_Iterator_inlines.hh line 1. */
60418/* Ptr_Iterator class implementation: inline functions.
60419*/
60420
60421
60422namespace Parma_Polyhedra_Library {
60423
60424namespace Implementation {
60425
60426template <typename P>
60427inline const P&
60428Ptr_Iterator<P>::base() const {
60429  return p;
60430}
60431
60432template <typename P>
60433inline
60434Ptr_Iterator<P>::Ptr_Iterator()
60435  : p(P()) {
60436}
60437
60438template <typename P>
60439inline
60440Ptr_Iterator<P>::Ptr_Iterator(const P& q)
60441  : p(q) {
60442}
60443
60444template <typename P>
60445template <typename Q>
60446inline
60447Ptr_Iterator<P>::Ptr_Iterator(const Ptr_Iterator<Q>& q)
60448  : p(q.base()) {
60449}
60450
60451template <typename P>
60452inline typename Ptr_Iterator<P>::reference
60453Ptr_Iterator<P>::operator*() const {
60454  return *p;
60455}
60456
60457template <typename P>
60458inline typename Ptr_Iterator<P>::pointer
60459Ptr_Iterator<P>::operator->() const {
60460  return p;
60461}
60462
60463template <typename P>
60464inline typename Ptr_Iterator<P>::reference
60465Ptr_Iterator<P>::operator[](const difference_type m) const {
60466  return p[m];
60467}
60468
60469template <typename P>
60470inline Ptr_Iterator<P>&
60471Ptr_Iterator<P>::operator++() {
60472  ++p;
60473  return *this;
60474}
60475
60476template <typename P>
60477inline Ptr_Iterator<P>
60478Ptr_Iterator<P>::operator++(int) {
60479  return Ptr_Iterator(p++);
60480}
60481
60482template <typename P>
60483inline Ptr_Iterator<P>&
60484Ptr_Iterator<P>::operator--() {
60485  --p;
60486  return *this;
60487}
60488
60489template <typename P>
60490inline Ptr_Iterator<P>
60491Ptr_Iterator<P>::operator--(int) {
60492  return Ptr_Iterator(p--);
60493}
60494
60495
60496template <typename P>
60497inline Ptr_Iterator<P>&
60498Ptr_Iterator<P>::operator+=(const difference_type m) {
60499  p += m;
60500  return *this;
60501}
60502
60503template <typename P>
60504inline Ptr_Iterator<P>&
60505Ptr_Iterator<P>::operator-=(const difference_type m) {
60506  p -= m;
60507  return *this;
60508}
60509
60510template <typename P>
60511inline typename Ptr_Iterator<P>::difference_type
60512Ptr_Iterator<P>::operator-(const Ptr_Iterator& y) const {
60513  return p - y.p;
60514}
60515
60516template <typename P>
60517inline Ptr_Iterator<P>
60518Ptr_Iterator<P>::operator+(const difference_type m) const {
60519  return Ptr_Iterator(p + m);
60520}
60521
60522template <typename P>
60523inline Ptr_Iterator<P>
60524Ptr_Iterator<P>::operator-(const difference_type m) const {
60525  return Ptr_Iterator(p - m);
60526}
60527
60528template<typename P, typename Q>
60529inline bool
60530operator==(const Ptr_Iterator<P>& x, const Ptr_Iterator<Q>& y) {
60531  return x.base() == y.base();
60532}
60533
60534template<typename P, typename Q>
60535inline bool
60536operator!=(const Ptr_Iterator<P>& x, const Ptr_Iterator<Q>& y) {
60537  return x.base() != y.base();
60538}
60539
60540template<typename P, typename Q>
60541inline bool
60542operator<(const Ptr_Iterator<P>& x, const Ptr_Iterator<Q>& y) {
60543  return x.base() < y.base();
60544}
60545
60546template<typename P, typename Q>
60547inline bool
60548operator<=(const Ptr_Iterator<P>& x, const Ptr_Iterator<Q>& y) {
60549  return x.base() <= y.base();
60550}
60551
60552template<typename P, typename Q>
60553inline bool
60554operator>(const Ptr_Iterator<P>& x, const Ptr_Iterator<Q>& y) {
60555  return x.base() > y.base();
60556}
60557
60558template<typename P, typename Q>
60559inline bool
60560operator>=(const Ptr_Iterator<P>& x, const Ptr_Iterator<Q>& y) {
60561  return x.base() >= y.base();
60562}
60563
60564template<typename P, typename Q>
60565inline typename Ptr_Iterator<P>::difference_type
60566operator-(const Ptr_Iterator<P>& x, const Ptr_Iterator<Q>& y) {
60567  return x.base() - y.base();
60568}
60569
60570template<typename P>
60571inline Ptr_Iterator<P>
60572operator+(typename Ptr_Iterator<P>::difference_type m,
60573          const Ptr_Iterator<P>& y) {
60574  return Ptr_Iterator<P>(m + y.base());
60575}
60576
60577} // namespace Implementation
60578
60579} // namespace Parma_Polyhedra_Library
60580
60581/* Automatically generated from PPL source file ../src/Ptr_Iterator_defs.hh line 171. */
60582
60583/* Automatically generated from PPL source file ../src/DB_Row_defs.hh line 30. */
60584#include <cstddef>
60585#include <vector>
60586
60587#ifndef PPL_DB_ROW_EXTRA_DEBUG
60588#ifdef PPL_ABI_BREAKING_EXTRA_DEBUG
60589#ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
60590/*! \brief
60591  When PPL_DB_ROW_EXTRA_DEBUG evaluates to <CODE>true</CODE>, each instance
60592  of the class DB_Row carries its own capacity; this enables extra
60593  consistency checks to be performed.
60594  \ingroup PPL_CXX_interface
60595*/
60596#endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
60597#define PPL_DB_ROW_EXTRA_DEBUG 1
60598#else // !defined(PPL_ABI_BREAKING_EXTRA_DEBUG)
60599#define PPL_DB_ROW_EXTRA_DEBUG 0
60600#endif // !defined(PPL_ABI_BREAKING_EXTRA_DEBUG)
60601#endif // !defined(PPL_DB_ROW_EXTRA_DEBUG)
60602
60603
60604#ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
60605//! The handler of the actual DB_Row implementation.
60606/*! \ingroup PPL_CXX_interface
60607  Exception-safety is the only responsibility of this class: it has
60608  to ensure that its \p impl member is correctly deallocated.
60609*/
60610#endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
60611template <typename T>
60612class Parma_Polyhedra_Library::DB_Row_Impl_Handler {
60613public:
60614  //! Default constructor.
60615  DB_Row_Impl_Handler();
60616
60617  //! Destructor.
60618  ~DB_Row_Impl_Handler();
60619
60620  class Impl;
60621
60622  //! A pointer to the actual implementation.
60623  Impl* impl;
60624
60625#if PPL_DB_ROW_EXTRA_DEBUG
60626  //! The capacity of \p impl (only available during debugging).
60627  dimension_type capacity_;
60628#endif // PPL_DB_ROW_EXTRA_DEBUG
60629
60630private:
60631  //! Private and unimplemented: copy construction is not allowed.
60632  DB_Row_Impl_Handler(const DB_Row_Impl_Handler&);
60633
60634  //! Private and unimplemented: copy assignment is not allowed.
60635  DB_Row_Impl_Handler& operator=(const DB_Row_Impl_Handler&);
60636};
60637
60638#ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
60639//! The base class for the single rows of matrices.
60640/*! \ingroup PPL_CXX_interface
60641  The class template DB_Row<T> allows for the efficient representation of
60642  the single rows of a DB_Matrix. It contains elements of type T stored
60643  as a vector. The class T is a family of extended numbers that
60644  must provide representation for
60645  \f$ -\infty \f$, \f$0\f$,\f$ +\infty \f$ (and, consequently for <EM>nan</EM>,
60646  <EM>not a number</EM>, since this arises as the ``result'' of
60647  undefined sums like \f$ +\infty + (-\infty) \f$).
60648
60649  The class T must provide the following methods:
60650
60651  \code
60652    T()
60653  \endcode
60654  is the default constructor: no assumption is made on the particular
60655  object constructed, provided <CODE>T().OK()</CODE> gives <CODE>true</CODE>
60656  (see below).
60657  \code
60658    ~T()
60659  \endcode
60660  is the destructor.
60661  \code
60662    bool is_nan() const
60663  \endcode
60664  returns <CODE>true</CODE> if and only \p *this represents
60665  the  <EM>not a number</EM> value.
60666  \code
60667    bool OK() const
60668  \endcode
60669  returns <CODE>true</CODE> if and only if \p *this satisfies all
60670  its invariants.
60671*/
60672#endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
60673template <typename T>
60674class Parma_Polyhedra_Library::DB_Row : private DB_Row_Impl_Handler<T> {
60675public:
60676  //! Pre-constructs a row: construction must be completed by construct().
60677  DB_Row();
60678
60679  //! \name Post-constructors.
60680  //@{
60681  //! Constructs properly a default-constructed element.
60682  /*!
60683    Builds a row with size \p sz and minimum capacity.
60684  */
60685  void construct(dimension_type sz);
60686
60687  //! Constructs properly a default-constructed element.
60688  /*!
60689    \param sz
60690    The size of the row that will be constructed.
60691
60692    \param capacity
60693    The minimum capacity of the row that will be constructed.
60694
60695    The row that we are constructing has a minimum capacity of
60696    (i.e., it can contain at least) \p elements, \p sz of which
60697    will be constructed now.
60698  */
60699  void construct(dimension_type sz, dimension_type capacity);
60700
60701  //! Constructs properly a conservative approximation of \p y.
60702  /*!
60703    \param y
60704    A row containing the elements whose upward approximations will
60705    be used to properly construct \p *this.
60706
60707    \param capacity
60708    The capacity of the constructed row.
60709
60710    It is assumed that \p capacity is greater than or equal to the
60711    size of \p y.
60712  */
60713  template <typename U>
60714  void construct_upward_approximation(const DB_Row<U>& y,
60715                                      dimension_type capacity);
60716
60717  //@}
60718
60719  //! Tight constructor: resizing will require reallocation.
60720  DB_Row(dimension_type sz);
60721
60722  //! Sizing constructor with capacity.
60723  DB_Row(dimension_type sz, dimension_type capacity);
60724
60725  //! Ordinary copy constructor.
60726  DB_Row(const DB_Row& y);
60727
60728  //! Copy constructor with specified capacity.
60729  /*!
60730    It is assumed that \p capacity is greater than or equal to \p y size.
60731  */
60732  DB_Row(const DB_Row& y, dimension_type capacity);
60733
60734  //! Copy constructor with specified size and capacity.
60735  /*!
60736    It is assumed that \p sz is greater than or equal to the size of \p y
60737    and, of course, that \p sz is less than or equal to \p capacity.
60738    Any new position is initialized to \f$+\infty\f$.
60739  */
60740  DB_Row(const DB_Row& y, dimension_type sz, dimension_type capacity);
60741
60742  //! Destructor.
60743  ~DB_Row();
60744
60745  //! Assignment operator.
60746  DB_Row& operator=(const DB_Row& y);
60747
60748  //! Swaps \p *this with \p y.
60749  void m_swap(DB_Row& y);
60750
60751  //! Assigns the implementation of \p y to \p *this.
60752  void assign(DB_Row& y);
60753
60754  /*! \brief
60755    Allocates memory for a default constructed DB_Row object,
60756    allowing for \p capacity coefficients at most.
60757
60758    It is assumed that no allocation has been performed before
60759    (otherwise, a memory leak will occur).
60760    After execution, the size of the DB_Row object is zero.
60761  */
60762  void allocate(dimension_type capacity);
60763
60764  //! Expands the row to size \p new_size.
60765  /*!
60766    Adds new positions to the implementation of the row
60767    obtaining a new row with size \p new_size.
60768    It is assumed that \p new_size is between the current size
60769    and capacity of the row. The new positions are initialized
60770    to \f$+\infty\f$.
60771  */
60772  void expand_within_capacity(dimension_type new_size);
60773
60774  //! Shrinks the row by erasing elements at the end.
60775  /*!
60776    Destroys elements of the row implementation
60777    from position \p new_size to the end.
60778    It is assumed that \p new_size is not greater than the current size.
60779  */
60780  void shrink(dimension_type new_size);
60781
60782  //! Returns the size() of the largest possible DB_Row.
60783  static dimension_type max_size();
60784
60785  //! Gives the number of coefficients currently in use.
60786  dimension_type size() const;
60787
60788  //! \name Subscript operators.
60789  //@{
60790  //! Returns a reference to the element of the row indexed by \p k.
60791  T& operator[](dimension_type k);
60792
60793  //! Returns a constant reference to the element of the row indexed by \p k.
60794  const T& operator[](dimension_type k) const;
60795  //@}
60796
60797  //! A (non const) random access iterator to access the row's elements.
60798  typedef Implementation::Ptr_Iterator<T*> iterator;
60799
60800  //! A const random access iterator to access the row's elements.
60801  typedef Implementation::Ptr_Iterator<const T*> const_iterator;
60802
60803  /*! \brief
60804    Returns the const iterator pointing to the first element,
60805    if \p *this is not empty;
60806    otherwise, returns the past-the-end const iterator.
60807  */
60808  iterator begin();
60809
60810  //! Returns the past-the-end iterator.
60811  iterator end();
60812
60813  /*! \brief
60814    Returns the const iterator pointing to the first element,
60815    if \p *this is not empty;
60816    otherwise, returns the past-the-end const iterator.
60817  */
60818  const_iterator begin() const;
60819
60820  //! Returns the past-the-end const iterator.
60821  const_iterator end() const;
60822
60823  /*! \brief
60824    Returns a lower bound to the total size in bytes of the memory
60825    occupied by \p *this.
60826  */
60827  memory_size_type total_memory_in_bytes() const;
60828
60829  /*! \brief
60830    Returns a lower bound to the size in bytes of the memory
60831    managed by \p *this.
60832  */
60833  memory_size_type external_memory_in_bytes() const;
60834
60835  /*! \brief
60836    Returns the total size in bytes of the memory occupied by \p *this,
60837    provided the capacity of \p *this is given by \p capacity.
60838  */
60839  memory_size_type total_memory_in_bytes(dimension_type capacity) const;
60840
60841  /*! \brief
60842    Returns the size in bytes of the memory managed by \p *this,
60843    provided the capacity of \p *this is given by \p capacity.
60844  */
60845  memory_size_type external_memory_in_bytes(dimension_type capacity) const;
60846
60847  //! Checks if all the invariants are satisfied.
60848  bool OK(dimension_type row_size, dimension_type row_capacity) const;
60849
60850private:
60851  template <typename U> friend class Parma_Polyhedra_Library::DB_Row;
60852
60853  //! Exception-safe copy construction mechanism for coefficients.
60854  void copy_construct_coefficients(const DB_Row& y);
60855
60856#if PPL_DB_ROW_EXTRA_DEBUG
60857  //! Returns the capacity of the row (only available during debugging).
60858  dimension_type capacity() const;
60859#endif // PPL_DB_ROW_EXTRA_DEBUG
60860};
60861
60862namespace Parma_Polyhedra_Library {
60863
60864#ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
60865//! Swaps \p x with \p y.
60866/*! \relates DB_Row */
60867#endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
60868template <typename T>
60869void swap(DB_Row<T>& x, DB_Row<T>& y);
60870
60871#ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
60872//! Swaps objects referred by \p x and \p y.
60873/*! \relates DB_Row */
60874#endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
60875template <typename T>
60876void iter_swap(typename std::vector<DB_Row<T> >::iterator x,
60877               typename std::vector<DB_Row<T> >::iterator y);
60878
60879#ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
60880//! \name Classical comparison operators.
60881//@{
60882#endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
60883/*! \relates DB_Row */
60884template <typename T>
60885bool operator==(const DB_Row<T>& x, const DB_Row<T>& y);
60886
60887/*! \relates DB_Row */
60888template <typename T>
60889bool operator!=(const DB_Row<T>& x, const DB_Row<T>& y);
60890#ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
60891//@}
60892#endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
60893
60894} // namespace Parma_Polyhedra_Library
60895
60896
60897#ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
60898//! The real implementation of a DB_Row object.
60899/*! \ingroup PPL_CXX_interface
60900  The class DB_Row_Impl_Handler::Impl provides the implementation of
60901  DB_Row objects and, in particular, of the corresponding memory
60902  allocation functions.
60903*/
60904#endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
60905template <typename T>
60906class Parma_Polyhedra_Library::DB_Row_Impl_Handler<T>::Impl {
60907public:
60908  //! \name Custom allocator and deallocator.
60909  //@{
60910
60911  /*! \brief
60912    Allocates a chunk of memory able to contain \p capacity T objects
60913    beyond the specified \p fixed_size and returns a pointer to the new
60914    allocated memory.
60915  */
60916  static void* operator new(size_t fixed_size, dimension_type capacity);
60917
60918  //! Uses the standard delete operator to free the memory \p p points to.
60919  static void operator delete(void* p);
60920
60921  /*! \brief
60922    Placement version: uses the standard operator delete to free
60923    the memory \p p points to.
60924  */
60925  static void operator delete(void* p, dimension_type capacity);
60926  //@}
60927
60928  //! Default constructor.
60929  Impl();
60930
60931  //! Destructor.
60932  /*!
60933    Uses <CODE>shrink()</CODE> method with argument \f$0\f$
60934    to delete all the row elements.
60935  */
60936  ~Impl();
60937
60938  //! Expands the row to size \p new_size.
60939  /*!
60940    It is assumed that \p new_size is between the current size and capacity.
60941  */
60942  void expand_within_capacity(dimension_type new_size);
60943
60944  //! Shrinks the row by erasing elements at the end.
60945  /*!
60946    It is assumed that \p new_size is not greater than the current size.
60947  */
60948  void shrink(dimension_type new_size);
60949
60950  //! Exception-safe copy construction mechanism for coefficients.
60951  void copy_construct_coefficients(const Impl& y);
60952
60953  /*! \brief
60954    Exception-safe upward approximation construction mechanism
60955    for coefficients.
60956  */
60957  template <typename U>
60958  void construct_upward_approximation(const U& y);
60959
60960  //! Returns the size() of the largest possible Impl.
60961  static dimension_type max_size();
60962
60963  //! \name Size accessors.
60964  //@{
60965  //! Returns the actual size of \p this.
60966  dimension_type size() const;
60967
60968  //! Sets to \p new_sz the actual size of \p *this.
60969  void set_size(dimension_type new_sz);
60970
60971  //! Increments the size of \p *this by 1.
60972  void bump_size();
60973  //@}
60974
60975  //! \name Subscript operators.
60976  //@{
60977  //! Returns a reference to the element of \p *this indexed by \p k.
60978  T& operator[](dimension_type k);
60979
60980  //! Returns a constant reference to the element of \p *this indexed by \p k.
60981  const T& operator[](dimension_type k) const;
60982  //@}
60983
60984  /*! \brief
60985    Returns a lower bound to the total size in bytes of the memory
60986    occupied by \p *this.
60987  */
60988  memory_size_type total_memory_in_bytes() const;
60989
60990  //! Returns the total size in bytes of the memory occupied by \p *this.
60991  memory_size_type total_memory_in_bytes(dimension_type capacity) const;
60992
60993  //! Returns the size in bytes of the memory managed by \p *this.
60994  memory_size_type external_memory_in_bytes() const;
60995
60996private:
60997  friend class DB_Row<T>;
60998
60999  //! The number of coefficients in the row.
61000  dimension_type size_;
61001
61002  //! The vector of coefficients.
61003  T vec_[
61004#if PPL_CXX_SUPPORTS_ZERO_LENGTH_ARRAYS
61005          0
61006#else
61007          1
61008#endif
61009  ];
61010
61011  //! Private and unimplemented: copy construction is not allowed.
61012  Impl(const Impl& y);
61013
61014  //! Private and unimplemented: assignment is not allowed.
61015  Impl& operator=(const Impl&);
61016
61017  //! Exception-safe copy construction mechanism.
61018  void copy_construct(const Impl& y);
61019};
61020
61021/* Automatically generated from PPL source file ../src/DB_Row_inlines.hh line 1. */
61022/* DB_Row class implementation: inline functions.
61023*/
61024
61025
61026/* Automatically generated from PPL source file ../src/DB_Row_inlines.hh line 29. */
61027#include <cstddef>
61028#include <limits>
61029#include <algorithm>
61030#include <iostream>
61031
61032namespace Parma_Polyhedra_Library {
61033
61034template <typename T>
61035inline void*
61036DB_Row_Impl_Handler<T>::Impl::operator new(const size_t fixed_size,
61037                                           const dimension_type capacity) {
61038#if PPL_CXX_SUPPORTS_ZERO_LENGTH_ARRAYS
61039  return ::operator new(fixed_size + capacity*sizeof(T));
61040#else
61041  PPL_ASSERT(capacity >= 1);
61042  return ::operator new(fixed_size + (capacity-1)*sizeof(T));
61043#endif
61044}
61045
61046template <typename T>
61047inline void
61048DB_Row_Impl_Handler<T>::Impl::operator delete(void* p) {
61049  ::operator delete(p);
61050}
61051
61052template <typename T>
61053inline void
61054DB_Row_Impl_Handler<T>::Impl::operator delete(void* p, dimension_type) {
61055  ::operator delete(p);
61056}
61057
61058template <typename T>
61059inline memory_size_type
61060DB_Row_Impl_Handler<T>::Impl
61061::total_memory_in_bytes(dimension_type capacity) const {
61062  return
61063    sizeof(*this)
61064    + capacity*sizeof(T)
61065#if !PPL_CXX_SUPPORTS_ZERO_LENGTH_ARRAYS
61066    - 1*sizeof(T)
61067#endif
61068    + external_memory_in_bytes();
61069}
61070
61071template <typename T>
61072inline memory_size_type
61073DB_Row_Impl_Handler<T>::Impl::total_memory_in_bytes() const {
61074  // In general, this is a lower bound, as the capacity of *this
61075  // may be strictly greater than `size_'
61076  return total_memory_in_bytes(size_);
61077}
61078
61079template <typename T>
61080inline dimension_type
61081DB_Row_Impl_Handler<T>::Impl::max_size() {
61082  return std::numeric_limits<size_t>::max() / sizeof(T);
61083}
61084
61085template <typename T>
61086inline dimension_type
61087DB_Row_Impl_Handler<T>::Impl::size() const {
61088  return size_;
61089}
61090
61091template <typename T>
61092inline void
61093DB_Row_Impl_Handler<T>::Impl::set_size(const dimension_type new_sz) {
61094  size_ = new_sz;
61095}
61096
61097template <typename T>
61098inline void
61099DB_Row_Impl_Handler<T>::Impl::bump_size() {
61100  ++size_;
61101}
61102
61103template <typename T>
61104inline
61105DB_Row_Impl_Handler<T>::Impl::Impl()
61106  : size_(0) {
61107}
61108
61109template <typename T>
61110inline
61111DB_Row_Impl_Handler<T>::Impl::~Impl() {
61112  shrink(0);
61113}
61114
61115template <typename T>
61116inline
61117DB_Row_Impl_Handler<T>::DB_Row_Impl_Handler()
61118  : impl(0) {
61119#if PPL_DB_ROW_EXTRA_DEBUG
61120  capacity_ = 0;
61121#endif
61122}
61123
61124template <typename T>
61125inline
61126DB_Row_Impl_Handler<T>::~DB_Row_Impl_Handler() {
61127  delete impl;
61128}
61129
61130template <typename T>
61131inline T&
61132DB_Row_Impl_Handler<T>::Impl::operator[](const dimension_type k) {
61133  PPL_ASSERT(k < size());
61134  return vec_[k];
61135}
61136
61137template <typename T>
61138inline const T&
61139DB_Row_Impl_Handler<T>::Impl::operator[](const dimension_type k) const {
61140  PPL_ASSERT(k < size());
61141  return vec_[k];
61142}
61143
61144template <typename T>
61145inline dimension_type
61146DB_Row<T>::max_size() {
61147  return DB_Row_Impl_Handler<T>::Impl::max_size();
61148}
61149
61150template <typename T>
61151inline dimension_type
61152DB_Row<T>::size() const {
61153  return this->impl->size();
61154}
61155
61156#if PPL_DB_ROW_EXTRA_DEBUG
61157template <typename T>
61158inline dimension_type
61159DB_Row<T>::capacity() const {
61160  return this->capacity_;
61161}
61162#endif // PPL_DB_ROW_EXTRA_DEBUG
61163
61164template <typename T>
61165inline
61166DB_Row<T>::DB_Row()
61167  : DB_Row_Impl_Handler<T>() {
61168}
61169
61170template <typename T>
61171inline void
61172DB_Row<T>::allocate(
61173#if PPL_CXX_SUPPORTS_ZERO_LENGTH_ARRAYS
61174               const
61175#endif
61176               dimension_type capacity) {
61177  DB_Row<T>& x = *this;
61178  PPL_ASSERT(capacity <= max_size());
61179#if !PPL_CXX_SUPPORTS_ZERO_LENGTH_ARRAYS
61180  if (capacity == 0) {
61181    ++capacity;
61182  }
61183#endif
61184  PPL_ASSERT(x.impl == 0);
61185  x.impl = new(capacity) typename DB_Row_Impl_Handler<T>::Impl();
61186#if PPL_DB_ROW_EXTRA_DEBUG
61187  PPL_ASSERT(x.capacity_ == 0);
61188  x.capacity_ = capacity;
61189#endif
61190}
61191
61192template <typename T>
61193inline void
61194DB_Row<T>::expand_within_capacity(const dimension_type new_size) {
61195  DB_Row<T>& x = *this;
61196  PPL_ASSERT(x.impl);
61197#if PPL_DB_ROW_EXTRA_DEBUG
61198  PPL_ASSERT(new_size <= x.capacity_);
61199#endif
61200  x.impl->expand_within_capacity(new_size);
61201}
61202
61203template <typename T>
61204inline void
61205DB_Row<T>::copy_construct_coefficients(const DB_Row& y) {
61206  DB_Row<T>& x = *this;
61207  PPL_ASSERT(x.impl && y.impl);
61208#if PPL_DB_ROW_EXTRA_DEBUG
61209  PPL_ASSERT(y.size() <= x.capacity_);
61210#endif
61211  x.impl->copy_construct_coefficients(*(y.impl));
61212}
61213
61214template <typename T>
61215template <typename U>
61216inline void
61217DB_Row<T>::construct_upward_approximation(const DB_Row<U>& y,
61218                                          const dimension_type capacity) {
61219  DB_Row<T>& x = *this;
61220  PPL_ASSERT(y.size() <= capacity && capacity <= max_size());
61221  allocate(capacity);
61222  PPL_ASSERT(y.impl);
61223  x.impl->construct_upward_approximation(*(y.impl));
61224}
61225
61226template <typename T>
61227inline void
61228DB_Row<T>::construct(const dimension_type sz,
61229                     const dimension_type capacity) {
61230  PPL_ASSERT(sz <= capacity && capacity <= max_size());
61231  allocate(capacity);
61232  expand_within_capacity(sz);
61233}
61234
61235template <typename T>
61236inline void
61237DB_Row<T>::construct(const dimension_type sz) {
61238  construct(sz, sz);
61239}
61240
61241template <typename T>
61242inline
61243DB_Row<T>::DB_Row(const dimension_type sz,
61244                  const dimension_type capacity)
61245  : DB_Row_Impl_Handler<T>() {
61246  construct(sz, capacity);
61247}
61248
61249template <typename T>
61250inline
61251DB_Row<T>::DB_Row(const dimension_type sz) {
61252  construct(sz);
61253}
61254
61255template <typename T>
61256inline
61257DB_Row<T>::DB_Row(const DB_Row& y)
61258  : DB_Row_Impl_Handler<T>() {
61259  if (y.impl != 0) {
61260    allocate(compute_capacity(y.size(), max_size()));
61261    copy_construct_coefficients(y);
61262  }
61263}
61264
61265template <typename T>
61266inline
61267DB_Row<T>::DB_Row(const DB_Row& y,
61268                  const dimension_type capacity)
61269  : DB_Row_Impl_Handler<T>() {
61270  PPL_ASSERT(y.impl);
61271  PPL_ASSERT(y.size() <= capacity && capacity <= max_size());
61272  allocate(capacity);
61273  copy_construct_coefficients(y);
61274}
61275
61276template <typename T>
61277inline
61278DB_Row<T>::DB_Row(const DB_Row& y,
61279                  const dimension_type sz,
61280                  const dimension_type capacity)
61281  : DB_Row_Impl_Handler<T>() {
61282  PPL_ASSERT(y.impl);
61283  PPL_ASSERT(y.size() <= sz && sz <= capacity && capacity <= max_size());
61284  allocate(capacity);
61285  copy_construct_coefficients(y);
61286  expand_within_capacity(sz);
61287}
61288
61289template <typename T>
61290inline
61291DB_Row<T>::~DB_Row() {
61292}
61293
61294template <typename T>
61295inline void
61296DB_Row<T>::shrink(const dimension_type new_size) {
61297  DB_Row<T>& x = *this;
61298  PPL_ASSERT(x.impl);
61299  x.impl->shrink(new_size);
61300}
61301
61302template <typename T>
61303inline void
61304DB_Row<T>::m_swap(DB_Row& y) {
61305  using std::swap;
61306  DB_Row<T>& x = *this;
61307  swap(x.impl, y.impl);
61308#if PPL_DB_ROW_EXTRA_DEBUG
61309  swap(x.capacity_, y.capacity_);
61310#endif
61311}
61312
61313template <typename T>
61314inline void
61315DB_Row<T>::assign(DB_Row& y) {
61316  DB_Row<T>& x = *this;
61317  x.impl = y.impl;
61318#if PPL_DB_ROW_EXTRA_DEBUG
61319  x.capacity_ = y.capacity_;
61320#endif
61321}
61322
61323template <typename T>
61324inline DB_Row<T>&
61325DB_Row<T>::operator=(const DB_Row& y) {
61326  DB_Row tmp(y);
61327  m_swap(tmp);
61328  return *this;
61329}
61330
61331template <typename T>
61332inline T&
61333DB_Row<T>::operator[](const dimension_type k) {
61334  DB_Row<T>& x = *this;
61335  return (*x.impl)[k];
61336}
61337
61338template <typename T>
61339inline const T&
61340DB_Row<T>::operator[](const dimension_type k) const {
61341  const DB_Row<T>& x = *this;
61342  return (*x.impl)[k];
61343}
61344
61345template <typename T>
61346inline typename DB_Row<T>::iterator
61347DB_Row<T>::begin() {
61348  DB_Row<T>& x = *this;
61349  return iterator(x.impl->vec_);
61350}
61351
61352template <typename T>
61353inline typename DB_Row<T>::iterator
61354DB_Row<T>::end() {
61355  DB_Row<T>& x = *this;
61356  return iterator(x.impl->vec_ + x.impl->size_);
61357}
61358
61359template <typename T>
61360inline typename DB_Row<T>::const_iterator
61361DB_Row<T>::begin() const {
61362  const DB_Row<T>& x = *this;
61363  return const_iterator(x.impl->vec_);
61364}
61365
61366template <typename T>
61367inline typename DB_Row<T>::const_iterator
61368DB_Row<T>::end() const {
61369  const DB_Row<T>& x = *this;
61370  return const_iterator(x.impl->vec_ + x.impl->size_);
61371}
61372
61373template <typename T>
61374inline memory_size_type
61375DB_Row<T>::external_memory_in_bytes(dimension_type capacity) const {
61376  const DB_Row<T>& x = *this;
61377  return x.impl->total_memory_in_bytes(capacity);
61378}
61379
61380template <typename T>
61381inline memory_size_type
61382DB_Row<T>::total_memory_in_bytes(dimension_type capacity) const {
61383  return sizeof(*this) + external_memory_in_bytes(capacity);
61384}
61385
61386template <typename T>
61387inline memory_size_type
61388DB_Row<T>::external_memory_in_bytes() const {
61389  const DB_Row<T>& x = *this;
61390#if PPL_DB_ROW_EXTRA_DEBUG
61391  return x.impl->total_memory_in_bytes(x.capacity_);
61392#else
61393  return x.impl->total_memory_in_bytes();
61394#endif
61395}
61396
61397template <typename T>
61398inline memory_size_type
61399DB_Row<T>::total_memory_in_bytes() const {
61400  return sizeof(*this) + external_memory_in_bytes();
61401}
61402
61403/*! \relates DB_Row */
61404template <typename T>
61405inline bool
61406operator!=(const DB_Row<T>& x, const DB_Row<T>& y) {
61407  return !(x == y);
61408}
61409
61410/*! \relates DB_Row */
61411template <typename T>
61412inline void
61413swap(DB_Row<T>& x, DB_Row<T>& y) {
61414  x.m_swap(y);
61415}
61416
61417/*! \relates DB_Row */
61418template <typename T>
61419inline void
61420iter_swap(typename std::vector<DB_Row<T> >::iterator x,
61421          typename std::vector<DB_Row<T> >::iterator y) {
61422  swap(*x, *y);
61423}
61424
61425} // namespace Parma_Polyhedra_Library
61426
61427/* Automatically generated from PPL source file ../src/DB_Row_templates.hh line 1. */
61428/* DB_Row class implementation: non-inline template functions.
61429*/
61430
61431
61432/* Automatically generated from PPL source file ../src/DB_Row_templates.hh line 28. */
61433
61434namespace Parma_Polyhedra_Library {
61435
61436template <typename T>
61437template <typename U>
61438void
61439DB_Row_Impl_Handler<T>::Impl::construct_upward_approximation(const U& y) {
61440  const dimension_type y_size = y.size();
61441#if PPL_CXX_SUPPORTS_ZERO_LENGTH_ARRAYS
61442  // Construct in direct order: will destroy in reverse order.
61443  for (dimension_type i = 0; i < y_size; ++i) {
61444    construct(vec_[i], y[i], ROUND_UP);
61445    bump_size();
61446  }
61447#else // PPL_CXX_SUPPORTS_ZERO_LENGTH_ARRAYS
61448  if (y_size > 0) {
61449    assign_r(vec_[0], y[0], ROUND_UP);
61450    bump_size();
61451    // Construct in direct order: will destroy in reverse order.
61452    for (dimension_type i = 1; i < y_size; ++i) {
61453      construct(vec_[i], y[i], ROUND_UP);
61454      bump_size();
61455    }
61456  }
61457#endif // PPL_CXX_SUPPORTS_ZERO_LENGTH_ARRAYS
61458}
61459
61460template <typename T>
61461void
61462DB_Row_Impl_Handler<T>::
61463Impl::expand_within_capacity(const dimension_type new_size) {
61464  PPL_ASSERT(size() <= new_size && new_size <= max_size());
61465#if !PPL_CXX_SUPPORTS_ZERO_LENGTH_ARRAYS
61466  if (size() == 0 && new_size > 0) {
61467    // vec_[0] is already constructed: we just need to assign +infinity.
61468    assign_r(vec_[0], PLUS_INFINITY, ROUND_NOT_NEEDED);
61469    bump_size();
61470  }
61471#endif
61472  // Construct in direct order: will destroy in reverse order.
61473  for (dimension_type i = size(); i < new_size; ++i) {
61474    new(&vec_[i]) T(PLUS_INFINITY, ROUND_NOT_NEEDED);
61475    bump_size();
61476  }
61477}
61478
61479template <typename T>
61480void
61481DB_Row_Impl_Handler<T>::Impl::shrink(dimension_type new_size) {
61482  const dimension_type old_size = size();
61483  PPL_ASSERT(new_size <= old_size);
61484  // Since ~T() does not throw exceptions, nothing here does.
61485  set_size(new_size);
61486#if !PPL_CXX_SUPPORTS_ZERO_LENGTH_ARRAYS
61487  // Make sure we do not try to destroy vec_[0].
61488  if (new_size == 0) {
61489    ++new_size;
61490  }
61491#endif
61492  // We assume construction was done "forward".
61493  // We thus perform destruction "backward".
61494  for (dimension_type i = old_size; i-- > new_size; ) {
61495    vec_[i].~T();
61496  }
61497}
61498
61499template <typename T>
61500void
61501DB_Row_Impl_Handler<T>::Impl::copy_construct_coefficients(const Impl& y) {
61502  const dimension_type y_size = y.size();
61503#if PPL_CXX_SUPPORTS_ZERO_LENGTH_ARRAYS
61504  // Construct in direct order: will destroy in reverse order.
61505  for (dimension_type i = 0; i < y_size; ++i) {
61506    new(&vec_[i]) T(y.vec_[i]);
61507    bump_size();
61508  }
61509#else // PPL_CXX_SUPPORTS_ZERO_LENGTH_ARRAYS
61510  if (y_size > 0) {
61511    vec_[0] = y.vec_[0];
61512    bump_size();
61513    // Construct in direct order: will destroy in reverse order.
61514    for (dimension_type i = 1; i < y_size; ++i) {
61515      new(&vec_[i]) T(y.vec_[i]);
61516      bump_size();
61517    }
61518  }
61519#endif // PPL_CXX_SUPPORTS_ZERO_LENGTH_ARRAYS
61520}
61521
61522template <typename T>
61523memory_size_type
61524DB_Row_Impl_Handler<T>::Impl::external_memory_in_bytes() const {
61525  memory_size_type n = 0;
61526  for (dimension_type i = size(); i-- > 0; ) {
61527    n += Parma_Polyhedra_Library::external_memory_in_bytes(vec_[i]);
61528  }
61529  return n;
61530}
61531
61532template <typename T>
61533bool
61534DB_Row<T>::OK(const dimension_type row_size,
61535              const dimension_type
61536#if PPL_DB_ROW_EXTRA_DEBUG
61537              row_capacity
61538#endif
61539              ) const {
61540#ifndef NDEBUG
61541  using std::endl;
61542  using std::cerr;
61543#endif
61544
61545  const DB_Row<T>& x = *this;
61546  bool is_broken = false;
61547
61548#if PPL_DB_ROW_EXTRA_DEBUG
61549# if !PPL_CXX_SUPPORTS_ZERO_LENGTH_ARRAYS
61550  if (x.capacity_ == 0) {
61551    cerr << "Illegal row capacity: is 0, should be at least 1"
61552         << endl;
61553    is_broken = true;
61554  }
61555  else if (x.capacity_ == 1 && row_capacity == 0)
61556    // This is fine.
61557    ;
61558  else
61559# endif // !PPL_CXX_SUPPORTS_ZERO_LENGTH_ARRAYS
61560  if (x.capacity_ != row_capacity) {
61561    cerr << "DB_Row capacity mismatch: is " << x.capacity_
61562         << ", should be " << row_capacity << "."
61563         << endl;
61564    is_broken = true;
61565  }
61566#endif // PPL_DB_ROW_EXTRA_DEBUG
61567
61568  if (x.size() != row_size) {
61569#ifndef NDEBUG
61570    cerr << "DB_Row size mismatch: is " << x.size()
61571         << ", should be " << row_size << "."
61572         << endl;
61573#endif
61574    is_broken = true;
61575  }
61576
61577#if PPL_DB_ROW_EXTRA_DEBUG
61578  if (x.capacity_ < x.size()) {
61579#ifndef NDEBUG
61580    cerr << "DB_Row is completely broken: capacity is " << x.capacity_
61581         << ", size is " << x.size() << "."
61582         << endl;
61583#endif
61584    is_broken = true;
61585  }
61586#endif // PPL_DB_ROW_EXTRA_DEBUG
61587
61588  for (dimension_type i = x.size(); i-- > 0; ) {
61589    const T& element = x[i];
61590    // Not OK is bad.
61591    if (!element.OK()) {
61592      is_broken = true;
61593      break;
61594    }
61595    // In addition, nans should never occur.
61596    if (is_not_a_number(element)) {
61597#ifndef NDEBUG
61598      cerr << "Not-a-number found in DB_Row."
61599           << endl;
61600#endif
61601      is_broken = true;
61602      break;
61603    }
61604  }
61605
61606  return !is_broken;
61607}
61608
61609/*! \relates DB_Row */
61610template <typename T>
61611bool
61612operator==(const DB_Row<T>& x, const DB_Row<T>& y) {
61613  if (x.size() != y.size()) {
61614    return false;
61615  }
61616  for (dimension_type i = x.size(); i-- > 0; ) {
61617    if (x[i] != y[i]) {
61618      return false;
61619    }
61620  }
61621  return true;
61622}
61623
61624} // namespace Parma_Polyhedra_Library
61625
61626/* Automatically generated from PPL source file ../src/DB_Row_defs.hh line 469. */
61627
61628/* Automatically generated from PPL source file ../src/DB_Matrix_defs.hh line 32. */
61629#include <vector>
61630#include <cstddef>
61631#include <iosfwd>
61632
61633namespace Parma_Polyhedra_Library {
61634
61635namespace IO_Operators {
61636
61637#ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
61638//! Output operator.
61639/*! \relates Parma_Polyhedra_Library::DB_Matrix */
61640#endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
61641template <typename T>
61642std::ostream&
61643operator<<(std::ostream& s, const DB_Matrix<T>& c);
61644
61645} // namespace IO_Operators
61646
61647} // namespace Parma_Polyhedra_Library
61648
61649
61650#ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
61651//! The base class for the square matrices.
61652/*! \ingroup PPL_CXX_interface
61653  The template class DB_Matrix<T> allows for the representation of
61654  a square matrix of T objects.
61655  Each DB_Matrix<T> object can be viewed as a multiset of DB_Row<T>.
61656*/
61657#endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
61658template <typename T>
61659class Parma_Polyhedra_Library::DB_Matrix {
61660public:
61661  //! Returns the maximum number of rows a DB_Matrix can handle.
61662  static dimension_type max_num_rows();
61663
61664  //! Returns the maximum number of columns a DB_Matrix can handle.
61665  static dimension_type max_num_columns();
61666
61667  //! Builds an empty matrix.
61668  /*!
61669    DB_Rows' size and capacity are initialized to \f$0\f$.
61670  */
61671  DB_Matrix();
61672
61673  //! Builds a square matrix having the specified dimension.
61674  explicit DB_Matrix(dimension_type n_rows);
61675
61676  //! Copy constructor.
61677  DB_Matrix(const DB_Matrix& y);
61678
61679  //! Constructs a conservative approximation of \p y.
61680  template <typename U>
61681  explicit DB_Matrix(const DB_Matrix<U>& y);
61682
61683  //! Destructor.
61684  ~DB_Matrix();
61685
61686  //! Assignment operator.
61687  DB_Matrix& operator=(const DB_Matrix& y);
61688
61689#ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
61690  //! A read-only iterator over the rows of the matrix.
61691  /*! \ingroup PPL_CXX_interface */
61692#endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
61693  class const_iterator {
61694  private:
61695    typedef typename std::vector<DB_Row<T> >::const_iterator Iter;
61696    //! The const iterator on the rows' vector \p rows.
61697    Iter i;
61698
61699  public:
61700    typedef std::forward_iterator_tag iterator_category;
61701    typedef typename std::iterator_traits<Iter>::value_type value_type;
61702    typedef typename std::iterator_traits<Iter>::difference_type
61703    difference_type;
61704    typedef typename std::iterator_traits<Iter>::pointer pointer;
61705    typedef typename std::iterator_traits<Iter>::reference reference;
61706
61707    //! Default constructor.
61708    const_iterator();
61709
61710    /*! \brief
61711      Builds a const iterator on the matrix starting from
61712      an iterator \p b on the elements of the vector \p rows.
61713    */
61714    explicit const_iterator(const Iter& b);
61715
61716    //! Ordinary copy constructor.
61717    const_iterator(const const_iterator& y);
61718
61719    //! Assignment operator.
61720    const_iterator& operator=(const const_iterator& y);
61721
61722    //! Dereference operator.
61723    reference operator*() const;
61724
61725    //! Indirect member selector.
61726    pointer operator->() const;
61727
61728    //! Prefix increment operator.
61729    const_iterator& operator++();
61730
61731    //! Postfix increment operator.
61732    const_iterator operator++(int);
61733
61734    /*! \brief
61735      Returns <CODE>true</CODE> if and only if
61736      \p *this and \p y are identical.
61737    */
61738    bool operator==(const const_iterator& y) const;
61739
61740    /*! \brief
61741      Returns <CODE>true</CODE> if and only if
61742      \p *this and \p y are different.
61743    */
61744    bool operator!=(const const_iterator& y) const;
61745  };
61746
61747  /*! \brief
61748    Returns the const_iterator pointing to the first row,
61749    if \p *this is not empty;
61750    otherwise, returns the past-the-end const_iterator.
61751  */
61752  const_iterator begin() const;
61753
61754  //! Returns the past-the-end const_iterator.
61755  const_iterator end() const;
61756
61757private:
61758  template <typename U> friend class DB_Matrix;
61759
61760  //! The rows of the matrix.
61761  std::vector<DB_Row<T> > rows;
61762
61763  //! Size of the initialized part of each row.
61764  dimension_type row_size;
61765
61766  /*! \brief
61767    Capacity allocated for each row, i.e., number of
61768    <CODE>long</CODE> objects that each row can contain.
61769  */
61770  dimension_type row_capacity;
61771
61772public:
61773  //! Swaps \p *this with \p y.
61774  void m_swap(DB_Matrix& y);
61775
61776  //! Makes the matrix grow by adding more rows and more columns.
61777  /*!
61778    \param new_n_rows
61779    The number of rows and columns of the resized matrix.
61780
61781    A new matrix, with the specified dimension, is created.
61782    The contents of the old matrix are copied in the upper, left-hand
61783    corner of the new matrix, which is then assigned to \p *this.
61784  */
61785  void grow(dimension_type new_n_rows);
61786
61787  //! Resizes the matrix without worrying about the old contents.
61788  /*!
61789    \param new_n_rows
61790    The number of rows and columns of the resized matrix.
61791
61792    A new matrix, with the specified dimension, is created without copying
61793    the content of the old matrix and assigned to \p *this.
61794  */
61795  void resize_no_copy(dimension_type new_n_rows);
61796
61797  //! Returns the number of rows in the matrix.
61798  dimension_type num_rows() const;
61799
61800  //! \name Subscript operators.
61801  //@{
61802  //! Returns a reference to the \p k-th row of the matrix.
61803  DB_Row<T>& operator[](dimension_type k);
61804
61805  //! Returns a constant reference to the \p k-th row of the matrix.
61806  const DB_Row<T>& operator[](dimension_type k) const;
61807  //@}
61808
61809  PPL_OUTPUT_DECLARATIONS
61810
61811  /*! \brief
61812    Loads from \p s an ASCII representation (as produced by
61813    ascii_dump(std::ostream&) const) and sets \p *this accordingly.
61814    Returns <CODE>true</CODE> if successful, <CODE>false</CODE> otherwise.
61815  */
61816  bool ascii_load(std::istream& s);
61817
61818  //! Returns the total size in bytes of the memory occupied by \p *this.
61819  memory_size_type total_memory_in_bytes() const;
61820
61821  //! Returns the size in bytes of the memory managed by \p *this.
61822  memory_size_type external_memory_in_bytes() const;
61823
61824  //! Checks if all the invariants are satisfied.
61825  bool OK() const;
61826};
61827
61828namespace Parma_Polyhedra_Library {
61829
61830#ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
61831//! Swaps \p x with \p y.
61832/*! \relates DB_Matrix */
61833#endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
61834template <typename T>
61835void swap(DB_Matrix<T>& x, DB_Matrix<T>& y);
61836
61837#ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
61838//! Returns <CODE>true</CODE> if and only if \p x and \p y are identical.
61839/*! \relates DB_Matrix */
61840#endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
61841template <typename T>
61842bool operator==(const DB_Matrix<T>& x, const DB_Matrix<T>& y);
61843
61844#ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
61845//! Returns <CODE>true</CODE> if and only if \p x and \p y are different.
61846/*! \relates DB_Matrix */
61847#endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
61848template <typename T>
61849bool operator!=(const DB_Matrix<T>& x, const DB_Matrix<T>& y);
61850
61851#ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
61852//! Computes the rectilinear (or Manhattan) distance between \p x and \p y.
61853/*! \relates DB_Matrix
61854  If the rectilinear distance between \p x and \p y is defined,
61855  stores an approximation of it into to \p r
61856  and returns <CODE>true</CODE>;  returns <CODE>false</CODE> otherwise.
61857
61858  The direction of the approximation is specified by \p dir.
61859
61860  All computations are performed using the temporary variables
61861  \p tmp0, \p tmp1 and \p tmp2.
61862*/
61863#endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
61864template <typename Temp, typename To, typename T>
61865bool rectilinear_distance_assign(Checked_Number<To, Extended_Number_Policy>& r,
61866                                 const DB_Matrix<T>& x,
61867                                 const DB_Matrix<T>& y,
61868                                 Rounding_Dir dir,
61869                                 Temp& tmp0,
61870                                 Temp& tmp1,
61871                                 Temp& tmp2);
61872
61873#ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
61874//! Computes the euclidean distance between \p x and \p y.
61875/*! \relates DB_Matrix
61876  If the Euclidean distance between \p x and \p y is defined,
61877  stores an approximation of it into to \p r
61878  and returns <CODE>true</CODE>;  returns <CODE>false</CODE> otherwise.
61879
61880  The direction of the approximation is specified by \p dir.
61881
61882  All computations are performed using the temporary variables
61883  \p tmp0, \p tmp1 and \p tmp2.
61884*/
61885#endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
61886template <typename Temp, typename To, typename T>
61887bool euclidean_distance_assign(Checked_Number<To, Extended_Number_Policy>& r,
61888                               const DB_Matrix<T>& x,
61889                               const DB_Matrix<T>& y,
61890                               Rounding_Dir dir,
61891                               Temp& tmp0,
61892                               Temp& tmp1,
61893                               Temp& tmp2);
61894
61895#ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
61896//! Computes the \f$L_\infty\f$ distance between \p x and \p y.
61897/*! \relates DB_Matrix
61898  If the \f$L_\infty\f$ distance between \p x and \p y is defined,
61899  stores an approximation of it into to \p r
61900  and returns <CODE>true</CODE>;  returns <CODE>false</CODE> otherwise.
61901
61902  The direction of the approximation is specified by \p dir.
61903
61904  All computations are performed using the temporary variables
61905  \p tmp0, \p tmp1 and \p tmp2.
61906*/
61907#endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
61908template <typename Temp, typename To, typename T>
61909bool l_infinity_distance_assign(Checked_Number<To, Extended_Number_Policy>& r,
61910                                const DB_Matrix<T>& x,
61911                                const DB_Matrix<T>& y,
61912                                Rounding_Dir dir,
61913                                Temp& tmp0,
61914                                Temp& tmp1,
61915                                Temp& tmp2);
61916
61917} // namespace Parma_Polyhedra_Library
61918
61919/* Automatically generated from PPL source file ../src/DB_Matrix_inlines.hh line 1. */
61920/* DB_Matrix class implementation: inline functions.
61921*/
61922
61923
61924/* Automatically generated from PPL source file ../src/DB_Matrix_inlines.hh line 31. */
61925#include <iostream>
61926
61927namespace Parma_Polyhedra_Library {
61928
61929template <typename T>
61930inline void
61931DB_Matrix<T>::m_swap(DB_Matrix& y) {
61932  using std::swap;
61933  swap(rows, y.rows);
61934  swap(row_size, y.row_size);
61935  swap(row_capacity, y.row_capacity);
61936}
61937
61938template <typename T>
61939inline dimension_type
61940DB_Matrix<T>::max_num_rows() {
61941  return std::vector<DB_Row<T> >().max_size();
61942}
61943
61944template <typename T>
61945inline dimension_type
61946DB_Matrix<T>::max_num_columns() {
61947  return DB_Row<T>::max_size();
61948}
61949
61950template <typename T>
61951inline memory_size_type
61952DB_Matrix<T>::total_memory_in_bytes() const {
61953  return sizeof(*this) + external_memory_in_bytes();
61954}
61955
61956template <typename T>
61957inline
61958DB_Matrix<T>::const_iterator::const_iterator()
61959  : i(Iter()) {
61960}
61961
61962template <typename T>
61963inline
61964DB_Matrix<T>::const_iterator::const_iterator(const Iter& b)
61965  : i(b) {
61966}
61967
61968template <typename T>
61969inline
61970DB_Matrix<T>::const_iterator::const_iterator(const const_iterator& y)
61971  : i(y.i) {
61972}
61973
61974template <typename T>
61975inline typename DB_Matrix<T>::const_iterator&
61976DB_Matrix<T>::const_iterator::operator=(const const_iterator& y) {
61977  i = y.i;
61978  return *this;
61979}
61980
61981template <typename T>
61982inline typename DB_Matrix<T>::const_iterator::reference
61983DB_Matrix<T>::const_iterator::operator*() const {
61984  return *i;
61985}
61986
61987template <typename T>
61988inline typename DB_Matrix<T>::const_iterator::pointer
61989DB_Matrix<T>::const_iterator::operator->() const {
61990  return &*i;
61991}
61992
61993template <typename T>
61994inline typename DB_Matrix<T>::const_iterator&
61995DB_Matrix<T>::const_iterator::operator++() {
61996  ++i;
61997  return *this;
61998}
61999
62000template <typename T>
62001inline typename DB_Matrix<T>::const_iterator
62002DB_Matrix<T>::const_iterator::operator++(int) {
62003  return const_iterator(i++);
62004}
62005
62006template <typename T>
62007inline bool
62008DB_Matrix<T>::const_iterator::operator==(const const_iterator& y) const {
62009  return i == y.i;
62010}
62011
62012template <typename T>
62013inline bool
62014DB_Matrix<T>::const_iterator::operator!=(const const_iterator& y) const {
62015  return !operator==(y);
62016}
62017
62018template <typename T>
62019inline typename DB_Matrix<T>::const_iterator
62020DB_Matrix<T>::begin() const {
62021  return const_iterator(rows.begin());
62022}
62023
62024template <typename T>
62025inline typename DB_Matrix<T>::const_iterator
62026DB_Matrix<T>::end() const {
62027  return const_iterator(rows.end());
62028}
62029
62030template <typename T>
62031inline
62032DB_Matrix<T>::DB_Matrix()
62033  : rows(),
62034    row_size(0),
62035    row_capacity(0) {
62036}
62037
62038template <typename T>
62039inline
62040DB_Matrix<T>::~DB_Matrix() {
62041}
62042
62043template <typename T>
62044inline DB_Row<T>&
62045DB_Matrix<T>::operator[](const dimension_type k) {
62046  PPL_ASSERT(k < rows.size());
62047  return rows[k];
62048}
62049
62050template <typename T>
62051inline const DB_Row<T>&
62052DB_Matrix<T>::operator[](const dimension_type k) const {
62053  PPL_ASSERT(k < rows.size());
62054  return rows[k];
62055}
62056
62057template <typename T>
62058inline dimension_type
62059DB_Matrix<T>::num_rows() const {
62060  return rows.size();
62061}
62062
62063#ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
62064/*! \relates DB_Matrix */
62065#endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
62066template <typename T>
62067inline bool
62068operator!=(const DB_Matrix<T>& x, const DB_Matrix<T>& y) {
62069  return !(x == y);
62070}
62071
62072template <typename T>
62073inline
62074DB_Matrix<T>::DB_Matrix(const DB_Matrix& y)
62075  : rows(y.rows),
62076    row_size(y.row_size),
62077    row_capacity(compute_capacity(y.row_size, max_num_columns())) {
62078}
62079
62080template <typename T>
62081inline DB_Matrix<T>&
62082DB_Matrix<T>::operator=(const DB_Matrix& y) {
62083  // Without the following guard against auto-assignments we would
62084  // recompute the row capacity based on row size, possibly without
62085  // actually increasing the capacity of the rows.  This would lead to
62086  // an inconsistent state.
62087  if (this != &y) {
62088    // The following assignment may do nothing on auto-assignments...
62089    rows = y.rows;
62090    row_size = y.row_size;
62091    // ... hence the following assignment must not be done on
62092    // auto-assignments.
62093    row_capacity = compute_capacity(y.row_size, max_num_columns());
62094  }
62095  return *this;
62096}
62097
62098#ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
62099/*! \relates DB_Matrix */
62100#endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
62101template <typename Specialization, typename Temp, typename To, typename T>
62102inline bool
62103l_m_distance_assign(Checked_Number<To, Extended_Number_Policy>& r,
62104                    const DB_Matrix<T>& x,
62105                    const DB_Matrix<T>& y,
62106                    const Rounding_Dir dir,
62107                    Temp& tmp0,
62108                    Temp& tmp1,
62109                    Temp& tmp2) {
62110  const dimension_type x_num_rows = x.num_rows();
62111  if (x_num_rows != y.num_rows()) {
62112    return false;
62113  }
62114  assign_r(tmp0, 0, ROUND_NOT_NEEDED);
62115  for (dimension_type i = x_num_rows; i-- > 0; ) {
62116    const DB_Row<T>& x_i = x[i];
62117    const DB_Row<T>& y_i = y[i];
62118    for (dimension_type j = x_num_rows; j-- > 0; ) {
62119      const T& x_i_j = x_i[j];
62120      const T& y_i_j = y_i[j];
62121      if (is_plus_infinity(x_i_j)) {
62122        if (is_plus_infinity(y_i_j)) {
62123          continue;
62124        }
62125        else {
62126        pinf:
62127          assign_r(r, PLUS_INFINITY, ROUND_NOT_NEEDED);
62128          return true;
62129        }
62130      }
62131      else if (is_plus_infinity(y_i_j)) {
62132        goto pinf;
62133      }
62134      const Temp* tmp1p;
62135      const Temp* tmp2p;
62136      if (x_i_j > y_i_j) {
62137        maybe_assign(tmp1p, tmp1, x_i_j, dir);
62138        maybe_assign(tmp2p, tmp2, y_i_j, inverse(dir));
62139      }
62140      else {
62141        maybe_assign(tmp1p, tmp1, y_i_j, dir);
62142        maybe_assign(tmp2p, tmp2, x_i_j, inverse(dir));
62143      }
62144      sub_assign_r(tmp1, *tmp1p, *tmp2p, dir);
62145      PPL_ASSERT(sgn(tmp1) >= 0);
62146      Specialization::combine(tmp0, tmp1, dir);
62147    }
62148  }
62149  Specialization::finalize(tmp0, dir);
62150  assign_r(r, tmp0, dir);
62151  return true;
62152}
62153
62154#ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
62155/*! \relates DB_Matrix */
62156#endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
62157template <typename Temp, typename To, typename T>
62158inline bool
62159rectilinear_distance_assign(Checked_Number<To, Extended_Number_Policy>& r,
62160                            const DB_Matrix<T>& x,
62161                            const DB_Matrix<T>& y,
62162                            const Rounding_Dir dir,
62163                            Temp& tmp0,
62164                            Temp& tmp1,
62165                            Temp& tmp2) {
62166  return
62167    l_m_distance_assign<Rectilinear_Distance_Specialization<Temp> >(r, x, y,
62168                                                                    dir,
62169                                                                    tmp0,
62170                                                                    tmp1,
62171                                                                    tmp2);
62172}
62173
62174
62175#ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
62176/*! \relates DB_Matrix */
62177#endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
62178template <typename Temp, typename To, typename T>
62179inline bool
62180euclidean_distance_assign(Checked_Number<To, Extended_Number_Policy>& r,
62181                          const DB_Matrix<T>& x,
62182                          const DB_Matrix<T>& y,
62183                          const Rounding_Dir dir,
62184                          Temp& tmp0,
62185                          Temp& tmp1,
62186                          Temp& tmp2) {
62187  return
62188    l_m_distance_assign<Euclidean_Distance_Specialization<Temp> >(r, x, y,
62189                                                                  dir,
62190                                                                  tmp0,
62191                                                                  tmp1,
62192                                                                  tmp2);
62193}
62194
62195#ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
62196/*! \relates DB_Matrix */
62197#endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
62198template <typename Temp, typename To, typename T>
62199inline bool
62200l_infinity_distance_assign(Checked_Number<To, Extended_Number_Policy>& r,
62201                           const DB_Matrix<T>& x,
62202                           const DB_Matrix<T>& y,
62203                           const Rounding_Dir dir,
62204                           Temp& tmp0,
62205                           Temp& tmp1,
62206                           Temp& tmp2) {
62207  return
62208    l_m_distance_assign<L_Infinity_Distance_Specialization<Temp> >(r, x, y,
62209                                                                   dir,
62210                                                                   tmp0,
62211                                                                   tmp1,
62212                                                                   tmp2);
62213}
62214
62215#ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
62216/*! \relates DB_Matrix */
62217#endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
62218template <typename T>
62219inline void
62220swap(DB_Matrix<T>& x, DB_Matrix<T>& y) {
62221  x.m_swap(y);
62222}
62223
62224} // namespace Parma_Polyhedra_Library
62225
62226/* Automatically generated from PPL source file ../src/DB_Matrix_templates.hh line 1. */
62227/* DB_Matrix class implementation: non-inline template functions.
62228*/
62229
62230
62231namespace Parma_Polyhedra_Library {
62232
62233template <typename T>
62234DB_Matrix<T>::DB_Matrix(const dimension_type n_rows)
62235  : rows(n_rows),
62236    row_size(n_rows),
62237    row_capacity(compute_capacity(n_rows, max_num_columns())) {
62238  // Construct in direct order: will destroy in reverse order.
62239  for (dimension_type i = 0; i < n_rows; ++i) {
62240    rows[i].construct(n_rows, row_capacity);
62241  }
62242  PPL_ASSERT(OK());
62243}
62244
62245template <typename T>
62246template <typename U>
62247DB_Matrix<T>::DB_Matrix(const DB_Matrix<U>& y)
62248  : rows(y.rows.size()),
62249    row_size(y.row_size),
62250    row_capacity(compute_capacity(y.row_size, max_num_columns())) {
62251  // Construct in direct order: will destroy in reverse order.
62252  for (dimension_type i = 0, n_rows = rows.size(); i < n_rows; ++i) {
62253    rows[i].construct_upward_approximation(y[i], row_capacity);
62254  }
62255  PPL_ASSERT(OK());
62256}
62257
62258template <typename T>
62259void
62260DB_Matrix<T>::grow(const dimension_type new_n_rows) {
62261  const dimension_type old_n_rows = rows.size();
62262  PPL_ASSERT(new_n_rows >= old_n_rows);
62263
62264  if (new_n_rows > old_n_rows) {
62265    if (new_n_rows <= row_capacity) {
62266      // We can recycle the old rows.
62267      if (rows.capacity() < new_n_rows) {
62268        // Reallocation will take place.
62269        std::vector<DB_Row<T> > new_rows;
62270        new_rows.reserve(compute_capacity(new_n_rows, max_num_rows()));
62271        new_rows.insert(new_rows.end(), new_n_rows, DB_Row<T>());
62272        // Construct the new rows.
62273        dimension_type i = new_n_rows;
62274        while (i-- > old_n_rows) {
62275          new_rows[i].construct(new_n_rows, row_capacity);
62276        }
62277        // Steal the old rows.
62278        ++i;
62279        while (i-- > 0) {
62280          swap(new_rows[i], rows[i]);
62281        }
62282        // Put the new vector into place.
62283        using std::swap;
62284        swap(rows, new_rows);
62285      }
62286      else {
62287        // Reallocation will NOT take place.
62288        rows.insert(rows.end(), new_n_rows - old_n_rows, DB_Row<T>());
62289        for (dimension_type i = new_n_rows; i-- > old_n_rows; ) {
62290          rows[i].construct(new_n_rows, row_capacity);
62291        }
62292      }
62293    }
62294    else {
62295      // We cannot even recycle the old rows.
62296      DB_Matrix new_matrix;
62297      new_matrix.rows.reserve(compute_capacity(new_n_rows, max_num_rows()));
62298      new_matrix.rows.insert(new_matrix.rows.end(), new_n_rows, DB_Row<T>());
62299      // Construct the new rows.
62300      new_matrix.row_size = new_n_rows;
62301      new_matrix.row_capacity = compute_capacity(new_n_rows,
62302                                                 max_num_columns());
62303      dimension_type i = new_n_rows;
62304      while (i-- > old_n_rows) {
62305        new_matrix.rows[i].construct(new_matrix.row_size,
62306                                     new_matrix.row_capacity);
62307      }
62308      // Copy the old rows.
62309      ++i;
62310      while (i-- > 0) {
62311        // FIXME: copying may be unnecessarily costly.
62312        DB_Row<T> new_row(rows[i],
62313                          new_matrix.row_size,
62314                          new_matrix.row_capacity);
62315        swap(new_matrix.rows[i], new_row);
62316      }
62317      // Put the new vector into place.
62318      m_swap(new_matrix);
62319      return;
62320    }
62321  }
62322  // Here we have the right number of rows.
62323  if (new_n_rows > row_size) {
62324    // We need more columns.
62325    if (new_n_rows <= row_capacity) {
62326      // But we have enough capacity: we resize existing rows.
62327      for (dimension_type i = old_n_rows; i-- > 0; ) {
62328        rows[i].expand_within_capacity(new_n_rows);
62329      }
62330    }
62331    else {
62332      // Capacity exhausted: we must reallocate the rows and
62333      // make sure all the rows have the same capacity.
62334      const dimension_type new_row_capacity
62335        = compute_capacity(new_n_rows, max_num_columns());
62336      for (dimension_type i = old_n_rows; i-- > 0; ) {
62337        // FIXME: copying may be unnecessarily costly.
62338        DB_Row<T> new_row(rows[i], new_n_rows, new_row_capacity);
62339        swap(rows[i], new_row);
62340      }
62341      row_capacity = new_row_capacity;
62342    }
62343    // Rows have grown or shrunk.
62344    row_size = new_n_rows;
62345  }
62346}
62347
62348template <typename T>
62349void
62350DB_Matrix<T>::resize_no_copy(const dimension_type new_n_rows) {
62351  dimension_type old_n_rows = rows.size();
62352
62353  if (new_n_rows > old_n_rows) {
62354    // Rows will be inserted.
62355    if (new_n_rows <= row_capacity) {
62356      // We can recycle the old rows.
62357      if (rows.capacity() < new_n_rows) {
62358        // Reallocation (of vector `rows') will take place.
62359        std::vector<DB_Row<T> > new_rows;
62360        new_rows.reserve(compute_capacity(new_n_rows, max_num_rows()));
62361        new_rows.insert(new_rows.end(), new_n_rows, DB_Row<T>());
62362        // Construct the new rows (be careful: each new row must have
62363        // the same capacity as each one of the old rows).
62364        dimension_type i = new_n_rows;
62365        while (i-- > old_n_rows) {
62366          new_rows[i].construct(new_n_rows, row_capacity);
62367        // Steal the old rows.
62368        }
62369        ++i;
62370        while (i-- > 0) {
62371          swap(new_rows[i], rows[i]);
62372        }
62373        // Put the new vector into place.
62374        using std::swap;
62375        swap(rows, new_rows);
62376      }
62377      else {
62378        // Reallocation (of vector `rows') will NOT take place.
62379        rows.insert(rows.end(), new_n_rows - old_n_rows, DB_Row<T>());
62380        // Be careful: each new row must have
62381        // the same capacity as each one of the old rows.
62382        for (dimension_type i = new_n_rows; i-- > old_n_rows; ) {
62383          rows[i].construct(new_n_rows, row_capacity);
62384        }
62385      }
62386    }
62387    else {
62388      // We cannot even recycle the old rows: allocate a new matrix and swap.
62389      DB_Matrix new_matrix(new_n_rows);
62390      m_swap(new_matrix);
62391      return;
62392    }
62393  }
62394  else if (new_n_rows < old_n_rows) {
62395    // Drop some rows.
62396    rows.resize(new_n_rows);
62397    // Shrink the existing rows.
62398    for (dimension_type i = new_n_rows; i-- > 0; ) {
62399      rows[i].shrink(new_n_rows);
62400    }
62401    old_n_rows = new_n_rows;
62402  }
62403  // Here we have the right number of rows.
62404  if (new_n_rows > row_size) {
62405    // We need more columns.
62406    if (new_n_rows <= row_capacity) {
62407      // But we have enough capacity: we resize existing rows.
62408      for (dimension_type i = old_n_rows; i-- > 0; ) {
62409        rows[i].expand_within_capacity(new_n_rows);
62410      }
62411    }
62412    else {
62413      // Capacity exhausted: we must reallocate the rows and
62414      // make sure all the rows have the same capacity.
62415      const dimension_type new_row_capacity
62416        = compute_capacity(new_n_rows, max_num_columns());
62417      for (dimension_type i = old_n_rows; i-- > 0; ) {
62418        DB_Row<T> new_row(new_n_rows, new_row_capacity);
62419        swap(rows[i], new_row);
62420      }
62421      row_capacity = new_row_capacity;
62422    }
62423  }
62424  // DB_Rows have grown or shrunk.
62425  row_size = new_n_rows;
62426}
62427
62428template <typename T>
62429void
62430DB_Matrix<T>::ascii_dump(std::ostream& s) const {
62431  const DB_Matrix<T>& x = *this;
62432  const char separator = ' ';
62433  const dimension_type nrows = x.num_rows();
62434  s << nrows << separator << "\n";
62435  for (dimension_type i = 0; i < nrows;  ++i) {
62436    for (dimension_type j = 0; j < nrows; ++j) {
62437      using namespace IO_Operators;
62438      s << x[i][j] << separator;
62439    }
62440    s << "\n";
62441  }
62442}
62443
62444PPL_OUTPUT_TEMPLATE_DEFINITIONS(T, DB_Matrix<T>)
62445
62446template <typename T>
62447bool
62448DB_Matrix<T>::ascii_load(std::istream& s) {
62449  dimension_type nrows;
62450  if (!(s >> nrows)) {
62451    return false;
62452  }
62453  resize_no_copy(nrows);
62454  DB_Matrix& x = *this;
62455  for (dimension_type i = 0; i < nrows;  ++i) {
62456    for (dimension_type j = 0; j < nrows; ++j) {
62457      Result r = input(x[i][j], s, ROUND_CHECK);
62458      if (result_relation(r) != VR_EQ || is_minus_infinity(x[i][j])) {
62459        return false;
62460      }
62461    }
62462  }
62463
62464  // Check invariants.
62465  PPL_ASSERT(OK());
62466  return true;
62467}
62468
62469#ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
62470/*! \relates DB_Matrix */
62471#endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
62472template <typename T>
62473bool
62474operator==(const DB_Matrix<T>& x, const DB_Matrix<T>& y) {
62475  const dimension_type x_num_rows = x.num_rows();
62476  if (x_num_rows != y.num_rows()) {
62477    return false;
62478  }
62479  for (dimension_type i = x_num_rows; i-- > 0; ) {
62480    if (x[i] != y[i]) {
62481      return false;
62482    }
62483  }
62484  return true;
62485}
62486
62487template <typename T>
62488memory_size_type
62489DB_Matrix<T>::external_memory_in_bytes() const {
62490  memory_size_type n = rows.capacity() * sizeof(DB_Row<T>);
62491  for (dimension_type i = num_rows(); i-- > 0; ) {
62492    n += rows[i].external_memory_in_bytes(row_capacity);
62493  }
62494  return n;
62495}
62496
62497template <typename T>
62498bool
62499DB_Matrix<T>::OK() const {
62500#ifndef NDEBUG
62501  using std::endl;
62502  using std::cerr;
62503#endif
62504
62505  // The matrix must be square.
62506  if (num_rows() != row_size) {
62507#ifndef NDEBUG
62508    cerr << "DB_Matrix has fewer columns than rows:\n"
62509         << "row_size is " << row_size
62510         << ", num_rows() is " << num_rows() << "!"
62511         << endl;
62512#endif
62513    return false;
62514  }
62515
62516  const DB_Matrix& x = *this;
62517  const dimension_type n_rows = x.num_rows();
62518  for (dimension_type i = 0; i < n_rows; ++i) {
62519    if (!x[i].OK(row_size, row_capacity)) {
62520      return false;
62521    }
62522  }
62523
62524  // All checks passed.
62525  return true;
62526}
62527
62528#ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
62529/*! \relates Parma_Polyhedra_Library::DB_Matrix */
62530#endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
62531template <typename T>
62532std::ostream&
62533IO_Operators::operator<<(std::ostream& s, const DB_Matrix<T>& c) {
62534  const dimension_type n = c.num_rows();
62535  for (dimension_type i = 0; i < n; ++i) {
62536    for (dimension_type j = 0; j < n; ++j) {
62537      s << c[i][j] << " ";
62538    }
62539    s << "\n";
62540  }
62541  return s;
62542}
62543
62544} // namespace Parma_Polyhedra_Library
62545
62546/* Automatically generated from PPL source file ../src/DB_Matrix_defs.hh line 324. */
62547
62548/* Automatically generated from PPL source file ../src/WRD_coefficient_types_defs.hh line 1. */
62549/* Coefficient types of weakly-relational domains: declarations.
62550*/
62551
62552
62553/* Automatically generated from PPL source file ../src/WRD_coefficient_types_defs.hh line 28. */
62554
62555namespace Parma_Polyhedra_Library {
62556
62557#ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
62558/*! \ingroup PPL_CXX_interface \brief
62559  The production policy for checked numbers used in weakly-relational
62560  domains.
62561 */
62562#endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
62563struct WRD_Extended_Number_Policy {
62564  //! Check for overflowed result.
62565  const_bool_nodef(check_overflow, true);
62566
62567  //! Do not check for attempts to add infinities with different sign.
62568  const_bool_nodef(check_inf_add_inf, false);
62569
62570  //! Do not check for attempts to subtract infinities with same sign.
62571  const_bool_nodef(check_inf_sub_inf, false);
62572
62573  //! Do not check for attempts to multiply infinities by zero.
62574  const_bool_nodef(check_inf_mul_zero, false);
62575
62576  //! Do not check for attempts to divide by zero.
62577  const_bool_nodef(check_div_zero, false);
62578
62579  //! Do not check for attempts to divide infinities.
62580  const_bool_nodef(check_inf_div_inf, false);
62581
62582  //! Do not check for attempts to compute remainder of infinities.
62583  const_bool_nodef(check_inf_mod, false);
62584
62585  //! Do not checks for attempts to take the square root of a negative number.
62586  const_bool_nodef(check_sqrt_neg, false);
62587
62588  //! Handle not-a-number special value.
62589  const_bool_nodef(has_nan, true);
62590
62591  //! Handle infinity special values.
62592  const_bool_nodef(has_infinity, true);
62593
62594  // `convertible' is intentionally not defined: the compile time
62595  // error on conversions is the expected behavior.
62596
62597  //! Honor requests to check for FPU inexact results.
62598  const_bool_nodef(fpu_check_inexact, true);
62599
62600  //! Do not make extra checks to detect FPU NaN results.
62601  const_bool_nodef(fpu_check_nan_result, false);
62602
62603  // ROUND_DEFAULT_CONSTRUCTOR is intentionally not defined.
62604  // ROUND_DEFAULT_OPERATOR is intentionally not defined.
62605  // ROUND_DEFAULT_FUNCTION is intentionally not defined.
62606  // ROUND_DEFAULT_INPUT is intentionally not defined.
62607  // ROUND_DEFAULT_OUTPUT is intentionally not defined.
62608
62609  /*! \brief
62610    Handles \p r: called by all constructors, operators and functions that
62611    do not return a Result value.
62612  */
62613  static void handle_result(Result r);
62614};
62615
62616#ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
62617/*! \ingroup PPL_CXX_interface \brief
62618  The debugging policy for checked numbers used in weakly-relational
62619  domains.
62620 */
62621#endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
62622struct Debug_WRD_Extended_Number_Policy {
62623  //! Check for overflowed result.
62624  const_bool_nodef(check_overflow, true);
62625
62626  //! Check for attempts to add infinities with different sign.
62627  const_bool_nodef(check_inf_add_inf, true);
62628
62629  //! Check for attempts to subtract infinities with same sign.
62630  const_bool_nodef(check_inf_sub_inf, true);
62631
62632  //! Check for attempts to multiply infinities by zero.
62633  const_bool_nodef(check_inf_mul_zero, true);
62634
62635  //! Check for attempts to divide by zero.
62636  const_bool_nodef(check_div_zero, true);
62637
62638  //! Check for attempts to divide infinities.
62639  const_bool_nodef(check_inf_div_inf, true);
62640
62641  //! Check for attempts to compute remainder of infinities.
62642  const_bool_nodef(check_inf_mod, true);
62643
62644  //! Checks for attempts to take the square root of a negative number.
62645  const_bool_nodef(check_sqrt_neg, true);
62646
62647  //! Handle not-a-number special value.
62648  const_bool_nodef(has_nan, true);
62649
62650  //! Handle infinity special values.
62651  const_bool_nodef(has_infinity, true);
62652
62653  // `convertible' is intentionally not defined: the compile time
62654  // error on conversions is the expected behavior.
62655
62656  //! Honor requests to check for FPU inexact results.
62657  const_bool_nodef(fpu_check_inexact, true);
62658
62659  //! Make extra checks to detect FPU NaN results.
62660  const_bool_nodef(fpu_check_nan_result, true);
62661
62662  // ROUND_DEFAULT_CONSTRUCTOR is intentionally not defined.
62663  // ROUND_DEFAULT_OPERATOR is intentionally not defined.
62664  // ROUND_DEFAULT_FUNCTION is intentionally not defined.
62665  // ROUND_DEFAULT_INPUT is intentionally not defined.
62666  // ROUND_DEFAULT_OUTPUT is intentionally not defined.
62667
62668  /*! \brief
62669    Handles \p r: called by all constructors, operators and functions that
62670    do not return a Result value.
62671  */
62672  static void handle_result(Result r);
62673};
62674
62675} // namespace Parma_Polyhedra_Library
62676
62677/* Automatically generated from PPL source file ../src/WRD_coefficient_types_inlines.hh line 1. */
62678/* Coefficient types of weakly-relational domains: inline functions.
62679*/
62680
62681
62682namespace Parma_Polyhedra_Library {
62683
62684inline void
62685WRD_Extended_Number_Policy::handle_result(Result r) {
62686  if (result_class(r) == VC_NAN) {
62687    throw_result_exception(r);
62688  }
62689}
62690
62691inline void
62692Debug_WRD_Extended_Number_Policy::handle_result(Result r) {
62693  if (result_class(r) == VC_NAN) {
62694    throw_result_exception(r);
62695  }
62696}
62697
62698} // namespace Parma_Polyhedra_Library
62699
62700/* Automatically generated from PPL source file ../src/WRD_coefficient_types_defs.hh line 152. */
62701
62702/* Automatically generated from PPL source file ../src/BD_Shape_defs.hh line 52. */
62703#include <cstddef>
62704#include <iosfwd>
62705#include <vector>
62706
62707namespace Parma_Polyhedra_Library {
62708
62709namespace IO_Operators {
62710
62711//! Output operator.
62712/*! \relates Parma_Polyhedra_Library::BD_Shape
62713  Writes a textual representation of \p bds on \p s:
62714  <CODE>false</CODE> is written if \p bds is an empty polyhedron;
62715  <CODE>true</CODE> is written if \p bds is the universe polyhedron;
62716  a system of constraints defining \p bds is written otherwise,
62717  all constraints separated by ", ".
62718*/
62719template <typename T>
62720std::ostream&
62721operator<<(std::ostream& s, const BD_Shape<T>& bds);
62722
62723} // namespace IO_Operators
62724
62725//! Swaps \p x with \p y.
62726/*! \relates BD_Shape */
62727template <typename T>
62728void swap(BD_Shape<T>& x, BD_Shape<T>& y);
62729
62730//! Returns <CODE>true</CODE> if and only if \p x and \p y are the same BDS.
62731/*! \relates BD_Shape
62732  Note that \p x and \p y may be dimension-incompatible shapes:
62733  in this case, the value <CODE>false</CODE> is returned.
62734*/
62735template <typename T>
62736bool operator==(const BD_Shape<T>& x, const BD_Shape<T>& y);
62737
62738//! Returns <CODE>true</CODE> if and only if \p x and \p y are not the same BDS.
62739/*! \relates BD_Shape
62740  Note that \p x and \p y may be dimension-incompatible shapes:
62741  in this case, the value <CODE>true</CODE> is returned.
62742*/
62743template <typename T>
62744bool operator!=(const BD_Shape<T>& x, const BD_Shape<T>& y);
62745
62746//! Computes the rectilinear (or Manhattan) distance between \p x and \p y.
62747/*! \relates BD_Shape
62748  If the rectilinear distance between \p x and \p y is defined,
62749  stores an approximation of it into \p r and returns <CODE>true</CODE>;
62750  returns <CODE>false</CODE> otherwise.
62751
62752  The direction of the approximation is specified by \p dir.
62753
62754  All computations are performed using variables of type
62755  <CODE>Checked_Number\<To, Extended_Number_Policy\></CODE>.
62756*/
62757template <typename To, typename T>
62758bool rectilinear_distance_assign(Checked_Number<To, Extended_Number_Policy>& r,
62759                                 const BD_Shape<T>& x,
62760                                 const BD_Shape<T>& y,
62761                                 Rounding_Dir dir);
62762
62763//! Computes the rectilinear (or Manhattan) distance between \p x and \p y.
62764/*! \relates BD_Shape
62765  If the rectilinear distance between \p x and \p y is defined,
62766  stores an approximation of it into \p r and returns <CODE>true</CODE>;
62767  returns <CODE>false</CODE> otherwise.
62768
62769  The direction of the approximation is specified by \p dir.
62770
62771  All computations are performed using variables of type
62772  <CODE>Checked_Number\<Temp, Extended_Number_Policy\></CODE>.
62773*/
62774template <typename Temp, typename To, typename T>
62775bool rectilinear_distance_assign(Checked_Number<To, Extended_Number_Policy>& r,
62776                                 const BD_Shape<T>& x,
62777                                 const BD_Shape<T>& y,
62778                                 Rounding_Dir dir);
62779
62780//! Computes the rectilinear (or Manhattan) distance between \p x and \p y.
62781/*! \relates BD_Shape
62782  If the rectilinear distance between \p x and \p y is defined,
62783  stores an approximation of it into \p r and returns <CODE>true</CODE>;
62784  returns <CODE>false</CODE> otherwise.
62785
62786  The direction of the approximation is specified by \p dir.
62787
62788  All computations are performed using the temporary variables
62789  \p tmp0, \p tmp1 and \p tmp2.
62790*/
62791template <typename Temp, typename To, typename T>
62792bool rectilinear_distance_assign(Checked_Number<To, Extended_Number_Policy>& r,
62793                                 const BD_Shape<T>& x,
62794                                 const BD_Shape<T>& y,
62795                                 Rounding_Dir dir,
62796                                 Temp& tmp0,
62797                                 Temp& tmp1,
62798                                 Temp& tmp2);
62799
62800//! Computes the euclidean distance between \p x and \p y.
62801/*! \relates BD_Shape
62802  If the euclidean distance between \p x and \p y is defined,
62803  stores an approximation of it into \p r and returns <CODE>true</CODE>;
62804  returns <CODE>false</CODE> otherwise.
62805
62806  The direction of the approximation is specified by \p dir.
62807
62808  All computations are performed using variables of type
62809  <CODE>Checked_Number\<To, Extended_Number_Policy\></CODE>.
62810*/
62811template <typename To, typename T>
62812bool euclidean_distance_assign(Checked_Number<To, Extended_Number_Policy>& r,
62813                               const BD_Shape<T>& x,
62814                               const BD_Shape<T>& y,
62815                               Rounding_Dir dir);
62816
62817//! Computes the euclidean distance between \p x and \p y.
62818/*! \relates BD_Shape
62819  If the euclidean distance between \p x and \p y is defined,
62820  stores an approximation of it into \p r and returns <CODE>true</CODE>;
62821  returns <CODE>false</CODE> otherwise.
62822
62823  The direction of the approximation is specified by \p dir.
62824
62825  All computations are performed using variables of type
62826  <CODE>Checked_Number\<Temp, Extended_Number_Policy\></CODE>.
62827*/
62828template <typename Temp, typename To, typename T>
62829bool euclidean_distance_assign(Checked_Number<To, Extended_Number_Policy>& r,
62830                               const BD_Shape<T>& x,
62831                               const BD_Shape<T>& y,
62832                               Rounding_Dir dir);
62833
62834//! Computes the euclidean distance between \p x and \p y.
62835/*! \relates BD_Shape
62836  If the euclidean distance between \p x and \p y is defined,
62837  stores an approximation of it into \p r and returns <CODE>true</CODE>;
62838  returns <CODE>false</CODE> otherwise.
62839
62840  The direction of the approximation is specified by \p dir.
62841
62842  All computations are performed using the temporary variables
62843  \p tmp0, \p tmp1 and \p tmp2.
62844*/
62845template <typename Temp, typename To, typename T>
62846bool euclidean_distance_assign(Checked_Number<To, Extended_Number_Policy>& r,
62847                               const BD_Shape<T>& x,
62848                               const BD_Shape<T>& y,
62849                               Rounding_Dir dir,
62850                               Temp& tmp0,
62851                               Temp& tmp1,
62852                               Temp& tmp2);
62853
62854//! Computes the \f$L_\infty\f$ distance between \p x and \p y.
62855/*! \relates BD_Shape
62856  If the \f$L_\infty\f$ distance between \p x and \p y is defined,
62857  stores an approximation of it into \p r and returns <CODE>true</CODE>;
62858  returns <CODE>false</CODE> otherwise.
62859
62860  The direction of the approximation is specified by \p dir.
62861
62862  All computations are performed using variables of type
62863  <CODE>Checked_Number\<To, Extended_Number_Policy\></CODE>.
62864*/
62865template <typename To, typename T>
62866bool l_infinity_distance_assign(Checked_Number<To, Extended_Number_Policy>& r,
62867                                const BD_Shape<T>& x,
62868                                const BD_Shape<T>& y,
62869                                Rounding_Dir dir);
62870
62871//! Computes the \f$L_\infty\f$ distance between \p x and \p y.
62872/*! \relates BD_Shape
62873  If the \f$L_\infty\f$ distance between \p x and \p y is defined,
62874  stores an approximation of it into \p r and returns <CODE>true</CODE>;
62875  returns <CODE>false</CODE> otherwise.
62876
62877  The direction of the approximation is specified by \p dir.
62878
62879  All computations are performed using variables of type
62880  <CODE>Checked_Number\<Temp, Extended_Number_Policy\></CODE>.
62881*/
62882template <typename Temp, typename To, typename T>
62883bool l_infinity_distance_assign(Checked_Number<To, Extended_Number_Policy>& r,
62884                                const BD_Shape<T>& x,
62885                                const BD_Shape<T>& y,
62886                                Rounding_Dir dir);
62887
62888//! Computes the \f$L_\infty\f$ distance between \p x and \p y.
62889/*! \relates BD_Shape
62890  If the \f$L_\infty\f$ distance between \p x and \p y is defined,
62891  stores an approximation of it into \p r and returns <CODE>true</CODE>;
62892  returns <CODE>false</CODE> otherwise.
62893
62894  The direction of the approximation is specified by \p dir.
62895
62896  All computations are performed using the temporary variables
62897  \p tmp0, \p tmp1 and \p tmp2.
62898*/
62899template <typename Temp, typename To, typename T>
62900bool l_infinity_distance_assign(Checked_Number<To, Extended_Number_Policy>& r,
62901                                const BD_Shape<T>& x,
62902                                const BD_Shape<T>& y,
62903                                Rounding_Dir dir,
62904                                Temp& tmp0,
62905                                Temp& tmp1,
62906                                Temp& tmp2);
62907
62908// This class contains some helper functions that need to be friends of
62909// Linear_Expression.
62910class BD_Shape_Helpers {
62911public:
62912  #ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
62913  //! Decodes the constraint \p c as a bounded difference.
62914  /*! \relates BD_Shape
62915    \return
62916    <CODE>true</CODE> if the constraint \p c is a
62917    \ref Bounded_Difference_Shapes "bounded difference";
62918    <CODE>false</CODE> otherwise.
62919
62920    \param c
62921    The constraint to be decoded.
62922
62923    \param c_num_vars
62924    If <CODE>true</CODE> is returned, then it will be set to the number
62925    of variables having a non-zero coefficient. The only legal values
62926    will therefore be 0, 1 and 2.
62927
62928    \param c_first_var
62929    If <CODE>true</CODE> is returned and if \p c_num_vars is not set to 0,
62930    then it will be set to the index of the first variable having
62931    a non-zero coefficient in \p c.
62932
62933    \param c_second_var
62934    If <CODE>true</CODE> is returned and if \p c_num_vars is set to 2,
62935    then it will be set to the index of the second variable having
62936    a non-zero coefficient in \p c. If \p c_num_vars is set to 1, this must be
62937    0.
62938
62939    \param c_coeff
62940    If <CODE>true</CODE> is returned and if \p c_num_vars is not set to 0,
62941    then it will be set to the value of the first non-zero coefficient
62942    in \p c.
62943  */
62944  #endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
62945  static bool extract_bounded_difference(const Constraint& c,
62946                                         dimension_type& c_num_vars,
62947                                         dimension_type& c_first_var,
62948                                         dimension_type& c_second_var,
62949                                         Coefficient& c_coeff);
62950};
62951
62952#ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
62953//! Extracts leader indices from the predecessor relation.
62954/*! \relates BD_Shape */
62955#endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
62956void compute_leader_indices(const std::vector<dimension_type>& predecessor,
62957                            std::vector<dimension_type>& indices);
62958
62959} // namespace Parma_Polyhedra_Library
62960
62961//! A bounded difference shape.
62962/*! \ingroup PPL_CXX_interface
62963  The class template BD_Shape<T> allows for the efficient representation
62964  of a restricted kind of <EM>topologically closed</EM> convex polyhedra
62965  called <EM>bounded difference shapes</EM> (BDSs, for short).
62966  The name comes from the fact that the closed affine half-spaces that
62967  characterize the polyhedron can be expressed by constraints of the form
62968  \f$\pm x_i \leq k\f$ or \f$x_i - x_j \leq k\f$, where the inhomogeneous
62969  term \f$k\f$ is a rational number.
62970
62971  Based on the class template type parameter \p T, a family of extended
62972  numbers is built and used to approximate the inhomogeneous term of
62973  bounded differences. These extended numbers provide a representation
62974  for the value \f$+\infty\f$, as well as <EM>rounding-aware</EM>
62975  implementations for several arithmetic functions.
62976  The value of the type parameter \p T may be one of the following:
62977    - a bounded precision integer type (e.g., \c int32_t or \c int64_t);
62978    - a bounded precision floating point type (e.g., \c float or \c double);
62979    - an unbounded integer or rational type, as provided by GMP
62980      (i.e., \c mpz_class or \c mpq_class).
62981
62982  The user interface for BDSs is meant to be as similar as possible to
62983  the one developed for the polyhedron class C_Polyhedron.
62984
62985  The domain of BD shapes <EM>optimally supports</EM>:
62986    - tautological and inconsistent constraints and congruences;
62987    - bounded difference constraints;
62988    - non-proper congruences (i.e., equalities) that are expressible
62989      as bounded-difference constraints.
62990
62991  Depending on the method, using a constraint or congruence that is not
62992  optimally supported by the domain will either raise an exception or
62993  result in a (possibly non-optimal) upward approximation.
62994
62995  A constraint is a bounded difference if it has the form
62996    \f[
62997      a_i x_i - a_j x_j \relsym b
62998    \f]
62999  where \f$\mathord{\relsym} \in \{ \leq, =, \geq \}\f$ and
63000  \f$a_i\f$, \f$a_j\f$, \f$b\f$ are integer coefficients such that
63001  \f$a_i = 0\f$, or \f$a_j = 0\f$, or \f$a_i = a_j\f$.
63002  The user is warned that the above bounded difference Constraint object
63003  will be mapped into a \e correct and \e optimal approximation that,
63004  depending on the expressive power of the chosen template argument \p T,
63005  may loose some precision. Also note that strict constraints are not
63006  bounded differences.
63007
63008  For instance, a Constraint object encoding \f$3x - 3y \leq 1\f$ will be
63009  approximated by:
63010    - \f$x - y \leq 1\f$,
63011      if \p T is a (bounded or unbounded) integer type;
63012    - \f$x - y \leq \frac{1}{3}\f$,
63013      if \p T is the unbounded rational type \c mpq_class;
63014    - \f$x - y \leq k\f$, where \f$k > \frac{1}{3}\f$,
63015      if \p T is a floating point type (having no exact representation
63016      for \f$\frac{1}{3}\f$).
63017
63018  On the other hand, depending from the context, a Constraint object
63019  encoding \f$3x - y \leq 1\f$ will be either upward approximated
63020  (e.g., by safely ignoring it) or it will cause an exception.
63021
63022  In the following examples it is assumed that the type argument \p T
63023  is one of the possible instances listed above and that variables
63024  <CODE>x</CODE>, <CODE>y</CODE> and <CODE>z</CODE> are defined
63025  (where they are used) as follows:
63026  \code
63027    Variable x(0);
63028    Variable y(1);
63029    Variable z(2);
63030  \endcode
63031
63032  \par Example 1
63033  The following code builds a BDS corresponding to a cube in \f$\Rset^3\f$,
63034  given as a system of constraints:
63035  \code
63036    Constraint_System cs;
63037    cs.insert(x >= 0);
63038    cs.insert(x <= 1);
63039    cs.insert(y >= 0);
63040    cs.insert(y <= 1);
63041    cs.insert(z >= 0);
63042    cs.insert(z <= 1);
63043    BD_Shape<T> bd(cs);
63044  \endcode
63045  Since only those constraints having the syntactic form of a
63046  <EM>bounded difference</EM> are optimally supported, the following code
63047  will throw an exception (caused by constraints 7, 8 and 9):
63048  \code
63049    Constraint_System cs;
63050    cs.insert(x >= 0);
63051    cs.insert(x <= 1);
63052    cs.insert(y >= 0);
63053    cs.insert(y <= 1);
63054    cs.insert(z >= 0);
63055    cs.insert(z <= 1);
63056    cs.insert(x + y <= 0);      // 7
63057    cs.insert(x - z + x >= 0);  // 8
63058    cs.insert(3*z - y <= 1);    // 9
63059    BD_Shape<T> bd(cs);
63060  \endcode
63061*/
63062template <typename T>
63063class Parma_Polyhedra_Library::BD_Shape {
63064private:
63065  /*! \brief
63066    The (extended) numeric type of the inhomogeneous term of
63067    the inequalities defining a BDS.
63068  */
63069#ifndef NDEBUG
63070  typedef Checked_Number<T, Debug_WRD_Extended_Number_Policy> N;
63071#else
63072  typedef Checked_Number<T, WRD_Extended_Number_Policy> N;
63073#endif
63074
63075public:
63076  //! The numeric base type upon which bounded differences are built.
63077  typedef T coefficient_type_base;
63078
63079  /*! \brief
63080    The (extended) numeric type of the inhomogeneous term of the
63081    inequalities defining a BDS.
63082  */
63083  typedef N coefficient_type;
63084
63085  //! Returns the maximum space dimension that a BDS can handle.
63086  static dimension_type max_space_dimension();
63087
63088  /*! \brief
63089    Returns \c false indicating that this domain cannot recycle constraints.
63090  */
63091  static bool can_recycle_constraint_systems();
63092
63093  /*! \brief
63094    Returns \c false indicating that this domain cannot recycle congruences.
63095  */
63096  static bool can_recycle_congruence_systems();
63097
63098  //! \name Constructors, Assignment, Swap and Destructor
63099  //@{
63100
63101  //! Builds a universe or empty BDS of the specified space dimension.
63102  /*!
63103    \param num_dimensions
63104    The number of dimensions of the vector space enclosing the BDS;
63105
63106    \param kind
63107    Specifies whether the universe or the empty BDS has to be built.
63108  */
63109  explicit BD_Shape(dimension_type num_dimensions = 0,
63110                    Degenerate_Element kind = UNIVERSE);
63111
63112  //! Ordinary copy constructor.
63113  /*!
63114    The complexity argument is ignored.
63115  */
63116  BD_Shape(const BD_Shape& y,
63117           Complexity_Class complexity = ANY_COMPLEXITY);
63118
63119  //! Builds a conservative, upward approximation of \p y.
63120  /*!
63121    The complexity argument is ignored.
63122  */
63123  template <typename U>
63124  explicit BD_Shape(const BD_Shape<U>& y,
63125                    Complexity_Class complexity = ANY_COMPLEXITY);
63126
63127  //! Builds a BDS from the system of constraints \p cs.
63128  /*!
63129    The BDS inherits the space dimension of \p cs.
63130
63131    \param cs
63132    A system of BD constraints.
63133
63134    \exception std::invalid_argument
63135    Thrown if \p cs contains a constraint which is not optimally supported
63136    by the BD shape domain.
63137  */
63138  explicit BD_Shape(const Constraint_System& cs);
63139
63140  //! Builds a BDS from a system of congruences.
63141  /*!
63142    The BDS inherits the space dimension of \p cgs
63143
63144    \param cgs
63145    A system of congruences.
63146
63147    \exception std::invalid_argument
63148    Thrown if \p cgs contains congruences which are not optimally
63149    supported by the BD shape domain.
63150  */
63151  explicit BD_Shape(const Congruence_System& cgs);
63152
63153  //! Builds a BDS from the system of generators \p gs.
63154  /*!
63155    Builds the smallest BDS containing the polyhedron defined by \p gs.
63156    The BDS inherits the space dimension of \p gs.
63157
63158    \exception std::invalid_argument
63159    Thrown if the system of generators is not empty but has no points.
63160  */
63161  explicit BD_Shape(const Generator_System& gs);
63162
63163  //! Builds a BDS from the polyhedron \p ph.
63164  /*!
63165    Builds a BDS containing \p ph using algorithms whose complexity
63166    does not exceed the one specified by \p complexity.  If
63167    \p complexity is \p ANY_COMPLEXITY, then the BDS built is the
63168    smallest one containing \p ph.
63169  */
63170  explicit BD_Shape(const Polyhedron& ph,
63171                    Complexity_Class complexity = ANY_COMPLEXITY);
63172
63173  //! Builds a BDS out of a box.
63174  /*!
63175    The BDS inherits the space dimension of the box.
63176    The built BDS is the most precise BDS that includes the box.
63177
63178    \param box
63179    The box representing the BDS to be built.
63180
63181    \param complexity
63182    This argument is ignored as the algorithm used has
63183    polynomial complexity.
63184
63185    \exception std::length_error
63186    Thrown if the space dimension of \p box exceeds the maximum
63187    allowed space dimension.
63188  */
63189  template <typename Interval>
63190  explicit BD_Shape(const Box<Interval>& box,
63191                    Complexity_Class complexity = ANY_COMPLEXITY);
63192
63193  //! Builds a BDS out of a grid.
63194  /*!
63195    The BDS inherits the space dimension of the grid.
63196    The built BDS is the most precise BDS that includes the grid.
63197
63198    \param grid
63199    The grid used to build the BDS.
63200
63201    \param complexity
63202    This argument is ignored as the algorithm used has
63203    polynomial complexity.
63204
63205    \exception std::length_error
63206    Thrown if the space dimension of \p grid exceeds the maximum
63207    allowed space dimension.
63208  */
63209  explicit BD_Shape(const Grid& grid,
63210                    Complexity_Class complexity = ANY_COMPLEXITY);
63211
63212  //! Builds a BDS from an octagonal shape.
63213  /*!
63214    The BDS inherits the space dimension of the octagonal shape.
63215    The built BDS is the most precise BDS that includes the octagonal shape.
63216
63217    \param os
63218    The octagonal shape used to build the BDS.
63219
63220    \param complexity
63221    This argument is ignored as the algorithm used has
63222    polynomial complexity.
63223
63224    \exception std::length_error
63225    Thrown if the space dimension of \p os exceeds the maximum
63226    allowed space dimension.
63227  */
63228  template <typename U>
63229  explicit BD_Shape(const Octagonal_Shape<U>& os,
63230                    Complexity_Class complexity = ANY_COMPLEXITY);
63231
63232  /*! \brief
63233    The assignment operator
63234    (\p *this and \p y can be dimension-incompatible).
63235  */
63236  BD_Shape& operator=(const BD_Shape& y);
63237
63238  /*! \brief
63239    Swaps \p *this with \p y
63240    (\p *this and \p y can be dimension-incompatible).
63241  */
63242  void m_swap(BD_Shape& y);
63243
63244  //! Destructor.
63245  ~BD_Shape();
63246
63247  //@} Constructors, Assignment, Swap and Destructor
63248
63249  //! \name Member Functions that Do Not Modify the BD_Shape
63250  //@{
63251
63252  //! Returns the dimension of the vector space enclosing \p *this.
63253  dimension_type space_dimension() const;
63254
63255  /*! \brief
63256    Returns \f$0\f$, if \p *this is empty; otherwise, returns the
63257    \ref Affine_Independence_and_Affine_Dimension "affine dimension"
63258    of \p *this.
63259  */
63260  dimension_type affine_dimension() const;
63261
63262  //! Returns a system of constraints defining \p *this.
63263  Constraint_System constraints() const;
63264
63265  //! Returns a minimized system of constraints defining \p *this.
63266  Constraint_System minimized_constraints() const;
63267
63268  //! Returns a system of (equality) congruences satisfied by \p *this.
63269  Congruence_System congruences() const;
63270
63271  /*! \brief
63272    Returns a minimal system of (equality) congruences
63273    satisfied by \p *this with the same affine dimension as \p *this.
63274  */
63275  Congruence_System minimized_congruences() const;
63276
63277  /*! \brief
63278    Returns <CODE>true</CODE> if and only if \p expr is
63279    bounded from above in \p *this.
63280
63281    \exception std::invalid_argument
63282    Thrown if \p expr and \p *this are dimension-incompatible.
63283  */
63284  bool bounds_from_above(const Linear_Expression& expr) const;
63285
63286  /*! \brief
63287    Returns <CODE>true</CODE> if and only if \p expr is
63288    bounded from below in \p *this.
63289
63290    \exception std::invalid_argument
63291    Thrown if \p expr and \p *this are dimension-incompatible.
63292  */
63293  bool bounds_from_below(const Linear_Expression& expr) const;
63294
63295  /*! \brief
63296    Returns <CODE>true</CODE> if and only if \p *this is not empty
63297    and \p expr is bounded from above in \p *this, in which case
63298    the supremum value is computed.
63299
63300    \param expr
63301    The linear expression to be maximized subject to \p *this;
63302
63303    \param sup_n
63304    The numerator of the supremum value;
63305
63306    \param sup_d
63307    The denominator of the supremum value;
63308
63309    \param maximum
63310    <CODE>true</CODE> if and only if the supremum is also the maximum value.
63311
63312    \exception std::invalid_argument
63313    Thrown if \p expr and \p *this are dimension-incompatible.
63314
63315    If \p *this is empty or \p expr is not bounded from above,
63316    <CODE>false</CODE> is returned and \p sup_n, \p sup_d
63317    and \p maximum are left untouched.
63318  */
63319  bool maximize(const Linear_Expression& expr,
63320                Coefficient& sup_n, Coefficient& sup_d, bool& maximum) const;
63321
63322  /*! \brief
63323    Returns <CODE>true</CODE> if and only if \p *this is not empty
63324    and \p expr is bounded from above in \p *this, in which case
63325    the supremum value and a point where \p expr reaches it are computed.
63326
63327    \param expr
63328    The linear expression to be maximized subject to \p *this;
63329
63330    \param sup_n
63331    The numerator of the supremum value;
63332
63333    \param sup_d
63334    The denominator of the supremum value;
63335
63336    \param maximum
63337    <CODE>true</CODE> if and only if the supremum is also the maximum value;
63338
63339    \param g
63340    When maximization succeeds, will be assigned the point or
63341    closure point where \p expr reaches its supremum value.
63342
63343    \exception std::invalid_argument
63344    Thrown if \p expr and \p *this are dimension-incompatible.
63345
63346    If \p *this is empty or \p expr is not bounded from above,
63347    <CODE>false</CODE> is returned and \p sup_n, \p sup_d, \p maximum
63348    and \p g are left untouched.
63349  */
63350  bool maximize(const Linear_Expression& expr,
63351                Coefficient& sup_n, Coefficient& sup_d, bool& maximum,
63352                Generator& g) const;
63353
63354  /*! \brief
63355    Returns <CODE>true</CODE> if and only if \p *this is not empty
63356    and \p expr is bounded from below in \p *this, in which case
63357    the infimum value is computed.
63358
63359    \param expr
63360    The linear expression to be minimized subject to \p *this;
63361
63362    \param inf_n
63363    The numerator of the infimum value;
63364
63365    \param inf_d
63366    The denominator of the infimum value;
63367
63368    \param minimum
63369    <CODE>true</CODE> if and only if the infimum is also the minimum value.
63370
63371    \exception std::invalid_argument
63372    Thrown if \p expr and \p *this are dimension-incompatible.
63373
63374    If \p *this is empty or \p expr is not bounded from below,
63375    <CODE>false</CODE> is returned and \p inf_n, \p inf_d
63376    and \p minimum are left untouched.
63377  */
63378  bool minimize(const Linear_Expression& expr,
63379                Coefficient& inf_n, Coefficient& inf_d, bool& minimum) const;
63380
63381  /*! \brief
63382    Returns <CODE>true</CODE> if and only if \p *this is not empty
63383    and \p expr is bounded from below in \p *this, in which case
63384    the infimum value and a point where \p expr reaches it are computed.
63385
63386    \param expr
63387    The linear expression to be minimized subject to \p *this;
63388
63389    \param inf_n
63390    The numerator of the infimum value;
63391
63392    \param inf_d
63393    The denominator of the infimum value;
63394
63395    \param minimum
63396    <CODE>true</CODE> if and only if the infimum is also the minimum value;
63397
63398    \param g
63399    When minimization succeeds, will be assigned a point or
63400    closure point where \p expr reaches its infimum value.
63401
63402    \exception std::invalid_argument
63403    Thrown if \p expr and \p *this are dimension-incompatible.
63404
63405    If \p *this is empty or \p expr is not bounded from below,
63406    <CODE>false</CODE> is returned and \p inf_n, \p inf_d, \p minimum
63407    and \p g are left untouched.
63408  */
63409  bool minimize(const Linear_Expression& expr,
63410                Coefficient& inf_n, Coefficient& inf_d, bool& minimum,
63411                Generator& g) const;
63412
63413  /*! \brief
63414    Returns <CODE>true</CODE> if and only if there exist a
63415    unique value \p val such that \p *this
63416    saturates the equality <CODE>expr = val</CODE>.
63417
63418    \param expr
63419    The linear expression for which the frequency is needed;
63420
63421    \param freq_n
63422    If <CODE>true</CODE> is returned, the value is set to \f$0\f$;
63423    Present for interface compatibility with class Grid, where
63424    the \ref Grid_Frequency "frequency" can have a non-zero value;
63425
63426    \param freq_d
63427    If <CODE>true</CODE> is returned, the value is set to \f$1\f$;
63428
63429    \param val_n
63430    The numerator of \p val;
63431
63432    \param val_d
63433    The denominator of \p val;
63434
63435    \exception std::invalid_argument
63436    Thrown if \p expr and \p *this are dimension-incompatible.
63437
63438    If <CODE>false</CODE> is returned, then \p freq_n, \p freq_d,
63439    \p val_n and \p val_d are left untouched.
63440  */
63441  bool frequency(const Linear_Expression& expr,
63442                 Coefficient& freq_n, Coefficient& freq_d,
63443                 Coefficient& val_n, Coefficient& val_d) const;
63444
63445  //! Returns <CODE>true</CODE> if and only if \p *this contains \p y.
63446  /*!
63447    \exception std::invalid_argument
63448    Thrown if \p *this and \p y are dimension-incompatible.
63449  */
63450  bool contains(const BD_Shape& y) const;
63451
63452  //! Returns <CODE>true</CODE> if and only if \p *this strictly contains \p y.
63453  /*!
63454    \exception std::invalid_argument
63455    Thrown if \p *this and \p y are dimension-incompatible.
63456  */
63457  bool strictly_contains(const BD_Shape& y) const;
63458
63459  //! Returns <CODE>true</CODE> if and only if \p *this and \p y are disjoint.
63460  /*!
63461    \exception std::invalid_argument
63462    Thrown if \p x and \p y are topology-incompatible or
63463    dimension-incompatible.
63464  */
63465  bool is_disjoint_from(const BD_Shape& y) const;
63466
63467  //! Returns the relations holding between \p *this and the constraint \p c.
63468  /*!
63469    \exception std::invalid_argument
63470    Thrown if \p *this and constraint \p c are dimension-incompatible.
63471  */
63472  Poly_Con_Relation relation_with(const Constraint& c) const;
63473
63474  //! Returns the relations holding between \p *this and the congruence \p cg.
63475  /*!
63476    \exception std::invalid_argument
63477    Thrown if \p *this and congruence \p cg are dimension-incompatible.
63478  */
63479  Poly_Con_Relation relation_with(const Congruence& cg) const;
63480
63481  //! Returns the relations holding between \p *this and the generator \p g.
63482  /*!
63483    \exception std::invalid_argument
63484    Thrown if \p *this and generator \p g are dimension-incompatible.
63485  */
63486  Poly_Gen_Relation relation_with(const Generator& g) const;
63487
63488  //! Returns <CODE>true</CODE> if and only if \p *this is an empty BDS.
63489  bool is_empty() const;
63490
63491  //! Returns <CODE>true</CODE> if and only if \p *this is a universe BDS.
63492  bool is_universe() const;
63493
63494  //! Returns <CODE>true</CODE> if and only if \p *this is discrete.
63495  bool is_discrete() const;
63496
63497  /*! \brief
63498    Returns <CODE>true</CODE> if and only if \p *this
63499    is a topologically closed subset of the vector space.
63500  */
63501  bool is_topologically_closed() const;
63502
63503  //! Returns <CODE>true</CODE> if and only if \p *this is a bounded BDS.
63504  bool is_bounded() const;
63505
63506  /*! \brief
63507    Returns <CODE>true</CODE> if and only if \p *this
63508    contains at least one integer point.
63509  */
63510  bool contains_integer_point() const;
63511
63512  /*! \brief
63513    Returns <CODE>true</CODE> if and only if \p var is constrained in
63514    \p *this.
63515
63516    \exception std::invalid_argument
63517    Thrown if \p var is not a space dimension of \p *this.
63518  */
63519  bool constrains(Variable var) const;
63520
63521  /*! \brief
63522    Returns <CODE>true</CODE> if and only if \p *this satisfies
63523    all its invariants.
63524  */
63525  bool OK() const;
63526
63527  //@} Member Functions that Do Not Modify the BD_Shape
63528
63529  //! \name Space-Dimension Preserving Member Functions that May Modify the BD_Shape
63530  //@{
63531
63532  /*! \brief
63533    Adds a copy of constraint \p c to the system of bounded differences
63534    defining \p *this.
63535
63536    \param c
63537    The constraint to be added.
63538
63539    \exception std::invalid_argument
63540    Thrown if \p *this and constraint \p c are dimension-incompatible,
63541    or \p c is not optimally supported by the BD shape domain.
63542  */
63543  void add_constraint(const Constraint& c);
63544
63545  /*! \brief
63546    Adds a copy of congruence \p cg to the system of congruences of \p *this.
63547
63548    \param cg
63549    The congruence to be added.
63550
63551    \exception std::invalid_argument
63552    Thrown if \p *this and congruence \p cg are dimension-incompatible,
63553    or \p cg is not optimally supported by the BD shape domain.
63554  */
63555  void add_congruence(const Congruence& cg);
63556
63557  /*! \brief
63558    Adds the constraints in \p cs to the system of bounded differences
63559    defining \p *this.
63560
63561    \param  cs
63562    The constraints that will be added.
63563
63564    \exception std::invalid_argument
63565    Thrown if \p *this and \p cs are dimension-incompatible,
63566    or \p cs contains a constraint which is not optimally supported
63567    by the BD shape domain.
63568  */
63569  void add_constraints(const Constraint_System& cs);
63570
63571  /*! \brief
63572    Adds the constraints in \p cs to the system of constraints
63573    of \p *this.
63574
63575    \param cs
63576    The constraint system to be added to \p *this.  The constraints in
63577    \p cs may be recycled.
63578
63579    \exception std::invalid_argument
63580    Thrown if \p *this and \p cs are dimension-incompatible,
63581    or \p cs contains a constraint which is not optimally supported
63582    by the BD shape domain.
63583
63584    \warning
63585    The only assumption that can be made on \p cs upon successful or
63586    exceptional return is that it can be safely destroyed.
63587  */
63588  void add_recycled_constraints(Constraint_System& cs);
63589
63590  /*! \brief
63591    Adds to \p *this constraints equivalent to the congruences in \p cgs.
63592
63593    \param cgs
63594    Contains the congruences that will be added to the system of
63595    constraints of \p *this.
63596
63597    \exception std::invalid_argument
63598    Thrown if \p *this and \p cgs are dimension-incompatible,
63599    or \p cgs contains a congruence which is not optimally supported
63600    by the BD shape domain.
63601  */
63602  void add_congruences(const Congruence_System& cgs);
63603
63604  /*! \brief
63605    Adds to \p *this constraints equivalent to the congruences in \p cgs.
63606
63607    \param cgs
63608    Contains the congruences that will be added to the system of
63609    constraints of \p *this. Its elements may be recycled.
63610
63611    \exception std::invalid_argument
63612    Thrown if \p *this and \p cgs are dimension-incompatible,
63613    or \p cgs contains a congruence which is not optimally supported
63614    by the BD shape domain.
63615
63616    \warning
63617    The only assumption that can be made on \p cgs upon successful or
63618    exceptional return is that it can be safely destroyed.
63619  */
63620  void add_recycled_congruences(Congruence_System& cgs);
63621
63622  /*! \brief
63623    Uses a copy of constraint \p c to refine the system of bounded differences
63624    defining \p *this.
63625
63626    \param c
63627    The constraint. If it is not a bounded difference, it will be ignored.
63628
63629    \exception std::invalid_argument
63630    Thrown if \p *this and constraint \p c are dimension-incompatible.
63631  */
63632  void refine_with_constraint(const Constraint& c);
63633
63634  /*! \brief
63635    Uses a copy of congruence \p cg to refine the system of
63636    bounded differences  of \p *this.
63637
63638    \param cg
63639    The congruence. If it is not a bounded difference equality, it
63640    will be ignored.
63641
63642    \exception std::invalid_argument
63643    Thrown if \p *this and congruence \p cg are dimension-incompatible.
63644  */
63645  void refine_with_congruence(const Congruence& cg);
63646
63647  /*! \brief
63648    Uses a copy of the constraints in \p cs to refine the system of
63649    bounded differences defining \p *this.
63650
63651    \param  cs
63652    The constraint system to be used. Constraints that are not bounded
63653    differences are ignored.
63654
63655    \exception std::invalid_argument
63656    Thrown if \p *this and \p cs are dimension-incompatible.
63657  */
63658  void refine_with_constraints(const Constraint_System& cs);
63659
63660  /*! \brief
63661    Uses a copy of the congruences in \p cgs to refine the system of
63662    bounded differences defining \p *this.
63663
63664    \param  cgs
63665    The congruence system to be used. Congruences that are not bounded
63666    difference equalities are ignored.
63667
63668    \exception std::invalid_argument
63669    Thrown if \p *this and \p cgs are dimension-incompatible.
63670  */
63671  void refine_with_congruences(const Congruence_System& cgs);
63672
63673  /*! \brief
63674    Refines the system of BD_Shape constraints defining \p *this using
63675    the constraint expressed by \p left \f$\leq\f$ \p right.
63676
63677    \param left
63678    The linear form on intervals with floating point boundaries that
63679    is at the left of the comparison operator. All of its coefficients
63680    MUST be bounded.
63681
63682    \param right
63683    The linear form on intervals with floating point boundaries that
63684    is at the right of the comparison operator. All of its coefficients
63685    MUST be bounded.
63686
63687    \exception std::invalid_argument
63688    Thrown if \p left (or \p right) is dimension-incompatible with \p *this.
63689
63690    This function is used in abstract interpretation to model a filter
63691    that is generated by a comparison of two expressions that are correctly
63692    approximated by \p left and \p right respectively.
63693  */
63694  template <typename Interval_Info>
63695  void refine_with_linear_form_inequality(
63696                   const Linear_Form<Interval<T, Interval_Info> >& left,
63697                   const Linear_Form<Interval<T, Interval_Info> >& right);
63698
63699  /*! \brief
63700    Refines the system of BD_Shape constraints defining \p *this using
63701    the constraint expressed by \p left \f$\relsym\f$ \p right, where
63702    \f$\relsym\f$ is the relation symbol specified by \p relsym.
63703
63704    \param left
63705    The linear form on intervals with floating point boundaries that
63706    is at the left of the comparison operator. All of its coefficients
63707    MUST be bounded.
63708
63709    \param right
63710    The linear form on intervals with floating point boundaries that
63711    is at the right of the comparison operator. All of its coefficients
63712    MUST be bounded.
63713
63714    \param relsym
63715    The relation symbol.
63716
63717    \exception std::invalid_argument
63718    Thrown if \p left (or \p right) is dimension-incompatible with \p *this.
63719
63720    \exception std::runtime_error
63721    Thrown if \p relsym is not a valid relation symbol.
63722
63723    This function is used in abstract interpretation to model a filter
63724    that is generated by a comparison of two expressions that are correctly
63725    approximated by \p left and \p right respectively.
63726  */
63727  template <typename Interval_Info>
63728  void generalized_refine_with_linear_form_inequality(
63729                   const Linear_Form<Interval<T, Interval_Info> >& left,
63730                   const Linear_Form<Interval<T, Interval_Info> >& right,
63731                   Relation_Symbol relsym);
63732
63733  //! Applies to \p dest the interval constraints embedded in \p *this.
63734  /*!
63735    \param dest
63736    The object to which the constraints will be added.
63737
63738    \exception std::invalid_argument
63739    Thrown if \p *this is dimension-incompatible with \p dest.
63740
63741    The template type parameter U must provide the following methods.
63742    \code
63743      dimension_type space_dimension() const
63744    \endcode
63745    returns the space dimension of the object.
63746    \code
63747      void set_empty()
63748    \endcode
63749    sets the object to an empty object.
63750    \code
63751      bool restrict_lower(dimension_type dim, const T& lb)
63752    \endcode
63753    restricts the object by applying the lower bound \p lb to the space
63754    dimension \p dim and returns <CODE>false</CODE> if and only if the
63755    object becomes empty.
63756    \code
63757      bool restrict_upper(dimension_type dim, const T& ub)
63758    \endcode
63759    restricts the object by applying the upper bound \p ub to the space
63760    dimension \p dim and returns <CODE>false</CODE> if and only if the
63761    object becomes empty.
63762  */
63763  template <typename U>
63764  void export_interval_constraints(U& dest) const;
63765
63766  /*! \brief
63767    Computes the \ref Cylindrification "cylindrification" of \p *this with
63768    respect to space dimension \p var, assigning the result to \p *this.
63769
63770    \param var
63771    The space dimension that will be unconstrained.
63772
63773    \exception std::invalid_argument
63774    Thrown if \p var is not a space dimension of \p *this.
63775  */
63776  void unconstrain(Variable var);
63777
63778  /*! \brief
63779    Computes the \ref Cylindrification "cylindrification" of \p *this with
63780    respect to the set of space dimensions \p vars,
63781    assigning the result to \p *this.
63782
63783    \param vars
63784    The set of space dimension that will be unconstrained.
63785
63786    \exception std::invalid_argument
63787    Thrown if \p *this is dimension-incompatible with one of the
63788    Variable objects contained in \p vars.
63789  */
63790  void unconstrain(const Variables_Set& vars);
63791
63792  //! Assigns to \p *this the intersection of \p *this and \p y.
63793  /*!
63794    \exception std::invalid_argument
63795    Thrown if \p *this and \p y are dimension-incompatible.
63796  */
63797  void intersection_assign(const BD_Shape& y);
63798
63799  /*! \brief
63800    Assigns to \p *this the smallest BDS containing the union
63801    of \p *this and \p y.
63802
63803    \exception std::invalid_argument
63804    Thrown if \p *this and \p y are dimension-incompatible.
63805  */
63806  void upper_bound_assign(const BD_Shape& y);
63807
63808  /*! \brief
63809    If the upper bound of \p *this and \p y is exact, it is assigned
63810    to \p *this and <CODE>true</CODE> is returned,
63811    otherwise <CODE>false</CODE> is returned.
63812
63813    \exception std::invalid_argument
63814    Thrown if \p *this and \p y are dimension-incompatible.
63815  */
63816  bool upper_bound_assign_if_exact(const BD_Shape& y);
63817
63818  /*! \brief
63819    If the \e integer upper bound of \p *this and \p y is exact,
63820    it is assigned to \p *this and <CODE>true</CODE> is returned;
63821    otherwise <CODE>false</CODE> is returned.
63822
63823    \exception std::invalid_argument
63824    Thrown if \p *this and \p y are dimension-incompatible.
63825
63826    \note
63827    The integer upper bound of two rational BDS is the smallest rational
63828    BDS containing all the integral points of the two arguments.
63829    This method requires that the coefficient type parameter \c T is
63830    an integral type.
63831  */
63832  bool integer_upper_bound_assign_if_exact(const BD_Shape& y);
63833
63834  /*! \brief
63835    Assigns to \p *this the smallest BD shape containing
63836    the set difference of \p *this and \p y.
63837
63838    \exception std::invalid_argument
63839    Thrown if \p *this and \p y are dimension-incompatible.
63840  */
63841  void difference_assign(const BD_Shape& y);
63842
63843  /*! \brief
63844    Assigns to \p *this a \ref Meet_Preserving_Simplification
63845    "meet-preserving simplification" of \p *this with respect to \p y.
63846    If \c false is returned, then the intersection is empty.
63847
63848    \exception std::invalid_argument
63849    Thrown if \p *this and \p y are topology-incompatible or
63850    dimension-incompatible.
63851  */
63852  bool simplify_using_context_assign(const BD_Shape& y);
63853
63854  /*! \brief
63855    Assigns to \p *this the
63856    \ref Single_Update_Affine_Functions "affine image"
63857    of \p *this under the function mapping variable \p var into the
63858    affine expression specified by \p expr and \p denominator.
63859
63860    \param var
63861    The variable to which the affine expression is assigned.
63862
63863    \param expr
63864    The numerator of the affine expression.
63865
63866    \param denominator
63867    The denominator of the affine expression.
63868
63869    \exception std::invalid_argument
63870    Thrown if \p denominator is zero or if \p expr and \p *this
63871    are dimension-incompatible or if \p var is not a dimension of \p *this.
63872  */
63873  void affine_image(Variable var,
63874                    const Linear_Expression& expr,
63875                    Coefficient_traits::const_reference denominator
63876                    = Coefficient_one());
63877
63878  // FIXME: To be completed.
63879  /*! \brief
63880    Assigns to \p *this the \ref affine_form_relation "affine form image"
63881    of \p *this under the function mapping variable \p var into the
63882    affine expression(s) specified by \p lf.
63883
63884    \param var
63885    The variable to which the affine expression is assigned.
63886
63887    \param lf
63888    The linear form on intervals with floating point coefficients that
63889    defines the affine expression. ALL of its coefficients MUST be bounded.
63890
63891    \exception std::invalid_argument
63892    Thrown if \p lf and \p *this are dimension-incompatible or if \p var
63893    is not a dimension of \p *this.
63894  */
63895  template <typename Interval_Info>
63896  void affine_form_image(Variable var,
63897                        const Linear_Form<Interval<T, Interval_Info> >& lf);
63898
63899  /*! \brief
63900    Assigns to \p *this the
63901    \ref Single_Update_Affine_Functions "affine preimage"
63902    of \p *this under the function mapping variable \p var into the
63903    affine expression specified by \p expr and \p denominator.
63904
63905    \param var
63906    The variable to which the affine expression is substituted.
63907
63908    \param expr
63909    The numerator of the affine expression.
63910
63911    \param denominator
63912    The denominator of the affine expression.
63913
63914    \exception std::invalid_argument
63915    Thrown if \p denominator is zero or if \p expr and \p *this
63916    are dimension-incompatible or if \p var is not a dimension of \p *this.
63917  */
63918  void affine_preimage(Variable var,
63919                       const Linear_Expression& expr,
63920                       Coefficient_traits::const_reference denominator
63921                       = Coefficient_one());
63922
63923  /*! \brief
63924    Assigns to \p *this the image of \p *this with respect to the
63925    \ref Generalized_Affine_Relations "affine relation"
63926    \f$\mathrm{var}' \relsym \frac{\mathrm{expr}}{\mathrm{denominator}}\f$,
63927    where \f$\mathord{\relsym}\f$ is the relation symbol encoded
63928    by \p relsym.
63929
63930    \param var
63931    The left hand side variable of the generalized affine transfer function.
63932
63933    \param relsym
63934    The relation symbol.
63935
63936    \param expr
63937    The numerator of the right hand side affine expression.
63938
63939    \param denominator
63940    The denominator of the right hand side affine expression.
63941
63942    \exception std::invalid_argument
63943    Thrown if \p denominator is zero or if \p expr and \p *this
63944    are dimension-incompatible or if \p var is not a dimension
63945    of \p *this or if \p relsym is a strict relation symbol.
63946  */
63947  void generalized_affine_image(Variable var,
63948                                Relation_Symbol relsym,
63949                                const Linear_Expression& expr,
63950                                Coefficient_traits::const_reference denominator
63951                                = Coefficient_one());
63952
63953  /*! \brief
63954    Assigns to \p *this the image of \p *this with respect to the
63955    \ref Generalized_Affine_Relations "affine relation"
63956    \f$\mathrm{lhs}' \relsym \mathrm{rhs}\f$, where
63957    \f$\mathord{\relsym}\f$ is the relation symbol encoded by \p relsym.
63958
63959    \param lhs
63960    The left hand side affine expression.
63961
63962    \param relsym
63963    The relation symbol.
63964
63965    \param rhs
63966    The right hand side affine expression.
63967
63968    \exception std::invalid_argument
63969    Thrown if \p *this is dimension-incompatible with \p lhs or \p rhs
63970    or if \p relsym is a strict relation symbol.
63971  */
63972  void generalized_affine_image(const Linear_Expression& lhs,
63973                                Relation_Symbol relsym,
63974                                const Linear_Expression& rhs);
63975
63976  /*! \brief
63977    Assigns to \p *this the preimage of \p *this with respect to the
63978    \ref Generalized_Affine_Relations "affine relation"
63979    \f$\mathrm{var}' \relsym \frac{\mathrm{expr}}{\mathrm{denominator}}\f$,
63980    where \f$\mathord{\relsym}\f$ is the relation symbol encoded
63981    by \p relsym.
63982
63983    \param var
63984    The left hand side variable of the generalized affine transfer function.
63985
63986    \param relsym
63987    The relation symbol.
63988
63989    \param expr
63990    The numerator of the right hand side affine expression.
63991
63992    \param denominator
63993    The denominator of the right hand side affine expression.
63994
63995    \exception std::invalid_argument
63996    Thrown if \p denominator is zero or if \p expr and \p *this
63997    are dimension-incompatible or if \p var is not a dimension
63998    of \p *this or if \p relsym is a strict relation symbol.
63999  */
64000  void generalized_affine_preimage(Variable var,
64001                                   Relation_Symbol relsym,
64002                                   const Linear_Expression& expr,
64003                                   Coefficient_traits::const_reference
64004                                   denominator = Coefficient_one());
64005
64006  /*! \brief
64007    Assigns to \p *this the preimage of \p *this with respect to the
64008    \ref Generalized_Affine_Relations "affine relation"
64009    \f$\mathrm{lhs}' \relsym \mathrm{rhs}\f$, where
64010    \f$\mathord{\relsym}\f$ is the relation symbol encoded by \p relsym.
64011
64012    \param lhs
64013    The left hand side affine expression.
64014
64015    \param relsym
64016    The relation symbol.
64017
64018    \param rhs
64019    The right hand side affine expression.
64020
64021    \exception std::invalid_argument
64022    Thrown if \p *this is dimension-incompatible with \p lhs or \p rhs
64023    or if \p relsym is a strict relation symbol.
64024  */
64025  void generalized_affine_preimage(const Linear_Expression& lhs,
64026                                   Relation_Symbol relsym,
64027                                   const Linear_Expression& rhs);
64028
64029  /*!
64030    \brief
64031    Assigns to \p *this the image of \p *this with respect to the
64032    \ref Single_Update_Bounded_Affine_Relations "bounded affine relation"
64033    \f$\frac{\mathrm{lb\_expr}}{\mathrm{denominator}}
64034         \leq \mathrm{var}'
64035           \leq \frac{\mathrm{ub\_expr}}{\mathrm{denominator}}\f$.
64036
64037    \param var
64038    The variable updated by the affine relation;
64039
64040    \param lb_expr
64041    The numerator of the lower bounding affine expression;
64042
64043    \param ub_expr
64044    The numerator of the upper bounding affine expression;
64045
64046    \param denominator
64047    The (common) denominator for the lower and upper bounding
64048    affine expressions (optional argument with default value 1).
64049
64050    \exception std::invalid_argument
64051    Thrown if \p denominator is zero or if \p lb_expr (resp., \p ub_expr)
64052    and \p *this are dimension-incompatible or if \p var is not a space
64053    dimension of \p *this.
64054  */
64055  void bounded_affine_image(Variable var,
64056                            const Linear_Expression& lb_expr,
64057                            const Linear_Expression& ub_expr,
64058                            Coefficient_traits::const_reference denominator
64059                            = Coefficient_one());
64060
64061  /*!
64062    \brief
64063    Assigns to \p *this the preimage of \p *this with respect to the
64064    \ref Single_Update_Bounded_Affine_Relations "bounded affine relation"
64065    \f$\frac{\mathrm{lb\_expr}}{\mathrm{denominator}}
64066         \leq \mathrm{var}'
64067           \leq \frac{\mathrm{ub\_expr}}{\mathrm{denominator}}\f$.
64068
64069    \param var
64070    The variable updated by the affine relation;
64071
64072    \param lb_expr
64073    The numerator of the lower bounding affine expression;
64074
64075    \param ub_expr
64076    The numerator of the upper bounding affine expression;
64077
64078    \param denominator
64079    The (common) denominator for the lower and upper bounding
64080    affine expressions (optional argument with default value 1).
64081
64082    \exception std::invalid_argument
64083    Thrown if \p denominator is zero or if \p lb_expr (resp., \p ub_expr)
64084    and \p *this are dimension-incompatible or if \p var is not a space
64085    dimension of \p *this.
64086  */
64087  void bounded_affine_preimage(Variable var,
64088                               const Linear_Expression& lb_expr,
64089                               const Linear_Expression& ub_expr,
64090                               Coefficient_traits::const_reference denominator
64091                               = Coefficient_one());
64092  /*! \brief
64093    Assigns to \p *this the result of computing the
64094    \ref Time_Elapse_Operator "time-elapse" between \p *this and \p y.
64095
64096    \exception std::invalid_argument
64097    Thrown if \p *this and \p y are dimension-incompatible.
64098  */
64099  void time_elapse_assign(const BD_Shape& y);
64100
64101  /*! \brief
64102    \ref Wrapping_Operator "Wraps" the specified dimensions of the
64103    vector space.
64104
64105    \param vars
64106    The set of Variable objects corresponding to the space dimensions
64107    to be wrapped.
64108
64109    \param w
64110    The width of the bounded integer type corresponding to
64111    all the dimensions to be wrapped.
64112
64113    \param r
64114    The representation of the bounded integer type corresponding to
64115    all the dimensions to be wrapped.
64116
64117    \param o
64118    The overflow behavior of the bounded integer type corresponding to
64119    all the dimensions to be wrapped.
64120
64121    \param cs_p
64122    Possibly null pointer to a constraint system whose variables
64123    are contained in \p vars.  If <CODE>*cs_p</CODE> depends on
64124    variables not in \p vars, the behavior is undefined.
64125    When non-null, the pointed-to constraint system is assumed to
64126    represent the conditional or looping construct guard with respect
64127    to which wrapping is performed.  Since wrapping requires the
64128    computation of upper bounds and due to non-distributivity of
64129    constraint refinement over upper bounds, passing a constraint
64130    system in this way can be more precise than refining the result of
64131    the wrapping operation with the constraints in <CODE>*cs_p</CODE>.
64132
64133    \param complexity_threshold
64134    A precision parameter of the \ref Wrapping_Operator "wrapping operator":
64135    higher values result in possibly improved precision.
64136
64137    \param wrap_individually
64138    <CODE>true</CODE> if the dimensions should be wrapped individually
64139    (something that results in much greater efficiency to the detriment of
64140    precision).
64141
64142    \exception std::invalid_argument
64143    Thrown if <CODE>*cs_p</CODE> is dimension-incompatible with
64144    \p vars, or if \p *this is dimension-incompatible \p vars or with
64145    <CODE>*cs_p</CODE>.
64146  */
64147  void wrap_assign(const Variables_Set& vars,
64148                   Bounded_Integer_Type_Width w,
64149                   Bounded_Integer_Type_Representation r,
64150                   Bounded_Integer_Type_Overflow o,
64151                   const Constraint_System* cs_p = 0,
64152                   unsigned complexity_threshold = 16,
64153                   bool wrap_individually = true);
64154
64155  /*! \brief
64156    Possibly tightens \p *this by dropping some points with non-integer
64157    coordinates.
64158
64159    \param complexity
64160    The maximal complexity of any algorithms used.
64161
64162    \note
64163    Currently there is no optimality guarantee, not even if
64164    \p complexity is <CODE>ANY_COMPLEXITY</CODE>.
64165  */
64166  void drop_some_non_integer_points(Complexity_Class complexity
64167                                    = ANY_COMPLEXITY);
64168
64169  /*! \brief
64170    Possibly tightens \p *this by dropping some points with non-integer
64171    coordinates for the space dimensions corresponding to \p vars.
64172
64173    \param vars
64174    Points with non-integer coordinates for these variables/space-dimensions
64175    can be discarded.
64176
64177    \param complexity
64178    The maximal complexity of any algorithms used.
64179
64180    \note
64181    Currently there is no optimality guarantee, not even if
64182    \p complexity is <CODE>ANY_COMPLEXITY</CODE>.
64183  */
64184  void drop_some_non_integer_points(const Variables_Set& vars,
64185                                    Complexity_Class complexity
64186                                    = ANY_COMPLEXITY);
64187
64188  //! Assigns to \p *this its topological closure.
64189  void topological_closure_assign();
64190
64191  /*! \brief
64192    Assigns to \p *this the result of computing the
64193    \ref CC76_extrapolation "CC76-extrapolation" between \p *this and \p y.
64194
64195    \param y
64196    A BDS that <EM>must</EM> be contained in \p *this.
64197
64198    \param tp
64199    An optional pointer to an unsigned variable storing the number of
64200    available tokens (to be used when applying the
64201    \ref Widening_with_Tokens "widening with tokens" delay technique).
64202
64203    \exception std::invalid_argument
64204    Thrown if \p *this and \p y are dimension-incompatible.
64205  */
64206  void CC76_extrapolation_assign(const BD_Shape& y, unsigned* tp = 0);
64207
64208  /*! \brief
64209    Assigns to \p *this the result of computing the
64210    \ref CC76_extrapolation "CC76-extrapolation" between \p *this and \p y.
64211
64212    \param y
64213    A BDS that <EM>must</EM> be contained in \p *this.
64214
64215    \param first
64216    An iterator referencing the first stop-point.
64217
64218    \param last
64219    An iterator referencing one past the last stop-point.
64220
64221    \param tp
64222    An optional pointer to an unsigned variable storing the number of
64223    available tokens (to be used when applying the
64224    \ref Widening_with_Tokens "widening with tokens" delay technique).
64225
64226    \exception std::invalid_argument
64227    Thrown if \p *this and \p y are dimension-incompatible.
64228  */
64229  template <typename Iterator>
64230  void CC76_extrapolation_assign(const BD_Shape& y,
64231                                 Iterator first, Iterator last,
64232                                 unsigned* tp = 0);
64233
64234  /*! \brief
64235    Assigns to \p *this the result of computing the
64236    \ref BHMZ05_widening "BHMZ05-widening" of \p *this and \p y.
64237
64238    \param y
64239    A BDS that <EM>must</EM> be contained in \p *this.
64240
64241    \param tp
64242    An optional pointer to an unsigned variable storing the number of
64243    available tokens (to be used when applying the
64244    \ref Widening_with_Tokens "widening with tokens" delay technique).
64245
64246    \exception std::invalid_argument
64247    Thrown if \p *this and \p y are dimension-incompatible.
64248  */
64249  void BHMZ05_widening_assign(const BD_Shape& y, unsigned* tp = 0);
64250
64251  /*! \brief
64252    Improves the result of the \ref BHMZ05_widening "BHMZ05-widening"
64253    computation by also enforcing those constraints in \p cs that are
64254    satisfied by all the points of \p *this.
64255
64256    \param y
64257    A BDS that <EM>must</EM> be contained in \p *this.
64258
64259    \param cs
64260    The system of constraints used to improve the widened BDS.
64261
64262    \param tp
64263    An optional pointer to an unsigned variable storing the number of
64264    available tokens (to be used when applying the
64265    \ref Widening_with_Tokens "widening with tokens" delay technique).
64266
64267    \exception std::invalid_argument
64268    Thrown if \p *this, \p y and \p cs are dimension-incompatible or
64269    if \p cs contains a strict inequality.
64270  */
64271  void limited_BHMZ05_extrapolation_assign(const BD_Shape& y,
64272                                           const Constraint_System& cs,
64273                                           unsigned* tp = 0);
64274
64275  /*! \brief
64276    Assigns to \p *this the result of restoring in \p y the constraints
64277    of \p *this that were lost by
64278    \ref CC76_extrapolation "CC76-extrapolation" applications.
64279
64280    \param y
64281    A BDS that <EM>must</EM> contain \p *this.
64282
64283    \exception std::invalid_argument
64284    Thrown if \p *this and \p y are dimension-incompatible.
64285
64286    \note
64287    As was the case for widening operators, the argument \p y is meant to
64288    denote the value computed in the previous iteration step, whereas
64289    \p *this denotes the value computed in the current iteration step
64290    (in the <EM>decreasing</EM> iteration sequence). Hence, the call
64291    <CODE>x.CC76_narrowing_assign(y)</CODE> will assign to \p x
64292    the result of the computation \f$\mathtt{y} \Delta \mathtt{x}\f$.
64293  */
64294  void CC76_narrowing_assign(const BD_Shape& y);
64295
64296  /*! \brief
64297    Improves the result of the \ref CC76_extrapolation "CC76-extrapolation"
64298    computation by also enforcing those constraints in \p cs that are
64299    satisfied by all the points of \p *this.
64300
64301    \param y
64302    A BDS that <EM>must</EM> be contained in \p *this.
64303
64304    \param cs
64305    The system of constraints used to improve the widened BDS.
64306
64307    \param tp
64308    An optional pointer to an unsigned variable storing the number of
64309    available tokens (to be used when applying the
64310    \ref Widening_with_Tokens "widening with tokens" delay technique).
64311
64312    \exception std::invalid_argument
64313    Thrown if \p *this, \p y and \p cs are dimension-incompatible or
64314    if \p cs contains a strict inequality.
64315  */
64316  void limited_CC76_extrapolation_assign(const BD_Shape& y,
64317                                         const Constraint_System& cs,
64318                                         unsigned* tp = 0);
64319
64320  /*! \brief
64321    Assigns to \p *this the result of computing the
64322    \ref H79_widening "H79-widening" between \p *this and \p y.
64323
64324    \param y
64325    A BDS that <EM>must</EM> be contained in \p *this.
64326
64327    \param tp
64328    An optional pointer to an unsigned variable storing the number of
64329    available tokens (to be used when applying the
64330    \ref Widening_with_Tokens "widening with tokens" delay technique).
64331
64332    \exception std::invalid_argument
64333    Thrown if \p *this and \p y are dimension-incompatible.
64334  */
64335  void H79_widening_assign(const BD_Shape& y, unsigned* tp = 0);
64336
64337  //! Same as H79_widening_assign(y, tp).
64338  void widening_assign(const BD_Shape& y, unsigned* tp = 0);
64339
64340  /*! \brief
64341    Improves the result of the \ref H79_widening "H79-widening"
64342    computation by also enforcing those constraints in \p cs that are
64343    satisfied by all the points of \p *this.
64344
64345    \param y
64346    A BDS that <EM>must</EM> be contained in \p *this.
64347
64348    \param cs
64349    The system of constraints used to improve the widened BDS.
64350
64351    \param tp
64352    An optional pointer to an unsigned variable storing the number of
64353    available tokens (to be used when applying the
64354    \ref Widening_with_Tokens "widening with tokens" delay technique).
64355
64356    \exception std::invalid_argument
64357    Thrown if \p *this, \p y and \p cs are dimension-incompatible.
64358  */
64359  void limited_H79_extrapolation_assign(const BD_Shape& y,
64360                                        const Constraint_System& cs,
64361                                        unsigned* tp = 0);
64362
64363  //@} Space-Dimension Preserving Member Functions that May Modify [...]
64364
64365  //! \name Member Functions that May Modify the Dimension of the Vector Space
64366  //@{
64367
64368  //! Adds \p m new dimensions and embeds the old BDS into the new space.
64369  /*!
64370    \param m
64371    The number of dimensions to add.
64372
64373    The new dimensions will be those having the highest indexes in the new
64374    BDS, which is defined by a system of bounded differences in which the
64375    variables running through the new dimensions are unconstrained.
64376    For instance, when starting from the BDS \f$\cB \sseq \Rset^2\f$
64377    and adding a third dimension, the result will be the BDS
64378    \f[
64379      \bigl\{\,
64380        (x, y, z)^\transpose \in \Rset^3
64381      \bigm|
64382        (x, y)^\transpose \in \cB
64383      \,\bigr\}.
64384    \f]
64385  */
64386  void add_space_dimensions_and_embed(dimension_type m);
64387
64388  /*! \brief
64389    Adds \p m new dimensions to the BDS and does not embed it in
64390    the new vector space.
64391
64392    \param m
64393    The number of dimensions to add.
64394
64395    The new dimensions will be those having the highest indexes in the
64396    new BDS, which is defined by a system of bounded differences in
64397    which the variables running through the new dimensions are all
64398    constrained to be equal to 0.
64399    For instance, when starting from the BDS \f$\cB \sseq \Rset^2\f$
64400    and adding a third dimension, the result will be the BDS
64401    \f[
64402      \bigl\{\,
64403        (x, y, 0)^\transpose \in \Rset^3
64404      \bigm|
64405        (x, y)^\transpose \in \cB
64406      \,\bigr\}.
64407    \f]
64408  */
64409  void add_space_dimensions_and_project(dimension_type m);
64410
64411  /*! \brief
64412    Assigns to \p *this the \ref Concatenating_Polyhedra "concatenation"
64413    of \p *this and \p y, taken in this order.
64414
64415    \exception std::length_error
64416    Thrown if the concatenation would cause the vector space
64417    to exceed dimension <CODE>max_space_dimension()</CODE>.
64418  */
64419  void concatenate_assign(const BD_Shape& y);
64420
64421  //! Removes all the specified dimensions.
64422  /*!
64423    \param vars
64424    The set of Variable objects corresponding to the dimensions to be removed.
64425
64426    \exception std::invalid_argument
64427    Thrown if \p *this is dimension-incompatible with one of the Variable
64428    objects contained in \p vars.
64429  */
64430  void remove_space_dimensions(const Variables_Set& vars);
64431
64432  /*! \brief
64433    Removes the higher dimensions so that the resulting space
64434    will have dimension \p new_dimension.
64435
64436    \exception std::invalid_argument
64437    Thrown if \p new_dimension is greater than the space dimension
64438    of \p *this.
64439  */
64440  void remove_higher_space_dimensions(dimension_type new_dimension);
64441
64442  /*! \brief
64443    Remaps the dimensions of the vector space according to
64444    a \ref Mapping_the_Dimensions_of_the_Vector_Space "partial function".
64445
64446    \param pfunc
64447    The partial function specifying the destiny of each dimension.
64448
64449    The template type parameter Partial_Function must provide
64450    the following methods.
64451    \code
64452      bool has_empty_codomain() const
64453    \endcode
64454    returns <CODE>true</CODE> if and only if the represented partial
64455    function has an empty co-domain (i.e., it is always undefined).
64456    The <CODE>has_empty_codomain()</CODE> method will always be called
64457    before the methods below.  However, if
64458    <CODE>has_empty_codomain()</CODE> returns <CODE>true</CODE>, none
64459    of the functions below will be called.
64460    \code
64461      dimension_type max_in_codomain() const
64462    \endcode
64463    returns the maximum value that belongs to the co-domain
64464    of the partial function.
64465    \code
64466      bool maps(dimension_type i, dimension_type& j) const
64467    \endcode
64468    Let \f$f\f$ be the represented function and \f$k\f$ be the value
64469    of \p i.  If \f$f\f$ is defined in \f$k\f$, then \f$f(k)\f$ is
64470    assigned to \p j and <CODE>true</CODE> is returned.
64471    If \f$f\f$ is undefined in \f$k\f$, then <CODE>false</CODE> is
64472    returned.
64473
64474    The result is undefined if \p pfunc does not encode a partial
64475    function with the properties described in the
64476    \ref Mapping_the_Dimensions_of_the_Vector_Space
64477    "specification of the mapping operator".
64478  */
64479  template <typename Partial_Function>
64480  void map_space_dimensions(const Partial_Function& pfunc);
64481
64482  //! Creates \p m copies of the space dimension corresponding to \p var.
64483  /*!
64484    \param var
64485    The variable corresponding to the space dimension to be replicated;
64486
64487    \param m
64488    The number of replicas to be created.
64489
64490    \exception std::invalid_argument
64491    Thrown if \p var does not correspond to a dimension of the vector space.
64492
64493    \exception std::length_error
64494    Thrown if adding \p m new space dimensions would cause the
64495    vector space to exceed dimension <CODE>max_space_dimension()</CODE>.
64496
64497    If \p *this has space dimension \f$n\f$, with \f$n > 0\f$,
64498    and <CODE>var</CODE> has space dimension \f$k \leq n\f$,
64499    then the \f$k\f$-th space dimension is
64500    \ref expand_space_dimension "expanded" to \p m new space dimensions
64501    \f$n\f$, \f$n+1\f$, \f$\dots\f$, \f$n+m-1\f$.
64502  */
64503  void expand_space_dimension(Variable var, dimension_type m);
64504
64505  //! Folds the space dimensions in \p vars into \p dest.
64506  /*!
64507    \param vars
64508    The set of Variable objects corresponding to the space dimensions
64509    to be folded;
64510
64511    \param dest
64512    The variable corresponding to the space dimension that is the
64513    destination of the folding operation.
64514
64515    \exception std::invalid_argument
64516    Thrown if \p *this is dimension-incompatible with \p dest or with
64517    one of the Variable objects contained in \p vars.
64518    Also thrown if \p dest is contained in \p vars.
64519
64520    If \p *this has space dimension \f$n\f$, with \f$n > 0\f$,
64521    <CODE>dest</CODE> has space dimension \f$k \leq n\f$,
64522    \p vars is a set of variables whose maximum space dimension
64523    is also less than or equal to \f$n\f$, and \p dest is not a member
64524    of \p vars, then the space dimensions corresponding to
64525    variables in \p vars are \ref fold_space_dimensions "folded"
64526    into the \f$k\f$-th space dimension.
64527  */
64528  void fold_space_dimensions(const Variables_Set& vars, Variable dest);
64529
64530  //! Refines \p store with the constraints defining \p *this.
64531  /*!
64532    \param store
64533    The interval floating point abstract store to refine.
64534  */
64535  template <typename Interval_Info>
64536  void refine_fp_interval_abstract_store(Box<Interval<T, Interval_Info> >&
64537                                         store) const;
64538
64539
64540  //@} // Member Functions that May Modify the Dimension of the Vector Space
64541
64542  PPL_OUTPUT_DECLARATIONS
64543
64544  /*! \brief
64545    Loads from \p s an ASCII representation (as produced by
64546    ascii_dump(std::ostream&) const) and sets \p *this accordingly.
64547    Returns <CODE>true</CODE> if successful, <CODE>false</CODE> otherwise.
64548  */
64549  bool ascii_load(std::istream& s);
64550
64551  //! Returns the total size in bytes of the memory occupied by \p *this.
64552  memory_size_type total_memory_in_bytes() const;
64553
64554  //! Returns the size in bytes of the memory managed by \p *this.
64555  memory_size_type external_memory_in_bytes() const;
64556
64557  /*! \brief
64558    Returns a 32-bit hash code for \p *this.
64559
64560    If \p x and \p y are such that <CODE>x == y</CODE>,
64561    then <CODE>x.hash_code() == y.hash_code()</CODE>.
64562  */
64563  int32_t hash_code() const;
64564
64565  friend bool operator==<T>(const BD_Shape<T>& x, const BD_Shape<T>& y);
64566
64567  template <typename Temp, typename To, typename U>
64568  friend bool Parma_Polyhedra_Library
64569  ::rectilinear_distance_assign(Checked_Number<To, Extended_Number_Policy>& r,
64570                                const BD_Shape<U>& x, const BD_Shape<U>& y,
64571                                const Rounding_Dir dir,
64572                                Temp& tmp0, Temp& tmp1, Temp& tmp2);
64573  template <typename Temp, typename To, typename U>
64574  friend bool Parma_Polyhedra_Library
64575  ::euclidean_distance_assign(Checked_Number<To, Extended_Number_Policy>& r,
64576                              const BD_Shape<U>& x, const BD_Shape<U>& y,
64577                              const Rounding_Dir dir,
64578                              Temp& tmp0, Temp& tmp1, Temp& tmp2);
64579  template <typename Temp, typename To, typename U>
64580  friend bool Parma_Polyhedra_Library
64581  ::l_infinity_distance_assign(Checked_Number<To, Extended_Number_Policy>& r,
64582                               const BD_Shape<U>& x, const BD_Shape<U>& y,
64583                               const Rounding_Dir dir,
64584                               Temp& tmp0, Temp& tmp1, Temp& tmp2);
64585
64586private:
64587  template <typename U> friend class Parma_Polyhedra_Library::BD_Shape;
64588  template <typename Interval> friend class Parma_Polyhedra_Library::Box;
64589
64590  //! The matrix representing the system of bounded differences.
64591  DB_Matrix<N> dbm;
64592
64593#define PPL_IN_BD_Shape_CLASS
64594/* Automatically generated from PPL source file ../src/BDS_Status_idefs.hh line 1. */
64595/* BD_Shape<T>::Status class declaration.
64596*/
64597
64598
64599#ifndef PPL_IN_BD_Shape_CLASS
64600#error "Do not include BDS_Status_idefs.hh directly; use BD_Shape_defs.hh instead"
64601#endif
64602
64603//! A conjunctive assertion about a BD_Shape<T> object.
64604/*! \ingroup PPL_CXX_interface
64605  The assertions supported are:
64606  - <EM>zero-dim universe</EM>: the BDS is the zero-dimensional
64607    vector space \f$\Rset^0 = \{\cdot\}\f$;
64608  - <EM>empty</EM>: the BDS is the empty set;
64609  - <EM>shortest-path closed</EM>: the BDS is represented by a shortest-path
64610    closed system of bounded differences, so that all the constraints are
64611    as tight as possible;
64612  - <EM>shortest-path reduced</EM>: the BDS is represented by a shortest-path
64613    closed system of bounded differences and each constraint in such a system
64614    is marked as being either redundant or non-redundant.
64615
64616  Not all the conjunctions of these elementary assertions constitute
64617  a legal Status.  In fact:
64618  - <EM>zero-dim universe</EM> excludes any other assertion;
64619  - <EM>empty</EM>: excludes any other assertion;
64620  - <EM>shortest-path reduced</EM> implies <EM>shortest-path closed</EM>.
64621*/
64622class Status {
64623public:
64624  //! By default Status is the <EM>zero-dim universe</EM> assertion.
64625  Status();
64626
64627  //! \name Test, remove or add an individual assertion from the conjunction.
64628  //@{
64629  bool test_zero_dim_univ() const;
64630  void reset_zero_dim_univ();
64631  void set_zero_dim_univ();
64632
64633  bool test_empty() const;
64634  void reset_empty();
64635  void set_empty();
64636
64637  bool test_shortest_path_closed() const;
64638  void reset_shortest_path_closed();
64639  void set_shortest_path_closed();
64640
64641  bool test_shortest_path_reduced() const;
64642  void reset_shortest_path_reduced();
64643  void set_shortest_path_reduced();
64644  //@}
64645
64646  //! Checks if all the invariants are satisfied.
64647  bool OK() const;
64648
64649  PPL_OUTPUT_DECLARATIONS
64650
64651  /*! \brief
64652    Loads from \p s an ASCII representation (as produced by
64653    ascii_dump(std::ostream&) const) and sets \p *this accordingly.
64654    Returns <CODE>true</CODE> if successful, <CODE>false</CODE> otherwise.
64655  */
64656  bool ascii_load(std::istream& s);
64657
64658private:
64659  //! Status is implemented by means of a finite bitset.
64660  typedef unsigned int flags_t;
64661
64662  //! \name Bit-masks for the individual assertions.
64663  //@{
64664  static const flags_t ZERO_DIM_UNIV         = 0U;
64665  static const flags_t EMPTY                 = 1U << 0;
64666  static const flags_t SHORTEST_PATH_CLOSED  = 1U << 1;
64667  static const flags_t SHORTEST_PATH_REDUCED = 1U << 2;
64668  //@}
64669
64670  //! This holds the current bitset.
64671  flags_t flags;
64672
64673  //! Construct from a bit-mask.
64674  Status(flags_t mask);
64675
64676  //! Check whether <EM>all</EM> bits in \p mask are set.
64677  bool test_all(flags_t mask) const;
64678
64679  //! Check whether <EM>at least one</EM> bit in \p mask is set.
64680  bool test_any(flags_t mask) const;
64681
64682  //! Set the bits in \p mask.
64683  void set(flags_t mask);
64684
64685  //! Reset the bits in \p mask.
64686  void reset(flags_t mask);
64687};
64688
64689/* Automatically generated from PPL source file ../src/BD_Shape_defs.hh line 1944. */
64690#undef PPL_IN_BD_Shape_CLASS
64691
64692  //! The status flags to keep track of the internal state.
64693  Status status;
64694
64695  //! A matrix indicating which constraints are redundant.
64696  Bit_Matrix redundancy_dbm;
64697
64698  //! Returns <CODE>true</CODE> if the BDS is the zero-dimensional universe.
64699  bool marked_zero_dim_univ() const;
64700
64701  /*! \brief
64702    Returns <CODE>true</CODE> if the BDS is known to be empty.
64703
64704    The return value <CODE>false</CODE> does not necessarily
64705    implies that \p *this is non-empty.
64706  */
64707  bool marked_empty() const;
64708
64709  /*! \brief
64710    Returns <CODE>true</CODE> if the system of bounded differences
64711    is known to be shortest-path closed.
64712
64713    The return value <CODE>false</CODE> does not necessarily
64714    implies that <CODE>this->dbm</CODE> is not shortest-path closed.
64715  */
64716  bool marked_shortest_path_closed() const;
64717
64718  /*! \brief
64719    Returns <CODE>true</CODE> if the system of bounded differences
64720    is known to be shortest-path reduced.
64721
64722    The return value <CODE>false</CODE> does not necessarily
64723    implies that <CODE>this->dbm</CODE> is not shortest-path reduced.
64724  */
64725  bool marked_shortest_path_reduced() const;
64726
64727  //! Turns \p *this into an empty BDS.
64728  void set_empty();
64729
64730  //! Turns \p *this into an zero-dimensional universe BDS.
64731  void set_zero_dim_univ();
64732
64733  //! Marks \p *this as shortest-path closed.
64734  void set_shortest_path_closed();
64735
64736  //! Marks \p *this as shortest-path closed.
64737  void set_shortest_path_reduced();
64738
64739  //! Marks \p *this as possibly not shortest-path closed.
64740  void reset_shortest_path_closed();
64741
64742  //! Marks \p *this as possibly not shortest-path reduced.
64743  void reset_shortest_path_reduced();
64744
64745  //! Assigns to <CODE>this->dbm</CODE> its shortest-path closure.
64746  void shortest_path_closure_assign() const;
64747
64748  /*! \brief
64749    Assigns to <CODE>this->dbm</CODE> its shortest-path closure and
64750    records into <CODE>this->redundancy_dbm</CODE> which of the entries
64751    in <CODE>this->dbm</CODE> are redundant.
64752  */
64753  void shortest_path_reduction_assign() const;
64754
64755  /*! \brief
64756    Returns <CODE>true</CODE> if and only if <CODE>this->dbm</CODE>
64757    is shortest-path closed and <CODE>this->redundancy_dbm</CODE>
64758    correctly flags the redundant entries in <CODE>this->dbm</CODE>.
64759  */
64760  bool is_shortest_path_reduced() const;
64761
64762  /*! \brief
64763    Incrementally computes shortest-path closure, assuming that only
64764    constraints affecting variable \p var need to be considered.
64765
64766    \note
64767    It is assumed that \c *this, which was shortest-path closed,
64768    has only been modified by adding constraints affecting variable
64769    \p var. If this assumption is not satisfied, i.e., if a non-redundant
64770    constraint not affecting variable \p var has been added, the behavior
64771    is undefined.
64772  */
64773  void incremental_shortest_path_closure_assign(Variable var) const;
64774
64775  //! Checks if and how \p expr is bounded in \p *this.
64776  /*!
64777    Returns <CODE>true</CODE> if and only if \p from_above is
64778    <CODE>true</CODE> and \p expr is bounded from above in \p *this,
64779    or \p from_above is <CODE>false</CODE> and \p expr is bounded
64780    from below in \p *this.
64781
64782    \param expr
64783    The linear expression to test;
64784
64785    \param from_above
64786    <CODE>true</CODE> if and only if the boundedness of interest is
64787    "from above".
64788
64789    \exception std::invalid_argument
64790    Thrown if \p expr and \p *this are dimension-incompatible.
64791  */
64792  bool bounds(const Linear_Expression& expr, bool from_above) const;
64793
64794  //! Maximizes or minimizes \p expr subject to \p *this.
64795  /*!
64796    \param expr
64797    The linear expression to be maximized or minimized subject to \p
64798    *this;
64799
64800    \param maximize
64801    <CODE>true</CODE> if maximization is what is wanted;
64802
64803    \param ext_n
64804    The numerator of the extremum value;
64805
64806    \param ext_d
64807    The denominator of the extremum value;
64808
64809    \param included
64810    <CODE>true</CODE> if and only if the extremum of \p expr can
64811    actually be reached in \p * this;
64812
64813    \param g
64814    When maximization or minimization succeeds, will be assigned
64815    a point or closure point where \p expr reaches the
64816    corresponding extremum value.
64817
64818    \exception std::invalid_argument
64819    Thrown if \p expr and \p *this are dimension-incompatible.
64820
64821    If \p *this is empty or \p expr is not bounded in the appropriate
64822    direction, <CODE>false</CODE> is returned and \p ext_n, \p ext_d,
64823    \p included and \p g are left untouched.
64824  */
64825  bool max_min(const Linear_Expression& expr,
64826               bool maximize,
64827               Coefficient& ext_n, Coefficient& ext_d, bool& included,
64828               Generator& g) const;
64829
64830  //! Maximizes or minimizes \p expr subject to \p *this.
64831  /*!
64832    \param expr
64833    The linear expression to be maximized or minimized subject to \p
64834    *this;
64835
64836    \param maximize
64837    <CODE>true</CODE> if maximization is what is wanted;
64838
64839    \param ext_n
64840    The numerator of the extremum value;
64841
64842    \param ext_d
64843    The denominator of the extremum value;
64844
64845    \param included
64846    <CODE>true</CODE> if and only if the extremum of \p expr can
64847    actually be reached in \p * this;
64848
64849    \exception std::invalid_argument
64850    Thrown if \p expr and \p *this are dimension-incompatible.
64851
64852    If \p *this is empty or \p expr is not bounded in the appropriate
64853    direction, <CODE>false</CODE> is returned and \p ext_n, \p ext_d,
64854    \p included and \p point are left untouched.
64855  */
64856  bool max_min(const Linear_Expression& expr,
64857               bool maximize,
64858               Coefficient& ext_n, Coefficient& ext_d, bool& included) const;
64859
64860  /*! \brief
64861    If the upper bound of \p *this and \p y is exact it is assigned
64862    to \p *this and \c true is returned, otherwise \c false is returned.
64863
64864    Current implementation is based on a variant of Algorithm 4.1 in
64865      A. Bemporad, K. Fukuda, and F. D. Torrisi
64866      <em>Convexity Recognition of the Union of Polyhedra</em>
64867      Technical Report AUT00-13, ETH Zurich, 2000
64868    tailored to the special case of BD shapes.
64869
64870    \note
64871    It is assumed that \p *this and \p y are dimension-compatible;
64872    if the assumption does not hold, the behavior is undefined.
64873  */
64874  bool BFT00_upper_bound_assign_if_exact(const BD_Shape& y);
64875
64876  /*! \brief
64877    If the upper bound of \p *this and \p y is exact it is assigned
64878    to \p *this and \c true is returned, otherwise \c false is returned.
64879
64880    Implementation for the rational (resp., integer) case is based on
64881    Theorem 5.2 (resp. Theorem 5.3) of \ref BHZ09b "[BHZ09b]".
64882    The Boolean template parameter \c integer_upper_bound allows for
64883    choosing between the rational and integer upper bound algorithms.
64884
64885    \note
64886    It is assumed that \p *this and \p y are dimension-compatible;
64887    if the assumption does not hold, the behavior is undefined.
64888
64889    \note
64890    The integer case is only enabled if T is an integer data type.
64891  */
64892  template <bool integer_upper_bound>
64893  bool BHZ09_upper_bound_assign_if_exact(const BD_Shape& y);
64894
64895  /*! \brief
64896    Uses the constraint \p c to refine \p *this.
64897
64898    \param c
64899    The constraint to be added. Non BD constraints are ignored.
64900
64901    \warning
64902    If \p c and \p *this are dimension-incompatible,
64903    the behavior is undefined.
64904  */
64905  void refine_no_check(const Constraint& c);
64906
64907  /*! \brief
64908    Uses the congruence \p cg to refine \p *this.
64909
64910    \param cg
64911    The congruence to be added.
64912    Nontrivial proper congruences are ignored.
64913    Non BD equalities are ignored.
64914
64915    \warning
64916    If \p cg and \p *this are dimension-incompatible,
64917    the behavior is undefined.
64918  */
64919  void refine_no_check(const Congruence& cg);
64920
64921  //! Adds the constraint <CODE>dbm[i][j] \<= k</CODE>.
64922  void add_dbm_constraint(dimension_type i, dimension_type j, const N& k);
64923
64924  //! Adds the constraint <CODE>dbm[i][j] \<= numer/denom</CODE>.
64925  void add_dbm_constraint(dimension_type i, dimension_type j,
64926                          Coefficient_traits::const_reference numer,
64927                          Coefficient_traits::const_reference denom);
64928
64929  /*! \brief
64930    Adds to the BDS the constraint
64931    \f$\mathrm{var} \relsym \frac{\mathrm{expr}}{\mathrm{denominator}}\f$.
64932
64933    Note that the coefficient of \p var in \p expr is null.
64934  */
64935  void refine(Variable var, Relation_Symbol relsym,
64936              const Linear_Expression& expr,
64937              Coefficient_traits::const_reference denominator
64938              = Coefficient_one());
64939
64940  //! Removes all the constraints on row/column \p v.
64941  void forget_all_dbm_constraints(dimension_type v);
64942  //! Removes all binary constraints on row/column \p v.
64943  void forget_binary_dbm_constraints(dimension_type v);
64944
64945  //! An helper function for the computation of affine relations.
64946  /*!
64947    For each dbm index \p u (less than or equal to \p last_v and different
64948    from \p v), deduce constraints of the form <CODE>v - u \<= c</CODE>,
64949    starting from \p ub_v which is an upper bound for \p v.
64950
64951    The shortest-path closure is able to deduce the constraint
64952    <CODE>v - u \<= ub_v - lb_u</CODE>. We can be more precise if variable
64953    \p u played an active role in the computation of the upper bound for
64954    \p v, i.e., if the corresponding coefficient
64955    <CODE>q == sc_expr[u]/sc_denom</CODE> is greater than zero. In particular:
64956      - if <CODE>q \>= 1</CODE>, then <CODE>v - u \<= ub_v - ub_u</CODE>;
64957      - if <CODE>0 \< q \< 1</CODE>, then
64958        <CODE>v - u \<= ub_v - (q*ub_u + (1-q)*lb_u)</CODE>.
64959  */
64960  void deduce_v_minus_u_bounds(dimension_type v,
64961                               dimension_type last_v,
64962                               const Linear_Expression& sc_expr,
64963                               Coefficient_traits::const_reference sc_denom,
64964                               const N& ub_v);
64965
64966  /*! \brief
64967    Auxiliary function for \ref affine_form_relation "affine form image" that
64968    handle the general case: \f$l = c\f$
64969  */
64970  template <typename Interval_Info>
64971  void inhomogeneous_affine_form_image(const dimension_type& var_id,
64972                                       const Interval<T, Interval_Info>& b);
64973
64974  /*! \brief
64975    Auxiliary function for \ref affine_form_relation "affine form
64976    image" that handle the general case: \f$l = ax + c\f$
64977  */
64978  template <typename Interval_Info>
64979  void
64980  one_variable_affine_form_image(const dimension_type& var_id,
64981                                 const Interval<T, Interval_Info>& b,
64982                                 const Interval<T, Interval_Info>& w_coeff,
64983                                 const dimension_type& w_id,
64984                                 const dimension_type& space_dim);
64985
64986  /*! \brief
64987    Auxiliary function for \ref affine_form_relation "affine form image" that
64988    handle the general case: \f$l = ax + by + c\f$
64989  */
64990  template <typename Interval_Info>
64991  void
64992  two_variables_affine_form_image(const dimension_type& var_id,
64993                                  const Linear_Form<Interval<T,Interval_Info> >& lf,
64994                                  const dimension_type& space_dim);
64995
64996  /*! \brief
64997    Auxiliary function for refine with linear form that handle
64998    the general case: \f$l = ax + c\f$
64999  */
65000  template <typename Interval_Info>
65001  void
65002  left_inhomogeneous_refine(const dimension_type& right_t,
65003                            const dimension_type& right_w_id,
65004                            const Linear_Form<Interval<T, Interval_Info> >& left,
65005                            const Linear_Form<Interval<T, Interval_Info> >& right);
65006
65007  /*! \brief
65008    Auxiliary function for refine with linear form that handle
65009    the general case: \f$ax + b = cy + d\f$
65010  */
65011  template <typename Interval_Info>
65012  void
65013  left_one_var_refine(const dimension_type& left_w_id,
65014                      const dimension_type& right_t,
65015                      const dimension_type& right_w_id,
65016                      const Linear_Form<Interval<T, Interval_Info> >& left,
65017                      const Linear_Form<Interval<T, Interval_Info> >& right);
65018
65019  /*! \brief
65020    Auxiliary function for refine with linear form that handle
65021    the general case.
65022  */
65023  template <typename Interval_Info>
65024  void general_refine(const dimension_type& left_w_id,
65025                      const dimension_type& right_w_id,
65026                      const Linear_Form<Interval<T, Interval_Info> >& left,
65027                      const Linear_Form<Interval<T, Interval_Info> >& right);
65028
65029  template <typename Interval_Info>
65030  void linear_form_upper_bound(const Linear_Form<Interval<T, Interval_Info> >&
65031                               lf,
65032                               N& result) const;
65033
65034  //! An helper function for the computation of affine relations.
65035  /*!
65036    For each dbm index \p u (less than or equal to \p last_v and different
65037    from \p v), deduce constraints of the form <CODE>u - v \<= c</CODE>,
65038    starting from \p minus_lb_v which is a lower bound for \p v.
65039
65040    The shortest-path closure is able to deduce the constraint
65041    <CODE>u - v \<= ub_u - lb_v</CODE>. We can be more precise if variable
65042    \p u played an active role in the computation of the lower bound for
65043    \p v, i.e., if the corresponding coefficient
65044    <CODE>q == sc_expr[u]/sc_denom</CODE> is greater than zero.
65045    In particular:
65046      - if <CODE>q \>= 1</CODE>, then <CODE>u - v \<= lb_u - lb_v</CODE>;
65047      - if <CODE>0 \< q \< 1</CODE>, then
65048        <CODE>u - v \<= (q*lb_u + (1-q)*ub_u) - lb_v</CODE>.
65049  */
65050  void deduce_u_minus_v_bounds(dimension_type v,
65051                               dimension_type last_v,
65052                               const Linear_Expression& sc_expr,
65053                               Coefficient_traits::const_reference sc_denom,
65054                               const N& minus_lb_v);
65055
65056  /*! \brief
65057    Adds to \p limiting_shape the bounded differences in \p cs
65058    that are satisfied by \p *this.
65059  */
65060  void get_limiting_shape(const Constraint_System& cs,
65061                          BD_Shape& limiting_shape) const;
65062
65063  //! Compute the (zero-equivalence classes) predecessor relation.
65064  /*!
65065    It is assumed that the BDS is not empty and shortest-path closed.
65066  */
65067  void compute_predecessors(std::vector<dimension_type>& predecessor) const;
65068
65069  //! Compute the leaders of zero-equivalence classes.
65070  /*!
65071    It is assumed that the BDS is not empty and shortest-path closed.
65072  */
65073  void compute_leaders(std::vector<dimension_type>& leaders) const;
65074
65075  void drop_some_non_integer_points_helper(N& elem);
65076
65077  friend std::ostream&
65078  Parma_Polyhedra_Library::IO_Operators
65079  ::operator<<<>(std::ostream& s, const BD_Shape<T>& c);
65080
65081  //! \name Exception Throwers
65082  //@{
65083  void throw_dimension_incompatible(const char* method,
65084                                    const BD_Shape& y) const;
65085
65086  void throw_dimension_incompatible(const char* method,
65087                                    dimension_type required_dim) const;
65088
65089  void throw_dimension_incompatible(const char* method,
65090                                    const Constraint& c) const;
65091
65092  void throw_dimension_incompatible(const char* method,
65093                                    const Congruence& cg) const;
65094
65095  void throw_dimension_incompatible(const char* method,
65096                                    const Generator& g) const;
65097
65098  void throw_dimension_incompatible(const char* method,
65099                                    const char* le_name,
65100                                    const Linear_Expression& le) const;
65101
65102  template<typename Interval_Info>
65103  void
65104  throw_dimension_incompatible(const char* method,
65105                               const char* lf_name,
65106                               const Linear_Form<Interval<T, Interval_Info> >&
65107                               lf) const;
65108
65109  static void throw_expression_too_complex(const char* method,
65110                                           const Linear_Expression& le);
65111
65112  static void throw_invalid_argument(const char* method, const char* reason);
65113  //@} // Exception Throwers
65114};
65115
65116/* Automatically generated from PPL source file ../src/BDS_Status_inlines.hh line 1. */
65117/* BD_Shape<T>::Status class implementation: inline functions.
65118*/
65119
65120
65121namespace Parma_Polyhedra_Library {
65122
65123template <typename T>
65124inline
65125BD_Shape<T>::Status::Status(flags_t mask)
65126  : flags(mask) {
65127}
65128
65129template <typename T>
65130inline
65131BD_Shape<T>::Status::Status()
65132  : flags(ZERO_DIM_UNIV) {
65133}
65134
65135template <typename T>
65136inline bool
65137BD_Shape<T>::Status::test_all(flags_t mask) const {
65138  return (flags & mask) == mask;
65139}
65140
65141template <typename T>
65142inline bool
65143BD_Shape<T>::Status::test_any(flags_t mask) const {
65144  return (flags & mask) != 0;
65145}
65146
65147template <typename T>
65148inline void
65149BD_Shape<T>::Status::set(flags_t mask) {
65150  flags |= mask;
65151}
65152
65153template <typename T>
65154inline void
65155BD_Shape<T>::Status::reset(flags_t mask) {
65156  flags &= ~mask;
65157}
65158
65159template <typename T>
65160inline bool
65161BD_Shape<T>::Status::test_zero_dim_univ() const {
65162  return flags == ZERO_DIM_UNIV;
65163}
65164
65165template <typename T>
65166inline void
65167BD_Shape<T>::Status::reset_zero_dim_univ() {
65168  // This is a no-op if the current status is not zero-dim.
65169  if (flags == ZERO_DIM_UNIV) {
65170    // In the zero-dim space, if it is not the universe it is empty.
65171    flags = EMPTY;
65172  }
65173}
65174
65175template <typename T>
65176inline void
65177BD_Shape<T>::Status::set_zero_dim_univ() {
65178  // Zero-dim universe is incompatible with anything else.
65179  flags = ZERO_DIM_UNIV;
65180}
65181
65182template <typename T>
65183inline bool
65184BD_Shape<T>::Status::test_empty() const {
65185  return test_any(EMPTY);
65186}
65187
65188template <typename T>
65189inline void
65190BD_Shape<T>::Status::reset_empty() {
65191  reset(EMPTY);
65192}
65193
65194template <typename T>
65195inline void
65196BD_Shape<T>::Status::set_empty() {
65197  flags = EMPTY;
65198}
65199
65200template <typename T>
65201inline bool
65202BD_Shape<T>::Status::test_shortest_path_closed() const {
65203  return test_any(SHORTEST_PATH_CLOSED);
65204}
65205
65206template <typename T>
65207inline void
65208BD_Shape<T>::Status::reset_shortest_path_closed() {
65209  // A system is reduced only if it is also closed.
65210  reset(SHORTEST_PATH_CLOSED | SHORTEST_PATH_REDUCED);
65211}
65212
65213template <typename T>
65214inline void
65215BD_Shape<T>::Status::set_shortest_path_closed() {
65216  set(SHORTEST_PATH_CLOSED);
65217}
65218
65219template <typename T>
65220inline bool
65221BD_Shape<T>::Status::test_shortest_path_reduced() const {
65222  return test_any(SHORTEST_PATH_REDUCED);
65223}
65224
65225template <typename T>
65226inline void
65227BD_Shape<T>::Status::reset_shortest_path_reduced() {
65228  reset(SHORTEST_PATH_REDUCED);
65229}
65230
65231template <typename T>
65232inline void
65233BD_Shape<T>::Status::set_shortest_path_reduced() {
65234  PPL_ASSERT(test_shortest_path_closed());
65235  set(SHORTEST_PATH_REDUCED);
65236}
65237
65238template <typename T>
65239bool
65240BD_Shape<T>::Status::OK() const {
65241  if (test_zero_dim_univ()) {
65242    // Zero-dim universe is OK.
65243    return true;
65244  }
65245
65246  if (test_empty()) {
65247    Status copy = *this;
65248    copy.reset_empty();
65249    if (copy.test_zero_dim_univ()) {
65250      return true;
65251    }
65252    else {
65253#ifndef NDEBUG
65254      std::cerr << "The empty flag is incompatible with any other one."
65255                << std::endl;
65256#endif
65257      return false;
65258    }
65259  }
65260
65261  // Shortest-path reduction implies shortest-path closure.
65262  if (test_shortest_path_reduced()) {
65263    if (test_shortest_path_closed()) {
65264      return true;
65265    }
65266    else {
65267#ifndef NDEBUG
65268      std::cerr << "The shortest-path reduction flag should also imply "
65269                << "the closure flag."
65270                << std::endl;
65271#endif
65272      return false;
65273    }
65274  }
65275
65276  // Any other case is OK.
65277  return true;
65278}
65279
65280
65281namespace Implementation {
65282
65283namespace BD_Shapes {
65284
65285// These are the keywords that indicate the individual assertions.
65286extern const char* zero_dim_univ;
65287extern const char* empty;
65288extern const char* sp_closed;
65289extern const char* sp_reduced;
65290const char yes = '+';
65291const char no = '-';
65292const char separator = ' ';
65293
65294/*! \relates Parma_Polyhedra_Library::BD_Shape::Status
65295  Reads a keyword and its associated on/off flag from \p s.
65296  Returns <CODE>true</CODE> if the operation is successful,
65297  returns <CODE>false</CODE> otherwise.
65298  When successful, \p positive is set to <CODE>true</CODE> if the flag
65299  is on; it is set to <CODE>false</CODE> otherwise.
65300*/
65301inline bool
65302get_field(std::istream& s, const char* keyword, bool& positive) {
65303  std::string str;
65304  if (!(s >> str)
65305      || (str[0] != yes && str[0] != no)
65306      || str.substr(1) != keyword) {
65307    return false;
65308  }
65309  positive = (str[0] == yes);
65310  return true;
65311}
65312
65313} // namespace BD_Shapes
65314
65315} // namespace Implementation
65316
65317template <typename T>
65318void
65319BD_Shape<T>::Status::ascii_dump(std::ostream& s) const {
65320  using namespace Implementation::BD_Shapes;
65321  s << (test_zero_dim_univ() ? yes : no) << zero_dim_univ << separator
65322    << (test_empty() ? yes : no) << empty << separator
65323    << separator
65324    << (test_shortest_path_closed() ? yes : no) << sp_closed << separator
65325    << (test_shortest_path_reduced() ? yes : no) << sp_reduced << separator;
65326}
65327
65328PPL_OUTPUT_TEMPLATE_DEFINITIONS_ASCII_ONLY(T, BD_Shape<T>::Status)
65329
65330template <typename T>
65331bool
65332BD_Shape<T>::Status::ascii_load(std::istream& s) {
65333  using namespace Implementation::BD_Shapes;
65334  PPL_UNINITIALIZED(bool, positive);
65335
65336  if (!get_field(s, zero_dim_univ, positive)) {
65337    return false;
65338  }
65339  if (positive) {
65340    set_zero_dim_univ();
65341  }
65342
65343  if (!get_field(s, empty, positive)) {
65344    return false;
65345  }
65346  if (positive) {
65347    set_empty();
65348  }
65349
65350  if (!get_field(s, sp_closed, positive)) {
65351    return false;
65352  }
65353  if (positive) {
65354    set_shortest_path_closed();
65355  }
65356  else {
65357    reset_shortest_path_closed();
65358  }
65359
65360  if (!get_field(s, sp_reduced, positive)) {
65361    return false;
65362  }
65363  if (positive) {
65364    set_shortest_path_reduced();
65365  }
65366  else {
65367    reset_shortest_path_reduced();
65368  }
65369
65370  // Check invariants.
65371  PPL_ASSERT(OK());
65372  return true;
65373}
65374
65375} // namespace Parma_Polyhedra_Library
65376
65377/* Automatically generated from PPL source file ../src/BD_Shape_inlines.hh line 1. */
65378/* BD_Shape class implementation: inline functions.
65379*/
65380
65381
65382/* Automatically generated from PPL source file ../src/C_Polyhedron_defs.hh line 1. */
65383/* C_Polyhedron class declaration.
65384*/
65385
65386
65387/* Automatically generated from PPL source file ../src/C_Polyhedron_types.hh line 1. */
65388
65389
65390namespace Parma_Polyhedra_Library {
65391
65392class C_Polyhedron;
65393
65394} // namespace Parma_Polyhedra_Library
65395
65396/* Automatically generated from PPL source file ../src/NNC_Polyhedron_types.hh line 1. */
65397
65398
65399namespace Parma_Polyhedra_Library {
65400
65401class NNC_Polyhedron;
65402
65403} // namespace Parma_Polyhedra_Library
65404
65405/* Automatically generated from PPL source file ../src/C_Polyhedron_defs.hh line 33. */
65406
65407//! A closed convex polyhedron.
65408/*! \ingroup PPL_CXX_interface
65409    An object of the class C_Polyhedron represents a
65410    <EM>topologically closed</EM> convex polyhedron
65411    in the vector space \f$\Rset^n\f$.
65412
65413    When building a closed polyhedron starting from
65414    a system of constraints, an exception is thrown if the system
65415    contains a <EM>strict inequality</EM> constraint.
65416    Similarly, an exception is thrown when building a closed polyhedron
65417    starting from a system of generators containing a <EM>closure point</EM>.
65418
65419    \note
65420    Such an exception will be obtained even if the system of
65421    constraints (resp., generators) actually defines
65422    a topologically closed subset of the vector space, i.e.,
65423    even if all the strict inequalities (resp., closure points)
65424    in the system happen to be redundant with respect to the
65425    system obtained by removing all the strict inequality constraints
65426    (resp., all the closure points).
65427    In contrast, when building a closed polyhedron starting from
65428    an object of the class NNC_Polyhedron,
65429    the precise topological closure test will be performed.
65430*/
65431
65432class Parma_Polyhedra_Library::C_Polyhedron : public Polyhedron {
65433public:
65434  //! Builds either the universe or the empty C polyhedron.
65435  /*!
65436    \param num_dimensions
65437    The number of dimensions of the vector space enclosing the C polyhedron;
65438
65439    \param kind
65440    Specifies whether a universe or an empty C polyhedron should be built.
65441
65442    \exception std::length_error
65443    Thrown if \p num_dimensions exceeds the maximum allowed space dimension.
65444
65445    Both parameters are optional:
65446    by default, a 0-dimension space universe C polyhedron is built.
65447  */
65448  explicit C_Polyhedron(dimension_type num_dimensions = 0,
65449                        Degenerate_Element kind = UNIVERSE);
65450
65451  //! Builds a C polyhedron from a system of constraints.
65452  /*!
65453    The polyhedron inherits the space dimension of the constraint system.
65454
65455    \param cs
65456    The system of constraints defining the polyhedron.
65457
65458    \exception std::invalid_argument
65459    Thrown if the system of constraints contains strict inequalities.
65460  */
65461  explicit C_Polyhedron(const Constraint_System& cs);
65462
65463  //! Builds a C polyhedron recycling a system of constraints.
65464  /*!
65465    The polyhedron inherits the space dimension of the constraint system.
65466
65467    \param cs
65468    The system of constraints defining the polyhedron.  It is not
65469    declared <CODE>const</CODE> because its data-structures may be
65470    recycled to build the polyhedron.
65471
65472    \param dummy
65473    A dummy tag to syntactically differentiate this one
65474    from the other constructors.
65475
65476    \exception std::invalid_argument
65477    Thrown if the system of constraints contains strict inequalities.
65478  */
65479  C_Polyhedron(Constraint_System& cs, Recycle_Input dummy);
65480
65481  //! Builds a C polyhedron from a system of generators.
65482  /*!
65483    The polyhedron inherits the space dimension of the generator system.
65484
65485    \param gs
65486    The system of generators defining the polyhedron.
65487
65488    \exception std::invalid_argument
65489    Thrown if the system of generators is not empty but has no points,
65490    or if it contains closure points.
65491  */
65492  explicit C_Polyhedron(const Generator_System& gs);
65493
65494  //! Builds a C polyhedron recycling a system of generators.
65495  /*!
65496    The polyhedron inherits the space dimension of the generator system.
65497
65498    \param gs
65499    The system of generators defining the polyhedron.  It is not
65500    declared <CODE>const</CODE> because its data-structures may be
65501    recycled to build the polyhedron.
65502
65503    \param dummy
65504    A dummy tag to syntactically differentiate this one
65505    from the other constructors.
65506
65507    \exception std::invalid_argument
65508    Thrown if the system of generators is not empty but has no points,
65509    or if it contains closure points.
65510  */
65511  C_Polyhedron(Generator_System& gs, Recycle_Input dummy);
65512
65513  //! Builds a C polyhedron from a system of congruences.
65514  /*!
65515    The polyhedron inherits the space dimension of the congruence system.
65516
65517    \param cgs
65518    The system of congruences defining the polyhedron.
65519  */
65520  explicit C_Polyhedron(const Congruence_System& cgs);
65521
65522  //! Builds a C polyhedron recycling a system of congruences.
65523  /*!
65524    The polyhedron inherits the space dimension of the congruence
65525    system.
65526
65527    \param cgs
65528    The system of congruences defining the polyhedron.  It is not
65529    declared <CODE>const</CODE> because its data-structures may be
65530    recycled to build the polyhedron.
65531
65532    \param dummy
65533    A dummy tag to syntactically differentiate this one
65534    from the other constructors.
65535  */
65536  C_Polyhedron(Congruence_System& cgs, Recycle_Input dummy);
65537
65538  /*! \brief
65539    Builds a C polyhedron representing the topological closure
65540    of the NNC polyhedron \p y.
65541
65542    \param y
65543    The NNC polyhedron to be used;
65544
65545    \param complexity
65546    This argument is ignored.
65547  */
65548  explicit C_Polyhedron(const NNC_Polyhedron& y,
65549                        Complexity_Class complexity = ANY_COMPLEXITY);
65550
65551  //! Builds a C polyhedron out of a box.
65552  /*!
65553    The polyhedron inherits the space dimension of the box
65554    and is the most precise that includes the box.
65555    The algorithm used has polynomial complexity.
65556
65557    \param box
65558    The box representing the polyhedron to be approximated;
65559
65560    \param complexity
65561    This argument is ignored.
65562
65563    \exception std::length_error
65564    Thrown if the space dimension of \p box exceeds the maximum allowed
65565    space dimension.
65566  */
65567  template <typename Interval>
65568  explicit C_Polyhedron(const Box<Interval>& box,
65569                        Complexity_Class complexity = ANY_COMPLEXITY);
65570
65571  //! Builds a C polyhedron out of a BD shape.
65572  /*!
65573    The polyhedron inherits the space dimension of the BDS and is
65574    the most precise that includes the BDS.
65575
65576    \param bd
65577    The BDS used to build the polyhedron.
65578
65579    \param complexity
65580    This argument is ignored as the algorithm used has
65581    polynomial complexity.
65582  */
65583  template <typename U>
65584  explicit C_Polyhedron(const BD_Shape<U>& bd,
65585                        Complexity_Class complexity = ANY_COMPLEXITY);
65586
65587  //! Builds a C polyhedron out of an octagonal shape.
65588  /*!
65589    The polyhedron inherits the space dimension of the octagonal shape
65590    and is the most precise that includes the octagonal shape.
65591
65592    \param os
65593    The octagonal shape used to build the polyhedron.
65594
65595    \param complexity
65596    This argument is ignored as the algorithm used has
65597    polynomial complexity.
65598  */
65599  template <typename U>
65600  explicit C_Polyhedron(const Octagonal_Shape<U>& os,
65601                        Complexity_Class complexity = ANY_COMPLEXITY);
65602
65603  //! Builds a C polyhedron out of a grid.
65604  /*!
65605    The polyhedron inherits the space dimension of the grid
65606    and is the most precise that includes the grid.
65607
65608    \param grid
65609    The grid used to build the polyhedron.
65610
65611    \param complexity
65612    This argument is ignored as the algorithm used has
65613    polynomial complexity.
65614  */
65615  explicit C_Polyhedron(const Grid& grid,
65616                        Complexity_Class complexity = ANY_COMPLEXITY);
65617
65618  //! Ordinary copy constructor.
65619  /*!
65620    The complexity argument is ignored.
65621  */
65622  C_Polyhedron(const C_Polyhedron& y,
65623               Complexity_Class complexity = ANY_COMPLEXITY);
65624
65625  /*! \brief
65626    The assignment operator.
65627    (\p *this and \p y can be dimension-incompatible.)
65628  */
65629  C_Polyhedron& operator=(const C_Polyhedron& y);
65630
65631  //! Assigns to \p *this the topological closure of the NNC polyhedron \p y.
65632  C_Polyhedron& operator=(const NNC_Polyhedron& y);
65633
65634  //! Destructor.
65635  ~C_Polyhedron();
65636
65637  /*! \brief
65638    If the poly-hull of \p *this and \p y is exact it is assigned
65639    to \p *this and <CODE>true</CODE> is returned,
65640    otherwise <CODE>false</CODE> is returned.
65641
65642    \exception std::invalid_argument
65643    Thrown if \p *this and \p y are dimension-incompatible.
65644  */
65645  bool poly_hull_assign_if_exact(const C_Polyhedron& y);
65646
65647  //! Same as poly_hull_assign_if_exact(y).
65648  bool upper_bound_assign_if_exact(const C_Polyhedron& y);
65649
65650  /*! \brief
65651    Assigns to \p *this the smallest C polyhedron containing the
65652    result of computing the
65653    \ref Positive_Time_Elapse_Operator "positive time-elapse"
65654    between \p *this and \p y.
65655
65656    \exception std::invalid_argument
65657    Thrown if \p *this and \p y are dimension-incompatible.
65658  */
65659  void positive_time_elapse_assign(const Polyhedron& y);
65660};
65661
65662/* Automatically generated from PPL source file ../src/C_Polyhedron_inlines.hh line 1. */
65663/* C_Polyhedron class implementation: inline functions.
65664*/
65665
65666
65667#include <algorithm>
65668#include <stdexcept>
65669
65670namespace Parma_Polyhedra_Library {
65671
65672inline
65673C_Polyhedron::~C_Polyhedron() {
65674}
65675
65676inline
65677C_Polyhedron::C_Polyhedron(dimension_type num_dimensions,
65678                           Degenerate_Element kind)
65679  : Polyhedron(NECESSARILY_CLOSED,
65680               check_space_dimension_overflow(num_dimensions,
65681                                              NECESSARILY_CLOSED,
65682                                              "C_Polyhedron(n, k)",
65683                                              "n exceeds the maximum "
65684                                              "allowed space dimension"),
65685               kind) {
65686}
65687
65688inline
65689C_Polyhedron::C_Polyhedron(const Constraint_System& cs)
65690  : Polyhedron(NECESSARILY_CLOSED,
65691               check_obj_space_dimension_overflow(cs, NECESSARILY_CLOSED,
65692                                                  "C_Polyhedron(cs)",
65693                                                  "the space dimension of cs "
65694                                                  "exceeds the maximum allowed "
65695                                                  "space dimension")) {
65696}
65697
65698inline
65699C_Polyhedron::C_Polyhedron(Constraint_System& cs, Recycle_Input)
65700  : Polyhedron(NECESSARILY_CLOSED,
65701               check_obj_space_dimension_overflow(cs, NECESSARILY_CLOSED,
65702                                                  "C_Polyhedron(cs, recycle)",
65703                                                  "the space dimension of cs "
65704                                                  "exceeds the maximum allowed "
65705                                                  "space dimension"),
65706               Recycle_Input()) {
65707}
65708
65709inline
65710C_Polyhedron::C_Polyhedron(const Generator_System& gs)
65711  : Polyhedron(NECESSARILY_CLOSED,
65712               check_obj_space_dimension_overflow(gs, NECESSARILY_CLOSED,
65713                                                  "C_Polyhedron(gs)",
65714                                                  "the space dimension of gs "
65715                                                  "exceeds the maximum allowed "
65716                                                  "space dimension")) {
65717}
65718
65719inline
65720C_Polyhedron::C_Polyhedron(Generator_System& gs, Recycle_Input)
65721  : Polyhedron(NECESSARILY_CLOSED,
65722               check_obj_space_dimension_overflow(gs, NECESSARILY_CLOSED,
65723                                                  "C_Polyhedron(gs, recycle)",
65724                                                  "the space dimension of gs "
65725                                                  "exceeds the maximum allowed "
65726                                                  "space dimension"),
65727               Recycle_Input()) {
65728}
65729
65730template <typename Interval>
65731inline
65732C_Polyhedron::C_Polyhedron(const Box<Interval>& box, Complexity_Class)
65733  : Polyhedron(NECESSARILY_CLOSED,
65734               check_obj_space_dimension_overflow(box, NECESSARILY_CLOSED,
65735                                                  "C_Polyhedron(box)",
65736                                                  "the space dimension of box "
65737                                                  "exceeds the maximum allowed "
65738                                                  "space dimension")) {
65739}
65740
65741template <typename U>
65742inline
65743C_Polyhedron::C_Polyhedron(const BD_Shape<U>& bd, Complexity_Class)
65744  : Polyhedron(NECESSARILY_CLOSED,
65745               check_space_dimension_overflow(bd.space_dimension(),
65746                                              NECESSARILY_CLOSED,
65747                                              "C_Polyhedron(bd)",
65748                                              "the space dimension of bd "
65749                                              "exceeds the maximum allowed "
65750                                              "space dimension"),
65751               UNIVERSE) {
65752  add_constraints(bd.constraints());
65753}
65754
65755template <typename U>
65756inline
65757C_Polyhedron::C_Polyhedron(const Octagonal_Shape<U>& os, Complexity_Class)
65758  : Polyhedron(NECESSARILY_CLOSED,
65759               check_space_dimension_overflow(os.space_dimension(),
65760                                              NECESSARILY_CLOSED,
65761                                              "C_Polyhedron(os)",
65762                                              "the space dimension of os "
65763                                              "exceeds the maximum allowed "
65764                                              "space dimension"),
65765               UNIVERSE) {
65766  add_constraints(os.constraints());
65767}
65768
65769inline
65770C_Polyhedron::C_Polyhedron(const C_Polyhedron& y, Complexity_Class)
65771  : Polyhedron(y) {
65772}
65773
65774inline C_Polyhedron&
65775C_Polyhedron::operator=(const C_Polyhedron& y) {
65776  Polyhedron::operator=(y);
65777  return *this;
65778}
65779
65780inline C_Polyhedron&
65781C_Polyhedron::operator=(const NNC_Polyhedron& y) {
65782  C_Polyhedron c_y(y);
65783  m_swap(c_y);
65784  return *this;
65785}
65786
65787inline bool
65788C_Polyhedron::upper_bound_assign_if_exact(const C_Polyhedron& y) {
65789  return poly_hull_assign_if_exact(y);
65790}
65791
65792} // namespace Parma_Polyhedra_Library
65793
65794/* Automatically generated from PPL source file ../src/C_Polyhedron_defs.hh line 290. */
65795
65796/* Automatically generated from PPL source file ../src/Octagonal_Shape_defs.hh line 1. */
65797/* Octagonal_Shape class declaration.
65798*/
65799
65800
65801/* Automatically generated from PPL source file ../src/OR_Matrix_defs.hh line 1. */
65802/* OR_Matrix class declaration.
65803*/
65804
65805
65806/* Automatically generated from PPL source file ../src/OR_Matrix_types.hh line 1. */
65807
65808
65809namespace Parma_Polyhedra_Library {
65810
65811template <typename T>
65812class OR_Matrix;
65813
65814}
65815
65816/* Automatically generated from PPL source file ../src/OR_Matrix_defs.hh line 31. */
65817#include <cstddef>
65818#include <iosfwd>
65819
65820#ifndef PPL_OR_MATRIX_EXTRA_DEBUG
65821#ifdef PPL_ABI_BREAKING_EXTRA_DEBUG
65822#ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
65823/*! \brief
65824  When PPL_OR_MATRIX_EXTRA_DEBUG evaluates to <CODE>true</CODE>, each
65825  instance of the class OR_Matrix::Pseudo_Row carries its own size;
65826  this enables extra consistency checks to be performed.
65827  \ingroup PPL_CXX_interface
65828*/
65829#endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
65830#define PPL_OR_MATRIX_EXTRA_DEBUG 1
65831#else // !defined(PPL_ABI_BREAKING_EXTRA_DEBUG)
65832#define PPL_OR_MATRIX_EXTRA_DEBUG 0
65833#endif // !defined(PPL_ABI_BREAKING_EXTRA_DEBUG)
65834#endif // !defined(PPL_OR_MATRIX_EXTRA_DEBUG)
65835
65836namespace Parma_Polyhedra_Library {
65837
65838#ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
65839//! Returns <CODE>true</CODE> if and only if \p x and \p y are identical.
65840/*! \relates OR_Matrix */
65841#endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
65842template <typename T>
65843bool operator==(const OR_Matrix<T>& x, const OR_Matrix<T>& y);
65844
65845namespace IO_Operators {
65846
65847#ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
65848//! Output operator.
65849/*! \relates Parma_Polyhedra_Library::OR_Matrix */
65850#endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
65851template <typename T>
65852std::ostream&
65853operator<<(std::ostream& s, const OR_Matrix<T>& m);
65854
65855} // namespace IO_Operators
65856
65857} // namespace Parma_Polyhedra_Library
65858
65859
65860#ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
65861//! A matrix representing octagonal constraints.
65862/*!
65863  An OR_Matrix object is a DB_Row object that allows
65864  the representation of a \em pseudo-triangular matrix,
65865  like the following:
65866
65867<PRE>
65868         _ _
65869   0    |_|_|
65870   1    |_|_|_ _
65871   2    |_|_|_|_|
65872   3    |_|_|_|_|_ _
65873   4    |_|_|_|_|_|_|
65874   5    |_|_|_|_|_|_|
65875         . . .
65876         _ _ _ _ _ _       _
65877 2n-2   |_|_|_|_|_|_| ... |_|
65878 2n-1   |_|_|_|_|_|_| ... |_|
65879         0 1 2 3 4 5  ... 2n-1
65880
65881</PRE>
65882
65883  It is characterized by parameter n that defines the structure,
65884  and such that there are 2*n rows (and 2*n columns).
65885  It provides row_iterators for the access to the rows
65886  and element_iterators for the access to the elements.
65887*/
65888#endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
65889
65890template <typename T>
65891class Parma_Polyhedra_Library::OR_Matrix {
65892private:
65893  /*! \brief
65894    An object that behaves like a matrix's row with respect to
65895    the subscript operators.
65896  */
65897  template <typename U>
65898  class Pseudo_Row {
65899  public:
65900    /*! \brief
65901      Copy constructor allowing the construction of a const pseudo-row
65902      from a non-const pseudo-row.
65903      Ordinary copy constructor.
65904    */
65905    template <typename V>
65906    Pseudo_Row(const Pseudo_Row<V>& y);
65907
65908    //! Destructor.
65909    ~Pseudo_Row();
65910
65911    //! Subscript operator.
65912    U& operator[](dimension_type k) const;
65913
65914    //! Default constructor: creates an invalid object that has to be assigned.
65915    Pseudo_Row();
65916
65917    //! Assignment operator.
65918    Pseudo_Row& operator=(const Pseudo_Row& y);
65919
65920#if !defined(__GNUC__) || __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ > 0)
65921  private:
65922#else
65923  // Work around a bug of GCC 4.0.x (and, likely, previous versions).
65924  public:
65925#endif
65926
65927#if PPL_OR_MATRIX_EXTRA_DEBUG
65928
65929    //! Private constructor for a Pseudo_Row with size \p s beginning at \p y.
65930    Pseudo_Row(U& y, dimension_type s);
65931
65932#else // !PPL_OR_MATRIX_EXTRA_DEBUG
65933
65934    //! Private constructor for a Pseudo_Row beginning at \p y.
65935    explicit Pseudo_Row(U& y);
65936
65937#endif // !PPL_OR_MATRIX_EXTRA_DEBUG
65938
65939    //! Holds a reference to the beginning of this row.
65940    U* first;
65941
65942#if !defined(__GNUC__) || __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ > 0)
65943#else
65944  // Work around a bug of GCC 4.0.x (and, likely, previous versions).
65945  private:
65946#endif
65947
65948#if PPL_OR_MATRIX_EXTRA_DEBUG
65949
65950    //! The size of the row.
65951    dimension_type size_;
65952
65953    //! Returns the size of the row.
65954    dimension_type size() const;
65955
65956#endif // PPL_OR_MATRIX_EXTRA_DEBUG
65957
65958    // FIXME: the EDG-based compilers (such as Comeau and Intel)
65959    // are here in wild disagreement with GCC: what is a legal friend
65960    // declaration for one, is illegal for the others.
65961#ifdef __EDG__
65962    template <typename V> template<typename W>
65963    friend class OR_Matrix<V>::Pseudo_Row;
65964    template <typename V> template<typename W>
65965    friend class OR_Matrix<V>::any_row_iterator;
65966#else
65967    template <typename V> friend class Pseudo_Row;
65968    template <typename V> friend class any_row_iterator;
65969#endif
65970
65971    friend class OR_Matrix;
65972  }; // class Pseudo_Row
65973
65974public:
65975  //! A (non const) reference to a matrix's row.
65976  typedef Pseudo_Row<T> row_reference_type;
65977
65978  //! A const reference to a matrix's row.
65979  typedef Pseudo_Row<const T> const_row_reference_type;
65980
65981private:
65982  /*! \brief
65983    A template class to derive both OR_Matrix::iterator
65984    and OR_Matrix::const_iterator.
65985  */
65986  template <typename U>
65987  class any_row_iterator {
65988  public:
65989    typedef std::random_access_iterator_tag iterator_category;
65990    typedef Pseudo_Row<U> value_type;
65991    typedef long difference_type;
65992    typedef const Pseudo_Row<U>* pointer;
65993    typedef const Pseudo_Row<U>& reference;
65994
65995    //! Constructor to build past-the-end objects.
65996    any_row_iterator(dimension_type n_rows);
65997
65998    /*! \brief
65999      Builds an iterator pointing at the beginning of an OR_Matrix whose
66000      first element is \p base;
66001    */
66002    explicit any_row_iterator(U& base);
66003
66004    /*! \brief
66005      Copy constructor allowing the construction of a const_iterator
66006      from a non-const iterator.
66007    */
66008    template <typename V>
66009    any_row_iterator(const any_row_iterator<V>& y);
66010
66011    /*! \brief
66012      Assignment operator allowing the assignment of a non-const iterator
66013      to a const_iterator.
66014    */
66015    template <typename V>
66016    any_row_iterator& operator=(const any_row_iterator<V>& y);
66017
66018    //! Dereference operator.
66019    reference operator*() const;
66020
66021    //! Indirect member selector.
66022    pointer operator->() const;
66023
66024    //! Prefix increment operator.
66025    any_row_iterator& operator++();
66026
66027    //! Postfix increment operator.
66028    any_row_iterator operator++(int);
66029
66030    //! Prefix decrement operator.
66031    any_row_iterator& operator--();
66032
66033    //! Postfix decrement operator.
66034    any_row_iterator operator--(int);
66035
66036    //! Subscript operator.
66037    reference operator[](difference_type m) const;
66038
66039    //! Assignment-increment operator.
66040    any_row_iterator& operator+=(difference_type m);
66041
66042    //! Assignment-increment operator for \p m of unsigned type.
66043    template <typename Unsigned>
66044    typename Enable_If<(static_cast<Unsigned>(-1) > 0), any_row_iterator&>::type
66045    operator+=(Unsigned m);
66046
66047    //! Assignment-decrement operator.
66048    any_row_iterator& operator-=(difference_type m);
66049
66050    //! Returns the difference between \p *this and \p y.
66051    difference_type operator-(const any_row_iterator& y) const;
66052
66053    //! Returns the sum of \p *this and \p m.
66054    any_row_iterator operator+(difference_type m) const;
66055
66056    //! Returns the sum of \p *this and \p m, for \p m of unsigned type.
66057    template <typename Unsigned>
66058    typename Enable_If<(static_cast<Unsigned>(-1) > 0), any_row_iterator>::type
66059    operator+(Unsigned m) const;
66060
66061    //! Returns the difference of \p *this and \p m.
66062    any_row_iterator operator-(difference_type m) const;
66063
66064    //! Returns <CODE>true</CODE> if and only if \p *this is equal to \p y.
66065    bool operator==(const any_row_iterator& y) const;
66066
66067    /*! \brief
66068      Returns <CODE>true</CODE> if and only if \p *this
66069      is different from \p y.
66070    */
66071    bool operator!=(const any_row_iterator& y) const;
66072
66073    //! Returns <CODE>true</CODE> if and only if \p *this is less than \p y.
66074    bool operator<(const any_row_iterator& y) const;
66075
66076    /*! \brief
66077      Returns <CODE>true</CODE> if and only if \p *this is less than
66078      or equal to \p y.
66079    */
66080    bool operator<=(const any_row_iterator& y) const;
66081
66082    //! Returns <CODE>true</CODE> if and only if \p *this is greater than \p y.
66083    bool operator>(const any_row_iterator& y) const;
66084
66085    /*! \brief
66086      Returns <CODE>true</CODE> if and only if \p *this is greater than
66087      or equal to \p y.
66088    */
66089    bool operator>=(const any_row_iterator& y) const;
66090
66091    dimension_type row_size() const;
66092
66093    dimension_type index() const;
66094
66095  private:
66096    //! Represents the beginning of a row.
66097    Pseudo_Row<U> value;
66098
66099    //! External index.
66100    dimension_type e;
66101
66102    //! Internal index: <CODE>i = (e+1)*(e+1)/2</CODE>.
66103    dimension_type i;
66104
66105    // FIXME: the EDG-based compilers (such as Comeau and Intel)
66106    // are here in wild disagreement with GCC: what is a legal friend
66107    // declaration for one, is illegal for the others.
66108#ifdef __EDG__
66109    template <typename V> template<typename W>
66110    friend class OR_Matrix<V>::any_row_iterator;
66111#else
66112    template <typename V> friend class any_row_iterator;
66113#endif
66114  }; // class any_row_iterator
66115
66116public:
66117  //! A (non const) row iterator.
66118  typedef any_row_iterator<T> row_iterator;
66119
66120  //! A const row iterator.
66121  typedef any_row_iterator<const T> const_row_iterator;
66122
66123  //! A (non const) element iterator.
66124  typedef typename DB_Row<T>::iterator element_iterator;
66125
66126  //! A const element iterator.
66127  typedef typename DB_Row<T>::const_iterator const_element_iterator;
66128
66129public:
66130  //! Returns the maximum number of rows of a OR_Matrix.
66131  static dimension_type max_num_rows();
66132
66133  //! Builds a matrix with specified dimensions.
66134  /*!
66135    \param num_dimensions
66136    The space dimension of the matrix that will be created.
66137
66138    This constructor creates a matrix with \p 2*num_dimensions rows.
66139    Each element is initialized to plus infinity.
66140  */
66141  OR_Matrix(dimension_type num_dimensions);
66142
66143  //! Copy constructor.
66144  OR_Matrix(const OR_Matrix& y);
66145
66146  //! Constructs a conservative approximation of \p y.
66147  template <typename U>
66148  explicit OR_Matrix(const OR_Matrix<U>& y);
66149
66150  //! Destructor.
66151  ~OR_Matrix();
66152
66153  //! Assignment operator.
66154  OR_Matrix& operator=(const OR_Matrix& y);
66155
66156private:
66157  template <typename U> friend class OR_Matrix;
66158
66159  //! Contains the rows of the matrix.
66160  /*!
66161    A DB_Row which contains the rows of the OR_Matrix
66162    inserting each successive row to the end of the vec.
66163    To contain all the elements of OR_Matrix the size of the DB_Row
66164    is 2*n*(n+1), where the n is the characteristic parameter of
66165    OR_Matrix.
66166  */
66167  DB_Row<T> vec;
66168
66169  //! Contains the dimension of the space of the matrix.
66170  dimension_type space_dim;
66171
66172  //! Contains the capacity of \p vec.
66173  dimension_type vec_capacity;
66174
66175  //! Private and not implemented: default construction is not allowed.
66176  OR_Matrix();
66177
66178  /*! \brief
66179    Returns the index into <CODE>vec</CODE> of the first element
66180    of the row of index \p k.
66181  */
66182  static dimension_type row_first_element_index(dimension_type k);
66183
66184public:
66185  //! Returns the size of the row of index \p k.
66186  static dimension_type row_size(dimension_type k);
66187
66188  //! Swaps \p *this with \p y.
66189  void m_swap(OR_Matrix& y);
66190
66191  //! Makes the matrix grow by adding more space dimensions.
66192  /*!
66193    \param new_dim
66194    The new dimension of the resized matrix.
66195
66196    Adds new rows of right dimension to the end if
66197    there is enough capacity; otherwise, creates a new matrix,
66198    with the specified dimension, copying the old elements
66199    in the upper part of the new matrix, which is
66200    then assigned to \p *this.
66201    Each new element is initialized to plus infinity.
66202  */
66203  void grow(dimension_type new_dim);
66204
66205  //! Makes the matrix shrink by removing the last space dimensions.
66206  /*!
66207    \param new_dim
66208    The new dimension of the resized matrix.
66209
66210    Erases from matrix to the end the rows with index
66211    greater than 2*new_dim-1.
66212  */
66213  void shrink(dimension_type new_dim);
66214
66215  //! Resizes the matrix without worrying about the old contents.
66216  /*!
66217    \param new_dim
66218    The new dimension of the resized matrix.
66219
66220    If the new dimension is greater than the old one, it adds new rows
66221    of right dimension to the end if there is enough capacity; otherwise,
66222    it creates a new matrix, with the specified dimension, which is
66223    then assigned to \p *this.
66224    If the new dimension is less than the old one, it erase from the matrix
66225    the rows having index greater than 2*new_dim-1
66226  */
66227  void resize_no_copy(dimension_type new_dim);
66228
66229  //! Returns the space-dimension of the matrix.
66230  dimension_type space_dimension() const;
66231
66232  //! Returns the number of rows in the matrix.
66233  dimension_type num_rows() const;
66234
66235  //! \name Subscript operators.
66236  //@{
66237  //! Returns a reference to the \p k-th row of the matrix.
66238  row_reference_type operator[](dimension_type k);
66239
66240  //! Returns a constant reference to the \p k-th row of the matrix.
66241  const_row_reference_type operator[](dimension_type k) const;
66242  //@}
66243
66244
66245  /*! \brief
66246    Returns an iterator pointing to the first row,
66247    if \p *this is not empty;
66248    otherwise, returns the past-the-end const_iterator.
66249  */
66250  row_iterator row_begin();
66251
66252  //! Returns the past-the-end const_iterator.
66253  row_iterator row_end();
66254
66255  /*! \brief
66256    Returns a const row iterator pointing to the first row,
66257    if \p *this is not empty;
66258    otherwise, returns the past-the-end const_iterator.
66259  */
66260  const_row_iterator row_begin() const;
66261
66262  //! Returns the past-the-end const row iterator.
66263  const_row_iterator row_end() const;
66264
66265  /*! \brief
66266    Returns an iterator pointing to the first element,
66267    if \p *this is not empty;
66268    otherwise, returns the past-the-end const_iterator.
66269  */
66270  element_iterator element_begin();
66271
66272  //! Returns the past-the-end const_iterator.
66273  element_iterator element_end();
66274
66275  /*! \brief
66276    Returns a const element iterator pointing to the first element,
66277    if \p *this is not empty;
66278    otherwise, returns the past-the-end const_iterator.
66279  */
66280  const_element_iterator element_begin() const;
66281
66282  //! Returns the past-the-end const element iterator.
66283  const_element_iterator element_end() const;
66284
66285  //! Clears the matrix deallocating all its rows.
66286  void clear();
66287
66288  PPL_OUTPUT_DECLARATIONS
66289
66290  /*! \brief
66291    Loads from \p s an ASCII representation (as produced by
66292    ascii_dump(std::ostream&) const) and sets \p *this accordingly.
66293    Returns <CODE>true</CODE> if successful, <CODE>false</CODE> otherwise.
66294  */
66295  bool ascii_load(std::istream& s);
66296
66297  //! Returns the total size in bytes of the memory occupied by \p *this.
66298  memory_size_type total_memory_in_bytes() const;
66299
66300  //! Returns the size in bytes of the memory managed by \p *this.
66301  memory_size_type external_memory_in_bytes() const;
66302
66303  friend bool operator==<T>(const OR_Matrix<T>& x, const OR_Matrix<T>& y);
66304
66305  //! Checks if all the invariants are satisfied.
66306  bool OK() const;
66307};
66308
66309namespace Parma_Polyhedra_Library {
66310
66311#ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
66312//! Swaps \p x with \p y.
66313/*! \relates OR_Matrix */
66314#endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
66315template <typename T>
66316void swap(OR_Matrix<T>& x, OR_Matrix<T>& y);
66317
66318#ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
66319//! Returns <CODE>true</CODE> if and only if \p x and \p y are different.
66320/*! \relates OR_Matrix */
66321#endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
66322template <typename T>
66323bool operator!=(const OR_Matrix<T>& x, const OR_Matrix<T>& y);
66324
66325#ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
66326//! Computes the rectilinear (or Manhattan) distance between \p x and \p y.
66327/*! \relates OR_Matrix
66328  If the rectilinear distance between \p x and \p y is defined,
66329  stores an approximation of it into to \p r
66330  and returns <CODE>true</CODE>;  returns <CODE>false</CODE> otherwise.
66331
66332  The direction of the approximation is specified by \p dir.
66333
66334  All computations are performed using the temporary variables
66335  \p tmp0, \p tmp1 and \p tmp2.
66336*/
66337#endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
66338template <typename Temp, typename To, typename T>
66339bool rectilinear_distance_assign(Checked_Number<To, Extended_Number_Policy>& r,
66340                                 const OR_Matrix<T>& x,
66341                                 const OR_Matrix<T>& y,
66342                                 Rounding_Dir dir,
66343                                 Temp& tmp0,
66344                                 Temp& tmp1,
66345                                 Temp& tmp2);
66346
66347#ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
66348//! Computes the euclidean distance between \p x and \p y.
66349/*! \relates OR_Matrix
66350  If the Euclidean distance between \p x and \p y is defined,
66351  stores an approximation of it into to \p r
66352  and returns <CODE>true</CODE>;  returns <CODE>false</CODE> otherwise.
66353
66354  The direction of the approximation is specified by \p dir.
66355
66356  All computations are performed using the temporary variables
66357  \p tmp0, \p tmp1 and \p tmp2.
66358*/
66359#endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
66360template <typename Temp, typename To, typename T>
66361bool euclidean_distance_assign(Checked_Number<To, Extended_Number_Policy>& r,
66362                               const OR_Matrix<T>& x,
66363                               const OR_Matrix<T>& y,
66364                               Rounding_Dir dir,
66365                               Temp& tmp0,
66366                               Temp& tmp1,
66367                               Temp& tmp2);
66368
66369#ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
66370//! Computes the \f$L_\infty\f$ distance between \p x and \p y.
66371/*! \relates OR_Matrix
66372  If the \f$L_\infty\f$ distance between \p x and \p y is defined,
66373  stores an approximation of it into to \p r
66374  and returns <CODE>true</CODE>;  returns <CODE>false</CODE> otherwise.
66375
66376  The direction of the approximation is specified by \p dir.
66377
66378  All computations are performed using the temporary variables
66379  \p tmp0, \p tmp1 and \p tmp2.
66380*/
66381#endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
66382template <typename Temp, typename To, typename T>
66383bool l_infinity_distance_assign(Checked_Number<To, Extended_Number_Policy>& r,
66384                                 const OR_Matrix<T>& x,
66385                                 const OR_Matrix<T>& y,
66386                                 Rounding_Dir dir,
66387                                 Temp& tmp0,
66388                                 Temp& tmp1,
66389                                 Temp& tmp2);
66390
66391} // namespace Parma_Polyhedra_Library
66392
66393/* Automatically generated from PPL source file ../src/OR_Matrix_inlines.hh line 1. */
66394/* OR_Matrix class implementation: inline functions.
66395*/
66396
66397
66398/* Automatically generated from PPL source file ../src/OR_Matrix_inlines.hh line 33. */
66399#include <algorithm>
66400
66401namespace Parma_Polyhedra_Library {
66402
66403template <typename T>
66404inline dimension_type
66405OR_Matrix<T>::row_first_element_index(const dimension_type k) {
66406  return ((k + 1)*(k + 1))/2;
66407}
66408
66409template <typename T>
66410inline dimension_type
66411OR_Matrix<T>::row_size(const dimension_type k) {
66412  return k + 2 - k % 2;
66413}
66414
66415#if PPL_OR_MATRIX_EXTRA_DEBUG
66416
66417template <typename T>
66418template <typename U>
66419inline dimension_type
66420OR_Matrix<T>::Pseudo_Row<U>::size() const {
66421  return size_;
66422}
66423
66424#endif // PPL_OR_MATRIX_EXTRA_DEBUG
66425
66426template <typename T>
66427template <typename U>
66428inline
66429OR_Matrix<T>::Pseudo_Row<U>::Pseudo_Row()
66430  : first(0)
66431#if PPL_OR_MATRIX_EXTRA_DEBUG
66432  , size_(0)
66433#endif
66434{
66435}
66436
66437template <typename T>
66438template <typename U>
66439inline
66440OR_Matrix<T>::Pseudo_Row<U>::Pseudo_Row(U& y
66441#if PPL_OR_MATRIX_EXTRA_DEBUG
66442                , dimension_type s
66443#endif
66444                )
66445  : first(&y)
66446#if PPL_OR_MATRIX_EXTRA_DEBUG
66447  , size_(s)
66448#endif
66449{
66450}
66451
66452template <typename T>
66453template <typename U>
66454template <typename V>
66455inline
66456OR_Matrix<T>::Pseudo_Row<U>::Pseudo_Row(const Pseudo_Row<V>& y)
66457  : first(y.first)
66458#if PPL_OR_MATRIX_EXTRA_DEBUG
66459    , size_(y.size_)
66460#endif
66461{
66462}
66463
66464template <typename T>
66465template <typename U>
66466inline OR_Matrix<T>::Pseudo_Row<U>&
66467OR_Matrix<T>::Pseudo_Row<U>::operator=(const Pseudo_Row& y) {
66468  first = y.first;
66469#if PPL_OR_MATRIX_EXTRA_DEBUG
66470  size_ = y.size_;
66471#endif
66472  return *this;
66473}
66474
66475template <typename T>
66476template <typename U>
66477inline
66478OR_Matrix<T>::Pseudo_Row<U>::~Pseudo_Row() {
66479}
66480
66481template <typename T>
66482template <typename U>
66483inline U&
66484OR_Matrix<T>::Pseudo_Row<U>::operator[](const dimension_type k) const {
66485#if PPL_OR_MATRIX_EXTRA_DEBUG
66486  PPL_ASSERT(k < size_);
66487#endif
66488  return *(first + k);
66489}
66490
66491template <typename T>
66492template <typename U>
66493inline
66494OR_Matrix<T>::any_row_iterator<U>
66495::any_row_iterator(const dimension_type n_rows)
66496  : value(),
66497    e(n_rows)
66498    // Field `i' is intentionally not initialized here.
66499{
66500#if PPL_OR_MATRIX_EXTRA_DEBUG
66501  // Turn `value' into a valid object.
66502  value.size_ = OR_Matrix::row_size(e);
66503#endif
66504}
66505
66506template <typename T>
66507template <typename U>
66508inline
66509OR_Matrix<T>::any_row_iterator<U>::any_row_iterator(U& base)
66510  :  value(base
66511#if PPL_OR_MATRIX_EXTRA_DEBUG
66512           , OR_Matrix<T>::row_size(0)
66513#endif
66514           ),
66515     e(0),
66516     i(0) {
66517}
66518
66519template <typename T>
66520template <typename U>
66521template <typename V>
66522inline
66523OR_Matrix<T>::any_row_iterator<U>
66524::any_row_iterator(const any_row_iterator<V>& y)
66525  : value(y.value),
66526    e(y.e),
66527    i(y.i) {
66528}
66529
66530template <typename T>
66531template <typename U>
66532template <typename V>
66533inline typename OR_Matrix<T>::template any_row_iterator<U>&
66534OR_Matrix<T>::any_row_iterator<U>::operator=(const any_row_iterator<V>& y) {
66535  value = y.value;
66536  e = y.e;
66537  i = y.i;
66538  return *this;
66539}
66540
66541template <typename T>
66542template <typename U>
66543inline typename OR_Matrix<T>::template any_row_iterator<U>::reference
66544OR_Matrix<T>::any_row_iterator<U>::operator*() const {
66545  return value;
66546}
66547
66548template <typename T>
66549template <typename U>
66550inline typename OR_Matrix<T>::template any_row_iterator<U>::pointer
66551OR_Matrix<T>::any_row_iterator<U>::operator->() const {
66552  return &value;
66553}
66554
66555template <typename T>
66556template <typename U>
66557inline typename OR_Matrix<T>::template any_row_iterator<U>&
66558OR_Matrix<T>::any_row_iterator<U>::operator++() {
66559  ++e;
66560  dimension_type increment = e;
66561  if (e % 2 != 0) {
66562    ++increment;
66563  }
66564#if PPL_OR_MATRIX_EXTRA_DEBUG
66565  else {
66566    value.size_ += 2;
66567  }
66568#endif
66569  i += increment;
66570  value.first += increment;
66571  return *this;
66572}
66573
66574template <typename T>
66575template <typename U>
66576inline typename OR_Matrix<T>::template any_row_iterator<U>
66577OR_Matrix<T>::any_row_iterator<U>::operator++(int) {
66578  any_row_iterator old = *this;
66579  ++(*this);
66580  return old;
66581}
66582
66583template <typename T>
66584template <typename U>
66585inline typename OR_Matrix<T>::template any_row_iterator<U>&
66586OR_Matrix<T>::any_row_iterator<U>::operator--() {
66587  dimension_type decrement = e + 1;
66588  --e;
66589  if (e % 2 != 0) {
66590    ++decrement;
66591#if PPL_OR_MATRIX_EXTRA_DEBUG
66592    value.size_ -= 2;
66593#endif
66594  }
66595  i -= decrement;
66596  value.first -= decrement;
66597  return *this;
66598}
66599
66600template <typename T>
66601template <typename U>
66602inline typename OR_Matrix<T>::template any_row_iterator<U>
66603OR_Matrix<T>::any_row_iterator<U>::operator--(int) {
66604  any_row_iterator old = *this;
66605  --(*this);
66606  return old;
66607}
66608
66609template <typename T>
66610template <typename U>
66611inline typename OR_Matrix<T>::template any_row_iterator<U>&
66612OR_Matrix<T>::any_row_iterator<U>::operator+=(const difference_type m) {
66613  difference_type e_dt = static_cast<difference_type>(e);
66614  difference_type i_dt = static_cast<difference_type>(i);
66615  difference_type increment = m + (m * m) / 2 + m * e_dt;
66616  if (e_dt % 2 == 0 && m % 2 != 0) {
66617    ++increment;
66618  }
66619  e_dt += m;
66620  i_dt += increment;
66621  e = static_cast<dimension_type>(e_dt);
66622  i = static_cast<dimension_type>(i_dt);
66623  value.first += increment;
66624#if PPL_OR_MATRIX_EXTRA_DEBUG
66625  difference_type value_size_dt = static_cast<difference_type>(value.size_);
66626  value_size_dt += (m - m % 2);
66627  value.size_ = static_cast<dimension_type>(value_size_dt);
66628#endif
66629  return *this;
66630}
66631
66632template <typename T>
66633template <typename U>
66634template <typename Unsigned>
66635inline typename
66636Enable_If<(static_cast<Unsigned>(-1) > 0),
66637            typename OR_Matrix<T>::template any_row_iterator<U>& >::type
66638OR_Matrix<T>::any_row_iterator<U>::operator+=(Unsigned m) {
66639  dimension_type n = m;
66640  dimension_type increment = n + (n*n)/2 + n*e;
66641  if (e % 2 == 0 && n % 2 != 0) {
66642    ++increment;
66643  }
66644  e += n;
66645  i += increment;
66646  value.first += increment;
66647#if PPL_OR_MATRIX_EXTRA_DEBUG
66648  value.size_ = value.size_ + n - n % 2;
66649#endif
66650  return *this;
66651}
66652
66653template <typename T>
66654template <typename U>
66655inline typename OR_Matrix<T>::template any_row_iterator<U>&
66656OR_Matrix<T>::any_row_iterator<U>::operator-=(difference_type m) {
66657  return *this += -m;
66658}
66659
66660template <typename T>
66661template <typename U>
66662inline typename OR_Matrix<T>::template any_row_iterator<U>::difference_type
66663OR_Matrix<T>::any_row_iterator<U>::operator-(const any_row_iterator& y) const {
66664  return e - y.e;
66665}
66666
66667template <typename T>
66668template <typename U>
66669inline typename OR_Matrix<T>::template any_row_iterator<U>
66670OR_Matrix<T>::any_row_iterator<U>::operator+(difference_type m) const {
66671  any_row_iterator r = *this;
66672  r += m;
66673  return r;
66674}
66675
66676template <typename T>
66677template <typename U>
66678template <typename Unsigned>
66679inline typename
66680Enable_If<(static_cast<Unsigned>(-1) > 0),
66681            typename OR_Matrix<T>::template any_row_iterator<U> >::type
66682OR_Matrix<T>::any_row_iterator<U>::operator+(Unsigned m) const {
66683  any_row_iterator r = *this;
66684  r += m;
66685  return r;
66686}
66687
66688template <typename T>
66689template <typename U>
66690inline typename OR_Matrix<T>::template any_row_iterator<U>
66691OR_Matrix<T>::any_row_iterator<U>::operator-(const difference_type m) const {
66692  any_row_iterator r = *this;
66693  r -= m;
66694  return r;
66695}
66696
66697template <typename T>
66698template <typename U>
66699inline bool
66700OR_Matrix<T>::any_row_iterator<U>
66701::operator==(const any_row_iterator& y) const {
66702  return e == y.e;
66703}
66704
66705template <typename T>
66706template <typename U>
66707inline bool
66708OR_Matrix<T>::any_row_iterator<U>
66709::operator!=(const any_row_iterator& y) const {
66710  return e != y.e;
66711}
66712
66713template <typename T>
66714template <typename U>
66715inline bool
66716OR_Matrix<T>::any_row_iterator<U>::operator<(const any_row_iterator& y) const {
66717  return e < y.e;
66718}
66719
66720template <typename T>
66721template <typename U>
66722inline bool
66723OR_Matrix<T>::any_row_iterator<U>
66724::operator<=(const any_row_iterator& y) const {
66725  return e <= y.e;
66726}
66727
66728template <typename T>
66729template <typename U>
66730inline bool
66731OR_Matrix<T>::any_row_iterator<U>::operator>(const any_row_iterator& y) const {
66732  return e > y.e;
66733}
66734
66735template <typename T>
66736template <typename U>
66737inline bool
66738OR_Matrix<T>::any_row_iterator<U>
66739::operator>=(const any_row_iterator& y) const {
66740  return e >= y.e;
66741}
66742
66743template <typename T>
66744template <typename U>
66745inline dimension_type
66746OR_Matrix<T>::any_row_iterator<U>::row_size() const {
66747  return OR_Matrix::row_size(e);
66748}
66749
66750template <typename T>
66751template <typename U>
66752inline dimension_type
66753OR_Matrix<T>::any_row_iterator<U>::index() const {
66754  return e;
66755}
66756
66757template <typename T>
66758inline typename OR_Matrix<T>::row_iterator
66759OR_Matrix<T>::row_begin() {
66760  return num_rows() == 0 ? row_iterator(0) : row_iterator(vec[0]);
66761}
66762
66763template <typename T>
66764inline typename OR_Matrix<T>::row_iterator
66765OR_Matrix<T>::row_end() {
66766  return row_iterator(num_rows());
66767}
66768
66769template <typename T>
66770inline typename OR_Matrix<T>::const_row_iterator
66771OR_Matrix<T>::row_begin() const {
66772  return num_rows() == 0 ? const_row_iterator(0) : const_row_iterator(vec[0]);
66773}
66774
66775template <typename T>
66776inline typename OR_Matrix<T>::const_row_iterator
66777OR_Matrix<T>::row_end() const {
66778  return const_row_iterator(num_rows());
66779}
66780
66781template <typename T>
66782inline typename OR_Matrix<T>::element_iterator
66783OR_Matrix<T>::element_begin() {
66784  return vec.begin();
66785}
66786
66787template <typename T>
66788inline typename OR_Matrix<T>::element_iterator
66789OR_Matrix<T>::element_end() {
66790  return vec.end();
66791}
66792
66793template <typename T>
66794inline typename OR_Matrix<T>::const_element_iterator
66795OR_Matrix<T>::element_begin() const {
66796  return vec.begin();
66797}
66798
66799template <typename T>
66800inline typename OR_Matrix<T>::const_element_iterator
66801OR_Matrix<T>::element_end() const {
66802  return vec.end();
66803}
66804
66805template <typename T>
66806inline void
66807OR_Matrix<T>::m_swap(OR_Matrix& y) {
66808  using std::swap;
66809  swap(vec, y.vec);
66810  swap(space_dim, y.space_dim);
66811  swap(vec_capacity, y.vec_capacity);
66812}
66813
66814#ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
66815//! Returns the integer square root of \p x.
66816#endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
66817inline dimension_type
66818isqrt(dimension_type x) {
66819  dimension_type r = 0;
66820  const dimension_type FIRST_BIT_MASK = 0x40000000U;
66821  for (dimension_type t = FIRST_BIT_MASK; t != 0; t >>= 2) {
66822    const dimension_type s = r + t;
66823    if (s <= x) {
66824      x -= s;
66825      r = s + t;
66826    }
66827    r >>= 1;
66828  }
66829  return r;
66830}
66831
66832template <typename T>
66833inline dimension_type
66834OR_Matrix<T>::max_num_rows() {
66835  // Compute the maximum number of rows that are contained in a DB_Row
66836  // that allocates a pseudo-triangular matrix.
66837  const dimension_type k = isqrt(2*DB_Row<T>::max_size() + 1);
66838  return (k - 1) - (k - 1) % 2;
66839}
66840
66841template <typename T>
66842inline memory_size_type
66843OR_Matrix<T>::total_memory_in_bytes() const {
66844  return sizeof(*this) + external_memory_in_bytes();
66845}
66846
66847template <typename T>
66848inline
66849OR_Matrix<T>::OR_Matrix(const dimension_type num_dimensions)
66850  : vec(2*num_dimensions*(num_dimensions + 1)),
66851    space_dim(num_dimensions),
66852    vec_capacity(vec.size()) {
66853}
66854
66855template <typename T>
66856inline
66857OR_Matrix<T>::~OR_Matrix() {
66858}
66859
66860template <typename T>
66861inline typename OR_Matrix<T>::row_reference_type
66862OR_Matrix<T>::operator[](dimension_type k) {
66863  return row_reference_type(vec[row_first_element_index(k)]
66864#if PPL_OR_MATRIX_EXTRA_DEBUG
66865                            , row_size(k)
66866#endif
66867                            );
66868}
66869
66870template <typename T>
66871inline typename OR_Matrix<T>::const_row_reference_type
66872OR_Matrix<T>::operator[](dimension_type k) const {
66873  return const_row_reference_type(vec[row_first_element_index(k)]
66874#if PPL_OR_MATRIX_EXTRA_DEBUG
66875                                  , row_size(k)
66876#endif
66877                                  );
66878}
66879
66880template <typename T>
66881inline dimension_type
66882OR_Matrix<T>::space_dimension() const {
66883  return space_dim;
66884}
66885
66886template <typename T>
66887inline dimension_type
66888OR_Matrix<T>::num_rows() const {
66889  return 2*space_dimension();
66890}
66891
66892template <typename T>
66893inline void
66894OR_Matrix<T>::clear() {
66895  OR_Matrix<T>(0).m_swap(*this);
66896}
66897
66898#ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
66899/*! \relates OR_Matrix */
66900#endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
66901template <typename T>
66902inline bool
66903operator==(const OR_Matrix<T>& x, const OR_Matrix<T>& y) {
66904  return x.space_dim == y.space_dim && x.vec == y.vec;
66905}
66906
66907#ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
66908/*! \relates OR_Matrix */
66909#endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
66910template <typename T>
66911inline bool
66912operator!=(const OR_Matrix<T>& x, const OR_Matrix<T>& y) {
66913  return !(x == y);
66914}
66915
66916template <typename T>
66917inline
66918OR_Matrix<T>::OR_Matrix(const OR_Matrix& y)
66919  : vec(y.vec),
66920    space_dim(y.space_dim),
66921    vec_capacity(compute_capacity(y.vec.size(),
66922                                  DB_Row<T>::max_size())) {
66923}
66924
66925template <typename T>
66926template <typename U>
66927inline
66928OR_Matrix<T>::OR_Matrix(const OR_Matrix<U>& y)
66929  : vec(),
66930    space_dim(y.space_dim),
66931    vec_capacity(compute_capacity(y.vec.size(),
66932                                  DB_Row<T>::max_size())) {
66933  vec.construct_upward_approximation(y.vec, vec_capacity);
66934  PPL_ASSERT(OK());
66935}
66936
66937template <typename T>
66938inline OR_Matrix<T>&
66939OR_Matrix<T>::operator=(const OR_Matrix& y) {
66940  vec = y.vec;
66941  space_dim = y.space_dim;
66942  vec_capacity = compute_capacity(y.vec.size(), DB_Row<T>::max_size());
66943  return *this;
66944}
66945
66946template <typename T>
66947inline void
66948OR_Matrix<T>::grow(const dimension_type new_dim) {
66949  PPL_ASSERT(new_dim >= space_dim);
66950  if (new_dim > space_dim) {
66951    const dimension_type new_size = 2*new_dim*(new_dim + 1);
66952    if (new_size <= vec_capacity) {
66953      // We can recycle the old vec.
66954      vec.expand_within_capacity(new_size);
66955      space_dim = new_dim;
66956    }
66957    else {
66958      // We cannot recycle the old vec.
66959      OR_Matrix<T> new_matrix(new_dim);
66960      element_iterator j = new_matrix.element_begin();
66961      for (element_iterator i = element_begin(),
66962             mend = element_end(); i != mend; ++i, ++j) {
66963        assign_or_swap(*j, *i);
66964      }
66965      m_swap(new_matrix);
66966    }
66967  }
66968}
66969
66970template <typename T>
66971inline void
66972OR_Matrix<T>::shrink(const dimension_type new_dim) {
66973  PPL_ASSERT(new_dim <= space_dim);
66974  const dimension_type new_size = 2*new_dim*(new_dim + 1);
66975  vec.shrink(new_size);
66976  space_dim = new_dim;
66977}
66978
66979template <typename T>
66980inline void
66981OR_Matrix<T>::resize_no_copy(const dimension_type new_dim) {
66982  if (new_dim > space_dim) {
66983    const dimension_type new_size = 2*new_dim*(new_dim + 1);
66984    if (new_size <= vec_capacity) {
66985      // We can recycle the old vec.
66986      vec.expand_within_capacity(new_size);
66987      space_dim = new_dim;
66988    }
66989    else {
66990      // We cannot recycle the old vec.
66991      OR_Matrix<T> new_matrix(new_dim);
66992      m_swap(new_matrix);
66993    }
66994  }
66995  else if (new_dim < space_dim) {
66996    shrink(new_dim);
66997  }
66998}
66999
67000#ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
67001/*! \relates OR_Matrix */
67002#endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
67003template <typename Specialization, typename Temp, typename To, typename T>
67004inline bool
67005l_m_distance_assign(Checked_Number<To, Extended_Number_Policy>& r,
67006                    const OR_Matrix<T>& x,
67007                    const OR_Matrix<T>& y,
67008                    const Rounding_Dir dir,
67009                    Temp& tmp0,
67010                    Temp& tmp1,
67011                    Temp& tmp2) {
67012  if (x.num_rows() != y.num_rows()) {
67013    return false;
67014  }
67015  assign_r(tmp0, 0, ROUND_NOT_NEEDED);
67016  for (typename OR_Matrix<T>::const_element_iterator
67017         i = x.element_begin(), j = y.element_begin(),
67018         mat_end = x.element_end(); i != mat_end; ++i, ++j) {
67019    const T& x_i = *i;
67020    const T& y_i = *j;
67021    if (is_plus_infinity(x_i)) {
67022      if (is_plus_infinity(y_i)) {
67023        continue;
67024      }
67025      else {
67026      pinf:
67027        assign_r(r, PLUS_INFINITY, ROUND_NOT_NEEDED);
67028        return true;
67029      }
67030    }
67031    else if (is_plus_infinity(y_i)) {
67032      goto pinf;
67033    }
67034    const Temp* tmp1p;
67035    const Temp* tmp2p;
67036    if (x_i > y_i) {
67037      maybe_assign(tmp1p, tmp1, x_i, dir);
67038      maybe_assign(tmp2p, tmp2, y_i, inverse(dir));
67039    }
67040    else {
67041      maybe_assign(tmp1p, tmp1, y_i, dir);
67042      maybe_assign(tmp2p, tmp2, x_i, inverse(dir));
67043    }
67044    sub_assign_r(tmp1, *tmp1p, *tmp2p, dir);
67045    PPL_ASSERT(sgn(tmp1) >= 0);
67046    Specialization::combine(tmp0, tmp1, dir);
67047  }
67048
67049  Specialization::finalize(tmp0, dir);
67050  assign_r(r, tmp0, dir);
67051  return true;
67052}
67053
67054
67055#ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
67056/*! \relates OR_Matrix */
67057#endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
67058template <typename Temp, typename To, typename T>
67059inline bool
67060rectilinear_distance_assign(Checked_Number<To, Extended_Number_Policy>& r,
67061                            const OR_Matrix<T>& x,
67062                            const OR_Matrix<T>& y,
67063                            const Rounding_Dir dir,
67064                            Temp& tmp0,
67065                            Temp& tmp1,
67066                            Temp& tmp2) {
67067  return
67068    l_m_distance_assign<Rectilinear_Distance_Specialization<Temp> >(r, x, y,
67069                                                                    dir,
67070                                                                    tmp0,
67071                                                                    tmp1,
67072                                                                    tmp2);
67073}
67074
67075#ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
67076/*! \relates OR_Matrix */
67077#endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
67078template <typename Temp, typename To, typename T>
67079inline bool
67080euclidean_distance_assign(Checked_Number<To, Extended_Number_Policy>& r,
67081                          const OR_Matrix<T>& x,
67082                          const OR_Matrix<T>& y,
67083                          const Rounding_Dir dir,
67084                          Temp& tmp0,
67085                          Temp& tmp1,
67086                          Temp& tmp2) {
67087  return
67088    l_m_distance_assign<Euclidean_Distance_Specialization<Temp> >(r, x, y,
67089                                                                  dir,
67090                                                                  tmp0,
67091                                                                  tmp1,
67092                                                                  tmp2);
67093}
67094
67095#ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
67096/*! \relates OR_Matrix */
67097#endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
67098template <typename Temp, typename To, typename T>
67099inline bool
67100l_infinity_distance_assign(Checked_Number<To, Extended_Number_Policy>& r,
67101                           const OR_Matrix<T>& x,
67102                           const OR_Matrix<T>& y,
67103                           const Rounding_Dir dir,
67104                           Temp& tmp0,
67105                           Temp& tmp1,
67106                           Temp& tmp2) {
67107  return
67108    l_m_distance_assign<L_Infinity_Distance_Specialization<Temp> >(r, x, y,
67109                                                                   dir,
67110                                                                   tmp0,
67111                                                                   tmp1,
67112                                                                   tmp2);
67113}
67114
67115/*! \relates OR_Matrix */
67116template <typename T>
67117inline void
67118swap(OR_Matrix<T>& x, OR_Matrix<T>& y) {
67119  x.m_swap(y);
67120}
67121
67122} // namespace Parma_Polyhedra_Library
67123
67124/* Automatically generated from PPL source file ../src/OR_Matrix_templates.hh line 1. */
67125/* OR_Matrix class implementation: non-inline template functions.
67126*/
67127
67128
67129#include <iostream>
67130
67131namespace Parma_Polyhedra_Library {
67132
67133template <typename T>
67134memory_size_type
67135OR_Matrix<T>::external_memory_in_bytes() const{
67136  return vec.external_memory_in_bytes();
67137}
67138
67139template <typename T>
67140bool
67141OR_Matrix<T>::OK() const {
67142#ifndef NDEBUG
67143  using std::endl;
67144  using std::cerr;
67145#endif
67146  // The right number of cells should be in use.
67147  const dimension_type dim = space_dimension();
67148  if (vec.size() != 2*dim*(dim + 1)) {
67149#ifndef NDEBUG
67150    cerr << "OR_Matrix has a wrong number of cells:\n"
67151         << "vec.size() is " << vec.size()
67152         << ", expected size is " << (2*dim*(dim+1)) << "!\n";
67153#endif
67154    return false;
67155  }
67156
67157  // The underlying DB_Row should be OK.
67158  if (!vec.OK(vec.size(), vec_capacity)) {
67159    return false;
67160  }
67161
67162  // All checks passed.
67163  return true;
67164}
67165
67166template <typename T>
67167void
67168OR_Matrix<T>::ascii_dump(std::ostream& s) const {
67169  const OR_Matrix<T>& x = *this;
67170  const char separator = ' ';
67171  dimension_type space = x.space_dimension();
67172  s << space << separator << "\n";
67173  for (const_row_iterator i = x.row_begin(),
67174         x_row_end = x.row_end(); i != x_row_end; ++i) {
67175    const_row_reference_type r = *i;
67176    dimension_type rs = i.row_size();
67177    for (dimension_type j = 0; j < rs; ++j) {
67178      using namespace IO_Operators;
67179      s << r[j] << separator;
67180    }
67181    s << "\n";
67182  }
67183}
67184
67185PPL_OUTPUT_TEMPLATE_DEFINITIONS(T, OR_Matrix<T>)
67186
67187template <typename T>
67188bool
67189OR_Matrix<T>::ascii_load(std::istream& s) {
67190  dimension_type space;
67191  if (!(s >> space)) {
67192    return false;
67193  }
67194  resize_no_copy(space);
67195  for (row_iterator i = row_begin(),
67196         this_row_end = row_end(); i != this_row_end; ++i) {
67197    row_reference_type r_i = *i;
67198    const dimension_type rs = i.row_size();
67199    for (dimension_type j = 0; j < rs; ++j) {
67200      Result r = input(r_i[j], s, ROUND_CHECK);
67201      if (result_relation(r) != VR_EQ || is_minus_infinity(r_i[j])) {
67202        return false;
67203      }
67204    }
67205  }
67206  PPL_ASSERT(OK());
67207  return true;
67208}
67209
67210#ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
67211/*! \relates Parma_Polyhedra_Library::OR_Matrix */
67212#endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
67213template <typename T>
67214std::ostream&
67215IO_Operators::operator<<(std::ostream& s, const OR_Matrix<T>& m) {
67216  for (typename OR_Matrix<T>::const_row_iterator m_iter = m.row_begin(),
67217         m_end = m.row_end(); m_iter != m_end; ++m_iter) {
67218    typename OR_Matrix<T>::const_row_reference_type r_m = *m_iter;
67219    const dimension_type mr_size = m_iter.row_size();
67220    for (dimension_type j = 0; j < mr_size; ++j) {
67221      s << r_m[j] << " ";
67222    }
67223    s << "\n";
67224  }
67225  return s;
67226}
67227
67228} // namespace Parma_Polyhedra_Library
67229
67230/* Automatically generated from PPL source file ../src/OR_Matrix_defs.hh line 609. */
67231
67232/* Automatically generated from PPL source file ../src/Octagonal_Shape_defs.hh line 50. */
67233#include <vector>
67234#include <cstddef>
67235#include <climits>
67236#include <iosfwd>
67237
67238namespace Parma_Polyhedra_Library {
67239
67240namespace IO_Operators {
67241
67242//! Output operator.
67243/*! \relates Parma_Polyhedra_Library::Octagonal_Shape
67244  Writes a textual representation of \p oct on \p s:
67245  <CODE>false</CODE> is written if \p oct is an empty polyhedron;
67246  <CODE>true</CODE> is written if \p oct is a universe polyhedron;
67247  a system of constraints defining \p oct is written otherwise,
67248  all constraints separated by ", ".
67249*/
67250template <typename T>
67251std::ostream&
67252operator<<(std::ostream& s, const Octagonal_Shape<T>& oct);
67253
67254} // namespace IO_Operators
67255
67256//! Swaps \p x with \p y.
67257/*! \relates Octagonal_Shape */
67258template <typename T>
67259void swap(Octagonal_Shape<T>& x, Octagonal_Shape<T>& y);
67260
67261/*! \brief
67262  Returns <CODE>true</CODE> if and only if \p x and \p y are the same octagon.
67263
67264  \relates Octagonal_Shape
67265  Note that \p x and \p y may be dimension-incompatible shapes:
67266  in this case, the value <CODE>false</CODE> is returned.
67267*/
67268template <typename T>
67269bool operator==(const Octagonal_Shape<T>& x, const Octagonal_Shape<T>& y);
67270
67271/*! \brief
67272  Returns <CODE>true</CODE> if and only if \p x and \p y are different shapes.
67273
67274  \relates Octagonal_Shape
67275  Note that \p x and \p y may be dimension-incompatible shapes:
67276  in this case, the value <CODE>true</CODE> is returned.
67277*/
67278template <typename T>
67279bool operator!=(const Octagonal_Shape<T>& x, const Octagonal_Shape<T>& y);
67280
67281//! Computes the rectilinear (or Manhattan) distance between \p x and \p y.
67282/*! \relates Octagonal_Shape
67283  If the rectilinear distance between \p x and \p y is defined,
67284  stores an approximation of it into \p r and returns <CODE>true</CODE>;
67285  returns <CODE>false</CODE> otherwise.
67286
67287  The direction of the approximation is specified by \p dir.
67288
67289  All computations are performed using variables of type
67290  <CODE>Checked_Number\<To, Extended_Number_Policy\></CODE>.
67291*/
67292template <typename To, typename T>
67293bool rectilinear_distance_assign(Checked_Number<To, Extended_Number_Policy>& r,
67294                                 const Octagonal_Shape<T>& x,
67295                                 const Octagonal_Shape<T>& y,
67296                                 Rounding_Dir dir);
67297
67298//! Computes the rectilinear (or Manhattan) distance between \p x and \p y.
67299/*! \relates Octagonal_Shape
67300  If the rectilinear distance between \p x and \p y is defined,
67301  stores an approximation of it into \p r and returns <CODE>true</CODE>;
67302  returns <CODE>false</CODE> otherwise.
67303
67304  The direction of the approximation is specified by \p dir.
67305
67306  All computations are performed using variables of type
67307  <CODE>Checked_Number\<Temp, Extended_Number_Policy\></CODE>.
67308*/
67309template <typename Temp, typename To, typename T>
67310bool rectilinear_distance_assign(Checked_Number<To, Extended_Number_Policy>& r,
67311                                 const Octagonal_Shape<T>& x,
67312                                 const Octagonal_Shape<T>& y,
67313                                 Rounding_Dir dir);
67314
67315//! Computes the rectilinear (or Manhattan) distance between \p x and \p y.
67316/*! \relates Octagonal_Shape
67317  If the rectilinear distance between \p x and \p y is defined,
67318  stores an approximation of it into \p r and returns <CODE>true</CODE>;
67319  returns <CODE>false</CODE> otherwise.
67320
67321  The direction of the approximation is specified by \p dir.
67322
67323  All computations are performed using the temporary variables
67324  \p tmp0, \p tmp1 and \p tmp2.
67325*/
67326template <typename Temp, typename To, typename T>
67327bool rectilinear_distance_assign(Checked_Number<To, Extended_Number_Policy>& r,
67328                                 const Octagonal_Shape<T>& x,
67329                                 const Octagonal_Shape<T>& y,
67330                                 Rounding_Dir dir,
67331                                 Temp& tmp0,
67332                                 Temp& tmp1,
67333                                 Temp& tmp2);
67334
67335//! Computes the euclidean distance between \p x and \p y.
67336/*! \relates Octagonal_Shape
67337  If the euclidean distance between \p x and \p y is defined,
67338  stores an approximation of it into \p r and returns <CODE>true</CODE>;
67339  returns <CODE>false</CODE> otherwise.
67340
67341  The direction of the approximation is specified by \p dir.
67342
67343  All computations are performed using variables of type
67344  <CODE>Checked_Number\<To, Extended_Number_Policy\></CODE>.
67345*/
67346template <typename To, typename T>
67347bool euclidean_distance_assign(Checked_Number<To, Extended_Number_Policy>& r,
67348                               const Octagonal_Shape<T>& x,
67349                               const Octagonal_Shape<T>& y,
67350                               Rounding_Dir dir);
67351
67352//! Computes the euclidean distance between \p x and \p y.
67353/*! \relates Octagonal_Shape
67354  If the euclidean distance between \p x and \p y is defined,
67355  stores an approximation of it into \p r and returns <CODE>true</CODE>;
67356  returns <CODE>false</CODE> otherwise.
67357
67358  The direction of the approximation is specified by \p dir.
67359
67360  All computations are performed using variables of type
67361  <CODE>Checked_Number\<Temp, Extended_Number_Policy\></CODE>.
67362*/
67363template <typename Temp, typename To, typename T>
67364bool euclidean_distance_assign(Checked_Number<To, Extended_Number_Policy>& r,
67365                               const Octagonal_Shape<T>& x,
67366                               const Octagonal_Shape<T>& y,
67367                               Rounding_Dir dir);
67368
67369//! Computes the euclidean distance between \p x and \p y.
67370/*! \relates Octagonal_Shape
67371  If the euclidean distance between \p x and \p y is defined,
67372  stores an approximation of it into \p r and returns <CODE>true</CODE>;
67373  returns <CODE>false</CODE> otherwise.
67374
67375  The direction of the approximation is specified by \p dir.
67376
67377  All computations are performed using the temporary variables
67378  \p tmp0, \p tmp1 and \p tmp2.
67379*/
67380template <typename Temp, typename To, typename T>
67381bool euclidean_distance_assign(Checked_Number<To, Extended_Number_Policy>& r,
67382                               const Octagonal_Shape<T>& x,
67383                               const Octagonal_Shape<T>& y,
67384                               Rounding_Dir dir,
67385                               Temp& tmp0,
67386                               Temp& tmp1,
67387                               Temp& tmp2);
67388
67389//! Computes the \f$L_\infty\f$ distance between \p x and \p y.
67390/*! \relates Octagonal_Shape
67391  If the \f$L_\infty\f$ distance between \p x and \p y is defined,
67392  stores an approximation of it into \p r and returns <CODE>true</CODE>;
67393  returns <CODE>false</CODE> otherwise.
67394
67395  The direction of the approximation is specified by \p dir.
67396
67397  All computations are performed using variables of type
67398  <CODE>Checked_Number\<To, Extended_Number_Policy\></CODE>.
67399*/
67400template <typename To, typename T>
67401bool l_infinity_distance_assign(Checked_Number<To, Extended_Number_Policy>& r,
67402                                const Octagonal_Shape<T>& x,
67403                                const Octagonal_Shape<T>& y,
67404                                Rounding_Dir dir);
67405
67406//! Computes the \f$L_\infty\f$ distance between \p x and \p y.
67407/*! \relates Octagonal_Shape
67408  If the \f$L_\infty\f$ distance between \p x and \p y is defined,
67409  stores an approximation of it into \p r and returns <CODE>true</CODE>;
67410  returns <CODE>false</CODE> otherwise.
67411
67412  The direction of the approximation is specified by \p dir.
67413
67414  All computations are performed using variables of type
67415  <CODE>Checked_Number\<Temp, Extended_Number_Policy\></CODE>.
67416*/
67417template <typename Temp, typename To, typename T>
67418bool l_infinity_distance_assign(Checked_Number<To, Extended_Number_Policy>& r,
67419                                const Octagonal_Shape<T>& x,
67420                                const Octagonal_Shape<T>& y,
67421                                Rounding_Dir dir);
67422
67423//! Computes the \f$L_\infty\f$ distance between \p x and \p y.
67424/*! \relates Octagonal_Shape
67425  If the \f$L_\infty\f$ distance between \p x and \p y is defined,
67426  stores an approximation of it into \p r and returns <CODE>true</CODE>;
67427  returns <CODE>false</CODE> otherwise.
67428
67429  The direction of the approximation is specified by \p dir.
67430
67431  All computations are performed using the temporary variables
67432  \p tmp0, \p tmp1 and \p tmp2.
67433*/
67434template <typename Temp, typename To, typename T>
67435bool l_infinity_distance_assign(Checked_Number<To, Extended_Number_Policy>& r,
67436                                const Octagonal_Shape<T>& x,
67437                                const Octagonal_Shape<T>& y,
67438                                Rounding_Dir dir,
67439                                Temp& tmp0,
67440                                Temp& tmp1,
67441                                Temp& tmp2);
67442
67443// This class contains some helper functions that need to be friends of
67444// Linear_Expression.
67445class Octagonal_Shape_Helper {
67446public:
67447  #ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
67448  //! Decodes the constraint \p c as an octagonal difference.
67449  /*! \relates Octagonal_Shape
67450    \return
67451    <CODE>true</CODE> if the constraint \p c is an octagonal difference;
67452    <CODE>false</CODE> otherwise.
67453
67454    \param c
67455    The constraint to be decoded.
67456
67457    \param c_space_dim
67458    The space dimension of the constraint \p c (it is <EM>assumed</EM>
67459    to match the actual space dimension of \p c).
67460
67461    \param c_num_vars
67462    If <CODE>true</CODE> is returned, then it will be set to the number
67463    of variables having a non-zero coefficient. The only legal values
67464    will therefore be 0, 1 and 2.
67465
67466    \param c_first_var
67467    If <CODE>true</CODE> is returned and if \p c_num_vars is not set to 0,
67468    then it will be set to the index of the first variable having
67469    a non-zero coefficient in \p c.
67470
67471    \param c_second_var
67472    If <CODE>true</CODE> is returned and if \p c_num_vars is set to 2,
67473    then it will be set to the index of the second variable having
67474    a non-zero coefficient in \p c.
67475
67476    \param c_coeff
67477    If <CODE>true</CODE> is returned and if \p c_num_vars is not set to 0,
67478    then it will be set to the value of the first non-zero coefficient
67479    in \p c.
67480
67481    \param c_term
67482    If <CODE>true</CODE> is returned and if \p c_num_vars is not set to 0,
67483    then it will be set to the right value of the inhomogeneous term
67484    of \p c.
67485  */
67486  #endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
67487  static bool extract_octagonal_difference(const Constraint& c,
67488                                           dimension_type c_space_dim,
67489                                           dimension_type& c_num_vars,
67490                                           dimension_type& c_first_var,
67491                                           dimension_type& c_second_var,
67492                                           Coefficient& c_coeff,
67493                                           Coefficient& c_term);
67494};
67495
67496} // namespace Parma_Polyhedra_Library
67497
67498//! An octagonal shape.
67499/*! \ingroup PPL_CXX_interface
67500  The class template Octagonal_Shape<T> allows for the efficient
67501  representation of a restricted kind of <EM>topologically closed</EM>
67502  convex polyhedra called <EM>octagonal shapes</EM> (OSs, for short).
67503  The name comes from the fact that, in a vector space of dimension 2,
67504  bounded OSs are polygons with at most eight sides.
67505  The closed affine half-spaces that characterize the OS can be expressed
67506  by constraints of the form
67507  \f[
67508    ax_i + bx_j \leq k
67509  \f]
67510  where \f$a, b \in \{-1, 0, 1\}\f$ and \f$k\f$ is a rational number,
67511  which are called <EM>octagonal constraints</EM>.
67512
67513  Based on the class template type parameter \p T, a family of extended
67514  numbers is built and used to approximate the inhomogeneous term of
67515  octagonal constraints. These extended numbers provide a representation
67516  for the value \f$+\infty\f$, as well as <EM>rounding-aware</EM>
67517  implementations for several arithmetic functions.
67518  The value of the type parameter \p T may be one of the following:
67519    - a bounded precision integer type (e.g., \c int32_t or \c int64_t);
67520    - a bounded precision floating point type (e.g., \c float or \c double);
67521    - an unbounded integer or rational type, as provided by GMP
67522      (i.e., \c mpz_class or \c mpq_class).
67523
67524  The user interface for OSs is meant to be as similar as possible to
67525  the one developed for the polyhedron class C_Polyhedron.
67526
67527  The OS domain <EM>optimally supports</EM>:
67528    - tautological and inconsistent constraints and congruences;
67529    - octagonal constraints;
67530    - non-proper congruences (i.e., equalities) that are expressible
67531      as octagonal constraints.
67532
67533  Depending on the method, using a constraint or congruence that is not
67534  optimally supported by the domain will either raise an exception or
67535  result in a (possibly non-optimal) upward approximation.
67536
67537  A constraint is octagonal if it has the form
67538    \f[
67539      \pm a_i x_i \pm a_j x_j \relsym b
67540    \f]
67541  where \f$\mathord{\relsym} \in \{ \leq, =, \geq \}\f$ and
67542  \f$a_i\f$, \f$a_j\f$, \f$b\f$ are integer coefficients such that
67543  \f$a_i = 0\f$, or \f$a_j = 0\f$, or \f$a_i = a_j\f$.
67544  The user is warned that the above octagonal Constraint object
67545  will be mapped into a \e correct and \e optimal approximation that,
67546  depending on the expressive power of the chosen template argument \p T,
67547  may loose some precision.
67548  Also note that strict constraints are not octagonal.
67549
67550  For instance, a Constraint object encoding \f$3x + 3y \leq 1\f$ will be
67551  approximated by:
67552    - \f$x + y \leq 1\f$,
67553      if \p T is a (bounded or unbounded) integer type;
67554    - \f$x + y \leq \frac{1}{3}\f$,
67555      if \p T is the unbounded rational type \c mpq_class;
67556    - \f$x + y \leq k\f$, where \f$k > \frac{1}{3}\f$,
67557      if \p T is a floating point type (having no exact representation
67558      for \f$\frac{1}{3}\f$).
67559
67560  On the other hand, depending from the context, a Constraint object
67561  encoding \f$3x - y \leq 1\f$ will be either upward approximated
67562  (e.g., by safely ignoring it) or it will cause an exception.
67563
67564  In the following examples it is assumed that the type argument \p T
67565  is one of the possible instances listed above and that variables
67566  \c x, \c y and \c z are defined (where they are used) as follows:
67567  \code
67568    Variable x(0);
67569    Variable y(1);
67570    Variable z(2);
67571  \endcode
67572
67573  \par Example 1
67574  The following code builds an OS corresponding to a cube in \f$\Rset^3\f$,
67575  given as a system of constraints:
67576  \code
67577    Constraint_System cs;
67578    cs.insert(x >= 0);
67579    cs.insert(x <= 3);
67580    cs.insert(y >= 0);
67581    cs.insert(y <= 3);
67582    cs.insert(z >= 0);
67583    cs.insert(z <= 3);
67584    Octagonal_Shape<T> oct(cs);
67585  \endcode
67586  In contrast, the following code will raise an exception,
67587  since constraints 7, 8, and 9 are not octagonal:
67588  \code
67589    Constraint_System cs;
67590    cs.insert(x >= 0);
67591    cs.insert(x <= 3);
67592    cs.insert(y >= 0);
67593    cs.insert(y <= 3);
67594    cs.insert(z >= 0);
67595    cs.insert(z <= 3);
67596    cs.insert(x - 3*y <= 5);    // (7)
67597    cs.insert(x - y + z <= 5);  // (8)
67598    cs.insert(x + y + z <= 5);  // (9)
67599    Octagonal_Shape<T> oct(cs);
67600  \endcode
67601*/
67602template <typename T>
67603class Parma_Polyhedra_Library::Octagonal_Shape {
67604private:
67605  /*! \brief
67606    The (extended) numeric type of the inhomogeneous term of
67607    the inequalities defining an OS.
67608  */
67609#ifndef NDEBUG
67610  typedef Checked_Number<T, Debug_WRD_Extended_Number_Policy> N;
67611#else
67612  typedef Checked_Number<T, WRD_Extended_Number_Policy> N;
67613#endif
67614
67615public:
67616
67617  //! The numeric base type upon which OSs are built.
67618  typedef T coefficient_type_base;
67619
67620  /*! \brief
67621    The (extended) numeric type of the inhomogeneous term of the
67622    inequalities defining an OS.
67623  */
67624  typedef N coefficient_type;
67625
67626  //! Returns the maximum space dimension that an OS can handle.
67627  static dimension_type max_space_dimension();
67628
67629  /*! \brief
67630    Returns false indicating that this domain cannot recycle constraints
67631  */
67632  static bool can_recycle_constraint_systems();
67633
67634  /*! \brief
67635    Returns false indicating that this domain cannot recycle congruences
67636  */
67637  static bool can_recycle_congruence_systems();
67638
67639  //! \name Constructors, Assignment, Swap and Destructor
67640  //@{
67641
67642  //! Builds an universe or empty OS of the specified space dimension.
67643  /*!
67644    \param num_dimensions
67645    The number of dimensions of the vector space enclosing the OS;
67646
67647    \param kind
67648    Specifies whether the universe or the empty OS has to be built.
67649  */
67650  explicit Octagonal_Shape(dimension_type num_dimensions = 0,
67651                           Degenerate_Element kind = UNIVERSE);
67652
67653  //! Ordinary copy constructor.
67654  /*!
67655    The complexity argument is ignored.
67656  */
67657  Octagonal_Shape(const Octagonal_Shape& y,
67658                  Complexity_Class complexity = ANY_COMPLEXITY);
67659
67660  //! Builds a conservative, upward approximation of \p y.
67661  /*!
67662    The complexity argument is ignored.
67663  */
67664  template <typename U>
67665  explicit Octagonal_Shape(const Octagonal_Shape<U>& y,
67666                           Complexity_Class complexity = ANY_COMPLEXITY);
67667
67668  //! Builds an OS from the system of constraints \p cs.
67669  /*!
67670    The OS inherits the space dimension of \p cs.
67671
67672    \param cs
67673    A system of octagonal constraints.
67674
67675    \exception std::invalid_argument
67676    Thrown if \p cs contains a constraint which is not optimally supported
67677    by the Octagonal shape domain.
67678  */
67679  explicit Octagonal_Shape(const Constraint_System& cs);
67680
67681  //! Builds an OS from a system of congruences.
67682  /*!
67683    The OS inherits the space dimension of \p cgs
67684
67685    \param cgs
67686    A system of congruences.
67687
67688    \exception std::invalid_argument
67689    Thrown if \p cgs contains a congruence which is not optimally supported
67690    by the Octagonal shape domain.
67691  */
67692  explicit Octagonal_Shape(const Congruence_System& cgs);
67693
67694  //! Builds an OS from the system of generators \p gs.
67695  /*!
67696    Builds the smallest OS containing the polyhedron defined by \p gs.
67697    The OS inherits the space dimension of \p gs.
67698
67699    \exception std::invalid_argument
67700    Thrown if the system of generators is not empty but has no points.
67701  */
67702  explicit Octagonal_Shape(const Generator_System& gs);
67703
67704  //! Builds an OS from the polyhedron \p ph.
67705  /*!
67706    Builds an OS containing \p ph using algorithms whose complexity
67707    does not exceed the one specified by \p complexity.  If
67708    \p complexity is \p ANY_COMPLEXITY, then the OS built is the
67709    smallest one containing \p ph.
67710  */
67711  explicit Octagonal_Shape(const Polyhedron& ph,
67712                           Complexity_Class complexity = ANY_COMPLEXITY);
67713
67714  //! Builds an OS out of a box.
67715  /*!
67716    The OS inherits the space dimension of the box.
67717    The built OS is the most precise OS that includes the box.
67718
67719    \param box
67720    The box representing the OS to be built.
67721
67722    \param complexity
67723    This argument is ignored as the algorithm used has
67724    polynomial complexity.
67725
67726    \exception std::length_error
67727    Thrown if the space dimension of \p box exceeds the maximum
67728    allowed space dimension.
67729  */
67730  template <typename Interval>
67731  explicit Octagonal_Shape(const Box<Interval>& box,
67732                           Complexity_Class complexity = ANY_COMPLEXITY);
67733
67734  //! Builds an OS that approximates a grid.
67735  /*!
67736    The OS inherits the space dimension of the grid.
67737    The built OS is the most precise OS that includes the grid.
67738
67739    \param grid
67740    The grid used to build the OS.
67741
67742    \param complexity
67743    This argument is ignored as the algorithm used has
67744    polynomial complexity.
67745
67746    \exception std::length_error
67747    Thrown if the space dimension of \p grid exceeds the maximum
67748    allowed space dimension.
67749  */
67750  explicit Octagonal_Shape(const Grid& grid,
67751                           Complexity_Class complexity = ANY_COMPLEXITY);
67752
67753  //! Builds an OS from a BD shape.
67754  /*!
67755    The OS inherits the space dimension of the BD shape.
67756    The built OS is the most precise OS that includes the BD shape.
67757
67758    \param bd
67759    The BD shape used to build the OS.
67760
67761    \param complexity
67762    This argument is ignored as the algorithm used has
67763    polynomial complexity.
67764
67765    \exception std::length_error
67766    Thrown if the space dimension of \p bd exceeds the maximum
67767    allowed space dimension.
67768  */
67769  template <typename U>
67770  explicit Octagonal_Shape(const BD_Shape<U>& bd,
67771                           Complexity_Class complexity = ANY_COMPLEXITY);
67772
67773  /*! \brief
67774    The assignment operator.
67775    (\p *this and \p y can be dimension-incompatible.)
67776  */
67777  Octagonal_Shape& operator=(const Octagonal_Shape& y);
67778
67779  /*! \brief
67780    Swaps \p *this with octagon \p y.
67781    (\p *this and \p y can be dimension-incompatible.)
67782  */
67783  void m_swap(Octagonal_Shape& y);
67784
67785  //! Destructor.
67786  ~Octagonal_Shape();
67787
67788  //@} Constructors, Assignment, Swap and Destructor
67789
67790  //! \name Member Functions that Do Not Modify the Octagonal_Shape
67791  //@{
67792
67793  //! Returns the dimension of the vector space enclosing \p *this.
67794  dimension_type space_dimension() const;
67795
67796  /*! \brief
67797    Returns \f$0\f$, if \p *this is empty; otherwise, returns the
67798    \ref Affine_Independence_and_Affine_Dimension "affine dimension"
67799    of \p *this.
67800  */
67801  dimension_type affine_dimension() const;
67802
67803  //! Returns the system of constraints defining \p *this.
67804  Constraint_System constraints() const;
67805
67806  //! Returns a minimized system of constraints defining \p *this.
67807  Constraint_System minimized_constraints() const;
67808
67809  //! Returns a system of (equality) congruences satisfied by \p *this.
67810  Congruence_System congruences() const;
67811
67812  /*! \brief
67813    Returns a minimal system of (equality) congruences
67814    satisfied by \p *this with the same affine dimension as \p *this.
67815  */
67816  Congruence_System minimized_congruences() const;
67817
67818  //! Returns <CODE>true</CODE> if and only if \p *this contains \p y.
67819  /*!
67820    \exception std::invalid_argument
67821    Thrown if \p *this and \p y are dimension-incompatible.
67822  */
67823  bool contains(const Octagonal_Shape& y) const;
67824
67825  //! Returns <CODE>true</CODE> if and only if \p *this strictly contains \p y.
67826  /*!
67827    \exception std::invalid_argument
67828    Thrown if \p *this and \p y are dimension-incompatible.
67829  */
67830  bool strictly_contains(const Octagonal_Shape& y) const;
67831
67832  //! Returns <CODE>true</CODE> if and only if \p *this and \p y are disjoint.
67833  /*!
67834    \exception std::invalid_argument
67835    Thrown if \p x and \p y are topology-incompatible or
67836    dimension-incompatible.
67837  */
67838  bool is_disjoint_from(const Octagonal_Shape& y) const;
67839
67840  /*! \brief
67841    Returns the relations holding between \p *this and the constraint \p c.
67842
67843    \exception std::invalid_argument
67844    Thrown if \p *this and constraint \p c are dimension-incompatible.
67845  */
67846  Poly_Con_Relation relation_with(const Constraint& c) const;
67847
67848  /*! \brief
67849    Returns the relations holding between \p *this and the congruence \p cg.
67850
67851    \exception std::invalid_argument
67852    Thrown if \p *this and \p cg are dimension-incompatible.
67853  */
67854  Poly_Con_Relation relation_with(const Congruence& cg) const;
67855
67856  /*! \brief
67857    Returns the relations holding between \p *this and the generator \p g.
67858
67859    \exception std::invalid_argument
67860    Thrown if \p *this and generator \p g are dimension-incompatible.
67861  */
67862  Poly_Gen_Relation relation_with(const Generator& g) const;
67863
67864  //! Returns <CODE>true</CODE> if and only if \p *this is an empty OS.
67865  bool is_empty() const;
67866
67867  //! Returns <CODE>true</CODE> if and only if \p *this is a universe OS.
67868  bool is_universe() const;
67869
67870  //! Returns <CODE>true</CODE> if and only if \p *this is discrete.
67871  bool is_discrete() const;
67872
67873  /*! \brief
67874    Returns <CODE>true</CODE> if and only if \p *this
67875    is a bounded OS.
67876  */
67877  bool is_bounded() const;
67878
67879  /*! \brief
67880    Returns <CODE>true</CODE> if and only if \p *this
67881    is a topologically closed subset of the vector space.
67882  */
67883  bool is_topologically_closed() const;
67884
67885  /*! \brief
67886    Returns <CODE>true</CODE> if and only if \p *this
67887    contains (at least) an integer point.
67888  */
67889  bool contains_integer_point() const;
67890
67891  /*! \brief
67892    Returns <CODE>true</CODE> if and only if \p var is constrained in
67893    \p *this.
67894
67895    \exception std::invalid_argument
67896    Thrown if \p var is not a space dimension of \p *this.
67897  */
67898  bool constrains(Variable var) const;
67899
67900  /*! \brief
67901    Returns <CODE>true</CODE> if and only if \p expr is
67902    bounded from above in \p *this.
67903
67904    \exception std::invalid_argument
67905    Thrown if \p expr and \p *this are dimension-incompatible.
67906  */
67907  bool bounds_from_above(const Linear_Expression& expr) const;
67908
67909  /*! \brief
67910    Returns <CODE>true</CODE> if and only if \p expr is
67911    bounded from below in \p *this.
67912
67913    \exception std::invalid_argument
67914    Thrown if \p expr and \p *this are dimension-incompatible.
67915  */
67916  bool bounds_from_below(const Linear_Expression& expr) const;
67917
67918  /*! \brief
67919    Returns <CODE>true</CODE> if and only if \p *this is not empty
67920    and \p expr is bounded from above in \p *this, in which case
67921    the supremum value is computed.
67922
67923    \param expr
67924    The linear expression to be maximized subject to \p *this;
67925
67926    \param sup_n
67927    The numerator of the supremum value;
67928
67929    \param sup_d
67930    The denominator of the supremum value;
67931
67932    \param maximum
67933    <CODE>true</CODE> if and only if the supremum is also the maximum value.
67934
67935    \exception std::invalid_argument
67936    Thrown if \p expr and \p *this are dimension-incompatible.
67937
67938    If \p *this is empty or \p expr is not bounded from above,
67939    <CODE>false</CODE> is returned and \p sup_n, \p sup_d
67940    and \p maximum are left untouched.
67941  */
67942  bool maximize(const Linear_Expression& expr,
67943                Coefficient& sup_n, Coefficient& sup_d, bool& maximum) const;
67944
67945  /*! \brief
67946    Returns <CODE>true</CODE> if and only if \p *this is not empty
67947    and \p expr is bounded from above in \p *this, in which case
67948    the supremum value and a point where \p expr reaches it are computed.
67949
67950    \param expr
67951    The linear expression to be maximized subject to \p *this;
67952
67953    \param sup_n
67954    The numerator of the supremum value;
67955
67956    \param sup_d
67957    The denominator of the supremum value;
67958
67959    \param maximum
67960    <CODE>true</CODE> if and only if the supremum is also the maximum value;
67961
67962    \param g
67963    When maximization succeeds, will be assigned the point or
67964    closure point where \p expr reaches its supremum value.
67965
67966    \exception std::invalid_argument
67967    Thrown if \p expr and \p *this are dimension-incompatible.
67968
67969    If \p *this is empty or \p expr is not bounded from above,
67970    <CODE>false</CODE> is returned and \p sup_n, \p sup_d, \p maximum
67971    and \p g are left untouched.
67972  */
67973  bool maximize(const Linear_Expression& expr,
67974                Coefficient& sup_n, Coefficient& sup_d, bool& maximum,
67975                Generator& g) const;
67976
67977  /*! \brief
67978    Returns <CODE>true</CODE> if and only if \p *this is not empty
67979    and \p expr is bounded from below in \p *this, in which case
67980    the infimum value is computed.
67981
67982    \param expr
67983    The linear expression to be minimized subject to \p *this;
67984
67985    \param inf_n
67986    The numerator of the infimum value;
67987
67988    \param inf_d
67989    The denominator of the infimum value;
67990
67991    \param minimum
67992    <CODE>true</CODE> if and only if the infimum is also the minimum value.
67993
67994    \exception std::invalid_argument
67995    Thrown if \p expr and \p *this are dimension-incompatible.
67996
67997    If \p *this is empty or \p expr is not bounded from below,
67998    <CODE>false</CODE> is returned and \p inf_n, \p inf_d
67999    and \p minimum are left untouched.
68000  */
68001  bool minimize(const Linear_Expression& expr,
68002                Coefficient& inf_n, Coefficient& inf_d, bool& minimum) const;
68003
68004  /*! \brief
68005    Returns <CODE>true</CODE> if and only if \p *this is not empty
68006    and \p expr is bounded from below in \p *this, in which case
68007    the infimum value and a point where \p expr reaches it are computed.
68008
68009    \param expr
68010    The linear expression to be minimized subject to \p *this;
68011
68012    \param inf_n
68013    The numerator of the infimum value;
68014
68015    \param inf_d
68016    The denominator of the infimum value;
68017
68018    \param minimum
68019    <CODE>true</CODE> if and only if the infimum is also the minimum value;
68020
68021    \param g
68022    When minimization succeeds, will be assigned a point or
68023    closure point where \p expr reaches its infimum value.
68024
68025    \exception std::invalid_argument
68026    Thrown if \p expr and \p *this are dimension-incompatible.
68027
68028    If \p *this is empty or \p expr is not bounded from below,
68029    <CODE>false</CODE> is returned and \p inf_n, \p inf_d, \p minimum
68030    and \p g are left untouched.
68031  */
68032  bool minimize(const Linear_Expression& expr,
68033                Coefficient& inf_n, Coefficient& inf_d, bool& minimum,
68034                Generator& g) const;
68035
68036  /*! \brief
68037    Returns <CODE>true</CODE> if and only if there exist a
68038    unique value \p val such that \p *this
68039    saturates the equality <CODE>expr = val</CODE>.
68040
68041    \param expr
68042    The linear expression for which the frequency is needed;
68043
68044    \param freq_n
68045    If <CODE>true</CODE> is returned, the value is set to \f$0\f$;
68046    Present for interface compatibility with class Grid, where
68047    the \ref Grid_Frequency "frequency" can have a non-zero value;
68048
68049    \param freq_d
68050    If <CODE>true</CODE> is returned, the value is set to \f$1\f$;
68051
68052    \param val_n
68053    The numerator of \p val;
68054
68055    \param val_d
68056    The denominator of \p val;
68057
68058    \exception std::invalid_argument
68059    Thrown if \p expr and \p *this are dimension-incompatible.
68060
68061    If <CODE>false</CODE> is returned, then \p freq_n, \p freq_d,
68062    \p val_n and \p val_d are left untouched.
68063  */
68064  bool frequency(const Linear_Expression& expr,
68065                 Coefficient& freq_n, Coefficient& freq_d,
68066                 Coefficient& val_n, Coefficient& val_d) const;
68067
68068  //! Checks if all the invariants are satisfied.
68069  bool OK() const;
68070
68071  //@} Member Functions that Do Not Modify the Octagonal_Shape
68072
68073  //! \name Space-Dimension Preserving Member Functions that May Modify the Octagonal_Shape
68074  //@{
68075
68076  /*! \brief
68077    Adds a copy of constraint \p c to the system of constraints
68078    defining \p *this.
68079
68080    \param c
68081    The constraint to be added.
68082
68083    \exception std::invalid_argument
68084    Thrown if \p *this and constraint \p c are dimension-incompatible,
68085    or \p c is not optimally supported by the OS domain.
68086  */
68087  void add_constraint(const Constraint& c);
68088
68089  /*! \brief
68090    Adds the constraints in \p cs to the system of constraints
68091    defining \p *this.
68092
68093    \param  cs
68094    The constraints that will be added.
68095
68096    \exception std::invalid_argument
68097    Thrown if \p *this and \p cs are dimension-incompatible,
68098    or \p cs contains a constraint which is not optimally supported
68099    by the OS domain.
68100  */
68101  void add_constraints(const Constraint_System& cs);
68102
68103  /*! \brief
68104    Adds the constraints in \p cs to the system of constraints
68105    of \p *this.
68106
68107    \param cs
68108    The constraint system to be added to \p *this.  The constraints in
68109    \p cs may be recycled.
68110
68111    \exception std::invalid_argument
68112    Thrown if \p *this and \p cs are dimension-incompatible,
68113    or \p cs contains a constraint which is not optimally supported
68114    by the OS domain.
68115
68116    \warning
68117    The only assumption that can be made on \p cs upon successful or
68118    exceptional return is that it can be safely destroyed.
68119  */
68120  void add_recycled_constraints(Constraint_System& cs);
68121
68122  /*! \brief
68123    Adds to \p *this a constraint equivalent to the congruence \p cg.
68124
68125    \param cg
68126    The congruence to be added.
68127
68128    \exception std::invalid_argument
68129    Thrown if \p *this and congruence \p cg are dimension-incompatible,
68130    or \p cg is not optimally supported by the OS domain.
68131  */
68132  void add_congruence(const Congruence& cg);
68133
68134  /*! \brief
68135    Adds to \p *this constraints equivalent to the congruences in \p cgs.
68136
68137    \param cgs
68138    The congruences to be added.
68139
68140    \exception std::invalid_argument
68141    Thrown if \p *this and \p cgs are dimension-incompatible,
68142    or \p cgs contains a congruence which is not optimally supported
68143    by the OS domain.
68144  */
68145  void add_congruences(const Congruence_System& cgs);
68146
68147  /*! \brief
68148    Adds to \p *this constraints equivalent to the congruences in \p cgs.
68149
68150    \param cgs
68151    The congruence system to be added to \p *this.  The congruences in
68152    \p cgs may be recycled.
68153
68154    \exception std::invalid_argument
68155    Thrown if \p *this and \p cgs are dimension-incompatible,
68156    or \p cgs contains a congruence which is not optimally supported
68157    by the OS domain.
68158
68159    \warning
68160    The only assumption that can be made on \p cgs upon successful or
68161    exceptional return is that it can be safely destroyed.
68162  */
68163  void add_recycled_congruences(Congruence_System& cgs);
68164
68165  /*! \brief
68166    Uses a copy of constraint \p c to refine the system of octagonal
68167    constraints defining \p *this.
68168
68169    \param c
68170    The constraint. If it is not a octagonal constraint, it will be ignored.
68171
68172    \exception std::invalid_argument
68173    Thrown if \p *this and constraint \p c are dimension-incompatible.
68174  */
68175  void refine_with_constraint(const Constraint& c);
68176
68177  /*! \brief
68178    Uses a copy of congruence \p cg to refine the system of
68179    octagonal constraints  of \p *this.
68180
68181    \param cg
68182    The congruence. If it is not a octagonal equality, it
68183    will be ignored.
68184
68185    \exception std::invalid_argument
68186    Thrown if \p *this and congruence \p cg are dimension-incompatible.
68187  */
68188  void refine_with_congruence(const Congruence& cg);
68189
68190  /*! \brief
68191    Uses a copy of the constraints in \p cs to refine the system of
68192    octagonal constraints defining \p *this.
68193
68194    \param  cs
68195    The constraint system to be used. Constraints that are not octagonal
68196    are ignored.
68197
68198    \exception std::invalid_argument
68199    Thrown if \p *this and \p cs are dimension-incompatible.
68200  */
68201  void refine_with_constraints(const Constraint_System& cs);
68202
68203  /*! \brief
68204    Uses a copy of the congruences in \p cgs to refine the system of
68205    octagonal constraints defining \p *this.
68206
68207    \param  cgs
68208    The congruence system to be used. Congruences that are not octagonal
68209    equalities are ignored.
68210
68211    \exception std::invalid_argument
68212    Thrown if \p *this and \p cgs are dimension-incompatible.
68213  */
68214  void refine_with_congruences(const Congruence_System& cgs);
68215
68216  /*! \brief
68217    Refines the system of octagonal constraints defining \p *this using
68218    the constraint expressed by \p left \f$\leq\f$ \p right.
68219
68220    \param left
68221    The linear form on intervals with floating point boundaries that
68222    is at the left of the comparison operator. All of its coefficients
68223    MUST be bounded.
68224
68225    \param right
68226    The linear form on intervals with floating point boundaries that
68227    is at the right of the comparison operator. All of its coefficients
68228    MUST be bounded.
68229
68230    \exception std::invalid_argument
68231    Thrown if \p left (or \p right) is dimension-incompatible with \p *this.
68232
68233    This function is used in abstract interpretation to model a filter
68234    that is generated by a comparison of two expressions that are correctly
68235    approximated by \p left and \p right respectively.
68236  */
68237  template <typename Interval_Info>
68238  void refine_with_linear_form_inequality(
68239                   const Linear_Form< Interval<T, Interval_Info> >& left,
68240                   const Linear_Form< Interval<T, Interval_Info> >& right);
68241
68242  /*! \brief
68243    Refines the system of octagonal constraints defining \p *this using
68244    the constraint expressed by \p left \f$\relsym\f$ \p right, where
68245    \f$\relsym\f$ is the relation symbol specified by \p relsym.
68246
68247    \param left
68248    The linear form on intervals with floating point boundaries that
68249    is at the left of the comparison operator. All of its coefficients
68250    MUST be bounded.
68251
68252    \param right
68253    The linear form on intervals with floating point boundaries that
68254    is at the right of the comparison operator. All of its coefficients
68255    MUST be bounded.
68256
68257    \param relsym
68258    The relation symbol.
68259
68260    \exception std::invalid_argument
68261    Thrown if \p left (or \p right) is dimension-incompatible with \p *this.
68262
68263    \exception std::runtime_error
68264    Thrown if \p relsym is not a valid relation symbol.
68265
68266    This function is used in abstract interpretation to model a filter
68267    that is generated by a comparison of two expressions that are correctly
68268    approximated by \p left and \p right respectively.
68269  */
68270  template <typename Interval_Info>
68271  void generalized_refine_with_linear_form_inequality(
68272                   const Linear_Form< Interval<T, Interval_Info> >& left,
68273                   const Linear_Form< Interval<T, Interval_Info> >& right,
68274                   Relation_Symbol relsym);
68275
68276  /*! \brief
68277    Computes the \ref Cylindrification "cylindrification" of \p *this with
68278    respect to space dimension \p var, assigning the result to \p *this.
68279
68280    \param var
68281    The space dimension that will be unconstrained.
68282
68283    \exception std::invalid_argument
68284    Thrown if \p var is not a space dimension of \p *this.
68285  */
68286  void unconstrain(Variable var);
68287
68288  /*! \brief
68289    Computes the \ref Cylindrification "cylindrification" of \p *this with
68290    respect to the set of space dimensions \p vars,
68291    assigning the result to \p *this.
68292
68293    \param vars
68294    The set of space dimension that will be unconstrained.
68295
68296    \exception std::invalid_argument
68297    Thrown if \p *this is dimension-incompatible with one of the
68298    Variable objects contained in \p vars.
68299  */
68300  void unconstrain(const Variables_Set& vars);
68301
68302  //! Assigns to \p *this the intersection of \p *this and \p y.
68303  /*!
68304    \exception std::invalid_argument
68305    Thrown if \p *this and \p y are dimension-incompatible.
68306  */
68307  void intersection_assign(const Octagonal_Shape& y);
68308
68309  /*! \brief
68310    Assigns to \p *this the smallest OS that contains
68311    the convex union of \p *this and \p y.
68312
68313    \exception std::invalid_argument
68314    Thrown if \p *this and \p y are dimension-incompatible.
68315  */
68316  void upper_bound_assign(const Octagonal_Shape& y);
68317
68318  /*! \brief
68319    If the upper bound of \p *this and \p y is exact, it is assigned
68320    to \p *this and <CODE>true</CODE> is returned,
68321    otherwise <CODE>false</CODE> is returned.
68322
68323    \exception std::invalid_argument
68324    Thrown if \p *this and \p y are dimension-incompatible.
68325
68326    Implementation is based on Theorem 6.3 of \ref BHZ09b "[BHZ09b]".
68327  */
68328  bool upper_bound_assign_if_exact(const Octagonal_Shape& y);
68329
68330  /*! \brief
68331    If the \e integer upper bound of \p *this and \p y is exact,
68332    it is assigned to \p *this and <CODE>true</CODE> is returned;
68333    otherwise <CODE>false</CODE> is returned.
68334
68335    \exception std::invalid_argument
68336    Thrown if \p *this and \p y are dimension-incompatible.
68337
68338    \note
68339    This operator is only available when the class template parameter
68340    \c T is bound to an integer data type.
68341
68342    \note
68343    The integer upper bound of two rational OS is the smallest
68344    rational OS containing all the integral points in the two arguments.
68345    In general, the result is \e not an upper bound for the two input
68346    arguments, as it may cut away non-integral portions of the two
68347    rational shapes.
68348
68349    Implementation is based on Theorem 6.8 of \ref BHZ09b "[BHZ09b]".
68350  */
68351  bool integer_upper_bound_assign_if_exact(const Octagonal_Shape& y);
68352
68353  /*! \brief
68354    Assigns to \p *this the smallest octagon containing
68355    the set difference of \p *this and \p y.
68356
68357    \exception std::invalid_argument
68358    Thrown if \p *this and \p y are dimension-incompatible.
68359  */
68360  void difference_assign(const Octagonal_Shape& y);
68361
68362  /*! \brief
68363    Assigns to \p *this a \ref Meet_Preserving_Simplification
68364    "meet-preserving simplification" of \p *this with respect to \p y.
68365    If \c false is returned, then the intersection is empty.
68366
68367    \exception std::invalid_argument
68368    Thrown if \p *this and \p y are topology-incompatible or
68369    dimension-incompatible.
68370  */
68371  bool simplify_using_context_assign(const Octagonal_Shape& y);
68372
68373  /*! \brief
68374    Assigns to \p *this the \ref affine_relation "affine image"
68375    of \p *this under the function mapping variable \p var into the
68376    affine expression specified by \p expr and \p denominator.
68377
68378    \param var
68379    The variable to which the affine expression is assigned.
68380
68381    \param expr
68382    The numerator of the affine expression.
68383
68384    \param denominator
68385    The denominator of the affine expression.
68386
68387    \exception std::invalid_argument
68388    Thrown if \p denominator is zero or if \p expr and \p *this
68389    are dimension-incompatible or if \p var is not a dimension of \p *this.
68390  */
68391  void affine_image(Variable var,
68392                    const Linear_Expression& expr,
68393                    Coefficient_traits::const_reference  denominator
68394                    = Coefficient_one());
68395
68396  // FIXME: To be completed.
68397  /*! \brief
68398    Assigns to \p *this the \ref affine_form_relation "affine form image"
68399    of \p *this under the function mapping variable \p var into the
68400    affine expression(s) specified by \p lf.
68401
68402    \param var
68403    The variable to which the affine expression is assigned.
68404
68405    \param lf
68406    The linear form on intervals with floating point boundaries that
68407    defines the affine expression(s). ALL of its coefficients MUST be bounded.
68408
68409    \exception std::invalid_argument
68410    Thrown if \p lf and \p *this are dimension-incompatible or if \p var
68411    is not a dimension of \p *this.
68412
68413    This function is used in abstract interpretation to model an assignment
68414    of a value that is correctly overapproximated by \p lf to the
68415    floating point variable represented by \p var.
68416  */
68417  template <typename Interval_Info>
68418  void affine_form_image(Variable var,
68419                        const Linear_Form< Interval<T, Interval_Info> >& lf);
68420
68421  /*! \brief
68422    Assigns to \p *this the \ref affine_relation "affine preimage"
68423    of \p *this under the function mapping variable \p var into the
68424    affine expression specified by \p expr and \p denominator.
68425
68426    \param var
68427    The variable to which the affine expression is substituted.
68428
68429    \param expr
68430    The numerator of the affine expression.
68431
68432    \param denominator
68433    The denominator of the affine expression.
68434
68435    \exception std::invalid_argument
68436    Thrown if \p denominator is zero or if \p expr and \p *this
68437    are dimension-incompatible or if \p var is not a dimension of \p *this.
68438  */
68439  void affine_preimage(Variable var,
68440                       const Linear_Expression& expr,
68441                       Coefficient_traits::const_reference denominator
68442                       = Coefficient_one());
68443
68444  /*! \brief
68445    Assigns to \p *this the image of \p *this with respect to the
68446    \ref Generalized_Affine_Relations "generalized affine transfer function"
68447    \f$\mathrm{var}' \relsym \frac{\mathrm{expr}}{\mathrm{denominator}}\f$,
68448    where \f$\mathord{\relsym}\f$ is the relation symbol encoded
68449    by \p relsym.
68450
68451    \param var
68452    The left hand side variable of the generalized affine transfer function.
68453
68454    \param relsym
68455    The relation symbol.
68456
68457    \param expr
68458    The numerator of the right hand side affine expression.
68459
68460    \param denominator
68461    The denominator of the right hand side affine expression.
68462
68463    \exception std::invalid_argument
68464    Thrown if \p denominator is zero or if \p expr and \p *this
68465    are dimension-incompatible or if \p var is not a dimension of \p *this
68466    or if \p relsym is a strict relation symbol.
68467  */
68468  void generalized_affine_image(Variable var,
68469                                Relation_Symbol relsym,
68470                                const Linear_Expression& expr,
68471                                Coefficient_traits::const_reference denominator
68472                                = Coefficient_one());
68473
68474  /*! \brief
68475    Assigns to \p *this the image of \p *this with respect to the
68476    \ref Generalized_Affine_Relations "generalized affine transfer function"
68477    \f$\mathrm{lhs}' \relsym \mathrm{rhs}\f$, where
68478    \f$\mathord{\relsym}\f$ is the relation symbol encoded by \p relsym.
68479
68480    \param lhs
68481    The left hand side affine expression.
68482
68483    \param relsym
68484    The relation symbol.
68485
68486    \param rhs
68487    The right hand side affine expression.
68488
68489    \exception std::invalid_argument
68490    Thrown if \p *this is dimension-incompatible with \p lhs or \p rhs
68491    or if \p relsym is a strict relation symbol.
68492  */
68493  void generalized_affine_image(const Linear_Expression& lhs,
68494                                Relation_Symbol relsym,
68495                                const Linear_Expression& rhs);
68496
68497    /*!
68498    \brief
68499    Assigns to \p *this the image of \p *this with respect to the
68500    \ref Single_Update_Bounded_Affine_Relations "bounded affine relation"
68501    \f$\frac{\mathrm{lb\_expr}}{\mathrm{denominator}}
68502         \leq \mathrm{var}'
68503           \leq \frac{\mathrm{ub\_expr}}{\mathrm{denominator}}\f$.
68504
68505    \param var
68506    The variable updated by the affine relation;
68507
68508    \param lb_expr
68509    The numerator of the lower bounding affine expression;
68510
68511    \param ub_expr
68512    The numerator of the upper bounding affine expression;
68513
68514    \param denominator
68515    The (common) denominator for the lower and upper bounding
68516    affine expressions (optional argument with default value 1).
68517
68518    \exception std::invalid_argument
68519    Thrown if \p denominator is zero or if \p lb_expr (resp., \p ub_expr)
68520    and \p *this are dimension-incompatible or if \p var is not a space
68521    dimension of \p *this.
68522  */
68523  void bounded_affine_image(Variable var,
68524                            const Linear_Expression& lb_expr,
68525                            const Linear_Expression& ub_expr,
68526                            Coefficient_traits::const_reference denominator
68527                            = Coefficient_one());
68528
68529/*! \brief
68530    Assigns to \p *this the preimage of \p *this with respect to the
68531    \ref Generalized_Affine_Relations "affine relation"
68532    \f$\mathrm{var}' \relsym \frac{\mathrm{expr}}{\mathrm{denominator}}\f$,
68533    where \f$\mathord{\relsym}\f$ is the relation symbol encoded
68534    by \p relsym.
68535
68536    \param var
68537    The left hand side variable of the generalized affine transfer function.
68538
68539    \param relsym
68540    The relation symbol.
68541
68542    \param expr
68543    The numerator of the right hand side affine expression.
68544
68545    \param denominator
68546    The denominator of the right hand side affine expression.
68547
68548    \exception std::invalid_argument
68549    Thrown if \p denominator is zero or if \p expr and \p *this
68550    are dimension-incompatible or if \p var is not a dimension
68551    of \p *this or if \p relsym is a strict relation symbol.
68552  */
68553  void generalized_affine_preimage(Variable var,
68554                                   Relation_Symbol relsym,
68555                                   const Linear_Expression& expr,
68556                                   Coefficient_traits::const_reference
68557                                   denominator = Coefficient_one());
68558
68559  /*! \brief
68560    Assigns to \p *this the preimage of \p *this with respect to the
68561    \ref Generalized_Affine_Relations "generalized affine relation"
68562    \f$\mathrm{lhs}' \relsym \mathrm{rhs}\f$, where
68563    \f$\mathord{\relsym}\f$ is the relation symbol encoded by \p relsym.
68564
68565    \param lhs
68566    The left hand side affine expression;
68567
68568    \param relsym
68569    The relation symbol;
68570
68571    \param rhs
68572    The right hand side affine expression.
68573
68574    \exception std::invalid_argument
68575    Thrown if \p *this is dimension-incompatible with \p lhs or \p rhs
68576    or if \p relsym is a strict relation symbol.
68577  */
68578  void generalized_affine_preimage(const Linear_Expression& lhs,
68579                                   Relation_Symbol relsym,
68580                                   const Linear_Expression& rhs);
68581
68582  /*!
68583    \brief
68584    Assigns to \p *this the preimage of \p *this with respect to the
68585    \ref Single_Update_Bounded_Affine_Relations "bounded affine relation"
68586    \f$\frac{\mathrm{lb\_expr}}{\mathrm{denominator}}
68587         \leq \mathrm{var}'
68588         \leq \frac{\mathrm{ub\_expr}}{\mathrm{denominator}}\f$.
68589
68590    \param var
68591    The variable updated by the affine relation;
68592
68593    \param lb_expr
68594    The numerator of the lower bounding affine expression;
68595
68596    \param ub_expr
68597    The numerator of the upper bounding affine expression;
68598
68599    \param denominator
68600    The (common) denominator for the lower and upper bounding
68601    affine expressions (optional argument with default value 1).
68602
68603    \exception std::invalid_argument
68604    Thrown if \p denominator is zero or if \p lb_expr (resp., \p ub_expr)
68605    and \p *this are dimension-incompatible or if \p var is not a space
68606    dimension of \p *this.
68607  */
68608  void bounded_affine_preimage(Variable var,
68609                               const Linear_Expression& lb_expr,
68610                               const Linear_Expression& ub_expr,
68611                               Coefficient_traits::const_reference denominator
68612                               = Coefficient_one());
68613
68614  /*! \brief
68615    Assigns to \p *this the result of computing the
68616    \ref Time_Elapse_Operator "time-elapse" between \p *this and \p y.
68617
68618    \exception std::invalid_argument
68619    Thrown if \p *this and \p y are dimension-incompatible.
68620  */
68621  void time_elapse_assign(const Octagonal_Shape& y);
68622
68623  /*! \brief
68624    \ref Wrapping_Operator "Wraps" the specified dimensions of the
68625    vector space.
68626
68627    \param vars
68628    The set of Variable objects corresponding to the space dimensions
68629    to be wrapped.
68630
68631    \param w
68632    The width of the bounded integer type corresponding to
68633    all the dimensions to be wrapped.
68634
68635    \param r
68636    The representation of the bounded integer type corresponding to
68637    all the dimensions to be wrapped.
68638
68639    \param o
68640    The overflow behavior of the bounded integer type corresponding to
68641    all the dimensions to be wrapped.
68642
68643    \param cs_p
68644    Possibly null pointer to a constraint system whose variables
68645    are contained in \p vars.  If <CODE>*cs_p</CODE> depends on
68646    variables not in \p vars, the behavior is undefined.
68647    When non-null, the pointed-to constraint system is assumed to
68648    represent the conditional or looping construct guard with respect
68649    to which wrapping is performed.  Since wrapping requires the
68650    computation of upper bounds and due to non-distributivity of
68651    constraint refinement over upper bounds, passing a constraint
68652    system in this way can be more precise than refining the result of
68653    the wrapping operation with the constraints in <CODE>*cs_p</CODE>.
68654
68655    \param complexity_threshold
68656    A precision parameter of the \ref Wrapping_Operator "wrapping operator":
68657    higher values result in possibly improved precision.
68658
68659    \param wrap_individually
68660    <CODE>true</CODE> if the dimensions should be wrapped individually
68661    (something that results in much greater efficiency to the detriment of
68662    precision).
68663
68664    \exception std::invalid_argument
68665    Thrown if <CODE>*cs_p</CODE> is dimension-incompatible with
68666    \p vars, or if \p *this is dimension-incompatible \p vars or with
68667    <CODE>*cs_p</CODE>.
68668  */
68669  void wrap_assign(const Variables_Set& vars,
68670                   Bounded_Integer_Type_Width w,
68671                   Bounded_Integer_Type_Representation r,
68672                   Bounded_Integer_Type_Overflow o,
68673                   const Constraint_System* cs_p = 0,
68674                   unsigned complexity_threshold = 16,
68675                   bool wrap_individually = true);
68676
68677  /*! \brief
68678    Possibly tightens \p *this by dropping some points with non-integer
68679    coordinates.
68680
68681    \param complexity
68682    The maximal complexity of any algorithms used.
68683
68684    \note
68685    Currently there is no optimality guarantee, not even if
68686    \p complexity is <CODE>ANY_COMPLEXITY</CODE>.
68687  */
68688  void drop_some_non_integer_points(Complexity_Class complexity
68689                                    = ANY_COMPLEXITY);
68690
68691  /*! \brief
68692    Possibly tightens \p *this by dropping some points with non-integer
68693    coordinates for the space dimensions corresponding to \p vars.
68694
68695    \param vars
68696    Points with non-integer coordinates for these variables/space-dimensions
68697    can be discarded.
68698
68699    \param complexity
68700    The maximal complexity of any algorithms used.
68701
68702    \note
68703    Currently there is no optimality guarantee, not even if
68704    \p complexity is <CODE>ANY_COMPLEXITY</CODE>.
68705  */
68706  void drop_some_non_integer_points(const Variables_Set& vars,
68707                                    Complexity_Class complexity
68708                                    = ANY_COMPLEXITY);
68709
68710  //! Assigns to \p *this its topological closure.
68711  void topological_closure_assign();
68712
68713  /*! \brief
68714    Assigns to \p *this the result of computing the
68715    \ref CC76_extrapolation "CC76-extrapolation" between \p *this and \p y.
68716
68717    \param y
68718    An OS that <EM>must</EM> be contained in \p *this.
68719
68720    \param tp
68721    An optional pointer to an unsigned variable storing the number of
68722    available tokens (to be used when applying the
68723    \ref Widening_with_Tokens "widening with tokens" delay technique).
68724
68725    \exception std::invalid_argument
68726    Thrown if \p *this and \p y are dimension-incompatible.
68727  */
68728  void CC76_extrapolation_assign(const Octagonal_Shape& y, unsigned* tp = 0);
68729
68730  /*! \brief
68731    Assigns to \p *this the result of computing the
68732    \ref CC76_extrapolation "CC76-extrapolation" between \p *this and \p y.
68733
68734    \param y
68735    An OS that <EM>must</EM> be contained in \p *this.
68736
68737    \param first
68738    An iterator that points to the first stop_point.
68739
68740    \param last
68741    An iterator that points to the last stop_point.
68742
68743    \param tp
68744    An optional pointer to an unsigned variable storing the number of
68745    available tokens (to be used when applying the
68746    \ref Widening_with_Tokens "widening with tokens" delay technique).
68747
68748    \exception std::invalid_argument
68749    Thrown if \p *this and \p y are dimension-incompatible.
68750  */
68751  template <typename Iterator>
68752  void CC76_extrapolation_assign(const Octagonal_Shape& y,
68753                                 Iterator first, Iterator last,
68754                                 unsigned* tp = 0);
68755
68756  /*! \brief
68757    Assigns to \p *this the result of computing the
68758    \ref BHMZ05_widening "BHMZ05-widening" between \p *this and \p y.
68759
68760    \param y
68761    An OS that <EM>must</EM> be contained in \p *this.
68762
68763    \param tp
68764    An optional pointer to an unsigned variable storing the number of
68765    available tokens (to be used when applying the
68766    \ref Widening_with_Tokens "widening with tokens" delay technique).
68767
68768    \exception std::invalid_argument
68769    Thrown if \p *this and \p y are dimension-incompatible.
68770  */
68771  void BHMZ05_widening_assign(const Octagonal_Shape& y, unsigned* tp = 0);
68772
68773  //! Same as BHMZ05_widening_assign(y, tp).
68774  void widening_assign(const Octagonal_Shape& y, unsigned* tp = 0);
68775
68776  /*! \brief
68777    Improves the result of the \ref BHMZ05_widening "BHMZ05-widening"
68778    computation by also enforcing those constraints in \p cs that are
68779    satisfied by all the points of \p *this.
68780
68781    \param y
68782    An OS that <EM>must</EM> be contained in \p *this.
68783
68784    \param cs
68785    The system of constraints used to improve the widened OS.
68786
68787    \param tp
68788    An optional pointer to an unsigned variable storing the number of
68789    available tokens (to be used when applying the
68790    \ref Widening_with_Tokens "widening with tokens" delay technique).
68791
68792    \exception std::invalid_argument
68793    Thrown if \p *this, \p y and \p cs are dimension-incompatible or
68794    if there is in \p cs a strict inequality.
68795  */
68796  void limited_BHMZ05_extrapolation_assign(const Octagonal_Shape& y,
68797                                           const Constraint_System& cs,
68798                                           unsigned* tp = 0);
68799
68800  /*! \brief
68801    Restores from \p y the constraints of \p *this, lost by
68802    \ref CC76_extrapolation "CC76-extrapolation" applications.
68803
68804    \param y
68805    An OS that <EM>must</EM> contain \p *this.
68806
68807    \exception std::invalid_argument
68808    Thrown if \p *this and \p y are dimension-incompatible.
68809  */
68810  void CC76_narrowing_assign(const Octagonal_Shape& y);
68811
68812  /*! \brief
68813    Improves the result of the \ref CC76_extrapolation "CC76-extrapolation"
68814    computation by also enforcing those constraints in \p cs that are
68815    satisfied by all the points of \p *this.
68816
68817    \param y
68818    An OS that <EM>must</EM> be contained in \p *this.
68819
68820    \param cs
68821    The system of constraints used to improve the widened OS.
68822
68823    \param tp
68824    An optional pointer to an unsigned variable storing the number of
68825    available tokens (to be used when applying the
68826    \ref Widening_with_Tokens "widening with tokens" delay technique).
68827
68828    \exception std::invalid_argument
68829    Thrown if \p *this, \p y and \p cs are dimension-incompatible or
68830    if \p cs contains a strict inequality.
68831  */
68832  void limited_CC76_extrapolation_assign(const Octagonal_Shape& y,
68833                                         const Constraint_System& cs,
68834                                         unsigned* tp = 0);
68835
68836  //@} Space-Dimension Preserving Member Functions that May Modify [...]
68837
68838  //! \name Member Functions that May Modify the Dimension of the Vector Space
68839  //@{
68840
68841  //! Adds \p m new dimensions and embeds the old OS into the new space.
68842  /*!
68843    \param m
68844    The number of dimensions to add.
68845
68846    The new dimensions will be those having the highest indexes in the new OS,
68847    which is characterized by a system of constraints in which the variables
68848    running through the new dimensions are not constrained.
68849    For instance, when starting from the OS \f$\cO \sseq \Rset^2\f$
68850    and adding a third dimension, the result will be the OS
68851    \f[
68852      \bigl\{\,
68853        (x, y, z)^\transpose \in \Rset^3
68854      \bigm|
68855        (x, y)^\transpose \in \cO
68856      \,\bigr\}.
68857    \f]
68858  */
68859  void add_space_dimensions_and_embed(dimension_type m);
68860
68861  /*! \brief
68862    Adds \p m new dimensions to the OS
68863    and does not embed it in the new space.
68864
68865    \param m
68866    The number of dimensions to add.
68867
68868    The new dimensions will be those having the highest indexes
68869    in the new OS, which is characterized by a system
68870    of constraints in which the variables running through
68871    the new dimensions are all constrained to be equal to 0.
68872    For instance, when starting from the OS \f$\cO \sseq \Rset^2\f$
68873    and adding a third dimension, the result will be the OS
68874    \f[
68875      \bigl\{\,
68876        (x, y, 0)^\transpose \in \Rset^3
68877      \bigm|
68878        (x, y)^\transpose \in \cO
68879      \,\bigr\}.
68880    \f]
68881  */
68882  void add_space_dimensions_and_project(dimension_type m);
68883
68884  /*! \brief
68885    Assigns to \p *this the \ref Concatenating_Polyhedra "concatenation"
68886    of \p *this and \p y, taken in this order.
68887
68888    \exception std::length_error
68889    Thrown if the concatenation would cause the vector space
68890    to exceed dimension <CODE>max_space_dimension()</CODE>.
68891  */
68892  void concatenate_assign(const Octagonal_Shape& y);
68893
68894  //! Removes all the specified dimensions.
68895  /*!
68896    \param vars
68897    The set of Variable objects corresponding to the dimensions to be removed.
68898
68899    \exception std::invalid_argument
68900    Thrown if \p *this is dimension-incompatible with one of the Variable
68901    objects contained in \p vars.
68902  */
68903  void remove_space_dimensions(const Variables_Set& vars);
68904
68905  /*! \brief
68906    Removes the higher dimensions so that the resulting space
68907    will have dimension \p new_dimension.
68908
68909    \exception std::invalid_argument
68910    Thrown if \p new_dimension is greater than the space dimension
68911    of \p *this.
68912  */
68913  void remove_higher_space_dimensions(dimension_type new_dimension);
68914
68915  /*! \brief
68916    Remaps the dimensions of the vector space according to
68917    a \ref Mapping_the_Dimensions_of_the_Vector_Space "partial function".
68918
68919    \param pfunc
68920    The partial function specifying the destiny of each dimension.
68921
68922    The template type parameter Partial_Function must provide
68923    the following methods.
68924    \code
68925      bool has_empty_codomain() const
68926    \endcode
68927    returns <CODE>true</CODE> if and only if the represented partial
68928    function has an empty codomain (i.e., it is always undefined).
68929    The <CODE>has_empty_codomain()</CODE> method will always be called
68930    before the methods below.  However, if
68931    <CODE>has_empty_codomain()</CODE> returns <CODE>true</CODE>, none
68932    of the functions below will be called.
68933    \code
68934      dimension_type max_in_codomain() const
68935    \endcode
68936    returns the maximum value that belongs to the codomain
68937    of the partial function.
68938    \code
68939      bool maps(dimension_type i, dimension_type& j) const
68940    \endcode
68941    Let \f$f\f$ be the represented function and \f$k\f$ be the value
68942    of \p i.  If \f$f\f$ is defined in \f$k\f$, then \f$f(k)\f$ is
68943    assigned to \p j and <CODE>true</CODE> is returned.
68944    If \f$f\f$ is undefined in \f$k\f$, then <CODE>false</CODE> is
68945    returned.
68946
68947    The result is undefined if \p pfunc does not encode a partial
68948    function with the properties described in the
68949    \ref Mapping_the_Dimensions_of_the_Vector_Space "specification of the mapping operator".
68950  */
68951  template <typename Partial_Function>
68952  void map_space_dimensions(const Partial_Function& pfunc);
68953
68954  //! Creates \p m copies of the space dimension corresponding to \p var.
68955  /*!
68956    \param var
68957    The variable corresponding to the space dimension to be replicated;
68958
68959    \param m
68960    The number of replicas to be created.
68961
68962    \exception std::invalid_argument
68963    Thrown if \p var does not correspond to a dimension of the vector space.
68964
68965    \exception std::length_error
68966    Thrown if adding \p m new space dimensions would cause the
68967    vector space to exceed dimension <CODE>max_space_dimension()</CODE>.
68968
68969    If \p *this has space dimension \f$n\f$, with \f$n > 0\f$,
68970    and <CODE>var</CODE> has space dimension \f$k \leq n\f$,
68971    then the \f$k\f$-th space dimension is
68972    \ref expand_space_dimension "expanded" to \p m new space dimensions
68973    \f$n\f$, \f$n+1\f$, \f$\dots\f$, \f$n+m-1\f$.
68974  */
68975  void expand_space_dimension(Variable var, dimension_type m);
68976
68977  //! Folds the space dimensions in \p vars into \p dest.
68978  /*!
68979    \param vars
68980    The set of Variable objects corresponding to the space dimensions
68981    to be folded;
68982
68983    \param dest
68984    The variable corresponding to the space dimension that is the
68985    destination of the folding operation.
68986
68987    \exception std::invalid_argument
68988    Thrown if \p *this is dimension-incompatible with \p dest or with
68989    one of the Variable objects contained in \p vars.
68990    Also thrown if \p dest is contained in \p vars.
68991
68992    If \p *this has space dimension \f$n\f$, with \f$n > 0\f$,
68993    <CODE>dest</CODE> has space dimension \f$k \leq n\f$,
68994    \p vars is a set of variables whose maximum space dimension
68995    is also less than or equal to \f$n\f$, and \p dest is not a member
68996    of \p vars, then the space dimensions corresponding to
68997    variables in \p vars are \ref fold_space_dimensions "folded"
68998    into the \f$k\f$-th space dimension.
68999  */
69000  void fold_space_dimensions(const Variables_Set& vars, Variable dest);
69001
69002  //! Applies to \p dest the interval constraints embedded in \p *this.
69003  /*!
69004    \param dest
69005    The object to which the constraints will be added.
69006
69007    \exception std::invalid_argument
69008    Thrown if \p *this is dimension-incompatible with \p dest.
69009
69010    The template type parameter U must provide the following methods.
69011    \code
69012      dimension_type space_dimension() const
69013    \endcode
69014    returns the space dimension of the object.
69015    \code
69016      void set_empty()
69017    \endcode
69018    sets the object to an empty object.
69019    \code
69020      bool restrict_lower(dimension_type dim, const T& lb)
69021    \endcode
69022    restricts the object by applying the lower bound \p lb to the space
69023    dimension \p dim and returns <CODE>false</CODE> if and only if the
69024    object becomes empty.
69025    \code
69026      bool restrict_upper(dimension_type dim, const T& ub)
69027    \endcode
69028    restricts the object by applying the upper bound \p ub to the space
69029    dimension \p dim and returns <CODE>false</CODE> if and only if the
69030    object becomes empty.
69031  */
69032  template <typename U>
69033  void export_interval_constraints(U& dest) const;
69034
69035  //! Refines \p store with the constraints defining \p *this.
69036  /*!
69037    \param store
69038    The interval floating point abstract store to refine.
69039  */
69040  template <typename Interval_Info>
69041  void refine_fp_interval_abstract_store(
69042                          Box< Interval<T, Interval_Info> >& store) const;
69043
69044  //@} // Member Functions that May Modify the Dimension of the Vector Space
69045
69046  PPL_OUTPUT_DECLARATIONS
69047
69048  /*! \brief
69049    Loads from \p s an ASCII representation (as produced by
69050    ascii_dump(std::ostream&) const) and sets \p *this accordingly.
69051    Returns <CODE>true</CODE> if successful, <CODE>false</CODE> otherwise.
69052  */
69053  bool ascii_load(std::istream& s);
69054
69055  //! Returns the total size in bytes of the memory occupied by \p *this.
69056  memory_size_type total_memory_in_bytes() const;
69057
69058  //! Returns the size in bytes of the memory managed by \p *this.
69059  memory_size_type external_memory_in_bytes() const;
69060
69061  /*! \brief
69062    Returns a 32-bit hash code for \p *this.
69063
69064    If \p x and \p y are such that <CODE>x == y</CODE>,
69065    then <CODE>x.hash_code() == y.hash_code()</CODE>.
69066  */
69067  int32_t hash_code() const;
69068
69069  friend bool
69070  operator==<T>(const Octagonal_Shape<T>& x, const Octagonal_Shape<T>& y);
69071
69072  template <typename Temp, typename To, typename U>
69073  friend bool Parma_Polyhedra_Library
69074  ::rectilinear_distance_assign(Checked_Number<To, Extended_Number_Policy>& r,
69075                                const Octagonal_Shape<U>& x,
69076                                const Octagonal_Shape<U>& y,
69077                                const Rounding_Dir dir,
69078                                Temp& tmp0, Temp& tmp1, Temp& tmp2);
69079  template <typename Temp, typename To, typename U>
69080  friend bool Parma_Polyhedra_Library
69081  ::euclidean_distance_assign(Checked_Number<To, Extended_Number_Policy>& r,
69082                              const Octagonal_Shape<U>& x,
69083                              const Octagonal_Shape<U>& y,
69084                              const Rounding_Dir dir,
69085                              Temp& tmp0, Temp& tmp1, Temp& tmp2);
69086  template <typename Temp, typename To, typename U>
69087  friend bool Parma_Polyhedra_Library
69088  ::l_infinity_distance_assign(Checked_Number<To, Extended_Number_Policy>& r,
69089                               const Octagonal_Shape<U>& x,
69090                               const Octagonal_Shape<U>& y,
69091                               const Rounding_Dir dir,
69092                               Temp& tmp0, Temp& tmp1, Temp& tmp2);
69093
69094private:
69095  template <typename U> friend class Parma_Polyhedra_Library::Octagonal_Shape;
69096  template <typename Interval> friend class Parma_Polyhedra_Library::Box;
69097
69098  //! The matrix that represents the octagonal shape.
69099  OR_Matrix<N> matrix;
69100
69101  //! Dimension of the space of the octagonal shape.
69102  dimension_type space_dim;
69103
69104  // Please, do not move the following include directive:
69105  // `Og_Status_idefs.hh' must be included exactly at this point.
69106  // And please do not remove the space separating `#' from `include':
69107  // this ensures that the directive will not be moved during the
69108  // procedure that automatically creates the library's include file
69109  // (see `Makefile.am' in the `src' directory).
69110#define PPL_IN_Octagonal_Shape_CLASS
69111/* Automatically generated from PPL source file ../src/Og_Status_idefs.hh line 1. */
69112/* Octagonal_Shape<T>::Status class declaration.
69113*/
69114
69115
69116#ifndef PPL_IN_Octagonal_Shape_CLASS
69117#error "Do not include Og_Status_idefs.hh directly; use Octagonal_Shape_defs.hh instead"
69118#endif
69119
69120//! A conjunctive assertion about a Octagonal_Shape<T> object.
69121/*!
69122  The assertions supported are:
69123  - <EM>zero-dim universe</EM>: the polyhedron is the zero-dimensional
69124    vector space \f$\Rset^0 = \{\cdot\}\f$;
69125  - <EM>empty</EM>: the polyhedron is the empty set;
69126  - <EM>strongly closed</EM>: the Octagonal_Shape object is strongly
69127    closed, so that all the constraints are as tight as possible.
69128
69129  Not all the conjunctions of these elementary assertions constitute
69130  a legal Status.  In fact:
69131  - <EM>zero-dim universe</EM> excludes any other assertion;
69132  - <EM>empty</EM>: excludes any other assertion.
69133*/
69134class Status {
69135public:
69136  //! By default Status is the <EM>zero-dim universe</EM> assertion.
69137  Status();
69138
69139  //! \name Test, remove or add an individual assertion from the conjunction.
69140  //@{
69141  bool test_zero_dim_univ() const;
69142  void reset_zero_dim_univ();
69143  void set_zero_dim_univ();
69144
69145  bool test_empty() const;
69146  void reset_empty();
69147  void set_empty();
69148
69149  bool test_strongly_closed() const;
69150  void reset_strongly_closed();
69151  void set_strongly_closed();
69152  //@}
69153
69154  //! Checks if all the invariants are satisfied.
69155  bool OK() const;
69156
69157  /*! \brief
69158    Writes to \p s an ASCII representation of the internal
69159    representation of \p *this.
69160  */
69161  void ascii_dump(std::ostream& s) const;
69162
69163  /*! \brief
69164    Loads from \p s an ASCII representation (as produced by
69165    ascii_dump(std::ostream&) const) and sets \p *this accordingly.
69166    Returns <CODE>true</CODE> if successful, <CODE>false</CODE> otherwise.
69167  */
69168  bool ascii_load(std::istream& s);
69169
69170private:
69171  //! Status is implemented by means of a finite bitset.
69172  typedef unsigned int flags_t;
69173
69174  //! \name Bitmasks for the individual assertions.
69175  //@{
69176  static const flags_t ZERO_DIM_UNIV   = 0U;
69177  static const flags_t EMPTY           = 1U << 0;
69178  static const flags_t STRONGLY_CLOSED = 1U << 1;
69179  //@}
69180
69181  //! This holds the current bitset.
69182  flags_t flags;
69183
69184  //! Construct from a bitmask.
69185  Status(flags_t mask);
69186
69187  //! Check whether <EM>all</EM> bits in \p mask are set.
69188  bool test_all(flags_t mask) const;
69189
69190  //! Check whether <EM>at least one</EM> bit in \p mask is set.
69191  bool test_any(flags_t mask) const;
69192
69193  //! Set the bits in \p mask.
69194  void set(flags_t mask);
69195
69196  //! Reset the bits in \p mask.
69197  void reset(flags_t mask);
69198
69199};
69200
69201/* Automatically generated from PPL source file ../src/Octagonal_Shape_defs.hh line 1929. */
69202#undef PPL_IN_Octagonal_Shape_CLASS
69203
69204  //! The status flags to keep track of the internal state.
69205  Status status;
69206
69207  //! Returns <CODE>true</CODE> if the OS is the zero-dimensional universe.
69208  bool marked_zero_dim_univ() const;
69209
69210  //! Returns <CODE>true</CODE> if the OS is known to be empty.
69211  /*!
69212    The return value <CODE>false</CODE> does not necessarily
69213    implies that \p *this is non-empty.
69214  */
69215  bool marked_empty() const;
69216
69217  /*! \brief
69218    Returns <CODE>true</CODE> if \c this->matrix is known to be
69219    strongly closed.
69220
69221    The return value <CODE>false</CODE> does not necessarily
69222    implies that \c this->matrix is not strongly closed.
69223  */
69224  bool marked_strongly_closed() const;
69225
69226  //! Turns \p *this into a zero-dimensional universe OS.
69227  void set_zero_dim_univ();
69228
69229  //! Turns \p *this into an empty OS.
69230  void set_empty();
69231
69232  //! Marks \p *this as strongly closed.
69233  void set_strongly_closed();
69234
69235  //! Marks \p *this as possibly not strongly closed.
69236  void reset_strongly_closed();
69237
69238  N& matrix_at(dimension_type i, dimension_type j);
69239  const N& matrix_at(dimension_type i, dimension_type j) const;
69240
69241  /*! \brief
69242    Returns an upper bound for \p lf according to the constraints
69243    embedded in \p *this.
69244
69245    \p lf must be a linear form on intervals with floating point coefficients.
69246    If all coefficients in \p lf are bounded, then \p result will become a
69247    correct overapproximation of the value of \p lf when variables in
69248    \p lf satisfy the constraints expressed by \p *this. Otherwise the
69249    behavior of the method is undefined.
69250  */
69251  template <typename Interval_Info>
69252  void linear_form_upper_bound(
69253                   const Linear_Form< Interval<T, Interval_Info> >& lf,
69254                   N& result) const;
69255
69256  // FIXME: this function is currently not used. Consider removing it.
69257  static void interval_coefficient_upper_bound(const N& var_ub,
69258                                               const N& minus_var_ub,
69259                                               const N& int_ub, const N& int_lb,
69260                                               N& result);
69261
69262  /*! \brief
69263    Uses the constraint \p c to refine \p *this.
69264
69265    \param c
69266    The constraint to be added. Non-octagonal constraints are ignored.
69267
69268    \warning
69269    If \p c and \p *this are dimension-incompatible,
69270    the behavior is undefined.
69271  */
69272  void refine_no_check(const Constraint& c);
69273
69274  /*! \brief
69275    Uses the congruence \p cg to refine \p *this.
69276
69277    \param cg
69278    The congruence to be added.
69279    Nontrivial proper congruences are ignored.
69280    Non-octagonal equalities are ignored.
69281
69282    \warning
69283    If \p cg and \p *this are dimension-incompatible,
69284    the behavior is undefined.
69285  */
69286  void refine_no_check(const Congruence& cg);
69287
69288  //! Adds the constraint <CODE>matrix[i][j] <= k</CODE>.
69289  void add_octagonal_constraint(dimension_type i,
69290                                dimension_type j,
69291                                const N& k);
69292
69293  //! Adds the constraint <CODE>matrix[i][j] <= numer/denom</CODE>.
69294  void add_octagonal_constraint(dimension_type i,
69295                                dimension_type j,
69296                                Coefficient_traits::const_reference numer,
69297                                Coefficient_traits::const_reference denom);
69298
69299  /*! \brief
69300    Adds to the Octagonal_Shape the constraint
69301    \f$\mathrm{var} \relsym \frac{\mathrm{expr}}{\mathrm{denominator}}\f$.
69302
69303    Note that the coefficient of \p var in \p expr is null.
69304  */
69305  void refine(Variable var,
69306              Relation_Symbol relsym,
69307              const Linear_Expression& expr,
69308              Coefficient_traits::const_reference denominator
69309              = Coefficient_one());
69310
69311  //! Removes all the constraints on variable \p v_id.
69312  void forget_all_octagonal_constraints(dimension_type v_id);
69313
69314  //! Removes all binary constraints on variable \p v_id.
69315  void forget_binary_octagonal_constraints(dimension_type v_id);
69316
69317  //! An helper function for the computation of affine relations.
69318  /*!
69319    For each variable index \c u_id (less than or equal to \p last_id
69320    and different from \p v_id), deduce constraints of the form
69321    <CODE>v - u \<= k</CODE> and <CODE>v + u \<= k</CODE>,
69322    starting from \p ub_v, which is an upper bound for \c v
69323    computed according to \p sc_expr and \p sc_denom.
69324
69325    Strong-closure will be able to deduce the constraints
69326    <CODE>v - u \<= ub_v - lb_u</CODE> and <CODE>v + u \<= ub_v + ub_u</CODE>.
69327    We can be more precise if variable \c u played an active role in the
69328    computation of the upper bound for \c v.
69329
69330    Namely, if the corresponding coefficient
69331    <CODE>q == sc_expr[u]/sc_denom</CODE> of \c u in \p sc_expr
69332    is greater than zero, we can improve the bound for <CODE>v - u</CODE>.
69333    In particular:
69334      - if <CODE>q \>= 1</CODE>, then <CODE>v - u \<= ub_v - ub_u</CODE>;
69335      - if <CODE>0 \< q \< 1</CODE>, then
69336        <CODE>v - u \<= ub_v - (q*ub_u + (1-q)*lb_u)</CODE>.
69337
69338    Conversely, if \c q is less than zero, we can improve the bound for
69339    <CODE>v + u</CODE>. In particular:
69340      - if <CODE>q \<= -1</CODE>, then <CODE>v + u \<= ub_v + lb_u</CODE>;
69341      - if <CODE>-1 \< q \< 0</CODE>, then
69342        <CODE>v + u \<= ub_v + ((-q)*lb_u + (1+q)*ub_u)</CODE>.
69343  */
69344  void deduce_v_pm_u_bounds(dimension_type v_id,
69345                            dimension_type last_id,
69346                            const Linear_Expression& sc_expr,
69347                            Coefficient_traits::const_reference sc_denom,
69348                            const N& ub_v);
69349
69350  //! An helper function for the computation of affine relations.
69351  /*!
69352    For each variable index \c u_id (less than or equal to \p last_id
69353    and different from \p v_id), deduce constraints of the form
69354    <CODE>-v + u \<= k</CODE> and <CODE>-v - u \<= k</CODE>,
69355    starting from \p minus_lb_v, which is the negation of a lower bound
69356    for \c v computed according to \p sc_expr and \p sc_denom.
69357
69358    Strong-closure will be able to deduce the constraints
69359    <CODE>-v - u \<= -lb_v - lb_u</CODE> and
69360    <CODE>-v + u \<= -lb_v + ub_u</CODE>.
69361    We can be more precise if variable \c u played an active role in the
69362    computation of (the negation of) the lower bound for \c v.
69363
69364    Namely, if the corresponding coefficient
69365    <CODE>q == sc_expr[u]/sc_denom</CODE> of \c u in \p sc_expr
69366    is greater than zero, we can improve the bound for <CODE>-v + u</CODE>.
69367    In particular:
69368      - if <CODE>q \>= 1</CODE>, then <CODE>-v + u \<= -lb_v + lb_u</CODE>;
69369      - if <CODE>0 \< q \< 1</CODE>, then
69370        <CODE>-v + u \<= -lb_v + (q*lb_u + (1-q)*ub_u)</CODE>.
69371
69372    Conversely, if \c q is less than zero, we can improve the bound for
69373    <CODE>-v - u</CODE>. In particular:
69374      - if <CODE>q \<= -1</CODE>, then <CODE>-v - u \<= -lb_v - ub_u</CODE>;
69375      - if <CODE>-1 \< q \< 0</CODE>, then
69376        <CODE>-v - u \<= -lb_v - ((-q)*ub_u + (1+q)*lb_u)</CODE>.
69377  */
69378  void deduce_minus_v_pm_u_bounds(dimension_type v_id,
69379                                  dimension_type last_id,
69380                                  const Linear_Expression& sc_expr,
69381                                  Coefficient_traits::const_reference sc_denom,
69382                                  const N& minus_lb_v);
69383
69384  /*! \brief
69385    Adds to \p limiting_octagon the octagonal differences in \p cs
69386    that are satisfied by \p *this.
69387  */
69388  void get_limiting_octagon(const Constraint_System& cs,
69389                            Octagonal_Shape& limiting_octagon) const;
69390  //! Compute the (zero-equivalence classes) successor relation.
69391  /*!
69392    It is assumed that the octagon is not empty and strongly closed.
69393  */
69394  void compute_successors(std::vector<dimension_type>& successor) const;
69395
69396  //! Compute the leaders of zero-equivalence classes.
69397  /*!
69398    It is assumed that the OS is not empty and strongly closed.
69399  */
69400  void compute_leaders(std::vector<dimension_type>& successor,
69401                       std::vector<dimension_type>& no_sing_leaders,
69402                       bool& exist_sing_class,
69403                       dimension_type& sing_leader) const;
69404
69405  //! Compute the leaders of zero-equivalence classes.
69406  /*!
69407    It is assumed that the OS is not empty and strongly closed.
69408  */
69409  void compute_leaders(std::vector<dimension_type>& leaders) const;
69410
69411  /*! \brief
69412    Stores into \p non_redundant information about the matrix entries
69413    that are non-redundant (i.e., they will occur in the strongly
69414    reduced matrix).
69415
69416    It is assumed that the OS is not empty and strongly closed;
69417    moreover, argument \p non_redundant is assumed to be empty.
69418  */
69419  void non_redundant_matrix_entries(std::vector<Bit_Row>& non_redundant) const;
69420
69421  //! Removes the redundant constraints from \c this->matrix.
69422  void strong_reduction_assign() const;
69423
69424  /*! \brief
69425    Returns <CODE>true</CODE> if and only if \c this->matrix
69426    is strongly reduced.
69427  */
69428  bool is_strongly_reduced() const;
69429
69430  /*! \brief
69431    Returns <CODE>true</CODE> if in the octagon taken two at a time
69432    unary constraints, there is also the constraint that represent their sum.
69433  */
69434  bool is_strong_coherent() const;
69435
69436  bool tight_coherence_would_make_empty() const;
69437
69438  //! Assigns to \c this->matrix its strong closure.
69439  /*!
69440    Strong closure is a necessary condition for the precision and/or
69441    the correctness of many methods. It explicitly records into \c matrix
69442    those constraints that are implicitly obtainable by the other ones,
69443    therefore obtaining a canonical representation for the OS.
69444  */
69445  void strong_closure_assign() const;
69446
69447  //! Applies the strong-coherence step to \c this->matrix.
69448  void strong_coherence_assign();
69449
69450  //! Assigns to \c this->matrix its tight closure.
69451  /*!
69452    \note
69453    This is \e not marked as a <code>const</code> method,
69454    as it may modify the rational-valued geometric shape by cutting away
69455    non-integral points. The method is only available if the template
69456    parameter \c T is bound to an integer data type.
69457  */
69458  void tight_closure_assign();
69459
69460  /*! \brief
69461    Incrementally computes strong closure, assuming that only
69462    constraints affecting variable \p var need to be considered.
69463
69464    \note
69465    It is assumed that \c *this, which was strongly closed, has only been
69466    modified by adding constraints affecting variable \p var. If this
69467    assumption is not satisfied, i.e., if a non-redundant constraint not
69468    affecting variable \p var has been added, the behavior is undefined.
69469    Worst-case complexity is \f$O(n^2)\f$.
69470  */
69471  void incremental_strong_closure_assign(Variable var) const;
69472
69473  //! Checks if and how \p expr is bounded in \p *this.
69474  /*!
69475    Returns <CODE>true</CODE> if and only if \p from_above is
69476    <CODE>true</CODE> and \p expr is bounded from above in \p *this,
69477    or \p from_above is <CODE>false</CODE> and \p expr is bounded
69478    from below in \p *this.
69479
69480    \param expr
69481    The linear expression to test;
69482
69483    \param from_above
69484    <CODE>true</CODE> if and only if the boundedness of interest is
69485    "from above".
69486
69487    \exception std::invalid_argument
69488    Thrown if \p expr and \p *this are dimension-incompatible.
69489  */
69490  bool bounds(const Linear_Expression& expr, bool from_above) const;
69491
69492  //! Maximizes or minimizes \p expr subject to \p *this.
69493  /*!
69494    \param expr
69495    The linear expression to be maximized or minimized subject to \p
69496    *this;
69497
69498    \param maximize
69499    <CODE>true</CODE> if maximization is what is wanted;
69500
69501    \param ext_n
69502    The numerator of the extremum value;
69503
69504    \param ext_d
69505    The denominator of the extremum value;
69506
69507    \param included
69508    <CODE>true</CODE> if and only if the extremum of \p expr can
69509    actually be reached in \p * this;
69510
69511    \exception std::invalid_argument
69512    Thrown if \p expr and \p *this are dimension-incompatible.
69513
69514    If \p *this is empty or \p expr is not bounded in the appropriate
69515    direction, <CODE>false</CODE> is returned and \p ext_n, \p ext_d and
69516    \p included are left untouched.
69517  */
69518  bool max_min(const Linear_Expression& expr,
69519               bool maximize,
69520               Coefficient& ext_n, Coefficient& ext_d, bool& included) const;
69521
69522  //! Maximizes or minimizes \p expr subject to \p *this.
69523  /*!
69524    \param expr
69525    The linear expression to be maximized or minimized subject to \p
69526    *this;
69527
69528    \param maximize
69529    <CODE>true</CODE> if maximization is what is wanted;
69530
69531    \param ext_n
69532    The numerator of the extremum value;
69533
69534    \param ext_d
69535    The denominator of the extremum value;
69536
69537    \param included
69538    <CODE>true</CODE> if and only if the extremum of \p expr can
69539    actually be reached in \p * this;
69540
69541    \param g
69542    When maximization or minimization succeeds, will be assigned
69543    a point or closure point where \p expr reaches the
69544    corresponding extremum value.
69545
69546    \exception std::invalid_argument
69547    Thrown if \p expr and \p *this are dimension-incompatible.
69548
69549    If \p *this is empty or \p expr is not bounded in the appropriate
69550    direction, <CODE>false</CODE> is returned and \p ext_n, \p ext_d,
69551    \p included and \p g are left untouched.
69552  */
69553  bool max_min(const Linear_Expression& expr,
69554               bool maximize,
69555               Coefficient& ext_n, Coefficient& ext_d, bool& included,
69556               Generator& g) const;
69557
69558  void drop_some_non_integer_points_helper(N& elem);
69559
69560  friend std::ostream&
69561  Parma_Polyhedra_Library::IO_Operators
69562  ::operator<<<>(std::ostream& s, const Octagonal_Shape<T>& c);
69563
69564  //! \name Exception Throwers
69565  //@{
69566  void throw_dimension_incompatible(const char* method,
69567                                    const Octagonal_Shape& y) const;
69568
69569  void throw_dimension_incompatible(const char* method,
69570                                    dimension_type required_dim) const;
69571
69572  void throw_dimension_incompatible(const char* method,
69573                                    const Constraint& c) const;
69574
69575  void throw_dimension_incompatible(const char* method,
69576                                    const Congruence& cg) const;
69577
69578  void throw_dimension_incompatible(const char* method,
69579                                    const Generator& g) const;
69580
69581  void throw_dimension_incompatible(const char* method,
69582                                    const char* le_name,
69583                                    const Linear_Expression& le) const;
69584
69585  template <typename C>
69586  void throw_dimension_incompatible(const char* method,
69587                                    const char* lf_name,
69588                                    const Linear_Form<C>& lf) const;
69589
69590  static void throw_constraint_incompatible(const char* method);
69591
69592  static void throw_expression_too_complex(const char* method,
69593                                           const Linear_Expression& le);
69594
69595  static void throw_invalid_argument(const char* method, const char* reason);
69596  //@} // Exception Throwers
69597};
69598
69599/* Automatically generated from PPL source file ../src/Og_Status_inlines.hh line 1. */
69600/* Octagonal_Shape<T>::Status class implementation: inline functions.
69601*/
69602
69603
69604namespace Parma_Polyhedra_Library {
69605
69606template <typename T>
69607inline
69608Octagonal_Shape<T>::Status::Status(flags_t mask)
69609  : flags(mask) {
69610}
69611
69612template <typename T>
69613inline
69614Octagonal_Shape<T>::Status::Status()
69615  : flags(ZERO_DIM_UNIV) {
69616}
69617
69618template <typename T>
69619inline bool
69620Octagonal_Shape<T>::Status::test_all(flags_t mask) const {
69621  return (flags & mask) == mask;
69622}
69623
69624template <typename T>
69625inline bool
69626Octagonal_Shape<T>::Status::test_any(flags_t mask) const {
69627  return (flags & mask) != 0;
69628}
69629
69630template <typename T>
69631inline void
69632Octagonal_Shape<T>::Status::set(flags_t mask) {
69633  flags |= mask;
69634}
69635
69636template <typename T>
69637inline void
69638Octagonal_Shape<T>::Status::reset(flags_t mask) {
69639  flags &= ~mask;
69640}
69641
69642template <typename T>
69643inline bool
69644Octagonal_Shape<T>::Status::test_zero_dim_univ() const {
69645  return flags == ZERO_DIM_UNIV;
69646}
69647
69648template <typename T>
69649inline void
69650Octagonal_Shape<T>::Status::reset_zero_dim_univ() {
69651  // This is a no-op if the current status is not zero-dim.
69652  if (flags == ZERO_DIM_UNIV) {
69653    // In the zero-dim space, if it is not the universe it is empty.
69654    flags = EMPTY;
69655  }
69656}
69657
69658template <typename T>
69659inline void
69660Octagonal_Shape<T>::Status::set_zero_dim_univ() {
69661  // Zero-dim universe is incompatible with anything else.
69662  flags = ZERO_DIM_UNIV;
69663}
69664
69665template <typename T>
69666inline bool
69667Octagonal_Shape<T>::Status::test_empty() const {
69668  return test_any(EMPTY);
69669}
69670
69671template <typename T>
69672inline void
69673Octagonal_Shape<T>::Status::reset_empty() {
69674  reset(EMPTY);
69675}
69676
69677template <typename T>
69678inline void
69679Octagonal_Shape<T>::Status::set_empty() {
69680  flags = EMPTY;
69681}
69682
69683template <typename T>
69684inline bool
69685Octagonal_Shape<T>::Status::test_strongly_closed() const {
69686  return test_any(STRONGLY_CLOSED);
69687}
69688
69689template <typename T>
69690inline void
69691Octagonal_Shape<T>::Status::reset_strongly_closed() {
69692  reset(STRONGLY_CLOSED);
69693}
69694
69695template <typename T>
69696inline void
69697Octagonal_Shape<T>::Status::set_strongly_closed() {
69698  set(STRONGLY_CLOSED);
69699}
69700
69701template <typename T>
69702inline bool
69703Octagonal_Shape<T>::Status::OK() const {
69704  if (test_zero_dim_univ()) {
69705    // Zero-dim universe is OK.
69706    return true;
69707  }
69708
69709  if (test_empty()) {
69710    Status copy = *this;
69711    copy.reset_empty();
69712    if (copy.test_zero_dim_univ()) {
69713      return true;
69714    }
69715    else {
69716#ifndef NDEBUG
69717      std::cerr << "The empty flag is incompatible with any other one."
69718                << std::endl;
69719#endif
69720      return false;
69721    }
69722  }
69723
69724  // Any other case is OK.
69725  return true;
69726}
69727
69728
69729namespace Implementation {
69730
69731namespace Octagonal_Shapes {
69732// These are the keywords that indicate the individual assertions.
69733extern const char* zero_dim_univ;
69734extern const char* empty;
69735extern const char* strong_closed;
69736const char yes = '+';
69737const char no = '-';
69738const char separator = ' ';
69739
69740/*! \relates Parma_Polyhedra_Library::Octagonal_Shape::Status
69741  Reads a keyword and its associated on/off flag from \p s.
69742  Returns <CODE>true</CODE> if the operation is successful,
69743  returns <CODE>false</CODE> otherwise.
69744  When successful, \p positive is set to <CODE>true</CODE> if the flag
69745  is on; it is set to <CODE>false</CODE> otherwise.
69746*/
69747inline bool
69748get_field(std::istream& s, const char* keyword, bool& positive) {
69749  std::string str;
69750  if (!(s >> str)
69751      || (str[0] != yes && str[0] != no)
69752      || str.substr(1) != keyword) {
69753    return false;
69754  }
69755  positive = (str[0] == yes);
69756  return true;
69757}
69758
69759} // namespace Octagonal_Shapes
69760
69761} // namespace Implementation
69762
69763template <typename T>
69764inline void
69765Octagonal_Shape<T>::Status::ascii_dump(std::ostream& s) const {
69766  using namespace Implementation::Octagonal_Shapes;
69767  s << (test_zero_dim_univ() ? yes : no) << zero_dim_univ
69768    << separator
69769    << (test_empty() ? yes : no) << empty
69770    << separator
69771    << separator
69772    << (test_strongly_closed() ? yes : no) << strong_closed
69773    << separator;
69774}
69775
69776template <typename T>
69777inline bool
69778Octagonal_Shape<T>::Status::ascii_load(std::istream& s) {
69779  using namespace Implementation::Octagonal_Shapes;
69780  PPL_UNINITIALIZED(bool, positive);
69781
69782  if (!get_field(s, zero_dim_univ, positive)) {
69783    return false;
69784  }
69785  if (positive) {
69786    set_zero_dim_univ();
69787  }
69788
69789  if (!get_field(s, empty, positive)) {
69790    return false;
69791  }
69792
69793  if (positive) {
69794    set_empty();
69795  }
69796
69797  if (!get_field(s, strong_closed, positive)) {
69798    return false;
69799  }
69800  if (positive) {
69801    set_strongly_closed();
69802  }
69803  else {
69804    reset_strongly_closed();
69805  }
69806  // Check invariants.
69807  PPL_ASSERT(OK());
69808  return true;
69809}
69810
69811} // namespace Parma_Polyhedra_Library
69812
69813/* Automatically generated from PPL source file ../src/Octagonal_Shape_inlines.hh line 1. */
69814/* Octagonal_Shape class implementation: inline functions.
69815*/
69816
69817
69818/* Automatically generated from PPL source file ../src/wrap_assign.hh line 1. */
69819/* Generic implementation of the wrap_assign() function.
69820*/
69821
69822
69823/* Automatically generated from PPL source file ../src/wrap_assign.hh line 32. */
69824
69825namespace Parma_Polyhedra_Library {
69826
69827namespace Implementation {
69828
69829struct Wrap_Dim_Translations {
69830  Variable var;
69831  Coefficient first_quadrant;
69832  Coefficient last_quadrant;
69833  Wrap_Dim_Translations(Variable v,
69834                        Coefficient_traits::const_reference f,
69835                        Coefficient_traits::const_reference l)
69836    : var(v), first_quadrant(f), last_quadrant(l) {
69837  }
69838};
69839
69840typedef std::vector<Wrap_Dim_Translations> Wrap_Translations;
69841
69842template <typename PSET>
69843void
69844wrap_assign_ind(PSET& pointset,
69845                Variables_Set& vars,
69846                Wrap_Translations::const_iterator first,
69847                Wrap_Translations::const_iterator end,
69848                Bounded_Integer_Type_Width w,
69849                Coefficient_traits::const_reference min_value,
69850                Coefficient_traits::const_reference max_value,
69851                const Constraint_System& cs,
69852                Coefficient& tmp1,
69853                Coefficient& tmp2) {
69854  const dimension_type space_dim = pointset.space_dimension();
69855  for (Wrap_Translations::const_iterator i = first; i != end; ++i) {
69856    const Wrap_Dim_Translations& wrap_dim_translations = *i;
69857    const Variable x(wrap_dim_translations.var);
69858    const Coefficient& first_quadrant = wrap_dim_translations.first_quadrant;
69859    const Coefficient& last_quadrant = wrap_dim_translations.last_quadrant;
69860    Coefficient& quadrant = tmp1;
69861    Coefficient& shift = tmp2;
69862    PSET hull(space_dim, EMPTY);
69863    for (quadrant = first_quadrant; quadrant <= last_quadrant; ++quadrant) {
69864      PSET p(pointset);
69865      if (quadrant != 0) {
69866        mul_2exp_assign(shift, quadrant, w);
69867        p.affine_image(x, x - shift, 1);
69868      }
69869      // `x' has just been wrapped.
69870      vars.erase(x.id());
69871
69872      // Refine `p' with all the constraints in `cs' not depending
69873      // on variables in `vars'.
69874      if (vars.empty()) {
69875        p.refine_with_constraints(cs);
69876      }
69877      else {
69878        for (Constraint_System::const_iterator j = cs.begin(),
69879               cs_end = cs.end(); j != cs_end; ++j) {
69880          if (j->expression().all_zeroes(vars)) {
69881            // `*j' does not depend on variables in `vars'.
69882            p.refine_with_constraint(*j);
69883          }
69884        }
69885      }
69886      p.refine_with_constraint(min_value <= x);
69887      p.refine_with_constraint(x <= max_value);
69888      hull.upper_bound_assign(p);
69889    }
69890    pointset.m_swap(hull);
69891  }
69892}
69893
69894template <typename PSET>
69895void
69896wrap_assign_col(PSET& dest,
69897                const PSET& src,
69898                const Variables_Set& vars,
69899                Wrap_Translations::const_iterator first,
69900                Wrap_Translations::const_iterator end,
69901                Bounded_Integer_Type_Width w,
69902                Coefficient_traits::const_reference min_value,
69903                Coefficient_traits::const_reference max_value,
69904                const Constraint_System* cs_p,
69905                Coefficient& tmp) {
69906  if (first == end) {
69907    PSET p(src);
69908    if (cs_p != 0) {
69909      p.refine_with_constraints(*cs_p);
69910    }
69911    for (Variables_Set::const_iterator i = vars.begin(),
69912           vars_end = vars.end(); i != vars_end; ++i) {
69913      const Variable x(*i);
69914      p.refine_with_constraint(min_value <= x);
69915      p.refine_with_constraint(x <= max_value);
69916    }
69917    dest.upper_bound_assign(p);
69918  }
69919  else {
69920    const Wrap_Dim_Translations& wrap_dim_translations = *first;
69921    const Variable x(wrap_dim_translations.var);
69922    const Coefficient& first_quadrant = wrap_dim_translations.first_quadrant;
69923    const Coefficient& last_quadrant = wrap_dim_translations.last_quadrant;
69924    Coefficient& shift = tmp;
69925    PPL_DIRTY_TEMP_COEFFICIENT(quadrant);
69926    for (quadrant = first_quadrant; quadrant <= last_quadrant; ++quadrant) {
69927      if (quadrant != 0) {
69928        mul_2exp_assign(shift, quadrant, w);
69929        PSET p(src);
69930        p.affine_image(x, x - shift, 1);
69931        wrap_assign_col(dest, p, vars, first+1, end, w, min_value, max_value,
69932                        cs_p, tmp);
69933      }
69934      else {
69935        wrap_assign_col(dest, src, vars, first+1, end, w, min_value, max_value,
69936                        cs_p, tmp);
69937      }
69938    }
69939  }
69940}
69941
69942template <typename PSET>
69943void
69944wrap_assign(PSET& pointset,
69945            const Variables_Set& vars,
69946            const Bounded_Integer_Type_Width w,
69947            const Bounded_Integer_Type_Representation r,
69948            const Bounded_Integer_Type_Overflow o,
69949            const Constraint_System* cs_p,
69950            const unsigned complexity_threshold,
69951            const bool wrap_individually,
69952            const char* class_name) {
69953  // We must have cs_p->space_dimension() <= vars.space_dimension()
69954  //         and  vars.space_dimension() <= pointset.space_dimension().
69955
69956  // Dimension-compatibility check of `*cs_p', if any.
69957  if (cs_p != 0) {
69958    const dimension_type vars_space_dim = vars.space_dimension();
69959    if (cs_p->space_dimension() > vars_space_dim) {
69960      std::ostringstream s;
69961      s << "PPL::" << class_name << "::wrap_assign(..., cs_p, ...):"
69962        << std::endl
69963        << "vars.space_dimension() == " << vars_space_dim
69964        << ", cs_p->space_dimension() == " << cs_p->space_dimension() << ".";
69965      throw std::invalid_argument(s.str());
69966    }
69967
69968#ifndef NDEBUG
69969    // Check that all variables upon which `*cs_p' depends are in `vars'.
69970    // An assertion is violated otherwise.
69971    const Constraint_System cs = *cs_p;
69972    const dimension_type cs_space_dim = cs.space_dimension();
69973    Variables_Set::const_iterator vars_end = vars.end();
69974    for (Constraint_System::const_iterator i = cs.begin(),
69975           cs_end = cs.end(); i != cs_end; ++i) {
69976      const Constraint& c = *i;
69977      for (dimension_type d = cs_space_dim; d-- > 0; ) {
69978        PPL_ASSERT(c.coefficient(Variable(d)) == 0
69979                   || vars.find(d) != vars_end);
69980      }
69981    }
69982#endif
69983  }
69984
69985  // Wrapping no variable only requires refining with *cs_p, if any.
69986  if (vars.empty()) {
69987    if (cs_p != 0) {
69988      pointset.refine_with_constraints(*cs_p);
69989    }
69990    return;
69991  }
69992
69993  // Dimension-compatibility check of `vars'.
69994  const dimension_type space_dim = pointset.space_dimension();
69995  if (vars.space_dimension() > space_dim) {
69996    std::ostringstream s;
69997    s << "PPL::" << class_name << "::wrap_assign(vs, ...):" << std::endl
69998      << "this->space_dimension() == " << space_dim
69999      << ", required space dimension == " << vars.space_dimension() << ".";
70000    throw std::invalid_argument(s.str());
70001  }
70002
70003  // Wrapping an empty polyhedron is a no-op.
70004  if (pointset.is_empty()) {
70005    return;
70006  }
70007  // Set `min_value' and `max_value' to the minimum and maximum values
70008  // a variable of width `w' and signedness `s' can take.
70009  PPL_DIRTY_TEMP_COEFFICIENT(min_value);
70010  PPL_DIRTY_TEMP_COEFFICIENT(max_value);
70011  if (r == UNSIGNED) {
70012    min_value = 0;
70013    mul_2exp_assign(max_value, Coefficient_one(), w);
70014    --max_value;
70015  }
70016  else {
70017    PPL_ASSERT(r == SIGNED_2_COMPLEMENT);
70018    mul_2exp_assign(max_value, Coefficient_one(), w-1);
70019    neg_assign(min_value, max_value);
70020    --max_value;
70021  }
70022
70023  // If we are wrapping variables collectively, the ranges for the
70024  // required translations are saved in `translations' instead of being
70025  // immediately applied.
70026  Wrap_Translations translations;
70027
70028  // Dimensions subject to translation are added to this set if we are
70029  // wrapping collectively or if `cs_p' is non null.
70030  Variables_Set dimensions_to_be_translated;
70031
70032  // This will contain a lower bound to the number of abstractions
70033  // to be joined in order to obtain the collective wrapping result.
70034  // As soon as this exceeds `complexity_threshold', counting will be
70035  // interrupted and the full range will be the result of wrapping
70036  // any dimension that is not fully contained in quadrant 0.
70037  unsigned collective_wrap_complexity = 1;
70038
70039  // This flag signals that the maximum complexity for collective
70040  // wrapping as been exceeded.
70041  bool collective_wrap_too_complex = false;
70042
70043  if (!wrap_individually) {
70044    translations.reserve(space_dim);
70045  }
70046
70047  // We use `full_range_bounds' to delay conversions whenever
70048  // this delay does not negatively affect precision.
70049  Constraint_System full_range_bounds;
70050
70051  PPL_DIRTY_TEMP_COEFFICIENT(l_n);
70052  PPL_DIRTY_TEMP_COEFFICIENT(l_d);
70053  PPL_DIRTY_TEMP_COEFFICIENT(u_n);
70054  PPL_DIRTY_TEMP_COEFFICIENT(u_d);
70055
70056  for (Variables_Set::const_iterator i = vars.begin(),
70057         vars_end = vars.end(); i != vars_end; ++i) {
70058
70059    const Variable x(*i);
70060
70061    bool extremum;
70062
70063    if (!pointset.minimize(x, l_n, l_d, extremum)) {
70064    set_full_range:
70065      pointset.unconstrain(x);
70066      full_range_bounds.insert(min_value <= x);
70067      full_range_bounds.insert(x <= max_value);
70068      continue;
70069    }
70070
70071    if (!pointset.maximize(x, u_n, u_d, extremum)) {
70072      goto set_full_range;
70073    }
70074
70075    div_assign_r(l_n, l_n, l_d, ROUND_DOWN);
70076    div_assign_r(u_n, u_n, u_d, ROUND_DOWN);
70077    l_n -= min_value;
70078    u_n -= min_value;
70079    div_2exp_assign_r(l_n, l_n, w, ROUND_DOWN);
70080    div_2exp_assign_r(u_n, u_n, w, ROUND_DOWN);
70081    Coefficient& first_quadrant = l_n;
70082    const Coefficient& last_quadrant = u_n;
70083
70084    // Special case: this variable does not need wrapping.
70085    if (first_quadrant == 0 && last_quadrant == 0) {
70086      continue;
70087    }
70088
70089    // If overflow is impossible, try not to add useless constraints.
70090    if (o == OVERFLOW_IMPOSSIBLE) {
70091      if (first_quadrant < 0) {
70092        full_range_bounds.insert(min_value <= x);
70093      }
70094      if (last_quadrant > 0) {
70095        full_range_bounds.insert(x <= max_value);
70096      }
70097      continue;
70098    }
70099
70100    if (o == OVERFLOW_UNDEFINED || collective_wrap_too_complex) {
70101      goto set_full_range;
70102    }
70103
70104    Coefficient& quadrants = u_d;
70105    quadrants = last_quadrant - first_quadrant + 1;
70106
70107    PPL_UNINITIALIZED(unsigned, extension);
70108    Result res = assign_r(extension, quadrants, ROUND_IGNORE);
70109    if (result_overflow(res) != 0 || extension > complexity_threshold) {
70110      goto set_full_range;
70111    }
70112
70113    if (!wrap_individually && !collective_wrap_too_complex) {
70114      res = mul_assign_r(collective_wrap_complexity,
70115                         collective_wrap_complexity, extension, ROUND_IGNORE);
70116      if (result_overflow(res) != 0
70117          || collective_wrap_complexity > complexity_threshold) {
70118        collective_wrap_too_complex = true;
70119      }
70120      if (collective_wrap_too_complex) {
70121        // Set all the dimensions in `translations' to full range.
70122        for (Wrap_Translations::const_iterator j = translations.begin(),
70123               translations_end = translations.end();
70124             j != translations_end;
70125             ++j) {
70126          const Variable y(j->var);
70127          pointset.unconstrain(y);
70128          full_range_bounds.insert(min_value <= y);
70129          full_range_bounds.insert(y <= max_value);
70130        }
70131      }
70132    }
70133
70134    if (wrap_individually && cs_p == 0) {
70135      Coefficient& quadrant = first_quadrant;
70136      // Temporary variable holding the shifts to be applied in order
70137      // to implement the translations.
70138      Coefficient& shift = l_d;
70139      PSET hull(space_dim, EMPTY);
70140      for ( ; quadrant <= last_quadrant; ++quadrant) {
70141        PSET p(pointset);
70142        if (quadrant != 0) {
70143          mul_2exp_assign(shift, quadrant, w);
70144          p.affine_image(x, x - shift, 1);
70145        }
70146        p.refine_with_constraint(min_value <= x);
70147        p.refine_with_constraint(x <= max_value);
70148        hull.upper_bound_assign(p);
70149      }
70150      pointset.m_swap(hull);
70151    }
70152    else if (wrap_individually || !collective_wrap_too_complex) {
70153      PPL_ASSERT(!wrap_individually || cs_p != 0);
70154      dimensions_to_be_translated.insert(x);
70155      translations
70156        .push_back(Wrap_Dim_Translations(x, first_quadrant, last_quadrant));
70157    }
70158  }
70159
70160  if (!translations.empty()) {
70161    if (wrap_individually) {
70162      PPL_ASSERT(cs_p != 0);
70163      wrap_assign_ind(pointset, dimensions_to_be_translated,
70164                      translations.begin(), translations.end(),
70165                      w, min_value, max_value, *cs_p, l_n, l_d);
70166    }
70167    else {
70168      PSET hull(space_dim, EMPTY);
70169      wrap_assign_col(hull, pointset, dimensions_to_be_translated,
70170                      translations.begin(), translations.end(),
70171                      w, min_value, max_value, cs_p, l_n);
70172      pointset.m_swap(hull);
70173    }
70174  }
70175
70176  if (cs_p != 0) {
70177    pointset.refine_with_constraints(*cs_p);
70178  }
70179  pointset.refine_with_constraints(full_range_bounds);
70180}
70181
70182} // namespace Implementation
70183
70184} // namespace Parma_Polyhedra_Library
70185
70186/* Automatically generated from PPL source file ../src/Octagonal_Shape_inlines.hh line 36. */
70187#include <algorithm>
70188
70189namespace Parma_Polyhedra_Library {
70190
70191namespace Implementation {
70192
70193namespace Octagonal_Shapes {
70194
70195#ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
70196//! Returns the index coherent to \p i.
70197/*! \relates Parma_Polyhedra_Library::Octagonal_Shape */
70198#endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
70199inline dimension_type
70200coherent_index(const dimension_type i) {
70201  return (i % 2 != 0) ? (i-1) : (i+1);
70202}
70203
70204} // namespace Octagonal_Shapes
70205
70206} // namespace Implementation
70207
70208template <typename T>
70209inline dimension_type
70210Octagonal_Shape<T>::max_space_dimension() {
70211  return OR_Matrix<N>::max_num_rows()/2;
70212}
70213
70214template <typename T>
70215inline bool
70216Octagonal_Shape<T>::marked_zero_dim_univ() const {
70217  return status.test_zero_dim_univ();
70218}
70219
70220template <typename T>
70221inline bool
70222Octagonal_Shape<T>::marked_strongly_closed() const {
70223  return status.test_strongly_closed();
70224}
70225
70226template <typename T>
70227inline bool
70228Octagonal_Shape<T>::marked_empty() const {
70229  return status.test_empty();
70230}
70231
70232template <typename T>
70233inline void
70234Octagonal_Shape<T>::set_zero_dim_univ() {
70235  status.set_zero_dim_univ();
70236}
70237
70238template <typename T>
70239inline void
70240Octagonal_Shape<T>::set_empty() {
70241  status.set_empty();
70242}
70243
70244template <typename T>
70245inline void
70246Octagonal_Shape<T>::set_strongly_closed() {
70247  status.set_strongly_closed();
70248}
70249
70250template <typename T>
70251inline void
70252Octagonal_Shape<T>::reset_strongly_closed() {
70253  status.reset_strongly_closed();
70254}
70255
70256template <typename T>
70257inline
70258Octagonal_Shape<T>::Octagonal_Shape(const dimension_type num_dimensions,
70259                                    const Degenerate_Element kind)
70260  : matrix(num_dimensions), space_dim(num_dimensions), status() {
70261  if (kind == EMPTY) {
70262    set_empty();
70263  }
70264  else if (num_dimensions > 0) {
70265    // A (non zero-dim) universe octagon is strongly closed.
70266    set_strongly_closed();
70267  }
70268  PPL_ASSERT(OK());
70269}
70270
70271template <typename T>
70272inline
70273Octagonal_Shape<T>::Octagonal_Shape(const Octagonal_Shape& y, Complexity_Class)
70274  : matrix(y.matrix), space_dim(y.space_dim), status(y.status) {
70275}
70276
70277template <typename T>
70278template <typename U>
70279inline
70280Octagonal_Shape<T>::Octagonal_Shape(const Octagonal_Shape<U>& y,
70281                                    Complexity_Class)
70282  // For maximum precision, enforce shortest-path closure
70283  // before copying the DB matrix.
70284  : matrix((y.strong_closure_assign(), y.matrix)),
70285    space_dim(y.space_dim),
70286    status() {
70287  // TODO: handle flags properly, possibly taking special cases into account.
70288  if (y.marked_empty()) {
70289    set_empty();
70290  }
70291  else if (y.marked_zero_dim_univ()) {
70292    set_zero_dim_univ();
70293  }
70294}
70295
70296template <typename T>
70297inline
70298Octagonal_Shape<T>::Octagonal_Shape(const Constraint_System& cs)
70299  : matrix(cs.space_dimension()),
70300    space_dim(cs.space_dimension()),
70301    status() {
70302  if (cs.space_dimension() > 0) {
70303    // A (non zero-dim) universe octagon is strongly closed.
70304    set_strongly_closed();
70305  }
70306  add_constraints(cs);
70307}
70308
70309template <typename T>
70310inline
70311Octagonal_Shape<T>::Octagonal_Shape(const Congruence_System& cgs)
70312  : matrix(cgs.space_dimension()),
70313    space_dim(cgs.space_dimension()),
70314    status() {
70315  if (cgs.space_dimension() > 0) {
70316    // A (non zero-dim) universe octagon is strongly closed.
70317    set_strongly_closed();
70318  }
70319  add_congruences(cgs);
70320}
70321
70322template <typename T>
70323template <typename Interval>
70324inline
70325Octagonal_Shape<T>::Octagonal_Shape(const Box<Interval>& box,
70326                                    Complexity_Class)
70327  : matrix(box.space_dimension()),
70328    space_dim(box.space_dimension()),
70329    status() {
70330  // Check for emptiness for maximum precision.
70331  if (box.is_empty()) {
70332    set_empty();
70333  }
70334  else if (box.space_dimension() > 0) {
70335    // A (non zero-dim) universe OS is strongly closed.
70336    set_strongly_closed();
70337    refine_with_constraints(box.constraints());
70338  }
70339}
70340
70341template <typename T>
70342inline
70343Octagonal_Shape<T>::Octagonal_Shape(const Grid& grid,
70344                                    Complexity_Class)
70345  : matrix(grid.space_dimension()),
70346    space_dim(grid.space_dimension()),
70347    status() {
70348  if (grid.space_dimension() > 0) {
70349    // A (non zero-dim) universe OS is strongly closed.
70350    set_strongly_closed();
70351  }
70352  // Taking minimized congruences ensures maximum precision.
70353  refine_with_congruences(grid.minimized_congruences());
70354}
70355
70356template <typename T>
70357template <typename U>
70358inline
70359Octagonal_Shape<T>::Octagonal_Shape(const BD_Shape<U>& bd,
70360                                    Complexity_Class)
70361  : matrix(bd.space_dimension()),
70362    space_dim(bd.space_dimension()),
70363    status() {
70364  // Check for emptiness for maximum precision.
70365  if (bd.is_empty()) {
70366    set_empty();
70367  }
70368  else if (bd.space_dimension() > 0) {
70369    // A (non zero-dim) universe OS is strongly closed.
70370    set_strongly_closed();
70371    refine_with_constraints(bd.constraints());
70372  }
70373}
70374
70375template <typename T>
70376inline Congruence_System
70377Octagonal_Shape<T>::congruences() const {
70378  return minimized_congruences();
70379}
70380
70381template <typename T>
70382inline Octagonal_Shape<T>&
70383Octagonal_Shape<T>::operator=(const Octagonal_Shape& y) {
70384  matrix = y.matrix;
70385  space_dim = y.space_dim;
70386  status = y.status;
70387  return *this;
70388}
70389
70390template <typename T>
70391inline
70392Octagonal_Shape<T>::~Octagonal_Shape() {
70393}
70394
70395template <typename T>
70396inline void
70397Octagonal_Shape<T>::m_swap(Octagonal_Shape& y) {
70398  using std::swap;
70399  swap(matrix, y.matrix);
70400  swap(space_dim, y.space_dim);
70401  swap(status, y.status);
70402}
70403
70404template <typename T>
70405inline dimension_type
70406Octagonal_Shape<T>::space_dimension() const {
70407  return space_dim;
70408}
70409
70410template <typename T>
70411inline bool
70412Octagonal_Shape<T>::is_discrete() const {
70413  return affine_dimension() == 0;
70414}
70415
70416template <typename T>
70417inline bool
70418Octagonal_Shape<T>::is_empty() const {
70419  strong_closure_assign();
70420  return marked_empty();
70421}
70422
70423template <typename T>
70424inline bool
70425Octagonal_Shape<T>::bounds_from_above(const Linear_Expression& expr) const {
70426  return bounds(expr, true);
70427}
70428
70429template <typename T>
70430inline bool
70431Octagonal_Shape<T>::bounds_from_below(const Linear_Expression& expr) const {
70432  return bounds(expr, false);
70433}
70434
70435template <typename T>
70436inline bool
70437Octagonal_Shape<T>::maximize(const Linear_Expression& expr,
70438                             Coefficient& sup_n, Coefficient& sup_d,
70439                             bool& maximum) const {
70440  return max_min(expr, true, sup_n, sup_d, maximum);
70441}
70442
70443template <typename T>
70444inline bool
70445Octagonal_Shape<T>::maximize(const Linear_Expression& expr,
70446                             Coefficient& sup_n, Coefficient& sup_d,
70447                             bool& maximum,
70448                             Generator& g) const {
70449  return max_min(expr, true, sup_n, sup_d, maximum, g);
70450}
70451
70452template <typename T>
70453inline bool
70454Octagonal_Shape<T>::minimize(const Linear_Expression& expr,
70455                             Coefficient& inf_n, Coefficient& inf_d,
70456                             bool& minimum) const {
70457  return max_min(expr, false, inf_n, inf_d, minimum);
70458}
70459
70460template <typename T>
70461inline bool
70462Octagonal_Shape<T>::minimize(const Linear_Expression& expr,
70463                             Coefficient& inf_n, Coefficient& inf_d,
70464                             bool& minimum,
70465                             Generator& g) const {
70466  return max_min(expr, false, inf_n, inf_d, minimum, g);
70467}
70468
70469template <typename T>
70470inline bool
70471Octagonal_Shape<T>::is_topologically_closed() const {
70472  return true;
70473}
70474
70475template <typename T>
70476inline void
70477Octagonal_Shape<T>::topological_closure_assign() {
70478}
70479
70480/*! \relates Octagonal_Shape */
70481template <typename T>
70482inline bool
70483operator==(const Octagonal_Shape<T>& x, const Octagonal_Shape<T>& y) {
70484  if (x.space_dim != y.space_dim) {
70485    // Dimension-incompatible OSs are different.
70486    return false;
70487  }
70488  // Zero-dim OSs are equal if and only if they are both empty or universe.
70489  if (x.space_dim == 0) {
70490    if (x.marked_empty()) {
70491      return y.marked_empty();
70492    }
70493    else {
70494      return !y.marked_empty();
70495    }
70496  }
70497
70498  x.strong_closure_assign();
70499  y.strong_closure_assign();
70500  // If one of two octagons is empty, then they are equal if and only if
70501  // the other octagon is empty too.
70502  if (x.marked_empty()) {
70503    return y.marked_empty();
70504  }
70505  if (y.marked_empty()) {
70506    return false;
70507  }
70508  // Strong closure is a canonical form.
70509  return x.matrix == y.matrix;
70510}
70511
70512/*! \relates Octagonal_Shape */
70513template <typename T>
70514inline bool
70515operator!=(const Octagonal_Shape<T>& x, const Octagonal_Shape<T>& y) {
70516  return !(x == y);
70517}
70518
70519template <typename T>
70520inline const typename Octagonal_Shape<T>::coefficient_type&
70521Octagonal_Shape<T>::matrix_at(const dimension_type i,
70522                              const dimension_type j) const {
70523  PPL_ASSERT(i < matrix.num_rows() && j < matrix.num_rows());
70524  using namespace Implementation::Octagonal_Shapes;
70525  return (j < matrix.row_size(i))
70526    ? matrix[i][j]
70527    : matrix[coherent_index(j)][coherent_index(i)];
70528}
70529
70530template <typename T>
70531inline typename Octagonal_Shape<T>::coefficient_type&
70532Octagonal_Shape<T>::matrix_at(const dimension_type i,
70533                              const dimension_type j) {
70534  PPL_ASSERT(i < matrix.num_rows() && j < matrix.num_rows());
70535  using namespace Implementation::Octagonal_Shapes;
70536  return (j < matrix.row_size(i))
70537    ? matrix[i][j]
70538    : matrix[coherent_index(j)][coherent_index(i)];
70539}
70540
70541template <typename T>
70542inline Constraint_System
70543Octagonal_Shape<T>::minimized_constraints() const {
70544  strong_reduction_assign();
70545  return constraints();
70546}
70547
70548template <typename T>
70549inline void
70550Octagonal_Shape<T>::add_octagonal_constraint(const dimension_type i,
70551                                             const dimension_type j,
70552                                             const N& k) {
70553  // Private method: the caller has to ensure the following.
70554#ifndef NDEBUG
70555  PPL_ASSERT(i < 2*space_dim && j < 2*space_dim && i != j);
70556  typename OR_Matrix<N>::row_iterator m_i = matrix.row_begin() + i;
70557  PPL_ASSERT(j < m_i.row_size());
70558#endif
70559  N& r_i_j = matrix[i][j];
70560  if (r_i_j > k) {
70561    r_i_j = k;
70562    if (marked_strongly_closed()) {
70563      reset_strongly_closed();
70564    }
70565  }
70566}
70567
70568template <typename T>
70569inline void
70570Octagonal_Shape<T>
70571::add_octagonal_constraint(const dimension_type i,
70572                           const dimension_type j,
70573                           Coefficient_traits::const_reference numer,
70574                           Coefficient_traits::const_reference denom) {
70575#ifndef NDEBUG
70576  // Private method: the caller has to ensure the following.
70577  PPL_ASSERT(i < 2*space_dim && j < 2*space_dim && i != j);
70578  typename OR_Matrix<N>::row_iterator m_i = matrix.row_begin() + i;
70579  PPL_ASSERT(j < m_i.row_size());
70580  PPL_ASSERT(denom != 0);
70581#endif
70582  PPL_DIRTY_TEMP(N, k);
70583  div_round_up(k, numer, denom);
70584  add_octagonal_constraint(i, j, k);
70585}
70586
70587template <typename T>
70588inline void
70589Octagonal_Shape<T>::add_constraints(const Constraint_System& cs) {
70590  for (Constraint_System::const_iterator i = cs.begin(),
70591         i_end = cs.end(); i != i_end; ++i) {
70592    add_constraint(*i);
70593  }
70594}
70595
70596template <typename T>
70597inline void
70598Octagonal_Shape<T>::add_recycled_constraints(Constraint_System& cs) {
70599  add_constraints(cs);
70600}
70601
70602template <typename T>
70603inline void
70604Octagonal_Shape<T>::add_recycled_congruences(Congruence_System& cgs) {
70605  add_congruences(cgs);
70606}
70607
70608template <typename T>
70609inline void
70610Octagonal_Shape<T>::add_congruences(const Congruence_System& cgs) {
70611  for (Congruence_System::const_iterator i = cgs.begin(),
70612         cgs_end = cgs.end(); i != cgs_end; ++i) {
70613    add_congruence(*i);
70614  }
70615}
70616
70617template <typename T>
70618inline void
70619Octagonal_Shape<T>::refine_with_constraint(const Constraint& c) {
70620  // Dimension-compatibility check.
70621  if (c.space_dimension() > space_dimension()) {
70622    throw_dimension_incompatible("refine_with_constraint(c)", c);
70623  }
70624
70625  if (!marked_empty()) {
70626    refine_no_check(c);
70627  }
70628}
70629
70630template <typename T>
70631inline void
70632Octagonal_Shape<T>::refine_with_constraints(const Constraint_System& cs) {
70633  // Dimension-compatibility check.
70634  if (cs.space_dimension() > space_dimension()) {
70635    throw_invalid_argument("refine_with_constraints(cs)",
70636                           "cs and *this are space-dimension incompatible");
70637  }
70638
70639  for (Constraint_System::const_iterator i = cs.begin(),
70640         cs_end = cs.end(); !marked_empty() && i != cs_end; ++i) {
70641    refine_no_check(*i);
70642  }
70643}
70644
70645template <typename T>
70646inline void
70647Octagonal_Shape<T>::refine_with_congruence(const Congruence& cg) {
70648  const dimension_type cg_space_dim = cg.space_dimension();
70649  // Dimension-compatibility check.
70650  if (cg_space_dim > space_dimension()) {
70651    throw_dimension_incompatible("refine_with_congruence(cg)", cg);
70652  }
70653  if (!marked_empty()) {
70654    refine_no_check(cg);
70655  }
70656}
70657
70658template <typename T>
70659void
70660Octagonal_Shape<T>::refine_with_congruences(const Congruence_System& cgs) {
70661  // Dimension-compatibility check.
70662  if (cgs.space_dimension() > space_dimension()) {
70663    throw_invalid_argument("refine_with_congruences(cgs)",
70664                           "cgs and *this are space-dimension incompatible");
70665  }
70666
70667  for (Congruence_System::const_iterator i = cgs.begin(),
70668         cgs_end = cgs.end(); !marked_empty() && i != cgs_end; ++i) {
70669    refine_no_check(*i);
70670  }
70671}
70672
70673template <typename T>
70674inline void
70675Octagonal_Shape<T>::refine_no_check(const Congruence& cg) {
70676  PPL_ASSERT(!marked_empty());
70677  PPL_ASSERT(cg.space_dimension() <= space_dimension());
70678
70679  if (cg.is_proper_congruence()) {
70680    if (cg.is_inconsistent()) {
70681      set_empty();
70682    }
70683    // Other proper congruences are just ignored.
70684    return;
70685  }
70686
70687  PPL_ASSERT(cg.is_equality());
70688  Constraint c(cg);
70689  refine_no_check(c);
70690}
70691
70692template <typename T>
70693inline bool
70694Octagonal_Shape<T>::can_recycle_constraint_systems() {
70695  return false;
70696}
70697
70698template <typename T>
70699inline bool
70700Octagonal_Shape<T>::can_recycle_congruence_systems() {
70701  return false;
70702}
70703
70704template <typename T>
70705inline void
70706Octagonal_Shape<T>
70707::remove_higher_space_dimensions(const dimension_type new_dimension) {
70708  // Dimension-compatibility check.
70709  if (new_dimension > space_dim) {
70710    throw_dimension_incompatible("remove_higher_space_dimension(nd)",
70711                                 new_dimension);
70712  }
70713  // The removal of no dimensions from any octagon is a no-op.
70714  // Note that this case also captures the only legal removal of
70715  // dimensions from an octagon in a 0-dim space.
70716  if (new_dimension == space_dim) {
70717    PPL_ASSERT(OK());
70718    return;
70719  }
70720
70721  strong_closure_assign();
70722  matrix.shrink(new_dimension);
70723  // When we remove all dimensions from a non-empty octagon,
70724  // we obtain the zero-dimensional universe octagon.
70725  if (new_dimension == 0 && !marked_empty()) {
70726    set_zero_dim_univ();
70727  }
70728  space_dim = new_dimension;
70729  PPL_ASSERT(OK());
70730}
70731
70732template <typename T>
70733void
70734Octagonal_Shape<T>::wrap_assign(const Variables_Set& vars,
70735                                Bounded_Integer_Type_Width w,
70736                                Bounded_Integer_Type_Representation r,
70737                                Bounded_Integer_Type_Overflow o,
70738                                const Constraint_System* cs_p,
70739                                unsigned complexity_threshold,
70740                                bool wrap_individually) {
70741  Implementation::wrap_assign(*this,
70742                              vars, w, r, o, cs_p,
70743                              complexity_threshold, wrap_individually,
70744                              "Octagonal_Shape");
70745}
70746
70747template <typename T>
70748inline void
70749Octagonal_Shape<T>::widening_assign(const Octagonal_Shape& y, unsigned* tp) {
70750  BHMZ05_widening_assign(y, tp);
70751}
70752
70753template <typename T>
70754inline void
70755Octagonal_Shape<T>::CC76_extrapolation_assign(const Octagonal_Shape& y,
70756                                              unsigned* tp) {
70757  static N stop_points[] = {
70758    N(-2, ROUND_UP),
70759    N(-1, ROUND_UP),
70760    N( 0, ROUND_UP),
70761    N( 1, ROUND_UP),
70762    N( 2, ROUND_UP)
70763  };
70764  CC76_extrapolation_assign(y,
70765                            stop_points,
70766                            stop_points
70767                            + sizeof(stop_points)/sizeof(stop_points[0]),
70768                            tp);
70769}
70770
70771template <typename T>
70772inline void
70773Octagonal_Shape<T>::time_elapse_assign(const Octagonal_Shape& y) {
70774  // Dimension-compatibility check.
70775  if (space_dimension() != y.space_dimension()) {
70776    throw_dimension_incompatible("time_elapse_assign(y)", y);
70777  }
70778  // Compute time-elapse on polyhedra.
70779  // TODO: provide a direct implementation.
70780  C_Polyhedron ph_x(constraints());
70781  C_Polyhedron ph_y(y.constraints());
70782  ph_x.time_elapse_assign(ph_y);
70783  Octagonal_Shape<T> x(ph_x);
70784  m_swap(x);
70785  PPL_ASSERT(OK());
70786}
70787
70788template <typename T>
70789inline bool
70790Octagonal_Shape<T>::strictly_contains(const Octagonal_Shape& y) const {
70791  const Octagonal_Shape<T>& x = *this;
70792  return x.contains(y) && !y.contains(x);
70793}
70794
70795template <typename T>
70796template <typename Interval_Info>
70797inline void
70798Octagonal_Shape<T>::generalized_refine_with_linear_form_inequality(
70799                    const Linear_Form< Interval<T, Interval_Info> >& left,
70800                    const Linear_Form< Interval<T, Interval_Info> >& right,
70801                    const Relation_Symbol relsym) {
70802  switch (relsym) {
70803  case EQUAL:
70804    // TODO: see if we can handle this case more efficiently.
70805    refine_with_linear_form_inequality(left, right);
70806    refine_with_linear_form_inequality(right, left);
70807    break;
70808  case LESS_THAN:
70809  case LESS_OR_EQUAL:
70810    refine_with_linear_form_inequality(left, right);
70811    break;
70812  case GREATER_THAN:
70813  case GREATER_OR_EQUAL:
70814    refine_with_linear_form_inequality(right, left);
70815    break;
70816  case NOT_EQUAL:
70817    break;
70818  default:
70819    PPL_UNREACHABLE;
70820    break;
70821  }
70822}
70823
70824template <typename T>
70825template <typename Interval_Info>
70826inline void
70827Octagonal_Shape<T>::
70828refine_fp_interval_abstract_store(
70829          Box< Interval<T, Interval_Info> >& store) const {
70830
70831  // Check that T is a floating point type.
70832  PPL_COMPILE_TIME_CHECK(!std::numeric_limits<T>::is_exact,
70833                     "Octagonal_Shape<T>::refine_fp_interval_abstract_store:"
70834                     " T not a floating point type.");
70835
70836  typedef Interval<T, Interval_Info> FP_Interval_Type;
70837  store.intersection_assign(Box<FP_Interval_Type>(*this));
70838
70839}
70840
70841/*! \relates Octagonal_Shape */
70842template <typename Temp, typename To, typename T>
70843inline bool
70844rectilinear_distance_assign(Checked_Number<To, Extended_Number_Policy>& r,
70845                            const Octagonal_Shape<T>& x,
70846                            const Octagonal_Shape<T>& y,
70847                            const Rounding_Dir dir,
70848                            Temp& tmp0,
70849                            Temp& tmp1,
70850                            Temp& tmp2) {
70851  // Dimension-compatibility check.
70852  if (x.space_dim != y.space_dim) {
70853    return false;
70854  }
70855  // Zero-dim OSs are equal if and only if they are both empty or universe.
70856  if (x.space_dim == 0) {
70857    if (x.marked_empty() == y.marked_empty()) {
70858      assign_r(r, 0, ROUND_NOT_NEEDED);
70859    }
70860    else {
70861      assign_r(r, PLUS_INFINITY, ROUND_NOT_NEEDED);
70862    }
70863    return true;
70864  }
70865
70866  // The distance computation requires strong closure.
70867  x.strong_closure_assign();
70868  y.strong_closure_assign();
70869
70870  // If one of two OSs is empty, then they are equal if and only if
70871  // the other OS is empty too.
70872  if (x.marked_empty() ||  y.marked_empty()) {
70873    if (x.marked_empty() == y.marked_empty()) {
70874      assign_r(r, 0, ROUND_NOT_NEEDED);
70875    }
70876    else {
70877      assign_r(r, PLUS_INFINITY, ROUND_NOT_NEEDED);
70878    }
70879    return true;
70880  }
70881
70882  return rectilinear_distance_assign(r, x.matrix, y.matrix, dir,
70883                                     tmp0, tmp1, tmp2);
70884}
70885
70886/*! \relates Octagonal_Shape */
70887template <typename Temp, typename To, typename T>
70888inline bool
70889rectilinear_distance_assign(Checked_Number<To, Extended_Number_Policy>& r,
70890                            const Octagonal_Shape<T>& x,
70891                            const Octagonal_Shape<T>& y,
70892                            const Rounding_Dir dir) {
70893  typedef Checked_Number<Temp, Extended_Number_Policy> Checked_Temp;
70894  PPL_DIRTY_TEMP(Checked_Temp, tmp0);
70895  PPL_DIRTY_TEMP(Checked_Temp, tmp1);
70896  PPL_DIRTY_TEMP(Checked_Temp, tmp2);
70897  return rectilinear_distance_assign(r, x, y, dir, tmp0, tmp1, tmp2);
70898}
70899
70900/*! \relates Octagonal_Shape */
70901template <typename To, typename T>
70902inline bool
70903rectilinear_distance_assign(Checked_Number<To, Extended_Number_Policy>& r,
70904                            const Octagonal_Shape<T>& x,
70905                            const Octagonal_Shape<T>& y,
70906                            const Rounding_Dir dir) {
70907  return rectilinear_distance_assign<To, To, T>(r, x, y, dir);
70908}
70909
70910/*! \relates Octagonal_Shape */
70911template <typename Temp, typename To, typename T>
70912inline bool
70913euclidean_distance_assign(Checked_Number<To, Extended_Number_Policy>& r,
70914                          const Octagonal_Shape<T>& x,
70915                          const Octagonal_Shape<T>& y,
70916                          const Rounding_Dir dir,
70917                          Temp& tmp0,
70918                          Temp& tmp1,
70919                          Temp& tmp2) {
70920  // Dimension-compatibility check.
70921  if (x.space_dim != y.space_dim) {
70922    return false;
70923  }
70924
70925  // Zero-dim OSs are equal if and only if they are both empty or universe.
70926  if (x.space_dim == 0) {
70927    if (x.marked_empty() == y.marked_empty()) {
70928      assign_r(r, 0, ROUND_NOT_NEEDED);
70929    }
70930    else {
70931      assign_r(r, PLUS_INFINITY, ROUND_NOT_NEEDED);
70932    }
70933    return true;
70934  }
70935
70936  // The distance computation requires strong closure.
70937  x.strong_closure_assign();
70938  y.strong_closure_assign();
70939
70940  // If one of two OSs is empty, then they are equal if and only if
70941  // the other OS is empty too.
70942  if (x.marked_empty() ||  y.marked_empty()) {
70943    if (x.marked_empty() == y.marked_empty()) {
70944      assign_r(r, 0, ROUND_NOT_NEEDED);
70945    }
70946    else {
70947      assign_r(r, PLUS_INFINITY, ROUND_NOT_NEEDED);
70948    }
70949    return true;
70950  }
70951
70952  return euclidean_distance_assign(r, x.matrix, y.matrix, dir,
70953                                   tmp0, tmp1, tmp2);
70954}
70955
70956/*! \relates Octagonal_Shape */
70957template <typename Temp, typename To, typename T>
70958inline bool
70959euclidean_distance_assign(Checked_Number<To, Extended_Number_Policy>& r,
70960                          const Octagonal_Shape<T>& x,
70961                          const Octagonal_Shape<T>& y,
70962                          const Rounding_Dir dir) {
70963  typedef Checked_Number<Temp, Extended_Number_Policy> Checked_Temp;
70964  PPL_DIRTY_TEMP(Checked_Temp, tmp0);
70965  PPL_DIRTY_TEMP(Checked_Temp, tmp1);
70966  PPL_DIRTY_TEMP(Checked_Temp, tmp2);
70967  return euclidean_distance_assign(r, x, y, dir, tmp0, tmp1, tmp2);
70968}
70969
70970/*! \relates Octagonal_Shape */
70971template <typename To, typename T>
70972inline bool
70973euclidean_distance_assign(Checked_Number<To, Extended_Number_Policy>& r,
70974                          const Octagonal_Shape<T>& x,
70975                          const Octagonal_Shape<T>& y,
70976                          const Rounding_Dir dir) {
70977  return euclidean_distance_assign<To, To, T>(r, x, y, dir);
70978}
70979
70980/*! \relates Octagonal_Shape */
70981template <typename Temp, typename To, typename T>
70982inline bool
70983l_infinity_distance_assign(Checked_Number<To, Extended_Number_Policy>& r,
70984                           const Octagonal_Shape<T>& x,
70985                           const Octagonal_Shape<T>& y,
70986                           const Rounding_Dir dir,
70987                           Temp& tmp0,
70988                           Temp& tmp1,
70989                           Temp& tmp2) {
70990  // Dimension-compatibility check.
70991  if (x.space_dim != y.space_dim) {
70992    return false;
70993  }
70994  // Zero-dim OSs are equal if and only if they are both empty or universe.
70995  if (x.space_dim == 0) {
70996    if (x.marked_empty() == y.marked_empty()) {
70997      assign_r(r, 0, ROUND_NOT_NEEDED);
70998    }
70999    else {
71000      assign_r(r, PLUS_INFINITY, ROUND_NOT_NEEDED);
71001    }
71002    return true;
71003  }
71004
71005  // The distance computation requires strong closure.
71006  x.strong_closure_assign();
71007  y.strong_closure_assign();
71008
71009  // If one of two OSs is empty, then they are equal if and only if
71010  // the other OS is empty too.
71011  if (x.marked_empty() ||  y.marked_empty()) {
71012    if (x.marked_empty() == y.marked_empty()) {
71013      assign_r(r, 0, ROUND_NOT_NEEDED);
71014    }
71015    else {
71016      assign_r(r, PLUS_INFINITY, ROUND_NOT_NEEDED);
71017    }
71018    return true;
71019  }
71020
71021  return l_infinity_distance_assign(r, x.matrix, y.matrix, dir,
71022                                    tmp0, tmp1, tmp2);
71023}
71024
71025/*! \relates Octagonal_Shape */
71026template <typename Temp, typename To, typename T>
71027inline bool
71028l_infinity_distance_assign(Checked_Number<To, Extended_Number_Policy>& r,
71029                           const Octagonal_Shape<T>& x,
71030                           const Octagonal_Shape<T>& y,
71031                           const Rounding_Dir dir) {
71032  typedef Checked_Number<Temp, Extended_Number_Policy> Checked_Temp;
71033  PPL_DIRTY_TEMP(Checked_Temp, tmp0);
71034  PPL_DIRTY_TEMP(Checked_Temp, tmp1);
71035  PPL_DIRTY_TEMP(Checked_Temp, tmp2);
71036  return l_infinity_distance_assign(r, x, y, dir, tmp0, tmp1, tmp2);
71037}
71038
71039/*! \relates Octagonal_Shape */
71040template <typename To, typename T>
71041inline bool
71042l_infinity_distance_assign(Checked_Number<To, Extended_Number_Policy>& r,
71043                           const Octagonal_Shape<T>& x,
71044                           const Octagonal_Shape<T>& y,
71045                           const Rounding_Dir dir) {
71046  return l_infinity_distance_assign<To, To, T>(r, x, y, dir);
71047}
71048
71049template <typename T>
71050inline memory_size_type
71051Octagonal_Shape<T>::total_memory_in_bytes() const {
71052  return sizeof(*this) + external_memory_in_bytes();
71053}
71054
71055template <typename T>
71056inline int32_t
71057Octagonal_Shape<T>::hash_code() const {
71058  return hash_code_from_dimension(space_dimension());
71059}
71060
71061template <typename T>
71062inline void
71063Octagonal_Shape<T>::drop_some_non_integer_points_helper(N& elem) {
71064  if (!is_integer(elem)) {
71065#ifndef NDEBUG
71066    Result r =
71067#endif
71068    floor_assign_r(elem, elem, ROUND_DOWN);
71069    PPL_ASSERT(r == V_EQ);
71070    reset_strongly_closed();
71071  }
71072}
71073
71074/*! \relates Octagonal_Shape */
71075template <typename T>
71076inline void
71077swap(Octagonal_Shape<T>& x, Octagonal_Shape<T>& y) {
71078  x.m_swap(y);
71079}
71080
71081} // namespace Parma_Polyhedra_Library
71082
71083/* Automatically generated from PPL source file ../src/Octagonal_Shape_templates.hh line 1. */
71084/* Octagonal_Shape class implementation: non-inline template functions.
71085*/
71086
71087
71088/* Automatically generated from PPL source file ../src/Octagonal_Shape_templates.hh line 35. */
71089#include <vector>
71090#include <deque>
71091#include <string>
71092#include <iostream>
71093#include <sstream>
71094#include <stdexcept>
71095#include <algorithm>
71096
71097namespace Parma_Polyhedra_Library {
71098
71099template <typename T>
71100Octagonal_Shape<T>::Octagonal_Shape(const Polyhedron& ph,
71101                                    const Complexity_Class complexity)
71102  : matrix(0), space_dim(0), status() {
71103  const dimension_type num_dimensions = ph.space_dimension();
71104
71105  if (ph.marked_empty()) {
71106    *this = Octagonal_Shape(num_dimensions, EMPTY);
71107    return;
71108  }
71109
71110  if (num_dimensions == 0) {
71111    *this = Octagonal_Shape(num_dimensions, UNIVERSE);
71112    return;
71113  }
71114
71115  // Build from generators when we do not care about complexity
71116  // or when the process has polynomial complexity.
71117  if (complexity == ANY_COMPLEXITY
71118      || (!ph.has_pending_constraints() && ph.generators_are_up_to_date())) {
71119    *this = Octagonal_Shape(ph.generators());
71120    return;
71121  }
71122
71123  // We cannot afford exponential complexity, we do not have a complete set
71124  // of generators for the polyhedron, and the polyhedron is not trivially
71125  // empty or zero-dimensional.  Constraints, however, are up to date.
71126  PPL_ASSERT(ph.constraints_are_up_to_date());
71127
71128  if (!ph.has_something_pending() && ph.constraints_are_minimized()) {
71129    // If the constraint system of the polyhedron is minimized,
71130    // the test `is_universe()' has polynomial complexity.
71131    if (ph.is_universe()) {
71132      *this = Octagonal_Shape(num_dimensions, UNIVERSE);
71133      return;
71134    }
71135  }
71136
71137  // See if there is at least one inconsistent constraint in `ph.con_sys'.
71138  for (Constraint_System::const_iterator i = ph.con_sys.begin(),
71139         cs_end = ph.con_sys.end(); i != cs_end; ++i) {
71140    if (i->is_inconsistent()) {
71141      *this = Octagonal_Shape(num_dimensions, EMPTY);
71142      return;
71143    }
71144  }
71145
71146  // If `complexity' allows it, use simplex to derive the exact (modulo
71147  // the fact that our OSs are topologically closed) variable bounds.
71148  if (complexity == SIMPLEX_COMPLEXITY) {
71149    MIP_Problem lp(num_dimensions);
71150    lp.set_optimization_mode(MAXIMIZATION);
71151
71152    const Constraint_System& ph_cs = ph.constraints();
71153    if (!ph_cs.has_strict_inequalities()) {
71154      lp.add_constraints(ph_cs);
71155    }
71156    else {
71157      // Adding to `lp' a topologically closed version of `ph_cs'.
71158      for (Constraint_System::const_iterator i = ph_cs.begin(),
71159             ph_cs_end = ph_cs.end(); i != ph_cs_end; ++i) {
71160        const Constraint& c = *i;
71161        if (c.is_strict_inequality()) {
71162          Linear_Expression expr(c.expression());
71163          lp.add_constraint(expr >= 0);
71164        }
71165        else {
71166          lp.add_constraint(c);
71167        }
71168      }
71169    }
71170
71171    // Check for unsatisfiability.
71172    if (!lp.is_satisfiable()) {
71173      *this = Octagonal_Shape<T>(num_dimensions, EMPTY);
71174      return;
71175    }
71176
71177    // Start with a universe OS that will be refined by the simplex.
71178    *this = Octagonal_Shape<T>(num_dimensions, UNIVERSE);
71179    // Get all the upper bounds.
71180    Generator g(point());
71181    PPL_DIRTY_TEMP_COEFFICIENT(numer);
71182    PPL_DIRTY_TEMP_COEFFICIENT(denom);
71183    for (dimension_type i = 0; i < num_dimensions; ++i) {
71184      Variable x(i);
71185      // Evaluate optimal upper bound for `x <= ub'.
71186      lp.set_objective_function(x);
71187      if (lp.solve() == OPTIMIZED_MIP_PROBLEM) {
71188        g = lp.optimizing_point();
71189        lp.evaluate_objective_function(g, numer, denom);
71190        numer *= 2;
71191        div_round_up(matrix[2*i + 1][2*i], numer, denom);
71192      }
71193      // Evaluate optimal upper bounds for `x + y <= ub'.
71194      for (dimension_type j = 0; j < i; ++j) {
71195        Variable y(j);
71196        lp.set_objective_function(x + y);
71197        if (lp.solve() == OPTIMIZED_MIP_PROBLEM) {
71198          g = lp.optimizing_point();
71199          lp.evaluate_objective_function(g, numer, denom);
71200          div_round_up(matrix[2*i + 1][2*j], numer, denom);
71201        }
71202      }
71203      // Evaluate optimal upper bound for `x - y <= ub'.
71204      for (dimension_type j = 0; j < num_dimensions; ++j) {
71205        if (i == j) {
71206          continue;
71207        }
71208        Variable y(j);
71209        lp.set_objective_function(x - y);
71210        if (lp.solve() == OPTIMIZED_MIP_PROBLEM) {
71211          g = lp.optimizing_point();
71212          lp.evaluate_objective_function(g, numer, denom);
71213          div_round_up(((i < j) ?
71214                        matrix[2*j][2*i]
71215                        : matrix[2*i + 1][2*j + 1]),
71216                       numer, denom);
71217        }
71218      }
71219      // Evaluate optimal upper bound for `y - x <= ub'.
71220      for (dimension_type j = 0; j < num_dimensions; ++j) {
71221        if (i == j) {
71222          continue;
71223        }
71224        Variable y(j);
71225        lp.set_objective_function(x - y);
71226        if (lp.solve() == OPTIMIZED_MIP_PROBLEM) {
71227          g = lp.optimizing_point();
71228          lp.evaluate_objective_function(g, numer, denom);
71229          div_round_up(((i < j)
71230                        ? matrix[2*j][2*i]
71231                        : matrix[2*i + 1][2*j + 1]),
71232                       numer, denom);
71233        }
71234      }
71235      // Evaluate optimal upper bound for `-x - y <= ub'.
71236      for (dimension_type j = 0; j < i; ++j) {
71237        Variable y(j);
71238        lp.set_objective_function(-x - y);
71239        if (lp.solve() == OPTIMIZED_MIP_PROBLEM) {
71240          g = lp.optimizing_point();
71241          lp.evaluate_objective_function(g, numer, denom);
71242          div_round_up(matrix[2*i][2*j + 1], numer, denom);
71243        }
71244      }
71245      // Evaluate optimal upper bound for `-x <= ub'.
71246      lp.set_objective_function(-x);
71247      if (lp.solve() == OPTIMIZED_MIP_PROBLEM) {
71248        g = lp.optimizing_point();
71249        lp.evaluate_objective_function(g, numer, denom);
71250        numer *= 2;
71251        div_round_up(matrix[2*i][2*i + 1], numer, denom);
71252      }
71253    }
71254    set_strongly_closed();
71255    PPL_ASSERT(OK());
71256    return;
71257  }
71258
71259  // Extract easy-to-find bounds from constraints.
71260  PPL_ASSERT(complexity == POLYNOMIAL_COMPLEXITY);
71261  *this = Octagonal_Shape(num_dimensions, UNIVERSE);
71262  refine_with_constraints(ph.constraints());
71263}
71264
71265template <typename T>
71266Octagonal_Shape<T>::Octagonal_Shape(const Generator_System& gs)
71267  : matrix(gs.space_dimension()),
71268    space_dim(gs.space_dimension()),
71269    status() {
71270  const Generator_System::const_iterator gs_begin = gs.begin();
71271  const Generator_System::const_iterator gs_end = gs.end();
71272  if (gs_begin == gs_end) {
71273    // An empty generator system defines the empty polyhedron.
71274    set_empty();
71275    return;
71276  }
71277
71278  typedef typename OR_Matrix<N>::row_reference_type row_reference;
71279  typename OR_Matrix<N>::row_iterator mat_begin = matrix.row_begin();
71280
71281  PPL_DIRTY_TEMP(N, tmp);
71282  bool mat_initialized = false;
71283  bool point_seen = false;
71284  // Going through all the points and closure points.
71285  for (Generator_System::const_iterator k = gs_begin; k != gs_end; ++k) {
71286    const Generator& g = *k;
71287    switch (g.type()) {
71288    case Generator::POINT:
71289      point_seen = true;
71290      // Intentionally fall through.
71291    case Generator::CLOSURE_POINT:
71292      if (!mat_initialized) {
71293        // When handling the first (closure) point, we initialize the matrix.
71294        mat_initialized = true;
71295        const Coefficient& d = g.divisor();
71296        // TODO: This can be optimized more, if needed, exploiting the
71297        // (possible) sparseness of g. Also consider if OR_Matrix should be
71298        // sparse, too.
71299        for (dimension_type i = 0; i < space_dim; ++i) {
71300          const Coefficient& g_i = g.coefficient(Variable(i));
71301          const dimension_type di = 2*i;
71302          row_reference x_i = *(mat_begin + di);
71303          row_reference x_ii = *(mat_begin + (di + 1));
71304          for (dimension_type j = 0; j < i; ++j) {
71305            const Coefficient& g_j = g.coefficient(Variable(j));
71306            const dimension_type dj = 2*j;
71307            // Set for any point the hyperplanes passing in the point
71308            // and having the octagonal gradient.
71309            // Let be P = [P_1, P_2, ..., P_n] point.
71310            // Hyperplanes: X_i - X_j = P_i - P_j.
71311            div_round_up(x_i[dj], g_j - g_i, d);
71312            div_round_up(x_ii[dj + 1], g_i - g_j, d);
71313            // Hyperplanes: X_i + X_j = P_i + P_j.
71314            div_round_up(x_i[dj + 1], -g_j - g_i, d);
71315            div_round_up(x_ii[dj], g_i + g_j, d);
71316          }
71317          // Hyperplanes: X_i = P_i.
71318          div_round_up(x_i[di + 1], -g_i - g_i, d);
71319          div_round_up(x_ii[di], g_i + g_i, d);
71320        }
71321      }
71322      else {
71323        // This is not the first point: the matrix already contains
71324        // valid values and we must compute maxima.
71325        const Coefficient& d = g.divisor();
71326        // TODO: This can be optimized more, if needed, exploiting the
71327        // (possible) sparseness of g. Also consider if OR_Matrix should be
71328        // sparse, too.
71329        for (dimension_type i = 0; i < space_dim; ++i) {
71330          const Coefficient& g_i = g.coefficient(Variable(i));
71331          const dimension_type di = 2*i;
71332          row_reference x_i = *(mat_begin + di);
71333          row_reference x_ii = *(mat_begin + (di + 1));
71334          for (dimension_type j = 0; j < i; ++j) {
71335            const Coefficient& g_j = g.coefficient(Variable(j));
71336            const dimension_type dj = 2*j;
71337            // Set for any point the straight lines passing in the point
71338            // and having the octagonal gradient; compute maxima values.
71339            // Let be P = [P_1, P_2, ..., P_n] point.
71340            // Hyperplane: X_i - X_j = max (P_i - P_j, const).
71341            div_round_up(tmp, g_j - g_i, d);
71342            max_assign(x_i[dj], tmp);
71343            div_round_up(tmp, g_i - g_j, d);
71344            max_assign(x_ii[dj + 1], tmp);
71345            // Hyperplane: X_i + X_j = max (P_i + P_j, const).
71346            div_round_up(tmp, -g_j - g_i, d);
71347            max_assign(x_i[dj + 1], tmp);
71348            div_round_up(tmp, g_i + g_j, d);
71349            max_assign(x_ii[dj], tmp);
71350          }
71351          // Hyperplane: X_i = max (P_i, const).
71352          div_round_up(tmp, -g_i - g_i, d);
71353          max_assign(x_i[di + 1], tmp);
71354          div_round_up(tmp, g_i + g_i, d);
71355          max_assign(x_ii[di], tmp);
71356        }
71357      }
71358      break;
71359    default:
71360      // Lines and rays temporarily ignored.
71361      break;
71362    }
71363  }
71364
71365  if (!point_seen) {
71366    // The generator system is not empty, but contains no points.
71367    throw_invalid_argument("Octagonal_Shape(gs)",
71368                           "the non-empty generator system gs "
71369                           "contains no points.");
71370  }
71371
71372  // Going through all the lines and rays.
71373  for (Generator_System::const_iterator k = gs_begin; k != gs_end; ++k) {
71374    const Generator& g = *k;
71375    switch (g.type()) {
71376    case Generator::LINE:
71377        // TODO: This can be optimized more, if needed, exploiting the
71378        // (possible) sparseness of g. Also consider if OR_Matrix should be
71379        // sparse, too.
71380        for (dimension_type i = 0; i < space_dim; ++i) {
71381          const Coefficient& g_i = g.coefficient(Variable(i));
71382          const dimension_type di = 2*i;
71383          row_reference x_i = *(mat_begin + di);
71384          row_reference x_ii = *(mat_begin + (di + 1));
71385          for (dimension_type j = 0; j < i; ++j) {
71386            const Coefficient& g_j = g.coefficient(Variable(j));
71387            const dimension_type dj = 2*j;
71388            // Set for any line the right limit.
71389            if (g_i != g_j) {
71390              // Hyperplane: X_i - X_j <=/>= +Inf.
71391              assign_r(x_i[dj], PLUS_INFINITY, ROUND_NOT_NEEDED);
71392              assign_r(x_ii[dj + 1], PLUS_INFINITY, ROUND_NOT_NEEDED);
71393            }
71394            if (g_i != -g_j) {
71395              // Hyperplane: X_i + X_j <=/>= +Inf.
71396              assign_r(x_i[dj + 1], PLUS_INFINITY, ROUND_NOT_NEEDED);
71397              assign_r(x_ii[dj], PLUS_INFINITY, ROUND_NOT_NEEDED);
71398            }
71399          }
71400          if (g_i != 0) {
71401            // Hyperplane: X_i <=/>= +Inf.
71402            assign_r(x_i[di + 1], PLUS_INFINITY, ROUND_NOT_NEEDED);
71403            assign_r(x_ii[di], PLUS_INFINITY, ROUND_NOT_NEEDED);
71404          }
71405        }
71406      break;
71407    case Generator::RAY:
71408        // TODO: This can be optimized more, if needed, exploiting the
71409        // (possible) sparseness of g. Also consider if OR_Matrix should be
71410        // sparse, too.
71411        for (dimension_type i = 0; i < space_dim; ++i) {
71412          const Coefficient& g_i = g.coefficient(Variable(i));
71413          const dimension_type di = 2*i;
71414          row_reference x_i = *(mat_begin + di);
71415          row_reference x_ii = *(mat_begin + (di + 1));
71416          for (dimension_type j = 0; j < i; ++j) {
71417            const Coefficient& g_j = g.coefficient(Variable(j));
71418            const dimension_type dj = 2*j;
71419            // Set for any ray the right limit in the case
71420            // of the binary constraints.
71421            if (g_i < g_j) {
71422              // Hyperplane: X_i - X_j >= +Inf.
71423              assign_r(x_i[dj], PLUS_INFINITY, ROUND_NOT_NEEDED);
71424            }
71425            if (g_i > g_j) {
71426              // Hyperplane: X_i - X_j <= +Inf.
71427              assign_r(x_ii[dj + 1], PLUS_INFINITY, ROUND_NOT_NEEDED);
71428            }
71429            if (g_i < -g_j) {
71430              // Hyperplane: X_i + X_j >= +Inf.
71431              assign_r(x_i[dj + 1], PLUS_INFINITY, ROUND_NOT_NEEDED);
71432            }
71433            if (g_i > -g_j) {
71434              // Hyperplane: X_i + X_j <= +Inf.
71435              assign_r(x_ii[dj], PLUS_INFINITY, ROUND_NOT_NEEDED);
71436            }
71437          }
71438          // Case: unary constraints.
71439          if (g_i < 0) {
71440            // Hyperplane: X_i  = +Inf.
71441            assign_r(x_i[di + 1], PLUS_INFINITY, ROUND_NOT_NEEDED);
71442          }
71443          if (g_i > 0) {
71444            // Hyperplane: X_i  = +Inf.
71445            assign_r(x_ii[di], PLUS_INFINITY, ROUND_NOT_NEEDED);
71446          }
71447        }
71448      break;
71449    default:
71450      // Points and closure points already dealt with.
71451      break;
71452    }
71453  }
71454  set_strongly_closed();
71455  PPL_ASSERT(OK());
71456}
71457
71458template <typename T>
71459void
71460Octagonal_Shape<T>::add_constraint(const Constraint& c) {
71461  const dimension_type c_space_dim = c.space_dimension();
71462  // Dimension-compatibility check.
71463  if (c_space_dim > space_dim) {
71464    throw_dimension_incompatible("add_constraint(c)", c);
71465  }
71466  // Get rid of strict inequalities.
71467  if (c.is_strict_inequality()) {
71468    if (c.is_inconsistent()) {
71469      set_empty();
71470      return;
71471    }
71472    if (c.is_tautological()) {
71473      return;
71474    }
71475    // Nontrivial strict inequalities are not allowed.
71476    throw_invalid_argument("add_constraint(c)",
71477                           "strict inequalities are not allowed");
71478  }
71479
71480  dimension_type num_vars = 0;
71481  dimension_type i = 0;
71482  dimension_type j = 0;
71483  PPL_DIRTY_TEMP_COEFFICIENT(coeff);
71484  PPL_DIRTY_TEMP_COEFFICIENT(term);
71485  // Constraints that are not octagonal differences are not allowed.
71486  if (!Octagonal_Shape_Helper
71487    ::extract_octagonal_difference(c, c_space_dim, num_vars,
71488                                   i, j, coeff, term)) {
71489    throw_invalid_argument("add_constraint(c)",
71490                           "c is not an octagonal constraint");
71491  }
71492
71493  if (num_vars == 0) {
71494    // Dealing with a trivial constraint (not a strict inequality).
71495    if (c.inhomogeneous_term() < 0
71496        || (c.is_equality() && c.inhomogeneous_term() != 0)) {
71497      set_empty();
71498    }
71499    return;
71500  }
71501
71502  // Select the cell to be modified for the "<=" part of constraint.
71503  typename OR_Matrix<N>::row_iterator i_iter = matrix.row_begin() + i;
71504  typename OR_Matrix<N>::row_reference_type m_i = *i_iter;
71505  N& m_i_j = m_i[j];
71506  // Set `coeff' to the absolute value of itself.
71507  if (coeff < 0) {
71508    neg_assign(coeff);
71509  }
71510
71511  bool is_oct_changed = false;
71512  // Compute the bound for `m_i_j', rounding towards plus infinity.
71513  PPL_DIRTY_TEMP(N, d);
71514  div_round_up(d, term, coeff);
71515  if (m_i_j > d) {
71516    m_i_j = d;
71517    is_oct_changed = true;
71518  }
71519
71520  if (c.is_equality()) {
71521    // Select the cell to be modified for the ">=" part of constraint.
71522    if (i % 2 == 0) {
71523      ++i_iter;
71524    }
71525    else {
71526      --i_iter;
71527    }
71528
71529    typename OR_Matrix<N>::row_reference_type m_ci = *i_iter;
71530    using namespace Implementation::Octagonal_Shapes;
71531    dimension_type cj = coherent_index(j);
71532    N& m_ci_cj = m_ci[cj];
71533    // Also compute the bound for `m_ci_cj', rounding towards plus infinity.
71534    neg_assign(term);
71535    div_round_up(d, term, coeff);
71536    if (m_ci_cj > d) {
71537      m_ci_cj = d;
71538      is_oct_changed = true;
71539    }
71540  }
71541
71542  // This method does not preserve closure.
71543  if (is_oct_changed && marked_strongly_closed()) {
71544    reset_strongly_closed();
71545  }
71546  PPL_ASSERT(OK());
71547}
71548
71549template <typename T>
71550void
71551Octagonal_Shape<T>::add_congruence(const Congruence& cg) {
71552  const dimension_type cg_space_dim = cg.space_dimension();
71553  // Dimension-compatibility check:
71554  // the dimension of `cg' can not be greater than space_dim.
71555  if (space_dimension() < cg_space_dim) {
71556    throw_dimension_incompatible("add_congruence(cg)", cg);
71557  }
71558
71559  // Handle the case of proper congruences first.
71560  if (cg.is_proper_congruence()) {
71561    if (cg.is_tautological()) {
71562      return;
71563    }
71564    if (cg.is_inconsistent()) {
71565      set_empty();
71566      return;
71567    }
71568    // Non-trivial and proper congruences are not allowed.
71569    throw_invalid_argument("add_congruence(cg)",
71570                           "cg is a non-trivial, proper congruence");
71571  }
71572
71573  PPL_ASSERT(cg.is_equality());
71574  Constraint c(cg);
71575  add_constraint(c);
71576}
71577
71578template <typename T>
71579template <typename Interval_Info>
71580void
71581Octagonal_Shape<T>::refine_with_linear_form_inequality(
71582                    const Linear_Form< Interval<T, Interval_Info> >& left,
71583                    const Linear_Form< Interval<T, Interval_Info> >& right) {
71584
71585  // Check that T is a floating point type.
71586  PPL_COMPILE_TIME_CHECK(!std::numeric_limits<T>::is_exact,
71587                     "Octagonal_Shape<T>::refine_with_linear_form_inequality:"
71588                     " T not a floating point type.");
71589
71590  // We assume that the analyzer will not try to apply an unreachable filter.
71591  PPL_ASSERT(!marked_empty());
71592
71593  // Dimension-compatibility checks.
71594  // The dimensions of `left' and `right' should not be greater than the
71595  // dimension of `*this'.
71596  const dimension_type left_space_dim = left.space_dimension();
71597  if (space_dim < left_space_dim) {
71598    throw_dimension_incompatible(
71599          "refine_with_linear_form_inequality(left, right)", "left", left);
71600  }
71601
71602  const dimension_type right_space_dim = right.space_dimension();
71603  if (space_dim < right_space_dim) {
71604    throw_dimension_incompatible(
71605          "refine_with_linear_form_inequality(left, right)", "right", right);
71606  }
71607  // Number of non-zero coefficients in `left': will be set to
71608  // 0, 1, or 2, the latter value meaning any value greater than 1.
71609  dimension_type left_t = 0;
71610  // Variable-index of the last non-zero coefficient in `left', if any.
71611  dimension_type left_w_id = 0;
71612  // Number of non-zero coefficients in `right': will be set to
71613  // 0, 1, or 2, the latter value meaning any value greater than 1.
71614  dimension_type right_t = 0;
71615  // Variable-index of the last non-zero coefficient in `right', if any.
71616  dimension_type right_w_id = 0;
71617
71618  // Get information about the number of non-zero coefficients in `left'.
71619  for (dimension_type i = left_space_dim; i-- > 0; ) {
71620    if (left.coefficient(Variable(i)) != 0) {
71621      if (left_t++ == 1) {
71622        break;
71623      }
71624      else {
71625        left_w_id = i;
71626      }
71627    }
71628  }
71629
71630  // Get information about the number of non-zero coefficients in `right'.
71631  for (dimension_type i = right_space_dim; i-- > 0; ) {
71632    if (right.coefficient(Variable(i)) != 0) {
71633      if (right_t++ == 1) {
71634        break;
71635      }
71636      else {
71637        right_w_id = i;
71638      }
71639    }
71640  }
71641
71642  typedef typename OR_Matrix<N>::row_iterator row_iterator;
71643  typedef typename OR_Matrix<N>::row_reference_type row_reference;
71644  typedef Interval<T, Interval_Info> FP_Interval_Type;
71645
71646  // FIXME: there is plenty of duplicate code in the following lines. We could
71647  // shorten it at the expense of a bit of efficiency.
71648
71649  if (left_t == 0) {
71650    if (right_t == 0) {
71651      // The constraint involves constants only. Ignore it: it is up to
71652      // the analyzer to handle it.
71653      PPL_ASSERT(OK());
71654      return;
71655    }
71656
71657    if (right_t == 1) {
71658      // The constraint has the form [a-, a+] <= [b-, b+] + [c-, c+] * x.
71659      // Reduce it to the constraint +/-x <= b+ - a- if [c-, c+] = +/-[1, 1].
71660      const FP_Interval_Type& right_w_coeff =
71661                              right.coefficient(Variable(right_w_id));
71662      if (right_w_coeff == 1) {
71663        const dimension_type n_right = right_w_id * 2;
71664        PPL_DIRTY_TEMP(N, b_plus_minus_a_minus);
71665        const FP_Interval_Type& left_a = left.inhomogeneous_term();
71666        const FP_Interval_Type& right_b = right.inhomogeneous_term();
71667        sub_assign_r(b_plus_minus_a_minus, right_b.upper(), left_a.lower(),
71668                     ROUND_UP);
71669        mul_2exp_assign_r(b_plus_minus_a_minus, b_plus_minus_a_minus, 1,
71670                          ROUND_UP);
71671        add_octagonal_constraint(n_right, n_right + 1, b_plus_minus_a_minus);
71672        PPL_ASSERT(OK());
71673        return;
71674      }
71675
71676      if (right_w_coeff == -1) {
71677        const dimension_type n_right = right_w_id * 2;
71678        PPL_DIRTY_TEMP(N, b_plus_minus_a_minus);
71679        const FP_Interval_Type& left_a = left.inhomogeneous_term();
71680        const FP_Interval_Type& right_b = right.inhomogeneous_term();
71681        sub_assign_r(b_plus_minus_a_minus, right_b.upper(), left_a.lower(),
71682                     ROUND_UP);
71683        mul_2exp_assign_r(b_plus_minus_a_minus, b_plus_minus_a_minus, 1,
71684                          ROUND_UP);
71685        add_octagonal_constraint(n_right + 1, n_right, b_plus_minus_a_minus);
71686        PPL_ASSERT(OK());
71687        return;
71688      }
71689    }
71690  }
71691  else if (left_t == 1) {
71692    if (right_t == 0) {
71693      // The constraint has the form [b-, b+] + [c-, c+] * x <= [a-, a+]
71694      // Reduce it to the constraint +/-x <= a+ - b- if [c-, c+] = +/-[1, 1].
71695      const FP_Interval_Type& left_w_coeff =
71696                              left.coefficient(Variable(left_w_id));
71697      if (left_w_coeff == 1) {
71698        const dimension_type n_left = left_w_id * 2;
71699        PPL_DIRTY_TEMP(N, a_plus_minus_b_minus);
71700        const FP_Interval_Type& left_b = left.inhomogeneous_term();
71701        const FP_Interval_Type& right_a = right.inhomogeneous_term();
71702        sub_assign_r(a_plus_minus_b_minus, right_a.upper(), left_b.lower(),
71703                     ROUND_UP);
71704        mul_2exp_assign_r(a_plus_minus_b_minus, a_plus_minus_b_minus, 1,
71705                          ROUND_UP);
71706        add_octagonal_constraint(n_left + 1, n_left, a_plus_minus_b_minus);
71707        PPL_ASSERT(OK());
71708        return;
71709      }
71710
71711      if (left_w_coeff == -1) {
71712        const dimension_type n_left = left_w_id * 2;
71713        PPL_DIRTY_TEMP(N, a_plus_minus_b_minus);
71714        const FP_Interval_Type& left_b = left.inhomogeneous_term();
71715        const FP_Interval_Type& right_a = right.inhomogeneous_term();
71716        sub_assign_r(a_plus_minus_b_minus, right_a.upper(), left_b.lower(),
71717                     ROUND_UP);
71718        mul_2exp_assign_r(a_plus_minus_b_minus, a_plus_minus_b_minus, 1,
71719                          ROUND_UP);
71720        add_octagonal_constraint(n_left, n_left + 1, a_plus_minus_b_minus);
71721        PPL_ASSERT(OK());
71722        return;
71723      }
71724    }
71725
71726    if (right_t == 1) {
71727      // The constraint has the form
71728      // [a-, a+] + [b-, b+] * x <= [c-, c+] + [d-, d+] * y.
71729      // Reduce it to the constraint +/-x +/-y <= c+ - a-
71730      // if [b-, b+] = +/-[1, 1] and [d-, d+] = +/-[1, 1].
71731      const FP_Interval_Type& left_w_coeff =
71732                              left.coefficient(Variable(left_w_id));
71733      const FP_Interval_Type& right_w_coeff =
71734                              right.coefficient(Variable(right_w_id));
71735      bool is_left_coeff_one = (left_w_coeff == 1);
71736      bool is_left_coeff_minus_one = (left_w_coeff == -1);
71737      bool is_right_coeff_one = (right_w_coeff == 1);
71738      bool is_right_coeff_minus_one = (right_w_coeff == -1);
71739      if (left_w_id == right_w_id) {
71740        if ((is_left_coeff_one && is_right_coeff_one)
71741            || (is_left_coeff_minus_one && is_right_coeff_minus_one)) {
71742          // Here we have an identity or a constants-only constraint.
71743          PPL_ASSERT(OK());
71744          return;
71745        }
71746        if (is_left_coeff_one && is_right_coeff_minus_one) {
71747          // We fall back to a previous case
71748          // (but we do not need to multiply the result by two).
71749          const dimension_type n_left = left_w_id * 2;
71750          PPL_DIRTY_TEMP(N, a_plus_minus_b_minus);
71751          const FP_Interval_Type& left_b = left.inhomogeneous_term();
71752          const FP_Interval_Type& right_a = right.inhomogeneous_term();
71753          sub_assign_r(a_plus_minus_b_minus, right_a.upper(), left_b.lower(),
71754                       ROUND_UP);
71755          add_octagonal_constraint(n_left + 1, n_left, a_plus_minus_b_minus);
71756          PPL_ASSERT(OK());
71757          return;
71758        }
71759        if (is_left_coeff_minus_one && is_right_coeff_one) {
71760          // We fall back to a previous case
71761          // (but we do not need to multiply the result by two).
71762          const dimension_type n_left = left_w_id * 2;
71763          PPL_DIRTY_TEMP(N, a_plus_minus_b_minus);
71764          const FP_Interval_Type& left_b = left.inhomogeneous_term();
71765          const FP_Interval_Type& right_a = right.inhomogeneous_term();
71766          sub_assign_r(a_plus_minus_b_minus, right_a.upper(), left_b.lower(),
71767                       ROUND_UP);
71768          add_octagonal_constraint(n_left, n_left + 1, a_plus_minus_b_minus);
71769          PPL_ASSERT(OK());
71770          return;
71771        }
71772      }
71773      else if (is_left_coeff_one && is_right_coeff_one) {
71774        const dimension_type n_left = left_w_id * 2;
71775        const dimension_type n_right = right_w_id * 2;
71776        PPL_DIRTY_TEMP(N, c_plus_minus_a_minus);
71777        const FP_Interval_Type& left_a = left.inhomogeneous_term();
71778        const FP_Interval_Type& right_c = right.inhomogeneous_term();
71779        sub_assign_r(c_plus_minus_a_minus, right_c.upper(), left_a.lower(),
71780                     ROUND_UP);
71781        if (left_w_id < right_w_id) {
71782          add_octagonal_constraint(n_right, n_left, c_plus_minus_a_minus);
71783        }
71784        else {
71785          add_octagonal_constraint(n_left + 1, n_right + 1,
71786                                   c_plus_minus_a_minus);
71787        }
71788        PPL_ASSERT(OK());
71789        return;
71790      }
71791      if (is_left_coeff_one && is_right_coeff_minus_one) {
71792        const dimension_type n_left = left_w_id * 2;
71793        const dimension_type n_right = right_w_id * 2;
71794        PPL_DIRTY_TEMP(N, c_plus_minus_a_minus);
71795        const FP_Interval_Type& left_a = left.inhomogeneous_term();
71796        const FP_Interval_Type& right_c = right.inhomogeneous_term();
71797        sub_assign_r(c_plus_minus_a_minus, right_c.upper(), left_a.lower(),
71798                     ROUND_UP);
71799        if (left_w_id < right_w_id) {
71800          add_octagonal_constraint(n_right + 1, n_left, c_plus_minus_a_minus);
71801        }
71802        else {
71803          add_octagonal_constraint(n_left + 1, n_right, c_plus_minus_a_minus);
71804        }
71805        PPL_ASSERT(OK());
71806        return;
71807      }
71808      if (is_left_coeff_minus_one && is_right_coeff_one) {
71809        const dimension_type n_left = left_w_id * 2;
71810        const dimension_type n_right = right_w_id * 2;
71811        PPL_DIRTY_TEMP(N, c_plus_minus_a_minus);
71812        const FP_Interval_Type& left_a = left.inhomogeneous_term();
71813        const FP_Interval_Type& right_c = right.inhomogeneous_term();
71814        sub_assign_r(c_plus_minus_a_minus, right_c.upper(), left_a.lower(),
71815                     ROUND_UP);
71816        if (left_w_id < right_w_id) {
71817          add_octagonal_constraint(n_right, n_left + 1, c_plus_minus_a_minus);
71818        }
71819        else {
71820          add_octagonal_constraint(n_left, n_right + 1, c_plus_minus_a_minus);
71821        }
71822        PPL_ASSERT(OK());
71823        return;
71824      }
71825      if (is_left_coeff_minus_one && is_right_coeff_minus_one) {
71826        const dimension_type n_left = left_w_id * 2;
71827        const dimension_type n_right = right_w_id * 2;
71828        PPL_DIRTY_TEMP(N, c_plus_minus_a_minus);
71829        const FP_Interval_Type& left_a = left.inhomogeneous_term();
71830        const FP_Interval_Type& right_c = right.inhomogeneous_term();
71831        sub_assign_r(c_plus_minus_a_minus, right_c.upper(), left_a.lower(),
71832                     ROUND_UP);
71833        if (left_w_id < right_w_id) {
71834          add_octagonal_constraint(n_right + 1, n_left + 1,
71835                                   c_plus_minus_a_minus);
71836        }
71837        else {
71838          add_octagonal_constraint(n_left, n_right, c_plus_minus_a_minus);
71839        }
71840        PPL_ASSERT(OK());
71841        return;
71842      }
71843    }
71844  }
71845
71846  // General case.
71847
71848  // FIRST, update the binary constraints for each pair of DIFFERENT variables
71849  // in `left' and `right'.
71850
71851  // Declare temporaries outside of the loop.
71852  PPL_DIRTY_TEMP(N, low_coeff);
71853  PPL_DIRTY_TEMP(N, high_coeff);
71854  PPL_DIRTY_TEMP(N, upper_bound);
71855
71856  Linear_Form<FP_Interval_Type> right_minus_left(right);
71857  right_minus_left -= left;
71858
71859  dimension_type max_w_id = std::max(left_w_id, right_w_id);
71860  for (dimension_type first_v = 0; first_v < max_w_id; ++first_v) {
71861    for (dimension_type second_v = first_v + 1;
71862         second_v <= max_w_id; ++second_v) {
71863      const FP_Interval_Type& lfv_coefficient =
71864                        left.coefficient(Variable(first_v));
71865      const FP_Interval_Type& lsv_coefficient =
71866                        left.coefficient(Variable(second_v));
71867      const FP_Interval_Type& rfv_coefficient =
71868                        right.coefficient(Variable(first_v));
71869      const FP_Interval_Type& rsv_coefficient =
71870                        right.coefficient(Variable(second_v));
71871      // We update the constraints only when both variables appear in at
71872      // least one argument.
71873      bool do_update = false;
71874      assign_r(low_coeff, lfv_coefficient.lower(), ROUND_NOT_NEEDED);
71875      assign_r(high_coeff, lfv_coefficient.upper(), ROUND_NOT_NEEDED);
71876      if (low_coeff != 0 || high_coeff != 0) {
71877        assign_r(low_coeff, lsv_coefficient.lower(), ROUND_NOT_NEEDED);
71878        assign_r(high_coeff, lsv_coefficient.upper(), ROUND_NOT_NEEDED);
71879        if (low_coeff != 0 || high_coeff != 0) {
71880          do_update = true;
71881        }
71882        else {
71883          assign_r(low_coeff, rsv_coefficient.lower(), ROUND_NOT_NEEDED);
71884          assign_r(high_coeff, rsv_coefficient.upper(), ROUND_NOT_NEEDED);
71885          if (low_coeff != 0 || high_coeff != 0) {
71886            do_update = true;
71887          }
71888        }
71889      }
71890      else {
71891        assign_r(low_coeff, rfv_coefficient.lower(), ROUND_NOT_NEEDED);
71892        assign_r(high_coeff, rfv_coefficient.upper(), ROUND_NOT_NEEDED);
71893        if (low_coeff != 0 || high_coeff != 0) {
71894          assign_r(low_coeff, lsv_coefficient.lower(), ROUND_NOT_NEEDED);
71895          assign_r(high_coeff, lsv_coefficient.upper(), ROUND_NOT_NEEDED);
71896          if (low_coeff != 0 || high_coeff != 0) {
71897            do_update = true;
71898          }
71899          else {
71900            assign_r(low_coeff, rsv_coefficient.lower(), ROUND_NOT_NEEDED);
71901            assign_r(high_coeff, rsv_coefficient.upper(), ROUND_NOT_NEEDED);
71902            if (low_coeff != 0 || high_coeff != 0) {
71903              do_update = true;
71904            }
71905          }
71906        }
71907      }
71908
71909      if (do_update) {
71910        Variable first(first_v);
71911        Variable second(second_v);
71912        dimension_type n_first_var = first_v * 2;
71913        dimension_type n_second_var = second_v * 2;
71914        linear_form_upper_bound(right_minus_left - first + second,
71915                                upper_bound);
71916        add_octagonal_constraint(n_second_var + 1, n_first_var + 1,
71917                                 upper_bound);
71918        linear_form_upper_bound(right_minus_left + first + second,
71919                                upper_bound);
71920        add_octagonal_constraint(n_second_var + 1, n_first_var, upper_bound);
71921        linear_form_upper_bound(right_minus_left - first - second,
71922                                upper_bound);
71923        add_octagonal_constraint(n_second_var, n_first_var + 1, upper_bound);
71924        linear_form_upper_bound(right_minus_left + first - second,
71925                                upper_bound);
71926        add_octagonal_constraint(n_second_var, n_first_var, upper_bound);
71927      }
71928    }
71929  }
71930
71931  // Finally, update the unary constraints.
71932  for (dimension_type v = 0; v <= max_w_id; ++v) {
71933    const FP_Interval_Type& lv_coefficient =
71934                        left.coefficient(Variable(v));
71935    const FP_Interval_Type& rv_coefficient =
71936                        right.coefficient(Variable(v));
71937    // We update the constraints only if v appears in at least one of the
71938    // two arguments.
71939    bool do_update = false;
71940    assign_r(low_coeff, lv_coefficient.lower(), ROUND_NOT_NEEDED);
71941    assign_r(high_coeff, lv_coefficient.upper(), ROUND_NOT_NEEDED);
71942    if (low_coeff != 0 || high_coeff != 0) {
71943      do_update = true;
71944    }
71945    else {
71946      assign_r(low_coeff, rv_coefficient.lower(), ROUND_NOT_NEEDED);
71947      assign_r(high_coeff, rv_coefficient.upper(), ROUND_NOT_NEEDED);
71948      if (low_coeff != 0 || high_coeff != 0) {
71949        do_update = true;
71950      }
71951    }
71952
71953    if (do_update) {
71954      Variable var(v);
71955      dimension_type n_var = 2 * v;
71956      /*
71957        VERY DIRTY trick: since we need to keep the old unary constraints
71958        while computing the new ones, we momentarily keep the new coefficients
71959        in the main diagonal of the matrix. They will be moved later.
71960      */
71961      linear_form_upper_bound(right_minus_left + var, upper_bound);
71962      mul_2exp_assign_r(matrix[n_var + 1][n_var + 1], upper_bound, 1,
71963                        ROUND_UP);
71964      linear_form_upper_bound(right_minus_left - var, upper_bound);
71965      mul_2exp_assign_r(matrix[n_var][n_var], upper_bound, 1,
71966                        ROUND_UP);
71967    }
71968  }
71969
71970  /*
71971    Now move the newly computed coefficients from the main diagonal to
71972    their proper place, and restore +infinity on the diagonal.
71973  */
71974  row_iterator m_ite = matrix.row_begin();
71975  row_iterator m_end = matrix.row_end();
71976  for (dimension_type i = 0; m_ite != m_end; i += 2) {
71977    row_reference upper = *m_ite;
71978    N& ul = upper[i];
71979    add_octagonal_constraint(i, i + 1, ul);
71980    assign_r(ul, PLUS_INFINITY, ROUND_NOT_NEEDED);
71981    ++m_ite;
71982    row_reference lower = *m_ite;
71983    N& lr = lower[i + 1];
71984    add_octagonal_constraint(i + 1, i, lr);
71985    assign_r(lr, PLUS_INFINITY, ROUND_NOT_NEEDED);
71986    ++m_ite;
71987  }
71988  PPL_ASSERT(OK());
71989}
71990
71991template <typename T>
71992void
71993Octagonal_Shape<T>::refine_no_check(const Constraint& c) {
71994  PPL_ASSERT(!marked_empty());
71995  const dimension_type c_space_dim = c.space_dimension();
71996  PPL_ASSERT(c_space_dim <= space_dim);
71997
71998  dimension_type num_vars = 0;
71999  dimension_type i = 0;
72000  dimension_type j = 0;
72001  PPL_DIRTY_TEMP_COEFFICIENT(coeff);
72002  PPL_DIRTY_TEMP_COEFFICIENT(term);
72003  // Constraints that are not octagonal differences are ignored.
72004  if (!Octagonal_Shape_Helper
72005    ::extract_octagonal_difference(c, c_space_dim, num_vars,
72006                                   i, j, coeff, term)) {
72007    return;
72008  }
72009
72010  if (num_vars == 0) {
72011    const Coefficient& c_inhomo = c.inhomogeneous_term();
72012    // Dealing with a trivial constraint (maybe a strict inequality).
72013    if (c_inhomo < 0
72014        || (c_inhomo != 0 && c.is_equality())
72015        || (c_inhomo == 0 && c.is_strict_inequality())) {
72016      set_empty();
72017    }
72018    return;
72019  }
72020
72021  // Select the cell to be modified for the "<=" part of constraint.
72022  typename OR_Matrix<N>::row_iterator i_iter = matrix.row_begin() + i;
72023  typename OR_Matrix<N>::row_reference_type m_i = *i_iter;
72024  N& m_i_j = m_i[j];
72025  // Set `coeff' to the absolute value of itself.
72026  if (coeff < 0) {
72027    neg_assign(coeff);
72028  }
72029
72030  bool is_oct_changed = false;
72031  // Compute the bound for `m_i_j', rounding towards plus infinity.
72032  PPL_DIRTY_TEMP(N, d);
72033  div_round_up(d, term, coeff);
72034  if (m_i_j > d) {
72035    m_i_j = d;
72036    is_oct_changed = true;
72037  }
72038
72039  if (c.is_equality()) {
72040    // Select the cell to be modified for the ">=" part of constraint.
72041    if (i % 2 == 0) {
72042      ++i_iter;
72043    }
72044    else {
72045      --i_iter;
72046    }
72047
72048    typename OR_Matrix<N>::row_reference_type m_ci = *i_iter;
72049    using namespace Implementation::Octagonal_Shapes;
72050    dimension_type cj = coherent_index(j);
72051    N& m_ci_cj = m_ci[cj];
72052    // Also compute the bound for `m_ci_cj', rounding towards plus infinity.
72053    neg_assign(term);
72054    div_round_up(d, term, coeff);
72055    if (m_ci_cj > d) {
72056      m_ci_cj = d;
72057      is_oct_changed = true;
72058    }
72059  }
72060
72061  // This method does not preserve closure.
72062  if (is_oct_changed && marked_strongly_closed()) {
72063    reset_strongly_closed();
72064  }
72065  PPL_ASSERT(OK());
72066}
72067
72068template <typename T>
72069dimension_type
72070Octagonal_Shape<T>::affine_dimension() const {
72071  const dimension_type n_rows = matrix.num_rows();
72072  // A zero-space-dim shape always has affine dimension zero.
72073  if (n_rows == 0) {
72074    return 0;
72075  }
72076
72077  // Strong closure is necessary to detect emptiness
72078  // and all (possibly implicit) equalities.
72079  strong_closure_assign();
72080  if (marked_empty()) {
72081    return 0;
72082  }
72083
72084  // The vector `leaders' is used to represent non-singular
72085  // equivalence classes:
72086  // `leaders[i] == i' if and only if `i' is the leader of its
72087  // equivalence class (i.e., the minimum index in the class).
72088  std::vector<dimension_type> leaders;
72089  compute_leaders(leaders);
72090
72091  // Due to the splitting of variables, the affine dimension is the
72092  // number of non-singular positive zero-equivalence classes.
72093  dimension_type affine_dim = 0;
72094  for (dimension_type i = 0; i < n_rows; i += 2) {
72095    // Note: disregard the singular equivalence class.
72096    if (leaders[i] == i && leaders[i + 1] == i + 1) {
72097      ++affine_dim;
72098    }
72099  }
72100
72101  return affine_dim;
72102}
72103
72104template <typename T>
72105Congruence_System
72106Octagonal_Shape<T>::minimized_congruences() const {
72107  // Strong closure is necessary to detect emptiness
72108  // and all (possibly implicit) equalities.
72109  strong_closure_assign();
72110  Congruence_System cgs(space_dim);
72111
72112  if (space_dim == 0) {
72113    if (marked_empty()) {
72114      cgs = Congruence_System::zero_dim_empty();
72115    }
72116    return cgs;
72117  }
72118
72119  if (marked_empty()) {
72120    cgs.insert(Congruence::zero_dim_false());
72121    return cgs;
72122  }
72123
72124  // The vector `leaders' is used to represent equivalence classes:
72125  // `leaders[i] == i' if and only if `i' is the leader of its
72126  // equivalence class (i.e., the minimum index in the class).
72127  std::vector<dimension_type> leaders;
72128  compute_leaders(leaders);
72129
72130  PPL_DIRTY_TEMP_COEFFICIENT(numer);
72131  PPL_DIRTY_TEMP_COEFFICIENT(denom);
72132  for (dimension_type i = 0, i_end = 2*space_dim; i != i_end; i += 2) {
72133    const dimension_type lead_i = leaders[i];
72134    if (i == lead_i) {
72135      if (leaders[i + 1] == i) {
72136        // `i' is the leader of the singular equivalence class.
72137        goto singular;
72138      }
72139      else {
72140        // `i' is the leader of a non-singular equivalence class.
72141        continue;
72142      }
72143    }
72144    else {
72145      // `i' is not a leader.
72146      if (leaders[i + 1] == lead_i) {
72147        // `i' belongs to the singular equivalence class.
72148        goto singular;
72149      }
72150      else {
72151        // `i' does not belong to the singular equivalence class.
72152        goto non_singular;
72153      }
72154    }
72155
72156  singular:
72157    // `i' belongs to the singular equivalence class:
72158    // we have a unary equality constraint.
72159    {
72160      const Variable x(i/2);
72161      const N& c_ii_i = matrix[i + 1][i];
72162#ifndef NDEBUG
72163      const N& c_i_ii = matrix[i][i + 1];
72164      PPL_ASSERT(is_additive_inverse(c_i_ii, c_ii_i));
72165#endif
72166      numer_denom(c_ii_i, numer, denom);
72167      denom *= 2;
72168      cgs.insert(denom*x == numer);
72169    }
72170    continue;
72171
72172  non_singular:
72173    // `i' does not belong to the singular equivalence class.
72174    // we have a binary equality constraint.
72175    {
72176      const N& c_i_li = matrix[i][lead_i];
72177#ifndef NDEBUG
72178      using namespace Implementation::Octagonal_Shapes;
72179      const N& c_ii_lii = matrix[i + 1][coherent_index(lead_i)];
72180      PPL_ASSERT(is_additive_inverse(c_ii_lii, c_i_li));
72181#endif
72182      const Variable x(lead_i/2);
72183      const Variable y(i/2);
72184      numer_denom(c_i_li, numer, denom);
72185      if (lead_i % 2 == 0) {
72186        cgs.insert(denom*x - denom*y == numer);
72187      }
72188      else {
72189        cgs.insert(denom*x + denom*y + numer == 0);
72190      }
72191    }
72192    continue;
72193  }
72194  return cgs;
72195}
72196
72197template <typename T>
72198void
72199Octagonal_Shape<T>::concatenate_assign(const Octagonal_Shape& y) {
72200  // If `y' is an empty 0-dim space octagon, let `*this' become empty.
72201  // If `y' is an universal 0-dim space octagon, we simply return.
72202  if (y.space_dim == 0) {
72203    if (y.marked_empty()) {
72204      set_empty();
72205    }
72206    return;
72207  }
72208
72209  // If `*this' is an empty 0-dim space octagon, then it is sufficient
72210  // to adjust the dimension of the vector space.
72211  if (space_dim == 0 && marked_empty()) {
72212    add_space_dimensions_and_embed(y.space_dim);
72213    return;
72214  }
72215
72216  // This is the old number of rows in the matrix. It is equal to
72217  // the first index of columns to change.
72218  dimension_type old_num_rows = matrix.num_rows();
72219  // First we increase the space dimension of `*this' by adding
72220  // `y.space_dimension()' new dimensions.
72221  // The matrix for the new octagon is obtained
72222  // by leaving the old system of constraints in the upper left-hand side
72223  // (where they are at the present) and placing the constraints of `y' in the
72224  // lower right-hand side.
72225  add_space_dimensions_and_embed(y.space_dim);
72226  typename OR_Matrix<N>::const_element_iterator
72227    y_it = y.matrix.element_begin();
72228  for (typename OR_Matrix<N>::row_iterator
72229         i = matrix.row_begin() + old_num_rows,
72230         matrix_row_end = matrix.row_end(); i != matrix_row_end; ++i) {
72231    typename OR_Matrix<N>::row_reference_type r = *i;
72232    dimension_type rs_i = i.row_size();
72233    for (dimension_type j = old_num_rows; j < rs_i; ++j, ++y_it) {
72234      r[j] = *y_it;
72235    }
72236  }
72237
72238  // The concatenation does not preserve the closure.
72239  if (marked_strongly_closed()) {
72240    reset_strongly_closed();
72241  }
72242  PPL_ASSERT(OK());
72243}
72244
72245template <typename T>
72246bool
72247Octagonal_Shape<T>::contains(const Octagonal_Shape& y) const {
72248  // Dimension-compatibility check.
72249  if (space_dim != y.space_dim) {
72250    throw_dimension_incompatible("contains(y)", y);
72251  }
72252
72253  if (space_dim == 0) {
72254    // The zero-dimensional empty octagon only contains another
72255    // zero-dimensional empty octagon.
72256    // The zero-dimensional universe octagon contains any other
72257    // zero-dimensional octagon.
72258    return marked_empty() ? y.marked_empty() : true;
72259  }
72260
72261  // `y' needs to be transitively closed.
72262  y.strong_closure_assign();
72263  // An empty octagon is in any other dimension-compatible octagons.
72264  if (y.marked_empty()) {
72265    return true;
72266  }
72267
72268  // If `*this' is empty it can not contain `y' (which is not empty).
72269  if (is_empty()) {
72270    return false;
72271  }
72272
72273  // `*this' contains `y' if and only if every element of `*this'
72274  // is greater than or equal to the correspondent one of `y'.
72275  for (typename OR_Matrix<N>::const_element_iterator
72276         i = matrix.element_begin(), j = y.matrix.element_begin(),
72277         matrix_element_end = matrix.element_end();
72278       i != matrix_element_end; ++i, ++j) {
72279    if (*i < *j) {
72280      return false;
72281    }
72282  }
72283  return true;
72284}
72285
72286template <typename T>
72287bool
72288Octagonal_Shape<T>::is_disjoint_from(const Octagonal_Shape& y) const {
72289  // Dimension-compatibility check.
72290  if (space_dim != y.space_dim) {
72291    throw_dimension_incompatible("is_disjoint_from(y)", y);
72292  }
72293
72294  // If one Octagonal_Shape is empty, the Octagonal_Shapes are disjoint.
72295  strong_closure_assign();
72296  if (marked_empty()) {
72297    return true;
72298  }
72299  y.strong_closure_assign();
72300  if (y.marked_empty()) {
72301    return true;
72302  }
72303
72304  // Two Octagonal_Shapes are disjoint if and only if their
72305  // intersection is empty, i.e., if and only if there exists a
72306  // variable such that the upper bound of the constraint on that
72307  // variable in the first Octagonal_Shape is strictly less than the
72308  // lower bound of the corresponding constraint in the second
72309  // Octagonal_Shape or vice versa.
72310
72311  const dimension_type n_rows = matrix.num_rows();
72312
72313  typedef typename OR_Matrix<N>::const_row_iterator row_iterator;
72314  typedef typename OR_Matrix<N>::const_row_reference_type row_reference;
72315
72316  const row_iterator m_begin = matrix.row_begin();
72317  const row_iterator m_end = matrix.row_end();
72318
72319  const row_iterator y_begin = y.matrix.row_begin();
72320
72321  PPL_DIRTY_TEMP(N, neg_y_ci_cj);
72322  for (row_iterator i_iter = m_begin; i_iter != m_end; ++i_iter) {
72323    using namespace Implementation::Octagonal_Shapes;
72324    const dimension_type i = i_iter.index();
72325    const dimension_type ci = coherent_index(i);
72326    const dimension_type rs_i = i_iter.row_size();
72327    row_reference m_i = *i_iter;
72328    for (dimension_type j = 0; j < n_rows; ++j) {
72329      const dimension_type cj = coherent_index(j);
72330      row_reference m_cj = *(m_begin + cj);
72331      const N& m_i_j = (j < rs_i) ? m_i[j] : m_cj[ci];
72332      row_reference y_ci = *(y_begin + ci);
72333      row_reference y_j = *(y_begin + j);
72334      const N& y_ci_cj = (j < rs_i) ? y_ci[cj] : y_j[i];
72335      neg_assign_r(neg_y_ci_cj, y_ci_cj, ROUND_UP);
72336      if (m_i_j < neg_y_ci_cj) {
72337        return true;
72338      }
72339    }
72340  }
72341  return false;
72342}
72343
72344template <typename T>
72345bool
72346Octagonal_Shape<T>::is_universe() const {
72347  // An empty octagon is not universe.
72348  if (marked_empty()) {
72349    return false;
72350  }
72351
72352  // If the octagon is non-empty and zero-dimensional,
72353  // then it is necessarily the universe octagon.
72354  if (space_dim == 0) {
72355    return true;
72356  }
72357
72358  // An universe octagon can only contains trivial  constraints.
72359  for (typename OR_Matrix<N>::const_element_iterator
72360         i = matrix.element_begin(), matrix_element_end = matrix.element_end();
72361       i != matrix_element_end;
72362       ++i) {
72363    if (!is_plus_infinity(*i)) {
72364      return false;
72365    }
72366  }
72367
72368  return true;
72369}
72370
72371template <typename T>
72372bool
72373Octagonal_Shape<T>::is_bounded() const {
72374  strong_closure_assign();
72375  // A zero-dimensional or empty octagon is bounded.
72376  if (marked_empty() || space_dim == 0) {
72377    return true;
72378  }
72379
72380  // A bounded octagon never can contains trivial constraints.
72381  for (typename OR_Matrix<N>::const_row_iterator i = matrix.row_begin(),
72382         matrix_row_end = matrix.row_end(); i != matrix_row_end; ++i) {
72383    typename OR_Matrix<N>::const_row_reference_type x_i = *i;
72384    const dimension_type i_index = i.index();
72385    for (dimension_type j = i.row_size(); j-- > 0; ) {
72386      if (i_index != j) {
72387        if (is_plus_infinity(x_i[j])) {
72388          return false;
72389        }
72390      }
72391    }
72392  }
72393
72394  return true;
72395}
72396
72397template <typename T>
72398bool
72399Octagonal_Shape<T>::contains_integer_point() const {
72400  // Force strong closure.
72401  if (is_empty()) {
72402    return false;
72403  }
72404  if (space_dim == 0) {
72405    return true;
72406  }
72407  // A strongly closed and consistent Octagonal_Shape defined by
72408  // integer constraints can only be empty due to tight coherence.
72409  if (std::numeric_limits<T>::is_integer) {
72410    return !tight_coherence_would_make_empty();
72411  }
72412
72413  // Build an integer Octagonal_Shape oct_z with bounds at least as
72414  // tight as those in *this and then recheck for emptiness, also
72415  // exploiting tight-coherence.
72416  Octagonal_Shape<mpz_class> oct_z(space_dim);
72417  oct_z.reset_strongly_closed();
72418
72419  typedef Octagonal_Shape<mpz_class>::N Z;
72420  bool all_integers = true;
72421  typename OR_Matrix<N>::const_element_iterator x_i = matrix.element_begin();
72422  for (typename OR_Matrix<Z>::element_iterator
72423         z_i = oct_z.matrix.element_begin(),
72424         z_end = oct_z.matrix.element_end(); z_i != z_end; ++z_i, ++x_i) {
72425    const N& d = *x_i;
72426    if (is_plus_infinity(d)) {
72427      continue;
72428    }
72429    if (is_integer(d)) {
72430      assign_r(*z_i, d, ROUND_NOT_NEEDED);
72431    }
72432    else {
72433      all_integers = false;
72434      assign_r(*z_i, d, ROUND_DOWN);
72435    }
72436  }
72437  // Restore strong closure.
72438  if (all_integers) {
72439    // oct_z unchanged, so it is still strongly closed.
72440    oct_z.set_strongly_closed();
72441  }
72442  else {
72443    // oct_z changed: recompute strong closure.
72444    oct_z.strong_closure_assign();
72445    if (oct_z.marked_empty()) {
72446      return false;
72447    }
72448  }
72449  return !oct_z.tight_coherence_would_make_empty();
72450}
72451
72452template <typename T>
72453bool
72454Octagonal_Shape<T>::frequency(const Linear_Expression& expr,
72455                              Coefficient& freq_n, Coefficient& freq_d,
72456                              Coefficient& val_n, Coefficient& val_d) const {
72457  // The dimension of `expr' must be at most the dimension of *this.
72458  if (space_dim < expr.space_dimension()) {
72459    throw_dimension_incompatible("frequency(e, ...)", "e", expr);
72460  }
72461
72462  // Check if `expr' has a constant value.
72463  // If it is constant, set the frequency `freq_n' to 0
72464  // and return true. Otherwise the values for \p expr
72465  // are not discrete so return false.
72466
72467  // Space dimension is 0: if empty, then return false;
72468  // otherwise the frequency is 0 and the value is the inhomogeneous term.
72469  if (space_dim == 0) {
72470    if (is_empty()) {
72471      return false;
72472    }
72473    freq_n = 0;
72474    freq_d = 1;
72475    val_n = expr.inhomogeneous_term();
72476    val_d = 1;
72477    return true;
72478  }
72479
72480  strong_closure_assign();
72481  // For an empty Octagonal shape, we simply return false.
72482  if (marked_empty()) {
72483    return false;
72484  }
72485
72486  // The Octagonal shape has at least 1 dimension and is not empty.
72487  PPL_DIRTY_TEMP_COEFFICIENT(coeff);
72488  PPL_DIRTY_TEMP_COEFFICIENT(coeff_j);
72489  PPL_DIRTY_TEMP_COEFFICIENT(numer);
72490  PPL_DIRTY_TEMP_COEFFICIENT(denom);
72491  Linear_Expression le = expr;
72492  // Boolean to keep track of a variable `v' in expression `le'.
72493  // If we can replace `v' by an expression using variables other
72494  // than `v' and are already in `le', then this is set to true.
72495  bool constant_v = false;
72496
72497  typedef typename OR_Matrix<N>::const_row_iterator row_iterator;
72498  typedef typename OR_Matrix<N>::const_row_reference_type row_reference;
72499
72500  const row_iterator m_begin = matrix.row_begin();
72501  const row_iterator m_end = matrix.row_end();
72502
72503  PPL_DIRTY_TEMP_COEFFICIENT(val_denom);
72504  val_denom = 1;
72505
72506  for (row_iterator i_iter = m_begin; i_iter != m_end; i_iter += 2) {
72507    constant_v = false;
72508    dimension_type i = i_iter.index();
72509    const Variable v(i/2);
72510    coeff = le.coefficient(v);
72511    if (coeff == 0) {
72512      constant_v = true;
72513      continue;
72514    }
72515    // We check the unary constraints.
72516    row_reference m_i = *i_iter;
72517    row_reference m_ii = *(i_iter + 1);
72518    const N& m_i_ii = m_i[i + 1];
72519    const N& m_ii_i = m_ii[i];
72520    if ((!is_plus_infinity(m_i_ii) && !is_plus_infinity(m_ii_i))
72521        && (is_additive_inverse(m_i_ii, m_ii_i))) {
72522      // If `v' is constant, replace it in `le' by the value.
72523      numer_denom(m_i_ii, numer, denom);
72524      denom *= 2;
72525      le -= coeff*v;
72526      le *= denom;
72527      le -= numer*coeff;
72528      val_denom *= denom;
72529      constant_v = true;
72530      continue;
72531    }
72532    // Check the octagonal constraints between `v' and the other dimensions
72533    // that have non-zero coefficient in `le'.
72534    else {
72535      PPL_ASSERT(!constant_v);
72536      using namespace Implementation::Octagonal_Shapes;
72537      const dimension_type ci = coherent_index(i);
72538      for (row_iterator j_iter = i_iter; j_iter != m_end; j_iter += 2) {
72539        dimension_type j = j_iter.index();
72540        const Variable vj(j/2);
72541        coeff_j = le.coefficient(vj);
72542        if (coeff_j == 0) {
72543          // The coefficient in `le' is 0, so do nothing.
72544          continue;
72545        }
72546        const dimension_type cj = coherent_index(j);
72547        const dimension_type cjj = coherent_index(j + 1);
72548
72549        row_reference m_j = *(m_begin + j);
72550        row_reference m_cj = *(m_begin + cj);
72551        const N& m_j_i = m_j[i];
72552        const N& m_i_j = m_cj[ci];
72553        if ((!is_plus_infinity(m_i_j) && !is_plus_infinity(m_j_i))
72554            && (is_additive_inverse(m_i_j, m_j_i))) {
72555          // The coefficient for `vj' in `le' is not 0
72556          // and the constraint with `v' is an equality.
72557          // So apply this equality to eliminate `v' in `le'.
72558          numer_denom(m_i_j, numer, denom);
72559          le -= coeff*v;
72560          le += coeff*vj;
72561          le *= denom;
72562          le -= numer*coeff;
72563          val_denom *= denom;
72564          constant_v = true;
72565          break;
72566        }
72567
72568        m_j = *(m_begin + (j + 1));
72569        m_cj = *(m_begin + cjj);
72570        const N& m_j_i1 = m_j[i];
72571        const N& m_i_j1 = m_cj[ci];
72572        if ((!is_plus_infinity(m_i_j1) && !is_plus_infinity(m_j_i1))
72573            && (is_additive_inverse(m_i_j1, m_j_i1))) {
72574          // The coefficient for `vj' in `le' is not 0
72575          // and the constraint with `v' is an equality.
72576          // So apply this equality to eliminate `v' in `le'.
72577          numer_denom(m_i_j1, numer, denom);
72578          le -= coeff*v;
72579          le -= coeff*vj;
72580          le *= denom;
72581          le -= numer*coeff;
72582          val_denom *= denom;
72583          constant_v = true;
72584          break;
72585        }
72586      }
72587      if (!constant_v) {
72588        // The expression `expr' is not constant.
72589        return false;
72590      }
72591    }
72592  }
72593  if (!constant_v) {
72594    // The expression `expr' is not constant.
72595    return false;
72596  }
72597
72598  // The expression 'expr' is constant.
72599  freq_n = 0;
72600  freq_d = 1;
72601
72602  // Reduce `val_n' and `val_d'.
72603  normalize2(le.inhomogeneous_term(), val_denom, val_n, val_d);
72604  return true;
72605}
72606
72607template <typename T>
72608bool
72609Octagonal_Shape<T>::constrains(const Variable var) const {
72610  // `var' should be one of the dimensions of the octagonal shape.
72611  const dimension_type var_space_dim = var.space_dimension();
72612  if (space_dimension() < var_space_dim) {
72613    throw_dimension_incompatible("constrains(v)", "v", var);
72614  }
72615
72616  // An octagon known to be empty constrains all variables.
72617  // (Note: do not force emptiness check _yet_)
72618  if (marked_empty()) {
72619    return true;
72620  }
72621
72622  // Check whether `var' is syntactically constrained.
72623  const dimension_type n_v = 2*(var_space_dim - 1);
72624  typename OR_Matrix<N>::const_row_iterator m_iter = matrix.row_begin() + n_v;
72625  typename OR_Matrix<N>::const_row_reference_type r_v = *m_iter;
72626  typename OR_Matrix<N>::const_row_reference_type r_cv = *(++m_iter);
72627  for (dimension_type h = m_iter.row_size(); h-- > 0; ) {
72628    if (!is_plus_infinity(r_v[h]) || !is_plus_infinity(r_cv[h])) {
72629      return true;
72630    }
72631  }
72632  ++m_iter;
72633  for (typename OR_Matrix<N>::const_row_iterator m_end = matrix.row_end();
72634       m_iter != m_end; ++m_iter) {
72635    typename OR_Matrix<N>::const_row_reference_type r = *m_iter;
72636    if (!is_plus_infinity(r[n_v]) || !is_plus_infinity(r[n_v + 1])) {
72637      return true;
72638    }
72639  }
72640
72641  // `var' is not syntactically constrained:
72642  // now force an emptiness check.
72643  return is_empty();
72644}
72645
72646template <typename T>
72647bool
72648Octagonal_Shape<T>::is_strong_coherent() const {
72649  // This method is only used by method OK() so as to check if a
72650  // strongly closed matrix is also strong-coherent, as it must be.
72651  const dimension_type num_rows = matrix.num_rows();
72652
72653  // Allocated here once and for all.
72654  PPL_DIRTY_TEMP(N, semi_sum);
72655  // The strong-coherence is: for every indexes i and j (and i != j)
72656  // matrix[i][j] <= (matrix[i][ci] + matrix[cj][j])/2
72657  // where ci = i + 1, if i is even number or
72658  //       ci = i - 1, if i is odd.
72659  // Ditto for cj.
72660  for (dimension_type i = num_rows; i-- > 0; ) {
72661    typename OR_Matrix<N>::const_row_iterator iter = matrix.row_begin() + i;
72662    typename OR_Matrix<N>::const_row_reference_type m_i = *iter;
72663    using namespace Implementation::Octagonal_Shapes;
72664    const N& m_i_ci = m_i[coherent_index(i)];
72665    for (dimension_type j = matrix.row_size(i); j-- > 0; ) {
72666      // Note: on the main diagonal only PLUS_INFINITY can occur.
72667      if (i != j) {
72668        const N& m_cj_j = matrix[coherent_index(j)][j];
72669        if (!is_plus_infinity(m_i_ci)
72670            && !is_plus_infinity(m_cj_j)) {
72671          // Compute (m_i_ci + m_cj_j)/2 into `semi_sum',
72672          // rounding the result towards plus infinity.
72673          add_assign_r(semi_sum, m_i_ci, m_cj_j, ROUND_UP);
72674          div_2exp_assign_r(semi_sum, semi_sum, 1, ROUND_UP);
72675          if (m_i[j] > semi_sum) {
72676            return false;
72677          }
72678        }
72679      }
72680    }
72681  }
72682  return true;
72683}
72684
72685template <typename T>
72686bool
72687Octagonal_Shape<T>::is_strongly_reduced() const {
72688  // This method is only used in assertions: efficiency is not a must.
72689
72690  // An empty octagon is already transitively reduced.
72691  if (marked_empty()) {
72692    return true;
72693  }
72694
72695  Octagonal_Shape x = *this;
72696  // The matrix representing an OS is strongly reduced if, by removing
72697  // any constraint, the resulting matrix describes a different OS.
72698  for (typename OR_Matrix<N>::const_row_iterator iter = matrix.row_begin(),
72699         matrix_row_end = matrix.row_end(); iter != matrix_row_end; ++iter) {
72700    typename OR_Matrix<N>::const_row_reference_type m_i = *iter;
72701    const dimension_type i = iter.index();
72702    for (dimension_type j = iter.row_size(); j-- > 0; ) {
72703      if (!is_plus_infinity(m_i[j])) {
72704        Octagonal_Shape x_copy = *this;
72705        assign_r(x_copy.matrix[i][j], PLUS_INFINITY, ROUND_NOT_NEEDED);
72706        if (x == x_copy) {
72707          return false;
72708        }
72709      }
72710    }
72711  }
72712  // The octagon is just reduced.
72713  return true;
72714}
72715
72716template <typename T>
72717bool
72718Octagonal_Shape<T>::bounds(const Linear_Expression& expr,
72719                           const bool from_above) const {
72720  // The dimension of `expr' should not be greater than the dimension
72721  // of `*this'.
72722  const dimension_type expr_space_dim = expr.space_dimension();
72723  if (space_dim < expr_space_dim) {
72724    throw_dimension_incompatible((from_above
72725                                  ? "bounds_from_above(e)"
72726                                  : "bounds_from_below(e)"), "e", expr);
72727  }
72728  strong_closure_assign();
72729
72730  // A zero-dimensional or empty octagon bounds everything.
72731  if (space_dim == 0 || marked_empty()) {
72732    return true;
72733  }
72734
72735  // The constraint `c' is used to check if `expr' is an octagonal difference
72736  // and, in this case, to select the cell.
72737  const Constraint& c = (from_above) ? expr <= 0 : expr >= 0;
72738  dimension_type num_vars = 0;
72739  dimension_type i = 0;
72740  dimension_type j = 0;
72741  PPL_DIRTY_TEMP_COEFFICIENT(coeff);
72742  PPL_DIRTY_TEMP_COEFFICIENT(term);
72743  if (Octagonal_Shape_Helper
72744    ::extract_octagonal_difference(c, c.space_dimension(), num_vars,
72745                                   i, j, coeff, term)) {
72746    if (num_vars == 0) {
72747      return true;
72748    }
72749    // Select the cell to be checked.
72750    typename OR_Matrix<N>::const_row_iterator i_iter = matrix.row_begin() + i;
72751    typename OR_Matrix<N>::const_row_reference_type m_i = *i_iter;
72752    return !is_plus_infinity(m_i[j]);
72753  }
72754  else {
72755    // `c' is not an octagonal constraint: use the MIP solver.
72756    Optimization_Mode mode_bounds =
72757      from_above ? MAXIMIZATION : MINIMIZATION;
72758    MIP_Problem mip(space_dim, constraints(), expr, mode_bounds);
72759    return mip.solve() == OPTIMIZED_MIP_PROBLEM;
72760  }
72761}
72762
72763template <typename T>
72764bool
72765Octagonal_Shape<T>::max_min(const Linear_Expression& expr,
72766                            const bool maximize,
72767                            Coefficient& ext_n, Coefficient& ext_d,
72768                            bool& included) const {
72769  // The dimension of `expr' should not be greater than the dimension
72770  // of `*this'.
72771  const dimension_type expr_space_dim = expr.space_dimension();
72772  if (space_dim < expr_space_dim) {
72773    throw_dimension_incompatible((maximize
72774                                  ? "maximize(e, ...)"
72775                                  : "minimize(e, ...)"), "e", expr);
72776  }
72777  // Deal with zero-dim octagons first.
72778  if (space_dim == 0) {
72779    if (marked_empty()) {
72780      return false;
72781    }
72782    else {
72783      ext_n = expr.inhomogeneous_term();
72784      ext_d = 1;
72785      included = true;
72786      return true;
72787    }
72788  }
72789
72790  strong_closure_assign();
72791  // For an empty OS we simply return false.
72792  if (marked_empty()) {
72793    return false;
72794  }
72795
72796  // The constraint `c' is used to check if `expr' is an octagonal difference
72797  // and, in this case, to select the cell.
72798  const Constraint& c = (maximize) ? expr <= 0 : expr >= 0;
72799  dimension_type num_vars = 0;
72800  dimension_type i = 0;
72801  dimension_type j = 0;
72802  PPL_DIRTY_TEMP_COEFFICIENT(coeff);
72803  PPL_DIRTY_TEMP_COEFFICIENT(term);
72804  if (!Octagonal_Shape_Helper
72805    ::extract_octagonal_difference(c, c.space_dimension(), num_vars,
72806                                   i, j, coeff, term)) {
72807    // `c' is not an octagonal constraint: use the MIP solver.
72808    Optimization_Mode max_min = (maximize) ? MAXIMIZATION : MINIMIZATION;
72809    MIP_Problem mip(space_dim, constraints(), expr, max_min);
72810    if (mip.solve() == OPTIMIZED_MIP_PROBLEM) {
72811      mip.optimal_value(ext_n, ext_d);
72812      included = true;
72813      return true;
72814    }
72815    else {
72816      // Here`expr' is unbounded in `*this'.
72817      return false;
72818    }
72819  }
72820  else {
72821    // `c' is an octagonal constraint.
72822    if (num_vars == 0) {
72823      ext_n = expr.inhomogeneous_term();
72824      ext_d = 1;
72825      included = true;
72826      return true;
72827    }
72828
72829    // Select the cell to be checked.
72830    typename OR_Matrix<N>::const_row_iterator i_iter = matrix.row_begin() + i;
72831    typename OR_Matrix<N>::const_row_reference_type m_i = *i_iter;
72832    PPL_DIRTY_TEMP(N, d);
72833    if (!is_plus_infinity(m_i[j])) {
72834      const Coefficient& b = expr.inhomogeneous_term();
72835      PPL_DIRTY_TEMP_COEFFICIENT(minus_b);
72836      neg_assign(minus_b, b);
72837      const Coefficient& sc_b = maximize ? b : minus_b;
72838      assign_r(d, sc_b, ROUND_UP);
72839      // Set `coeff_expr' to the absolute value of coefficient of a variable
72840      // of `expr'.
72841      PPL_DIRTY_TEMP(N, coeff_expr);
72842      const Coefficient& coeff_i = expr.coefficient(Variable(i/2));
72843      const int sign_i = sgn(coeff_i);
72844      if (sign_i > 0) {
72845        assign_r(coeff_expr, coeff_i, ROUND_UP);
72846      }
72847      else {
72848        PPL_DIRTY_TEMP_COEFFICIENT(minus_coeff_i);
72849        neg_assign(minus_coeff_i, coeff_i);
72850        assign_r(coeff_expr, minus_coeff_i, ROUND_UP);
72851      }
72852      // Approximating the maximum/minimum of `expr'.
72853      if (num_vars == 1) {
72854        PPL_DIRTY_TEMP(N, m_i_j);
72855        div_2exp_assign_r(m_i_j, m_i[j], 1, ROUND_UP);
72856        add_mul_assign_r(d, coeff_expr, m_i_j, ROUND_UP);
72857      }
72858      else {
72859        add_mul_assign_r(d, coeff_expr, m_i[j], ROUND_UP);
72860      }
72861      numer_denom(d, ext_n, ext_d);
72862      if (!maximize) {
72863        neg_assign(ext_n);
72864      }
72865      included = true;
72866      return true;
72867    }
72868
72869    // The `expr' is unbounded.
72870    return false;
72871  }
72872}
72873
72874template <typename T>
72875bool
72876Octagonal_Shape<T>::max_min(const Linear_Expression& expr,
72877                            const bool maximize,
72878                            Coefficient& ext_n, Coefficient& ext_d,
72879                            bool& included, Generator& g) const {
72880  // The dimension of `expr' should not be greater than the dimension
72881  // of `*this'.
72882  const dimension_type expr_space_dim = expr.space_dimension();
72883  if (space_dim < expr_space_dim) {
72884    throw_dimension_incompatible((maximize
72885                                  ? "maximize(e, ...)"
72886                                  : "minimize(e, ...)"), "e", expr);
72887  }
72888  // Deal with zero-dim octagons first.
72889  if (space_dim == 0) {
72890    if (marked_empty()) {
72891      return false;
72892    }
72893    else {
72894      ext_n = expr.inhomogeneous_term();
72895      ext_d = 1;
72896      included = true;
72897      g = point();
72898      return true;
72899    }
72900  }
72901
72902  strong_closure_assign();
72903  // For an empty OS we simply return false.
72904  if (marked_empty()) {
72905    return false;
72906  }
72907  if (!is_universe()) {
72908    // We use MIP_Problems to handle constraints that are not
72909    // octagonal difference.
72910    Optimization_Mode max_min = (maximize) ? MAXIMIZATION : MINIMIZATION;
72911    MIP_Problem mip(space_dim, constraints(), expr, max_min);
72912    if (mip.solve() == OPTIMIZED_MIP_PROBLEM) {
72913      g = mip.optimizing_point();
72914      mip.evaluate_objective_function(g, ext_n, ext_d);
72915      included = true;
72916      return true;
72917    }
72918  }
72919  // The `expr' is unbounded.
72920  return false;
72921}
72922
72923template <typename T>
72924Poly_Con_Relation
72925Octagonal_Shape<T>::relation_with(const Congruence& cg) const {
72926  dimension_type cg_space_dim = cg.space_dimension();
72927
72928  // Dimension-compatibility check.
72929  if (cg_space_dim > space_dim) {
72930    throw_dimension_incompatible("relation_with(cg)", cg);
72931  }
72932
72933  // If the congruence is an equality,
72934  // find the relation with the equivalent equality constraint.
72935  if (cg.is_equality()) {
72936    Constraint c(cg);
72937    return relation_with(c);
72938  }
72939
72940  strong_closure_assign();
72941
72942  if (marked_empty()) {
72943    return Poly_Con_Relation::saturates()
72944      && Poly_Con_Relation::is_included()
72945      && Poly_Con_Relation::is_disjoint();
72946  }
72947
72948  if (space_dim == 0) {
72949    if (cg.is_inconsistent()) {
72950      return Poly_Con_Relation::is_disjoint();
72951    }
72952    else {
72953      return Poly_Con_Relation::saturates()
72954        && Poly_Con_Relation::is_included();
72955    }
72956  }
72957
72958  // Find the lower bound for a hyperplane with direction
72959  // defined by the congruence.
72960  Linear_Expression le(cg.expression());
72961  PPL_DIRTY_TEMP_COEFFICIENT(min_numer);
72962  PPL_DIRTY_TEMP_COEFFICIENT(min_denom);
72963  bool min_included;
72964  bool bounded_below = minimize(le, min_numer, min_denom, min_included);
72965
72966  // If there is no lower bound, then some of the hyperplanes defined by
72967  // the congruence will strictly intersect the shape.
72968  if (!bounded_below) {
72969    return Poly_Con_Relation::strictly_intersects();
72970  }
72971
72972  // TODO: Consider adding a max_and_min() method, performing both
72973  // maximization and minimization so as to possibly exploit
72974  // incrementality of the MIP solver.
72975
72976  // Find the upper bound for a hyperplane with direction
72977  // defined by the congruence.
72978  PPL_DIRTY_TEMP_COEFFICIENT(max_numer);
72979  PPL_DIRTY_TEMP_COEFFICIENT(max_denom);
72980  bool max_included;
72981  bool bounded_above = maximize(le, max_numer, max_denom, max_included);
72982
72983  // If there is no upper bound, then some of the hyperplanes defined by
72984  // the congruence will strictly intersect the shape.
72985  if (!bounded_above) {
72986    return Poly_Con_Relation::strictly_intersects();
72987  }
72988
72989  PPL_DIRTY_TEMP_COEFFICIENT(signed_distance);
72990
72991  // Find the position value for the hyperplane that satisfies the congruence
72992  // and is above the lower bound for the shape.
72993  PPL_DIRTY_TEMP_COEFFICIENT(min_value);
72994  min_value = min_numer / min_denom;
72995  const Coefficient& modulus = cg.modulus();
72996  signed_distance = min_value % modulus;
72997  min_value -= signed_distance;
72998  if (min_value * min_denom < min_numer) {
72999    min_value += modulus;
73000  }
73001
73002  // Find the position value for the hyperplane that satisfies the congruence
73003  // and is below the upper bound for the shape.
73004  PPL_DIRTY_TEMP_COEFFICIENT(max_value);
73005  max_value = max_numer / max_denom;
73006  signed_distance = max_value % modulus;
73007  max_value += signed_distance;
73008  if (max_value * max_denom > max_numer) {
73009    max_value -= modulus;
73010  }
73011
73012  // If the upper bound value is less than the lower bound value,
73013  // then there is an empty intersection with the congruence;
73014  // otherwise it will strictly intersect.
73015  if (max_value < min_value) {
73016    return Poly_Con_Relation::is_disjoint();
73017  }
73018  else {
73019    return Poly_Con_Relation::strictly_intersects();
73020  }
73021}
73022
73023template <typename T>
73024Poly_Con_Relation
73025Octagonal_Shape<T>::relation_with(const Constraint& c) const {
73026  dimension_type c_space_dim = c.space_dimension();
73027
73028  // Dimension-compatibility check.
73029  if (c_space_dim > space_dim) {
73030    throw_dimension_incompatible("relation_with(c)", c);
73031  }
73032
73033  // The closure needs to make explicit the implicit constraints.
73034  strong_closure_assign();
73035
73036  if (marked_empty()) {
73037    return Poly_Con_Relation::saturates()
73038      && Poly_Con_Relation::is_included()
73039      && Poly_Con_Relation::is_disjoint();
73040  }
73041
73042  if (space_dim == 0) {
73043    // Trivially false zero-dimensional constraint.
73044    if ((c.is_equality() && c.inhomogeneous_term() != 0)
73045        || (c.is_inequality() && c.inhomogeneous_term() < 0)) {
73046      return Poly_Con_Relation::is_disjoint();
73047    }
73048    else if (c.is_strict_inequality() && c.inhomogeneous_term() == 0) {
73049      // The constraint 0 > 0 implicitly defines the hyperplane 0 = 0;
73050      // thus, the zero-dimensional point also saturates it.
73051      return Poly_Con_Relation::saturates()
73052        && Poly_Con_Relation::is_disjoint();
73053    }
73054
73055    // Trivially true zero-dimensional constraint.
73056    else if (c.is_equality() || c.inhomogeneous_term() == 0) {
73057      return Poly_Con_Relation::saturates()
73058        && Poly_Con_Relation::is_included();
73059    }
73060    else {
73061      // The zero-dimensional point saturates
73062      // neither the positivity constraint 1 >= 0,
73063      // nor the strict positivity constraint 1 > 0.
73064      return Poly_Con_Relation::is_included();
73065    }
73066  }
73067
73068  dimension_type num_vars = 0;
73069  dimension_type i = 0;
73070  dimension_type j = 0;
73071  PPL_DIRTY_TEMP_COEFFICIENT(coeff);
73072  PPL_DIRTY_TEMP_COEFFICIENT(c_term);
73073  if (!Octagonal_Shape_Helper
73074    ::extract_octagonal_difference(c, c_space_dim, num_vars,
73075                                   i, j, coeff, c_term)) {
73076    // Constraints that are not octagonal differences.
73077    // Use maximize() and minimize() to do much of the work.
73078
73079    // Find the linear expression for the constraint and use that to
73080    // find if the expression is bounded from above or below and if it
73081    // is, find the maximum and minimum values.
73082    Linear_Expression le;
73083    le.set_space_dimension(c.space_dimension());
73084    le.linear_combine(c.expr, Coefficient_one(), Coefficient_one(),
73085                      1, c_space_dim + 1);
73086
73087    PPL_DIRTY_TEMP_COEFFICIENT(max_numer);
73088    PPL_DIRTY_TEMP_COEFFICIENT(max_denom);
73089    bool max_included;
73090    PPL_DIRTY_TEMP_COEFFICIENT(min_numer);
73091    PPL_DIRTY_TEMP_COEFFICIENT(min_denom);
73092    bool min_included;
73093    bool bounded_above = maximize(le, max_numer, max_denom, max_included);
73094    bool bounded_below = minimize(le, min_numer, min_denom, min_included);
73095    if (!bounded_above) {
73096      if (!bounded_below) {
73097        return Poly_Con_Relation::strictly_intersects();
73098      }
73099      min_numer += c.inhomogeneous_term() * min_denom;
73100      switch (sgn(min_numer)) {
73101      case 1:
73102        if (c.is_equality()) {
73103          return Poly_Con_Relation::is_disjoint();
73104        }
73105        return Poly_Con_Relation::is_included();
73106      case 0:
73107        if (c.is_strict_inequality() || c.is_equality()) {
73108          return Poly_Con_Relation::strictly_intersects();
73109        }
73110        return Poly_Con_Relation::is_included();
73111      case -1:
73112        return Poly_Con_Relation::strictly_intersects();
73113      }
73114    }
73115    if (!bounded_below) {
73116      max_numer += c.inhomogeneous_term() * max_denom;
73117      switch (sgn(max_numer)) {
73118      case 1:
73119        return Poly_Con_Relation::strictly_intersects();
73120      case 0:
73121        if (c.is_strict_inequality()) {
73122          return Poly_Con_Relation::is_disjoint();
73123        }
73124        return Poly_Con_Relation::strictly_intersects();
73125      case -1:
73126        return Poly_Con_Relation::is_disjoint();
73127      }
73128    }
73129    else {
73130      max_numer += c.inhomogeneous_term() * max_denom;
73131      min_numer += c.inhomogeneous_term() * min_denom;
73132      switch (sgn(max_numer)) {
73133      case 1:
73134        switch (sgn(min_numer)) {
73135        case 1:
73136          if (c.is_equality()) {
73137            return Poly_Con_Relation::is_disjoint();
73138          }
73139          return Poly_Con_Relation::is_included();
73140        case 0:
73141          if (c.is_equality()) {
73142            return Poly_Con_Relation::strictly_intersects();
73143          }
73144          if (c.is_strict_inequality()) {
73145            return Poly_Con_Relation::strictly_intersects();
73146          }
73147          return Poly_Con_Relation::is_included();
73148        case -1:
73149          return Poly_Con_Relation::strictly_intersects();
73150        }
73151        PPL_UNREACHABLE;
73152        break;
73153      case 0:
73154        if (min_numer == 0) {
73155          if (c.is_strict_inequality()) {
73156            return Poly_Con_Relation::is_disjoint()
73157              && Poly_Con_Relation::saturates();
73158          }
73159          return Poly_Con_Relation::is_included()
73160            && Poly_Con_Relation::saturates();
73161        }
73162        if (c.is_strict_inequality()) {
73163          return Poly_Con_Relation::is_disjoint();
73164        }
73165        return Poly_Con_Relation::strictly_intersects();
73166      case -1:
73167        return Poly_Con_Relation::is_disjoint();
73168      }
73169    }
73170  }
73171
73172  if (num_vars == 0) {
73173    // Dealing with a trivial constraint.
73174    switch (sgn(c.inhomogeneous_term())) {
73175    case -1:
73176      return Poly_Con_Relation::is_disjoint();
73177    case 0:
73178      if (c.is_strict_inequality()) {
73179        return Poly_Con_Relation::saturates()
73180          && Poly_Con_Relation::is_disjoint();
73181      }
73182      else {
73183        return Poly_Con_Relation::saturates()
73184          && Poly_Con_Relation::is_included();
73185      }
73186    case 1:
73187      if (c.is_equality()) {
73188        return Poly_Con_Relation::is_disjoint();
73189      }
73190      else {
73191        return Poly_Con_Relation::is_included();
73192      }
73193    }
73194  }
73195
73196  // Select the cell to be checked for the "<=" part of constraint.
73197  typename OR_Matrix<N>::const_row_iterator i_iter = matrix.row_begin() + i;
73198  typename OR_Matrix<N>::const_row_reference_type m_i = *i_iter;
73199  const N& m_i_j = m_i[j];
73200  // Set `coeff' to the absolute value of itself.
73201  if (coeff < 0) {
73202    neg_assign(coeff);
73203  }
73204
73205  // Select the cell to be checked for the ">=" part of constraint.
73206  // Select the right row of the cell.
73207  if (i % 2 == 0) {
73208    ++i_iter;
73209  }
73210  else {
73211    --i_iter;
73212  }
73213  typename OR_Matrix<N>::const_row_reference_type m_ci = *i_iter;
73214  using namespace Implementation::Octagonal_Shapes;
73215  const N& m_ci_cj = m_ci[coherent_index(j)];
73216  PPL_DIRTY_TEMP_COEFFICIENT(numer);
73217  PPL_DIRTY_TEMP_COEFFICIENT(denom);
73218  // The following variables of mpq_class type are used to be precise
73219  // when the octagon is defined by integer constraints.
73220  PPL_DIRTY_TEMP(mpq_class, q_x);
73221  PPL_DIRTY_TEMP(mpq_class, q_y);
73222  PPL_DIRTY_TEMP(mpq_class, d);
73223  PPL_DIRTY_TEMP(mpq_class, d1);
73224  PPL_DIRTY_TEMP(mpq_class, c_denom);
73225  PPL_DIRTY_TEMP(mpq_class, q_denom);
73226  assign_r(c_denom, coeff, ROUND_NOT_NEEDED);
73227  assign_r(d, c_term, ROUND_NOT_NEEDED);
73228  neg_assign_r(d1, d, ROUND_NOT_NEEDED);
73229  div_assign_r(d, d, c_denom, ROUND_NOT_NEEDED);
73230  div_assign_r(d1, d1, c_denom, ROUND_NOT_NEEDED);
73231
73232  if (is_plus_infinity(m_i_j)) {
73233    if (!is_plus_infinity(m_ci_cj)) {
73234      // `*this' is in the following form:
73235      // `-m_ci_cj <= v - u'.
73236      // In this case `*this' is disjoint from `c' if
73237      // `-m_ci_cj > d' (`-m_ci_cj >= d' if c is a strict inequality),
73238      // i.e., if `m_ci_cj < d1' (`m_ci_cj <= d1'
73239      // if c is a strict inequality).
73240      numer_denom(m_ci_cj, numer, denom);
73241      assign_r(q_denom, denom, ROUND_NOT_NEEDED);
73242      assign_r(q_y, numer, ROUND_NOT_NEEDED);
73243      div_assign_r(q_y, q_y, q_denom, ROUND_NOT_NEEDED);
73244      if (q_y < d1) {
73245        return Poly_Con_Relation::is_disjoint();
73246      }
73247      if (q_y == d1 && c.is_strict_inequality()) {
73248        return Poly_Con_Relation::is_disjoint();
73249      }
73250    }
73251
73252    // In all other cases `*this' intersects `c'.
73253    return Poly_Con_Relation::strictly_intersects();
73254  }
73255
73256  // Here `m_i_j' is not plus-infinity.
73257  numer_denom(m_i_j, numer, denom);
73258  assign_r(q_denom, denom, ROUND_NOT_NEEDED);
73259  assign_r(q_x, numer, ROUND_NOT_NEEDED);
73260  div_assign_r(q_x, q_x, q_denom, ROUND_NOT_NEEDED);
73261
73262  if (!is_plus_infinity(m_ci_cj)) {
73263    numer_denom(m_ci_cj, numer, denom);
73264    assign_r(q_denom, denom, ROUND_NOT_NEEDED);
73265    assign_r(q_y, numer, ROUND_NOT_NEEDED);
73266    div_assign_r(q_y, q_y, q_denom, ROUND_NOT_NEEDED);
73267    if (q_x == d && q_y == d1) {
73268      if (c.is_strict_inequality()) {
73269        return Poly_Con_Relation::saturates()
73270          && Poly_Con_Relation::is_disjoint();
73271      }
73272      else {
73273        return Poly_Con_Relation::saturates()
73274          && Poly_Con_Relation::is_included();
73275      }
73276    }
73277    // `*this' is disjoint from `c' when
73278    // `m_ci_cj < d1' (`m_ci_cj <= d1' if `c' is a strict inequality).
73279    if (q_y < d1) {
73280      return Poly_Con_Relation::is_disjoint();
73281    }
73282    if (q_y == d1 && c.is_strict_inequality()) {
73283      return Poly_Con_Relation::is_disjoint();
73284    }
73285  }
73286
73287  // Here `m_ci_cj' can be also plus-infinity.
73288  // If `c' is an equality, `*this' is disjoint from `c' if
73289  // `m_i_j < d'.
73290  if (d > q_x) {
73291    if (c.is_equality()) {
73292      return Poly_Con_Relation::is_disjoint();
73293    }
73294    else {
73295      return Poly_Con_Relation::is_included();
73296    }
73297  }
73298
73299  if (d == q_x && c.is_nonstrict_inequality()) {
73300    return Poly_Con_Relation::is_included();
73301  }
73302  // In all other cases `*this' intersects `c'.
73303  return Poly_Con_Relation::strictly_intersects();
73304}
73305
73306template <typename T>
73307Poly_Gen_Relation
73308Octagonal_Shape<T>::relation_with(const Generator& g) const {
73309  const dimension_type g_space_dim = g.space_dimension();
73310
73311  // Dimension-compatibility check.
73312  if (space_dim < g_space_dim) {
73313    throw_dimension_incompatible("relation_with(g)", g);
73314  }
73315
73316  // The closure needs to make explicit the implicit constraints and if the
73317  // octagon is empty.
73318  strong_closure_assign();
73319
73320  // The empty octagon cannot subsume a generator.
73321  if (marked_empty()) {
73322    return Poly_Gen_Relation::nothing();
73323  }
73324
73325  // A universe octagon in a zero-dimensional space subsumes
73326  // all the generators of a zero-dimensional space.
73327  if (space_dim == 0) {
73328    return Poly_Gen_Relation::subsumes();
73329  }
73330
73331  const bool is_line = g.is_line();
73332  const bool is_line_or_ray = g.is_line_or_ray();
73333
73334  // The relation between the octagon and the given generator is obtained
73335  // checking if the generator satisfies all the constraints in the octagon.
73336  // To check if the generator satisfies all the constraints it's enough
73337  // studying the sign of the scalar product between the generator and
73338  // all the constraints in the octagon.
73339
73340  typedef typename OR_Matrix<N>::const_row_iterator row_iterator;
73341  typedef typename OR_Matrix<N>::const_row_reference_type row_reference;
73342
73343  const row_iterator m_begin = matrix.row_begin();
73344  const row_iterator m_end = matrix.row_end();
73345
73346  PPL_DIRTY_TEMP_COEFFICIENT(numer);
73347  PPL_DIRTY_TEMP_COEFFICIENT(denom);
73348  PPL_DIRTY_TEMP_COEFFICIENT(product);
73349
73350  // We find in `*this' all the constraints.
73351  for (row_iterator i_iter = m_begin; i_iter != m_end; i_iter += 2) {
73352    dimension_type i = i_iter.index();
73353    row_reference m_i = *i_iter;
73354    row_reference m_ii = *(i_iter + 1);
73355    const N& m_i_ii = m_i[i + 1];
73356    const N& m_ii_i = m_ii[i];
73357    // We have the unary constraints.
73358    const Variable x(i/2);
73359    const Coefficient& g_coeff_x
73360      = (x.space_dimension() > g_space_dim)
73361      ? Coefficient_zero()
73362      : g.coefficient(x);
73363    if (is_additive_inverse(m_i_ii, m_ii_i)) {
73364      // The constraint has form ax = b.
73365      // To satisfy the constraint it is necessary that the scalar product
73366      // is not zero. The scalar product has the form
73367      // 'denom * g_coeff_x - numer * g.divisor()'.
73368      numer_denom(m_ii_i, numer, denom);
73369      denom *= 2;
73370      product = denom * g_coeff_x;
73371      // Note that if the generator `g' is a line or a ray,
73372      // its divisor is zero.
73373      if (!is_line_or_ray) {
73374        neg_assign(numer);
73375        add_mul_assign(product, numer, g.divisor());
73376      }
73377      if (product != 0) {
73378        return Poly_Gen_Relation::nothing();
73379      }
73380    }
73381    // We have 0, 1 or 2 inequality constraints.
73382    else {
73383      if (!is_plus_infinity(m_i_ii)) {
73384        // The constraint has form -ax <= b.
73385        // If the generator is a line it's necessary to check if
73386        // the scalar product is not zero, if it is positive otherwise.
73387        numer_denom(m_i_ii, numer, denom);
73388        denom *= -2;
73389        product = denom * g_coeff_x;
73390        // Note that if the generator `g' is a line or a ray,
73391        // its divisor is zero.
73392        if (!is_line_or_ray) {
73393          neg_assign(numer);
73394          add_mul_assign(product, numer, g.divisor());
73395        }
73396        if (is_line && product != 0) {
73397          return Poly_Gen_Relation::nothing();
73398        }
73399        else
73400          // If the generator is not a line it's necessary to check
73401          // that the scalar product sign is not positive and the scalar
73402          // product has the form
73403          // '-denom * g.coeff_x - numer * g.divisor()'.
73404          if (product > 0) {
73405            return Poly_Gen_Relation::nothing();
73406          }
73407      }
73408      if (!is_plus_infinity(m_ii_i)) {
73409        // The constraint has form ax <= b.
73410        numer_denom(m_ii_i, numer, denom);
73411        denom *= 2;
73412        product = denom * g_coeff_x;
73413         // Note that if the generator `g' is a line or a ray,
73414        // its divisor is zero.
73415        if (!is_line_or_ray) {
73416          neg_assign(numer);
73417          add_mul_assign(product, numer , g.divisor());
73418        }
73419        if (is_line && product != 0) {
73420          return Poly_Gen_Relation::nothing();
73421        }
73422        else {
73423          // If the generator is not a line it's necessary to check
73424          // that the scalar product sign is not positive and the scalar
73425          // product has the form
73426          // 'denom * g_coeff_x - numer * g.divisor()'.
73427          if (product > 0) {
73428            return Poly_Gen_Relation::nothing();
73429          }
73430        }
73431      }
73432    }
73433  }
73434
73435  // We have the binary constraints.
73436  for (row_iterator i_iter = m_begin ; i_iter != m_end; i_iter += 2) {
73437    dimension_type i = i_iter.index();
73438    row_reference m_i = *i_iter;
73439    row_reference m_ii = *(i_iter + 1);
73440    for (dimension_type j = 0; j < i; j += 2) {
73441      const N& m_i_j = m_i[j];
73442      const N& m_ii_jj = m_ii[j + 1];
73443      const N& m_ii_j = m_ii[j];
73444      const N& m_i_jj = m_i[j + 1];
73445      const Variable x(j/2);
73446      const Variable y(i/2);
73447      const Coefficient& g_coeff_x
73448        = (x.space_dimension() > g_space_dim)
73449        ? Coefficient_zero()
73450        : g.coefficient(x);
73451      const Coefficient& g_coeff_y
73452        = (y.space_dimension() > g_space_dim)
73453        ? Coefficient_zero()
73454        : g.coefficient(y);
73455
73456      const bool difference_is_equality = is_additive_inverse(m_ii_jj, m_i_j);
73457      if (difference_is_equality) {
73458        // The constraint has form a*x - a*y = b.
73459        // The scalar product has the form
73460        // 'denom * coeff_x - denom * coeff_y - numer * g.divisor()'.
73461        // To satisfy the constraint it's necessary that the scalar product
73462        // is not zero.
73463        numer_denom(m_i_j, numer, denom);
73464        product = denom * g_coeff_x;
73465        neg_assign(denom);
73466        add_mul_assign(product, denom, g_coeff_y);
73467        // Note that if the generator `g' is a line or a ray,
73468        // its divisor is zero.
73469        if (!is_line_or_ray) {
73470          neg_assign(numer);
73471          add_mul_assign(product, numer, g.divisor());
73472        }
73473        if (product != 0) {
73474          return Poly_Gen_Relation::nothing();
73475        }
73476      }
73477      else {
73478        if (!is_plus_infinity(m_i_j)) {
73479          // The constraint has form a*x - a*y <= b.
73480          // The scalar product has the form
73481          // 'denom * coeff_x - denom * coeff_y - numer * g.divisor()'.
73482          // If the generator is not a line it's necessary to check
73483          // that the scalar product sign is not positive.
73484          numer_denom(m_i_j, numer, denom);
73485          product = denom * g_coeff_x;
73486          neg_assign(denom);
73487          add_mul_assign(product, denom, g_coeff_y);
73488          // Note that if the generator `g' is a line or a ray,
73489          // its divisor is zero.
73490          if (!is_line_or_ray) {
73491            neg_assign(numer);
73492            add_mul_assign(product, numer, g.divisor());
73493          }
73494          if (is_line && product != 0) {
73495            return Poly_Gen_Relation::nothing();
73496          }
73497          else if (product > 0) {
73498            return Poly_Gen_Relation::nothing();
73499          }
73500        }
73501        if (!is_plus_infinity(m_ii_jj)) {
73502          // The constraint has form -a*x + a*y <= b.
73503          // The scalar product has the form
73504          // '-denom * coeff_x + denom * coeff_y - numer * g.divisor()'.
73505          // If the generator is not a line it's necessary to check
73506          // that the scalar product sign is not positive.
73507          numer_denom(m_ii_jj, numer, denom);
73508          product = denom * g_coeff_y;
73509          neg_assign(denom);
73510          add_mul_assign(product, denom, g_coeff_x);
73511          // Note that if the generator `g' is a line or a ray,
73512          // its divisor is zero.
73513          if (!is_line_or_ray) {
73514            neg_assign(numer);
73515            add_mul_assign(product, numer, g.divisor());
73516          }
73517          if (is_line && product != 0) {
73518            return Poly_Gen_Relation::nothing();
73519          }
73520          else if (product > 0) {
73521            return Poly_Gen_Relation::nothing();
73522          }
73523        }
73524      }
73525
73526      const bool sum_is_equality = is_additive_inverse(m_i_jj, m_ii_j);
73527      if (sum_is_equality) {
73528        // The constraint has form a*x + a*y = b.
73529        // The scalar product has the form
73530        // 'denom * coeff_x + denom * coeff_y - numer * g.divisor()'.
73531        // To satisfy the constraint it's necessary that the scalar product
73532        // is not zero.
73533        numer_denom(m_ii_j, numer, denom);
73534        product = denom * g_coeff_x;
73535        add_mul_assign(product, denom, g_coeff_y);
73536        // Note that if the generator `g' is a line or a ray,
73537        // its divisor is zero.
73538        if (!is_line_or_ray) {
73539          neg_assign(numer);
73540          add_mul_assign(product, numer, g.divisor());
73541        }
73542        if (product != 0) {
73543          return Poly_Gen_Relation::nothing();
73544        }
73545      }
73546      else {
73547        if (!is_plus_infinity(m_i_jj)) {
73548          // The constraint has form -a*x - a*y <= b.
73549          // The scalar product has the form
73550          // '-denom * coeff_x - denom * coeff_y - numer * g.divisor()'.
73551          // If the generator is not a line it's necessary to check
73552          // that the scalar product sign is not positive.
73553          numer_denom(m_i_jj, numer, denom);
73554          neg_assign(denom);
73555          product = denom * g_coeff_x;
73556          add_mul_assign(product, denom, g_coeff_y);
73557          // Note that if the generator `g' is a line or a ray,
73558          // its divisor is zero.
73559          if (!is_line_or_ray) {
73560            neg_assign(numer);
73561            add_mul_assign(product, numer, g.divisor());
73562          }
73563          if (is_line && product != 0) {
73564            return Poly_Gen_Relation::nothing();
73565          }
73566          else if (product > 0) {
73567            return Poly_Gen_Relation::nothing();
73568          }
73569        }
73570        if (!is_plus_infinity(m_ii_j)) {
73571          // The constraint has form a*x + a*y <= b.
73572          // The scalar product has the form
73573          // 'denom * coeff_x + denom * coeff_y - numer * g.divisor()'.
73574          // If the generator is not a line it's necessary to check
73575          // that the scalar product sign is not positive.
73576          numer_denom(m_ii_j, numer, denom);
73577          product = denom * g_coeff_x;
73578          add_mul_assign(product, denom, g_coeff_y);
73579          // Note that if the generator `g' is a line or a ray,
73580          // its divisor is zero.
73581          if (!is_line_or_ray) {
73582            neg_assign(numer);
73583            add_mul_assign(product, numer, g.divisor());
73584          }
73585          if (is_line && product != 0) {
73586            return Poly_Gen_Relation::nothing();
73587          }
73588          else if (product > 0) {
73589            return Poly_Gen_Relation::nothing();
73590          }
73591        }
73592      }
73593    }
73594  }
73595  // If this point is reached the constraint 'g' satisfies
73596  // all the constraints in the octagon.
73597  return Poly_Gen_Relation::subsumes();
73598}
73599
73600template <typename T>
73601void
73602Octagonal_Shape<T>::strong_closure_assign() const {
73603  // Do something only if necessary (zero-dim implies strong closure).
73604  if (marked_empty() || marked_strongly_closed() || space_dim == 0) {
73605    return;
73606  }
73607  // Even though the octagon will not change, its internal representation
73608  // is going to be modified by the closure algorithm.
73609  Octagonal_Shape& x = const_cast<Octagonal_Shape<T>&>(*this);
73610
73611  typedef typename OR_Matrix<N>::row_iterator row_iterator;
73612  typedef typename OR_Matrix<N>::row_reference_type row_reference;
73613
73614  const dimension_type n_rows = x.matrix.num_rows();
73615  const row_iterator m_begin = x.matrix.row_begin();
73616  const row_iterator m_end = x.matrix.row_end();
73617
73618  // Fill the main diagonal with zeros.
73619  for (row_iterator i = m_begin; i != m_end; ++i) {
73620    PPL_ASSERT(is_plus_infinity((*i)[i.index()]));
73621    assign_r((*i)[i.index()], 0, ROUND_NOT_NEEDED);
73622  }
73623
73624  // This algorithm is given by two steps: the first one is a simple
73625  // adaptation of the `shortest-path closure' using the Floyd-Warshall
73626  // algorithm; the second one is the `strong-coherence' algorithm.
73627  // It is important to note that after the strong-coherence,
73628  // the octagon is still shortest-path closed and hence, strongly closed.
73629
73630  // Recall that, given an index `h', we indicate with `ch' the coherent
73631  // index, i.e., the index such that:
73632  //   ch = h + 1, if h is an even number;
73633  //   ch = h - 1, if h is an odd number.
73634
73635  typename OR_Matrix<N>::element_iterator iter_ij;
73636  std::vector<N> vec_k(n_rows);
73637  std::vector<N> vec_ck(n_rows);
73638  PPL_DIRTY_TEMP(N, sum1);
73639  PPL_DIRTY_TEMP(N, sum2);
73640  row_reference x_k;
73641  row_reference x_ck;
73642  row_reference x_i;
73643  row_reference x_ci;
73644
73645  // Since the index `j' of the inner loop will go from 0 up to `i',
73646  // the three nested loops have to be executed twice.
73647  for (int twice = 0; twice < 2; ++twice) {
73648
73649    row_iterator x_k_iter = m_begin;
73650    row_iterator x_i_iter = m_begin;
73651    for (dimension_type k = 0; k < n_rows; k += 2) {
73652      const dimension_type ck = k + 1;
73653      // Re-initialize the element iterator.
73654      iter_ij = x.matrix.element_begin();
73655      // Compute the row references `x_k' and `x_ck'.
73656      x_k  = *x_k_iter;
73657      ++x_k_iter;
73658      x_ck = *x_k_iter;
73659      ++x_k_iter;
73660
73661      for (dimension_type i = 0; i <= k; i += 2) {
73662        const dimension_type ci = i + 1;
73663        // Storing x_k_i == x_ci_ck.
73664        vec_k[i] = x_k[i];
73665        // Storing x_k_ci == x_i_ck.
73666        vec_k[ci] = x_k[ci];
73667        // Storing x_ck_i == x_ci_k.
73668        vec_ck[i] = x_ck[i];
73669        // Storing x_ck_ci == x_i_k.
73670        vec_ck[ci] = x_ck[ci];
73671      }
73672      x_i_iter = x_k_iter;
73673      for (dimension_type i = k + 2; i < n_rows; i += 2) {
73674        const dimension_type ci = i + 1;
73675        x_i = *x_i_iter;
73676        ++x_i_iter;
73677        x_ci = *x_i_iter;
73678        ++x_i_iter;
73679        // Storing x_k_i == x_ci_ck.
73680        vec_k[i] = x_ci[ck];
73681        // Storing x_k_ci == x_i_ck.
73682        vec_k[ci] = x_i[ck];
73683        // Storing x_ck_i == x_ci_k.
73684        vec_ck[i] = x_ci[k];
73685        // Storing x_ck_ci == x_i_k.
73686        vec_ck[ci] = x_i[k];
73687      }
73688
73689      for (dimension_type i = 0; i < n_rows; ++i) {
73690        using namespace Implementation::Octagonal_Shapes;
73691        const dimension_type ci = coherent_index(i);
73692        const N& vec_k_ci = vec_k[ci];
73693        const N& vec_ck_ci = vec_ck[ci];
73694        // Unfolding two iterations on `j': this ensures that
73695        // the loop exit condition `j <= i' is OK.
73696        for (dimension_type j = 0; j <= i; ) {
73697          // First iteration: compute
73698          //
73699          // <CODE>
73700          //   sum1 = x_i_k + x_k_j == x_ck_ci + x_k_j;
73701          //   sum2 = x_i_ck + x_ck_j == x_k_ci + x_ck_j;
73702          // </CODE>
73703          add_assign_r(sum1, vec_ck_ci, vec_k[j], ROUND_UP);
73704          add_assign_r(sum2, vec_k_ci, vec_ck[j], ROUND_UP);
73705          min_assign(sum1, sum2);
73706          min_assign(*iter_ij, sum1);
73707          // Exiting the first iteration: loop index control.
73708          ++j;
73709          ++iter_ij;
73710          // Second iteration: ditto.
73711          add_assign_r(sum1, vec_ck_ci, vec_k[j], ROUND_UP);
73712          add_assign_r(sum2, vec_k_ci, vec_ck[j], ROUND_UP);
73713          min_assign(sum1, sum2);
73714          min_assign(*iter_ij, sum1);
73715          // Exiting the second iteration: loop index control.
73716          ++j;
73717          ++iter_ij;
73718        }
73719      }
73720    }
73721  }
73722
73723  // Check for emptiness: the octagon is empty if and only if there is a
73724  // negative value in the main diagonal.
73725  for (row_iterator i = m_begin; i != m_end; ++i) {
73726    N& x_i_i = (*i)[i.index()];
73727    if (sgn(x_i_i) < 0) {
73728      x.set_empty();
73729      return;
73730    }
73731    else {
73732      PPL_ASSERT(sgn(x_i_i) == 0);
73733      // Restore PLUS_INFINITY on the main diagonal.
73734      assign_r(x_i_i, PLUS_INFINITY, ROUND_NOT_NEEDED);
73735    }
73736  }
73737
73738  // Step 2: we enforce the strong coherence.
73739  x.strong_coherence_assign();
73740  // The octagon is not empty and it is now strongly closed.
73741  x.set_strongly_closed();
73742}
73743
73744template <typename T>
73745void
73746Octagonal_Shape<T>::strong_coherence_assign() {
73747  // The strong-coherence is: for every indexes i and j
73748  // m_i_j <= (m_i_ci + m_cj_j)/2
73749  // where ci = i + 1, if i is even number or
73750  //       ci = i - 1, if i is odd.
73751  // Ditto for cj.
73752  PPL_DIRTY_TEMP(N, semi_sum);
73753  for (typename OR_Matrix<N>::row_iterator i_iter = matrix.row_begin(),
73754         i_end = matrix.row_end(); i_iter != i_end; ++i_iter) {
73755    typename OR_Matrix<N>::row_reference_type x_i = *i_iter;
73756    const dimension_type i = i_iter.index();
73757    using namespace Implementation::Octagonal_Shapes;
73758    const N& x_i_ci = x_i[coherent_index(i)];
73759    // Avoid to do unnecessary sums.
73760    if (!is_plus_infinity(x_i_ci)) {
73761      for (dimension_type j = 0, rs_i = i_iter.row_size();
73762           j < rs_i; ++j) {
73763        if (i != j) {
73764          const N& x_cj_j = matrix[coherent_index(j)][j];
73765          if (!is_plus_infinity(x_cj_j)) {
73766            add_assign_r(semi_sum, x_i_ci, x_cj_j, ROUND_UP);
73767            div_2exp_assign_r(semi_sum, semi_sum, 1, ROUND_UP);
73768            min_assign(x_i[j], semi_sum);
73769          }
73770        }
73771      }
73772    }
73773  }
73774}
73775
73776template <typename T>
73777bool
73778Octagonal_Shape<T>::tight_coherence_would_make_empty() const {
73779  PPL_ASSERT(std::numeric_limits<N>::is_integer);
73780  PPL_ASSERT(marked_strongly_closed());
73781  for (dimension_type i = 0; i < 2*space_dim; i += 2) {
73782    const dimension_type ci = i + 1;
73783    const N& mat_i_ci = matrix[i][ci];
73784    if (!is_plus_infinity(mat_i_ci)
73785        // Check for oddness of `mat_i_ci'.
73786        && !is_even(mat_i_ci)
73787        // Check for zero-equivalence of `i' and `ci'.
73788        && is_additive_inverse(mat_i_ci, matrix[ci][i])) {
73789      return true;
73790    }
73791  }
73792  return false;
73793}
73794
73795template <typename T>
73796void
73797Octagonal_Shape<T>::tight_closure_assign() {
73798  PPL_COMPILE_TIME_CHECK(std::numeric_limits<T>::is_integer,
73799                         "Octagonal_Shape<T>::tight_closure_assign():"
73800                         " T in not an integer datatype.");
73801  // FIXME: this is just an executable specification.
73802  // (The following call could be replaced by shortest-path closure.)
73803  strong_closure_assign();
73804  if (marked_empty()) {
73805    return;
73806  }
73807  if (tight_coherence_would_make_empty()) {
73808    set_empty();
73809  }
73810  else {
73811    // Tighten the unary constraints.
73812    PPL_DIRTY_TEMP(N, temp_one);
73813    assign_r(temp_one, 1, ROUND_NOT_NEEDED);
73814    for (dimension_type i = 0; i < 2*space_dim; i += 2) {
73815      const dimension_type ci = i + 1;
73816      N& mat_i_ci = matrix[i][ci];
73817      if (!is_plus_infinity(mat_i_ci) && !is_even(mat_i_ci)) {
73818        sub_assign_r(mat_i_ci, mat_i_ci, temp_one, ROUND_UP);
73819      }
73820      N& mat_ci_i = matrix[ci][i];
73821      if (!is_plus_infinity(mat_ci_i) && !is_even(mat_ci_i)) {
73822        sub_assign_r(mat_ci_i, mat_ci_i, temp_one, ROUND_UP);
73823      }
73824    }
73825    // Propagate tightened unary constraints.
73826    strong_coherence_assign();
73827  }
73828  PPL_ASSERT(OK());
73829}
73830
73831template <typename T>
73832void
73833Octagonal_Shape<T>
73834::incremental_strong_closure_assign(const Variable var) const {
73835  // `var' should be one of the dimensions of the octagon.
73836  if (var.id() >= space_dim) {
73837    throw_dimension_incompatible("incremental_strong_closure_assign(v)",
73838                                 var.id());
73839  }
73840
73841  // Do something only if necessary.
73842  if (marked_empty() || marked_strongly_closed()) {
73843    return;
73844  }
73845
73846  Octagonal_Shape& x = const_cast<Octagonal_Shape<T>&>(*this);
73847
73848  typedef typename OR_Matrix<N>::row_iterator row_iterator;
73849  typedef typename OR_Matrix<N>::row_reference_type row_reference;
73850
73851  const row_iterator m_begin = x.matrix.row_begin();
73852  const row_iterator m_end = x.matrix.row_end();
73853
73854  // Fill the main diagonal with zeros.
73855  for (row_iterator i = m_begin; i != m_end; ++i) {
73856    PPL_ASSERT(is_plus_infinity((*i)[i.index()]));
73857    assign_r((*i)[i.index()], 0, ROUND_NOT_NEEDED);
73858  }
73859
73860  // Using the incremental Floyd-Warshall algorithm.
73861  // Step 1: Improve all constraints on variable `var'.
73862  const dimension_type v = 2*var.id();
73863  const dimension_type cv = v + 1;
73864  row_iterator v_iter = m_begin + v;
73865  row_iterator cv_iter = v_iter + 1;
73866  row_reference x_v = *v_iter;
73867  row_reference x_cv = *cv_iter;
73868  const dimension_type rs_v = v_iter.row_size();
73869  const dimension_type n_rows = x.matrix.num_rows();
73870  PPL_DIRTY_TEMP(N, sum);
73871  using namespace Implementation::Octagonal_Shapes;
73872  for (row_iterator k_iter = m_begin; k_iter != m_end; ++k_iter) {
73873    const dimension_type k = k_iter.index();
73874    const dimension_type ck = coherent_index(k);
73875    const dimension_type rs_k = k_iter.row_size();
73876    row_reference x_k = *k_iter;
73877    row_reference x_ck = (k % 2 != 0) ? *(k_iter-1) : *(k_iter + 1);
73878
73879    for (row_iterator i_iter = m_begin; i_iter != m_end; ++i_iter) {
73880      const dimension_type i = i_iter.index();
73881      const dimension_type ci = coherent_index(i);
73882      const dimension_type rs_i = i_iter.row_size();
73883      row_reference x_i = *i_iter;
73884      row_reference x_ci = (i % 2 != 0) ? *(i_iter-1) : *(i_iter + 1);
73885
73886      const N& x_i_k = (k < rs_i) ? x_i[k] : x_ck[ci];
73887      if (!is_plus_infinity(x_i_k)) {
73888        const N& x_k_v = (v < rs_k) ? x_k[v] : x_cv[ck];
73889        if (!is_plus_infinity(x_k_v)) {
73890          add_assign_r(sum, x_i_k, x_k_v, ROUND_UP);
73891          N& x_i_v = (v < rs_i) ? x_i[v] : x_cv[ci];
73892          min_assign(x_i_v, sum);
73893        }
73894        const N& x_k_cv = (cv < rs_k) ? x_k[cv] : x_v[ck];
73895        if (!is_plus_infinity(x_k_cv)) {
73896          add_assign_r(sum, x_i_k, x_k_cv, ROUND_UP);
73897          N& x_i_cv = (cv < rs_i) ? x_i[cv] : x_v[ci];
73898          min_assign(x_i_cv, sum);
73899        }
73900      }
73901      const N& x_k_i = (i < rs_k) ? x_k[i] : x_ci[ck];
73902      if (!is_plus_infinity(x_k_i)) {
73903        const N& x_v_k = (k < rs_v) ? x_v[k] : x_ck[cv];
73904        if (!is_plus_infinity(x_v_k)) {
73905          N& x_v_i = (i < rs_v) ? x_v[i] : x_ci[cv];
73906          add_assign_r(sum, x_v_k, x_k_i, ROUND_UP);
73907          min_assign(x_v_i, sum);
73908        }
73909        const N& x_cv_k = (k < rs_v) ? x_cv[k] : x_ck[v];
73910        if (!is_plus_infinity(x_cv_k)) {
73911          N& x_cv_i = (i < rs_v) ? x_cv[i] : x_ci[v];
73912          add_assign_r(sum, x_cv_k, x_k_i, ROUND_UP);
73913          min_assign(x_cv_i, sum);
73914        }
73915      }
73916
73917    }
73918  }
73919
73920  // Step 2: improve the other bounds by using the precise bounds
73921  // for the constraints on `var'.
73922  for (row_iterator i_iter = m_begin; i_iter != m_end; ++i_iter) {
73923    const dimension_type i = i_iter.index();
73924    const dimension_type ci = coherent_index(i);
73925    const dimension_type rs_i = i_iter.row_size();
73926    row_reference x_i = *i_iter;
73927    const N& x_i_v = (v < rs_i) ? x_i[v] : x_cv[ci];
73928    // TODO: see if it is possible to optimize this inner loop
73929    // by splitting it into several parts, so as to avoid
73930    // conditional expressions.
73931    for (dimension_type j = 0; j < n_rows; ++j) {
73932      const dimension_type cj = coherent_index(j);
73933      row_reference x_cj = *(m_begin + cj);
73934      N& x_i_j = (j < rs_i) ? x_i[j] : x_cj[ci];
73935      if (!is_plus_infinity(x_i_v)) {
73936        const N& x_v_j = (j < rs_v) ? x_v[j] : x_cj[cv];
73937        if (!is_plus_infinity(x_v_j)) {
73938          add_assign_r(sum, x_i_v, x_v_j, ROUND_UP);
73939          min_assign(x_i_j, sum);
73940        }
73941      }
73942      const N& x_i_cv = (cv < rs_i) ? x_i[cv] : x_v[ci];
73943      if (!is_plus_infinity(x_i_cv)) {
73944        const N& x_cv_j = (j < rs_v) ? x_cv[j] : x_cj[v];
73945        if (!is_plus_infinity(x_cv_j)) {
73946          add_assign_r(sum, x_i_cv, x_cv_j, ROUND_UP);
73947          min_assign(x_i_j, sum);
73948        }
73949      }
73950    }
73951  }
73952
73953  // Check for emptiness: the octagon is empty if and only if there is a
73954  // negative value on the main diagonal.
73955  for (row_iterator i = m_begin; i != m_end; ++i) {
73956    N& x_i_i = (*i)[i.index()];
73957    if (sgn(x_i_i) < 0) {
73958      x.set_empty();
73959      return;
73960    }
73961    else {
73962      // Restore PLUS_INFINITY on the main diagonal.
73963      PPL_ASSERT(sgn(x_i_i) == 0);
73964      assign_r(x_i_i, PLUS_INFINITY, ROUND_NOT_NEEDED);
73965    }
73966  }
73967
73968  // Step 3: we enforce the strong coherence.
73969  x.strong_coherence_assign();
73970  // The octagon is not empty and it is now strongly closed.
73971  x.set_strongly_closed();
73972}
73973
73974template <typename T>
73975void
73976Octagonal_Shape<T>
73977::compute_successors(std::vector<dimension_type>& successor) const {
73978  PPL_ASSERT(!marked_empty() && marked_strongly_closed());
73979  PPL_ASSERT(successor.size() == 0);
73980  // Variables are ordered according to their index.
73981  // The vector `successor' is used to indicate which variable
73982  // immediately follows a given one in the corresponding equivalence class.
73983  const dimension_type successor_size = matrix.num_rows();
73984  // Initially, each variable is successor of its own zero-equivalence class.
73985  successor.reserve(successor_size);
73986  for (dimension_type i = 0; i < successor_size; ++i) {
73987    successor.push_back(i);
73988  }
73989  // Now compute actual successors.
73990  for (dimension_type i = successor_size; i-- > 0; )  {
73991    typename OR_Matrix<N>::const_row_iterator i_iter = matrix.row_begin() + i;
73992    typename OR_Matrix<N>::const_row_reference_type m_i = *i_iter;
73993    typename OR_Matrix<N>::const_row_reference_type m_ci
73994      = (i % 2 != 0) ? *(i_iter-1) : *(i_iter + 1);
73995    for (dimension_type j = 0; j < i; ++j) {
73996      // FIXME: what is the following, commented-out for?
73997    //for (dimension_type j = i; j-- > 0; ) {
73998      using namespace Implementation::Octagonal_Shapes;
73999      dimension_type cj = coherent_index(j);
74000      if (is_additive_inverse(m_ci[cj], m_i[j])) {
74001        // Choose as successor the variable having the greatest index.
74002        successor[j] = i;
74003      }
74004    }
74005  }
74006}
74007
74008template <typename T>
74009void
74010Octagonal_Shape<T>
74011::compute_leaders(std::vector<dimension_type>& leaders) const {
74012  PPL_ASSERT(!marked_empty() && marked_strongly_closed());
74013  PPL_ASSERT(leaders.size() == 0);
74014  // Variables are ordered according to their index.
74015  // The vector `leaders' is used to indicate the smallest variable
74016  // that belongs to the corresponding equivalence class.
74017  const dimension_type leader_size = matrix.num_rows();
74018  // Initially, each variable is leader of its own zero-equivalence class.
74019  leaders.reserve(leader_size);
74020  for (dimension_type i = 0; i < leader_size; ++i) {
74021    leaders.push_back(i);
74022  }
74023  // Now compute actual leaders.
74024  for (typename OR_Matrix<N>::const_row_iterator i_iter = matrix.row_begin(),
74025         matrix_row_end = matrix.row_end();
74026       i_iter != matrix_row_end; ++i_iter) {
74027    typename OR_Matrix<N>::const_row_reference_type m_i = *i_iter;
74028    dimension_type i = i_iter.index();
74029    typename OR_Matrix<N>::const_row_reference_type m_ci
74030      = (i % 2 != 0) ? *(i_iter-1) : *(i_iter + 1);
74031    for (dimension_type j = 0; j < i; ++j) {
74032      using namespace Implementation::Octagonal_Shapes;
74033      dimension_type cj = coherent_index(j);
74034      if (is_additive_inverse(m_ci[cj], m_i[j])) {
74035        // Choose as leader the variable having the smaller index.
74036        leaders[i] = leaders[j];
74037      }
74038    }
74039  }
74040}
74041
74042template <typename T>
74043void
74044Octagonal_Shape<T>
74045::compute_leaders(std::vector<dimension_type>& successor,
74046                  std::vector<dimension_type>& no_sing_leaders,
74047                  bool& exist_sing_class,
74048                  dimension_type& sing_leader) const {
74049  PPL_ASSERT(!marked_empty() && marked_strongly_closed());
74050  PPL_ASSERT(no_sing_leaders.size() == 0);
74051  dimension_type successor_size = successor.size();
74052  std::deque<bool> dealt_with(successor_size, false);
74053  for (dimension_type i = 0; i < successor_size; ++i) {
74054    dimension_type next_i = successor[i];
74055    if (!dealt_with[i]) {
74056      // The index is a leader.
74057      // Now check if it is a leader of a singular class or not.
74058      using namespace Implementation::Octagonal_Shapes;
74059      if (next_i == coherent_index(i)) {
74060        exist_sing_class = true;
74061        sing_leader = i;
74062      }
74063      else {
74064        no_sing_leaders.push_back(i);
74065      }
74066    }
74067    // The following index is not a leader.
74068    dealt_with[next_i] = true;
74069  }
74070}
74071
74072template <typename T>
74073void
74074Octagonal_Shape<T>::strong_reduction_assign() const {
74075  // Zero-dimensional octagonal shapes are necessarily reduced.
74076  if (space_dim == 0) {
74077    return;
74078  }
74079  strong_closure_assign();
74080  // If `*this' is empty, then there is nothing to reduce.
74081  if (marked_empty()) {
74082    return;
74083  }
74084  // Detect non-redundant constraints.
74085  std::vector<Bit_Row> non_red;
74086  non_redundant_matrix_entries(non_red);
74087
74088  // Throw away redundant constraints.
74089  Octagonal_Shape<T>& x = const_cast<Octagonal_Shape<T>&>(*this);
74090#ifndef NDEBUG
74091  const Octagonal_Shape x_copy_before(x);
74092#endif
74093  typename OR_Matrix<N>::element_iterator x_i = x.matrix.element_begin();
74094  for (dimension_type i = 0; i < 2 * space_dim; ++i) {
74095    const Bit_Row& non_red_i = non_red[i];
74096    for (dimension_type j = 0,
74097           j_end = OR_Matrix<N>::row_size(i); j < j_end; ++j, ++x_i) {
74098      if (!non_red_i[j]) {
74099        assign_r(*x_i, PLUS_INFINITY, ROUND_NOT_NEEDED);
74100      }
74101    }
74102  }
74103  x.reset_strongly_closed();
74104#ifndef NDEBUG
74105  const Octagonal_Shape x_copy_after(x);
74106  PPL_ASSERT(x_copy_before == x_copy_after);
74107  PPL_ASSERT(x.is_strongly_reduced());
74108  PPL_ASSERT(x.OK());
74109#endif
74110}
74111
74112template <typename T>
74113void
74114Octagonal_Shape<T>
74115::non_redundant_matrix_entries(std::vector<Bit_Row>& non_redundant) const {
74116  // Private method: the caller has to ensure the following.
74117  PPL_ASSERT(space_dim > 0 && !marked_empty() && marked_strongly_closed());
74118  PPL_ASSERT(non_redundant.empty());
74119
74120  // Initialize `non_redundant' as if it was an OR_Matrix of booleans
74121  // (initially set to false).
74122  non_redundant.resize(2*space_dim);
74123
74124  // Step 1: compute zero-equivalence classes.
74125  // Variables corresponding to indices `i' and `j' are zero-equivalent
74126  // if they lie on a zero-weight loop; since the matrix is strongly
74127  // closed, this happens if and only if matrix[i][j] == -matrix[ci][cj].
74128  std::vector<dimension_type> no_sing_leaders;
74129  dimension_type sing_leader = 0;
74130  bool exist_sing_class = false;
74131  std::vector<dimension_type> successor;
74132  compute_successors(successor);
74133  compute_leaders(successor, no_sing_leaders, exist_sing_class, sing_leader);
74134  const dimension_type num_no_sing_leaders = no_sing_leaders.size();
74135
74136
74137  // Step 2: flag redundant constraints in `redundancy'.
74138  // Go through non-singular leaders first.
74139  for (dimension_type li = 0; li < num_no_sing_leaders; ++li) {
74140    const dimension_type i = no_sing_leaders[li];
74141    using namespace Implementation::Octagonal_Shapes;
74142    const dimension_type ci = coherent_index(i);
74143    typename OR_Matrix<N>::const_row_reference_type
74144      m_i = *(matrix.row_begin() + i);
74145    if (i % 2 == 0) {
74146      // Each positive equivalence class must have a single 0-cycle
74147      // connecting all equivalent variables in increasing order.
74148      // Note: by coherence assumption, the variables in the
74149      // corresponding negative equivalence class are
74150      // automatically connected.
74151      if (i != successor[i]) {
74152        dimension_type j = i;
74153        dimension_type next_j = successor[j];
74154        while (j != next_j) {
74155          non_redundant[next_j].set(j);
74156          j = next_j;
74157          next_j = successor[j];
74158        }
74159        const dimension_type cj = coherent_index(j);
74160        non_redundant[cj].set(ci);
74161      }
74162    }
74163
74164    dimension_type rs_li = (li % 2 != 0) ? li : (li + 1);
74165    // Check if the constraint is redundant.
74166    PPL_DIRTY_TEMP(N, tmp);
74167    for (dimension_type lj = 0 ; lj <= rs_li; ++lj) {
74168      const dimension_type j = no_sing_leaders[lj];
74169      const dimension_type cj = coherent_index(j);
74170      const N& m_i_j = m_i[j];
74171      const N& m_i_ci = m_i[ci];
74172      bool to_add = true;
74173      // Control if the constraint is redundant by strong-coherence,
74174      // that is:
74175      // m_i_j >= (m_i_ci + m_cj_j)/2,   where j != ci.
74176      if (j != ci) {
74177        add_assign_r(tmp, m_i_ci, matrix[cj][j], ROUND_UP);
74178        div_2exp_assign_r(tmp, tmp, 1, ROUND_UP);
74179        if (m_i_j >= tmp) {
74180          // The constraint is redundant.
74181          continue;
74182        }
74183      }
74184      // Control if the constraint is redundant by strong closure, that is
74185      // if there is a path from i to j (i = i_0, ... , i_n = j), such that
74186      // m_i_j = sum_{k=0}^{n-1} m_{i_k}_{i_(k + 1)}.
74187      // Since the octagon is already strongly closed, the above relation
74188      // is reduced to three case, in accordance with k, i, j inter-depend:
74189      // exit k such that
74190      // 1.) m_i_j >= m_i_k   + m_cj_ck,   if k < j < i; or
74191      // 2.) m_i_j >= m_i_k   + m_k,_j,    if j < k < i; or
74192      // 3.) m_i_j >= m_ck_ci + m_k_j,     if j < i < k.
74193      // Note: `i > j'.
74194      for (dimension_type lk = 0; lk < num_no_sing_leaders; ++lk) {
74195        const dimension_type k = no_sing_leaders[lk];
74196        if (k != i && k != j) {
74197          dimension_type ck = coherent_index(k);
74198          if (k < j) {
74199            // Case 1.
74200            add_assign_r(tmp, m_i[k], matrix[cj][ck], ROUND_UP);
74201          }
74202          else if (k < i) {
74203            // Case 2.
74204            add_assign_r(tmp, m_i[k], matrix[k][j], ROUND_UP);
74205          }
74206          else {
74207            // Case 3.
74208            add_assign_r(tmp, matrix[ck][ci], matrix[k][j], ROUND_UP);
74209          }
74210          // Checks if the constraint is redundant.
74211          if (m_i_j >= tmp) {
74212            to_add = false;
74213            break;
74214          }
74215        }
74216      }
74217
74218      if (to_add) {
74219        // The constraint is not redundant.
74220        non_redundant[i].set(j);
74221      }
74222    }
74223  }
74224
74225  // If there exist a singular equivalence class, then it must have a
74226  // single 0-cycle connecting all the positive and negative equivalent
74227  // variables.
74228  // Note: the singular class is not connected with the other classes.
74229  if (exist_sing_class) {
74230    non_redundant[sing_leader].set(sing_leader + 1);
74231    if (successor[sing_leader + 1] != sing_leader + 1) {
74232      dimension_type j = sing_leader;
74233      dimension_type next_j = successor[j + 1];
74234      while (next_j != j + 1) {
74235        non_redundant[next_j].set(j);
74236        j = next_j;
74237        next_j = successor[j + 1];
74238      }
74239      non_redundant[j + 1].set(j);
74240    }
74241    else {
74242      non_redundant[sing_leader + 1].set(sing_leader);
74243    }
74244  }
74245}
74246
74247template <typename T>
74248void
74249Octagonal_Shape<T>::upper_bound_assign(const Octagonal_Shape& y) {
74250  // Dimension-compatibility check.
74251  if (space_dim != y.space_dim) {
74252    throw_dimension_incompatible("upper_bound_assign(y)", y);
74253  }
74254
74255  // The hull of an octagon `x' with an empty octagon is `x'.
74256  y.strong_closure_assign();
74257  if (y.marked_empty()) {
74258    return;
74259  }
74260  strong_closure_assign();
74261  if (marked_empty()) {
74262    *this = y;
74263    return;
74264  }
74265
74266  // The oct-hull is obtained by computing maxima.
74267  typename OR_Matrix<N>::const_element_iterator j = y.matrix.element_begin();
74268  for (typename OR_Matrix<N>::element_iterator i = matrix.element_begin(),
74269         matrix_element_end = matrix.element_end();
74270       i != matrix_element_end; ++i, ++j) {
74271    max_assign(*i, *j);
74272  }
74273
74274  // The result is still closed.
74275  PPL_ASSERT(OK());
74276}
74277
74278template <typename T>
74279void
74280Octagonal_Shape<T>::difference_assign(const Octagonal_Shape& y) {
74281  // Dimension-compatibility check.
74282  if (space_dim != y.space_dim) {
74283    throw_dimension_incompatible("difference_assign(y)", y);
74284  }
74285
74286  Octagonal_Shape& x = *this;
74287
74288  // Being lazy here is only harmful.
74289  // We close.
74290  x.strong_closure_assign();
74291  // The difference of an empty octagon and of an octagon `p' is empty.
74292  if (x.marked_empty()) {
74293    return;
74294  }
74295  // The difference of a octagon `p' and an empty octagon is `p'.
74296  if (y.marked_empty()) {
74297    return;
74298  }
74299  // If both octagons are zero-dimensional,
74300  // then at this point they are necessarily universe octagons,
74301  // so that their difference is empty.
74302  if (x.space_dim == 0) {
74303    x.set_empty();
74304    return;
74305  }
74306
74307  // TODO: This is just an executable specification.
74308  //       Have to find a more efficient method.
74309  if (y.contains(x)) {
74310    x.set_empty();
74311    return;
74312  }
74313
74314  Octagonal_Shape new_oct(space_dim, EMPTY);
74315  // We take a constraint of the octagon y at the time and we
74316  // consider its complementary. Then we intersect the union
74317  // of these complementary constraints with the octagon x.
74318  const Constraint_System& y_cs = y.constraints();
74319  for (Constraint_System::const_iterator i = y_cs.begin(),
74320         y_cs_end = y_cs.end(); i != y_cs_end; ++i) {
74321    const Constraint& c = *i;
74322    // If the octagon `x' is included the octagon defined by `c',
74323    // then `c' _must_ be skipped, as adding its complement to `x'
74324    // would result in the empty octagon, and as we would obtain
74325    // a result that is less precise than the difference.
74326    if (x.relation_with(c).implies(Poly_Con_Relation::is_included())) {
74327      continue;
74328    }
74329    Octagonal_Shape z = x;
74330    const Linear_Expression e(c.expression());
74331    z.add_constraint(e <= 0);
74332    if (!z.is_empty()) {
74333      new_oct.upper_bound_assign(z);
74334    }
74335    if (c.is_equality()) {
74336      z = x;
74337      z.add_constraint(e >= 0);
74338      if (!z.is_empty()) {
74339        new_oct.upper_bound_assign(z);
74340      }
74341    }
74342  }
74343  *this = new_oct;
74344  PPL_ASSERT(OK());
74345}
74346
74347template <typename T>
74348bool
74349Octagonal_Shape<T>::simplify_using_context_assign(const Octagonal_Shape& y) {
74350  Octagonal_Shape& x = *this;
74351  const dimension_type dim = x.space_dimension();
74352  // Dimension-compatibility check.
74353  if (dim != y.space_dimension()) {
74354    throw_dimension_incompatible("simplify_using_context_assign(y)", y);
74355  }
74356
74357  // Filter away the zero-dimensional case.
74358  if (dim == 0) {
74359    if (y.marked_empty()) {
74360      x.set_zero_dim_univ();
74361      return false;
74362    }
74363    else {
74364      return !x.marked_empty();
74365    }
74366  }
74367
74368  // Filter away the case where `x' contains `y'
74369  // (this subsumes the case when `y' is empty).
74370  if (x.contains(y)) {
74371    Octagonal_Shape<T> res(dim, UNIVERSE);
74372    x.m_swap(res);
74373    return false;
74374  }
74375
74376  // Filter away the case where `x' is empty.
74377  x.strong_closure_assign();
74378  if (x.marked_empty()) {
74379    // Search for a constraint of `y' that is not a tautology.
74380    dimension_type i;
74381    dimension_type j;
74382    // Prefer unary constraints.
74383    for (i = 0; i < 2*dim; i += 2) {
74384      // FIXME: if N is a float or bounded integer type, then
74385      // we also need to check that we are actually able to construct
74386      // a constraint inconsistent with respect to this one.
74387      // Use something like !is_maximal()?
74388      if (!is_plus_infinity(y.matrix_at(i, i + 1))) {
74389        j = i + 1;
74390        goto found;
74391      }
74392      // Use something like !is_maximal()?
74393      if (!is_plus_infinity(y.matrix_at(i + 1, i))) {
74394        j = i;
74395        ++i;
74396        goto found;
74397      }
74398    }
74399    // Then search binary constraints.
74400    // TODO: use better iteration scheme.
74401    for (i = 2; i < 2*dim; ++i) {
74402      for (j = 0; j < i; ++j) {
74403        // Use something like !is_maximal()?
74404        if (!is_plus_infinity(y.matrix_at(i, j))) {
74405          goto found;
74406        }
74407      }
74408    }
74409
74410    // Not found: we were not able to build a constraint contradicting
74411    // one of the constraints in `y': `x' cannot be enlarged.
74412    return false;
74413
74414  found:
74415    // Found: build a new OS contradicting the constraint found.
74416    PPL_ASSERT(i < dim && j < dim && i != j);
74417    Octagonal_Shape<T> res(dim, UNIVERSE);
74418    // FIXME: compute a proper contradicting constraint.
74419    PPL_DIRTY_TEMP(N, tmp);
74420    assign_r(tmp, 1, ROUND_UP);
74421    add_assign_r(tmp, tmp, y.matrix_at(i, j), ROUND_UP);
74422    // CHECKME: round down is really meant.
74423    neg_assign_r(res.matrix_at(j, i), tmp, ROUND_DOWN);
74424    PPL_ASSERT(!is_plus_infinity(res.matrix_at(j, i)));
74425    x.m_swap(res);
74426    return false;
74427  }
74428
74429  // Here `x' and `y' are not empty and strongly closed;
74430  // also, `x' does not contain `y'.
74431  // Let `target' be the intersection of `x' and `y'.
74432  Octagonal_Shape<T> target = x;
74433  target.intersection_assign(y);
74434  const bool bool_result = !target.is_empty();
74435
74436  // Compute redundancy information for x and ...
74437  // TODO: provide a nicer data structure for redundancy.
74438  std::vector<Bit_Row> x_non_redundant;
74439  x.non_redundant_matrix_entries(x_non_redundant);
74440  // ... count the non-redundant constraints.
74441  dimension_type x_num_non_redundant = 0;
74442  for (size_t i = x_non_redundant.size(); i-- > 0 ; ) {
74443    x_num_non_redundant += x_non_redundant[i].count_ones();
74444  }
74445  PPL_ASSERT(x_num_non_redundant > 0);
74446
74447  // Let `yy' be a copy of `y': we will keep adding to `yy'
74448  // the non-redundant constraints of `x',
74449  // stopping as soon as `yy' becomes equal to `target'.
74450  Octagonal_Shape<T> yy = y;
74451
74452  // The constraints added to `yy' will be recorded in `res' ...
74453  Octagonal_Shape<T> res(dim, UNIVERSE);
74454  // ... and we will count them too.
74455  dimension_type res_num_non_redundant = 0;
74456
74457  // Compute leader information for `x'.
74458  std::vector<dimension_type> x_leaders;
74459  x.compute_leaders(x_leaders);
74460
74461  // First go through the unary equality constraints.
74462  // Find the leader of the singular equivalence class (it is even!).
74463  dimension_type sing_leader;
74464  for (sing_leader = 0; sing_leader < 2*dim; sing_leader += 2) {
74465    if (sing_leader == x_leaders[sing_leader]) {
74466      const N& x_s_ss = x.matrix_at(sing_leader, sing_leader + 1);
74467      const N& x_ss_s = x.matrix_at(sing_leader + 1, sing_leader);
74468      if (is_additive_inverse(x_s_ss, x_ss_s)) {
74469        // Singular leader found.
74470        break;
74471      }
74472    }
74473  }
74474
74475  // Unary equalities have `sing_leader' as a leader.
74476  for (dimension_type i = sing_leader; i < 2*dim; i += 2) {
74477    if (x_leaders[i] != sing_leader) {
74478      continue;
74479    }
74480    // Found a unary equality constraint:
74481    // see if any of the two inequalities have to be added.
74482    const N& x_i_ii = x.matrix_at(i, i + 1);
74483    N& yy_i_ii = yy.matrix_at(i, i + 1);
74484    if (x_i_ii < yy_i_ii) {
74485      // The \leq inequality is not implied by context.
74486      res.matrix_at(i, i + 1) = x_i_ii;
74487      ++res_num_non_redundant;
74488      // Tighten context `yy' using the newly added constraint.
74489      yy_i_ii = x_i_ii;
74490      yy.reset_strongly_closed();
74491    }
74492    const N& x_ii_i = x.matrix_at(i + 1, i);
74493    N& yy_ii_i = yy.matrix_at(i + 1, i);
74494    if (x_ii_i < yy_ii_i) {
74495      // The \geq inequality is not implied by context.
74496      res.matrix_at(i + 1, i) = x_ii_i;
74497      ++res_num_non_redundant;
74498      // Tighten context `yy' using the newly added constraint.
74499      yy_ii_i = x_ii_i;
74500      yy.reset_strongly_closed();
74501    }
74502    // Restore strong closure, if it was lost.
74503    if (!yy.marked_strongly_closed()) {
74504      Variable var_i(i/2);
74505      yy.incremental_strong_closure_assign(var_i);
74506      if (target.contains(yy)) {
74507        // Target reached: swap `x' and `res' if needed.
74508        if (res_num_non_redundant < x_num_non_redundant) {
74509          res.reset_strongly_closed();
74510          x.m_swap(res);
74511        }
74512        return bool_result;
74513      }
74514    }
74515  }
74516
74517  // Go through the binary equality constraints.
74518  for (dimension_type i = 0; i < 2*dim; ++i) {
74519    const dimension_type j = x_leaders[i];
74520    if (j == i || j == sing_leader) {
74521      continue;
74522    }
74523    const N& x_i_j = x.matrix_at(i, j);
74524    PPL_ASSERT(!is_plus_infinity(x_i_j));
74525    N& yy_i_j = yy.matrix_at(i, j);
74526    if (x_i_j < yy_i_j) {
74527      res.matrix_at(i, j) = x_i_j;
74528      ++res_num_non_redundant;
74529      // Tighten context `yy' using the newly added constraint.
74530      yy_i_j = x_i_j;
74531      yy.reset_strongly_closed();
74532    }
74533    const N& x_j_i = x.matrix_at(j, i);
74534    N& yy_j_i = yy.matrix_at(j, i);
74535    PPL_ASSERT(!is_plus_infinity(x_j_i));
74536    if (x_j_i < yy_j_i) {
74537      res.matrix_at(j, i) = x_j_i;
74538      ++res_num_non_redundant;
74539      // Tighten context `yy' using the newly added constraint.
74540      yy_j_i = x_j_i;
74541      yy.reset_strongly_closed();
74542    }
74543    // Restore strong closure, if it was lost.
74544    if (!yy.marked_strongly_closed()) {
74545      Variable var_j(j/2);
74546      yy.incremental_strong_closure_assign(var_j);
74547      if (target.contains(yy)) {
74548        // Target reached: swap `x' and `res' if needed.
74549        if (res_num_non_redundant < x_num_non_redundant) {
74550          res.reset_strongly_closed();
74551          x.m_swap(res);
74552        }
74553        return bool_result;
74554      }
74555    }
74556  }
74557
74558  // Finally go through the (proper) inequality constraints:
74559  // both indices i and j should be leaders.
74560  // FIXME: improve iteration scheme (are we doing twice the work?)
74561  for (dimension_type i = 0; i < 2*dim; ++i) {
74562    if (i != x_leaders[i]) {
74563      continue;
74564    }
74565    const Bit_Row& x_non_redundant_i = x_non_redundant[i];
74566    for (dimension_type j = 0; j < 2*dim; ++j) {
74567      if (j != x_leaders[j]) {
74568        continue;
74569      }
74570      if (i >= j) {
74571        if (!x_non_redundant_i[j]) {
74572          continue;
74573        }
74574      }
74575      else if (!x_non_redundant[j][i]) {
74576        continue;
74577      }
74578      N& yy_i_j = yy.matrix_at(i, j);
74579      const N& x_i_j = x.matrix_at(i, j);
74580      if (x_i_j < yy_i_j) {
74581        res.matrix_at(i, j) = x_i_j;
74582        ++res_num_non_redundant;
74583        // Tighten context `yy' using the newly added constraint.
74584        yy_i_j = x_i_j;
74585        yy.reset_strongly_closed();
74586        Variable var(i/2);
74587        yy.incremental_strong_closure_assign(var);
74588        if (target.contains(yy)) {
74589          // Target reached: swap `x' and `res' if needed.
74590          if (res_num_non_redundant < x_num_non_redundant) {
74591            res.reset_strongly_closed();
74592            x.m_swap(res);
74593          }
74594          return bool_result;
74595        }
74596      }
74597    }
74598  }
74599  // This point should be unreachable.
74600  PPL_UNREACHABLE;
74601  return false;
74602}
74603
74604template <typename T>
74605void
74606Octagonal_Shape<T>::add_space_dimensions_and_embed(dimension_type m) {
74607  // Adding no dimensions is a no-op.
74608  if (m == 0) {
74609    return;
74610  }
74611
74612  const dimension_type new_dim = space_dim + m;
74613  const bool was_zero_dim_univ = !marked_empty() && space_dim == 0;
74614
74615  // To embed an n-dimension space octagon in a (n + m)-dimension space,
74616  // we just add `m' variables in the matrix of constraints.
74617  matrix.grow(new_dim);
74618  space_dim = new_dim;
74619  // If `*this' was the zero-dim space universe octagon,
74620  // then we can set the strongly closure flag.
74621  if (was_zero_dim_univ) {
74622    set_strongly_closed();
74623  }
74624
74625  PPL_ASSERT(OK());
74626}
74627
74628template <typename T>
74629void
74630Octagonal_Shape<T>::add_space_dimensions_and_project(dimension_type m) {
74631  // Adding no dimensions is a no-op.
74632  if (m == 0) {
74633    return;
74634  }
74635
74636  const dimension_type n = matrix.num_rows();
74637
74638  // To project an n-dimension space OS in a (space_dim + m)-dimension space,
74639  // we just add `m' columns and rows in the matrix of constraints.
74640  add_space_dimensions_and_embed(m);
74641  // We insert 0 where it needs.
74642  // Attention: now num_rows of matrix is update!
74643  for (typename OR_Matrix<N>::row_iterator i = matrix.row_begin() + n,
74644         matrix_row_end =  matrix.row_end(); i != matrix_row_end; i += 2) {
74645    typename OR_Matrix<N>::row_reference_type x_i = *i;
74646    typename OR_Matrix<N>::row_reference_type x_ci = *(i + 1);
74647    const dimension_type ind = i.index();
74648    assign_r(x_i[ind + 1], 0, ROUND_NOT_NEEDED);
74649    assign_r(x_ci[ind], 0, ROUND_NOT_NEEDED);
74650  }
74651
74652  if (marked_strongly_closed()) {
74653    reset_strongly_closed();
74654  }
74655  PPL_ASSERT(OK());
74656}
74657
74658template <typename T>
74659void
74660Octagonal_Shape<T>::remove_space_dimensions(const Variables_Set& vars) {
74661  // The removal of no dimensions from any octagon is a no-op.
74662  // Note that this case also captures the only legal removal of
74663  // dimensions from a octagon in a 0-dim space.
74664  if (vars.empty()) {
74665    PPL_ASSERT(OK());
74666    return;
74667  }
74668
74669  // Dimension-compatibility check.
74670  const dimension_type min_space_dim = vars.space_dimension();
74671  if (space_dim < min_space_dim) {
74672    throw_dimension_incompatible("remove_space_dimensions(vs)", min_space_dim);
74673  }
74674
74675  const dimension_type new_space_dim = space_dim - vars.size();
74676
74677  strong_closure_assign();
74678  // When removing _all_ dimensions from an octagon,
74679  // we obtain the zero-dimensional octagon.
74680  if (new_space_dim == 0) {
74681    matrix.shrink(0);
74682    if (!marked_empty()) {
74683      // We set the zero_dim_univ flag.
74684      set_zero_dim_univ();
74685    }
74686    space_dim = 0;
74687    PPL_ASSERT(OK());
74688    return;
74689  }
74690
74691  // We consider each variable and we check if it has to be removed.
74692  // If it has to be removed, we pass to the next one, then we will
74693  // overwrite its representation in the matrix.
74694  typedef typename OR_Matrix<N>::element_iterator Elem_Iter;
74695  typedef typename std::iterator_traits<Elem_Iter>::difference_type diff_t;
74696
74697  dimension_type first = *vars.begin();
74698  const dimension_type first_size = 2 * first * (first + 1);
74699  Elem_Iter iter = matrix.element_begin() + static_cast<diff_t>(first_size);
74700
74701  for (dimension_type i = first + 1; i < space_dim; ++i) {
74702    if (vars.count(i) == 0) {
74703      typename OR_Matrix<N>::row_iterator row_iter = matrix.row_begin() + 2*i;
74704      typename OR_Matrix<N>::row_reference_type row_ref = *row_iter;
74705      typename OR_Matrix<N>::row_reference_type row_ref1 = *(++row_iter);
74706      // Beware: first we shift the cells corresponding to the first
74707      // row of variable(j), then we shift the cells corresponding to the
74708      // second row. We recall that every variable is represented
74709      // in the `matrix' by two rows and two columns.
74710      for (dimension_type j = 0; j <= i; ++j) {
74711        if (vars.count(j) == 0) {
74712          assign_or_swap(*(iter++), row_ref[2*j]);
74713          assign_or_swap(*(iter++), row_ref[2*j + 1]);
74714        }
74715      }
74716      for (dimension_type j = 0; j <= i; ++j) {
74717        if (vars.count(j) == 0) {
74718          assign_or_swap(*(iter++), row_ref1[2*j]);
74719          assign_or_swap(*(iter++), row_ref1[2*j + 1]);
74720        }
74721      }
74722    }
74723  }
74724  // Update the space dimension.
74725  matrix.shrink(new_space_dim);
74726  space_dim = new_space_dim;
74727  PPL_ASSERT(OK());
74728}
74729
74730template <typename T>
74731template <typename Partial_Function>
74732void
74733Octagonal_Shape<T>::map_space_dimensions(const Partial_Function& pfunc) {
74734  if (space_dim == 0) {
74735    return;
74736  }
74737
74738  if (pfunc.has_empty_codomain()) {
74739    // All dimensions vanish: the octagon becomes zero_dimensional.
74740    remove_higher_space_dimensions(0);
74741    return;
74742  }
74743
74744  const dimension_type new_space_dim = pfunc.max_in_codomain() + 1;
74745  // If we are going to actually reduce the space dimension,
74746  // then shortest-path closure is required to keep precision.
74747  if (new_space_dim < space_dim) {
74748    strong_closure_assign();
74749  }
74750  // If the octagon is empty, then it is sufficient to adjust
74751  // the space dimension of the octagon.
74752  if (marked_empty()) {
74753    remove_higher_space_dimensions(new_space_dim);
74754    return;
74755  }
74756
74757  // We create a new matrix with the new space dimension.
74758  OR_Matrix<N> x(new_space_dim);
74759
74760  typedef typename OR_Matrix<N>::row_iterator row_iterator;
74761  typedef typename OR_Matrix<N>::row_reference_type row_reference;
74762
74763  row_iterator m_begin = x.row_begin();
74764
74765  for (row_iterator i_iter = matrix.row_begin(), i_end = matrix.row_end();
74766       i_iter != i_end; i_iter += 2) {
74767    dimension_type new_i;
74768    dimension_type i = i_iter.index()/2;
74769    // We copy and place in the position into `x' the only cells of
74770    // the `matrix' that refer to both mapped variables,
74771    // the variable `i' and `j'.
74772    if (pfunc.maps(i, new_i)) {
74773      row_reference r_i = *i_iter;
74774      row_reference r_ii = *(i_iter + 1);
74775      dimension_type double_new_i = 2*new_i;
74776      row_iterator x_iter = m_begin + double_new_i;
74777      row_reference x_i = *x_iter;
74778      row_reference x_ii = *(x_iter + 1);
74779      for (dimension_type j = 0; j <= i; ++j) {
74780        dimension_type new_j;
74781        // If also the second variable is mapped, we work.
74782        if (pfunc.maps(j, new_j)) {
74783          dimension_type dj = 2*j;
74784          dimension_type double_new_j = 2*new_j;
74785          // Mapped the constraints, exchanging the indexes.
74786          // Attention: our matrix is pseudo-triangular.
74787          // If new_j > new_i, we must consider, as rows, the rows of
74788          // the variable new_j, and not of new_i ones.
74789          if (new_i >= new_j) {
74790            assign_or_swap(x_i[double_new_j], r_i[dj]);
74791            assign_or_swap(x_ii[double_new_j], r_ii[dj]);
74792            assign_or_swap(x_ii[double_new_j + 1], r_ii[dj + 1]);
74793            assign_or_swap(x_i[double_new_j + 1], r_i[dj + 1]);
74794          }
74795          else {
74796            row_iterator x_j_iter = m_begin + double_new_j;
74797            row_reference x_j = *x_j_iter;
74798            row_reference x_jj = *(x_j_iter + 1);
74799            assign_or_swap(x_jj[double_new_i + 1], r_i[dj]);
74800            assign_or_swap(x_jj[double_new_i], r_ii[dj]);
74801            assign_or_swap(x_j[double_new_i + 1], r_i[dj + 1]);
74802            assign_or_swap(x_j[double_new_i], r_ii[dj + 1]);
74803          }
74804
74805        }
74806      }
74807    }
74808  }
74809
74810  using std::swap;
74811  swap(matrix, x);
74812  space_dim = new_space_dim;
74813  PPL_ASSERT(OK());
74814}
74815
74816template <typename T>
74817void
74818Octagonal_Shape<T>::intersection_assign(const Octagonal_Shape& y) {
74819  // Dimension-compatibility check.
74820  if (space_dim != y.space_dim) {
74821    throw_dimension_incompatible("intersection_assign(y)", y);
74822  }
74823
74824  // If one of the two octagons is empty, the intersection is empty.
74825  if (marked_empty()) {
74826    return;
74827  }
74828  if (y.marked_empty()) {
74829    set_empty();
74830    return;
74831  }
74832  // If both octagons are zero-dimensional,then at this point
74833  // they are necessarily non-empty,
74834  // so that their intersection is non-empty too.
74835  if (space_dim == 0) {
74836    return;
74837  }
74838  // To intersect two octagons we compare the constraints
74839  // and we choose the less values.
74840  bool changed = false;
74841
74842  typename OR_Matrix<N>::const_element_iterator j = y.matrix.element_begin();
74843  for (typename OR_Matrix<N>::element_iterator i = matrix.element_begin(),
74844         matrix_element_end = matrix.element_end();
74845       i != matrix_element_end;
74846       ++i, ++j) {
74847    N& elem = *i;
74848    const N& y_elem = *j;
74849    if (y_elem < elem) {
74850      elem = y_elem;
74851      changed = true;
74852    }
74853  }
74854
74855  // This method not preserve the closure.
74856  if (changed && marked_strongly_closed()) {
74857    reset_strongly_closed();
74858  }
74859  PPL_ASSERT(OK());
74860}
74861
74862template <typename T>
74863template <typename Iterator>
74864void
74865Octagonal_Shape<T>::CC76_extrapolation_assign(const Octagonal_Shape& y,
74866                                              Iterator first, Iterator last,
74867                                              unsigned* tp) {
74868  // Dimension-compatibility check.
74869  if (space_dim != y.space_dim) {
74870    throw_dimension_incompatible("CC76_extrapolation_assign(y)", y);
74871  }
74872
74873  // Assume `y' is contained in or equal to `*this'.
74874  PPL_EXPECT_HEAVY(copy_contains(*this, y));
74875
74876  // If both octagons are zero-dimensional,
74877  // since `*this' contains `y', we simply return `*this'.
74878  if (space_dim == 0) {
74879    return;
74880  }
74881
74882  strong_closure_assign();
74883  // If `*this' is empty, since `*this' contains `y', `y' is empty too.
74884  if (marked_empty()) {
74885    return;
74886  }
74887  y.strong_closure_assign();
74888  // If `y' is empty, we return.
74889  if (y.marked_empty()) {
74890    return;
74891  }
74892
74893  // If there are tokens available, work on a temporary copy.
74894  if (tp != 0 && *tp > 0) {
74895    Octagonal_Shape x_tmp(*this);
74896    x_tmp.CC76_extrapolation_assign(y, first, last, 0);
74897    // If the widening was not precise, use one of the available tokens.
74898    if (!contains(x_tmp)) {
74899      --(*tp);
74900    }
74901    return;
74902  }
74903
74904  // Compare each constraint in `y' to the corresponding one in `*this'.
74905  // The constraint in `*this' is kept as is if it is stronger than or
74906  // equal to the constraint in `y'; otherwise, the inhomogeneous term
74907  // of the constraint in `*this' is further compared with elements taken
74908  // from a sorted container (the stop-points, provided by the user), and
74909  // is replaced by the first entry, if any, which is greater than or equal
74910  // to the inhomogeneous term. If no such entry exists, the constraint
74911  // is removed altogether.
74912  typename OR_Matrix<N>::const_element_iterator j = y.matrix.element_begin();
74913  for (typename OR_Matrix<N>::element_iterator i = matrix.element_begin(),
74914         matrix_element_end = matrix.element_end();
74915       i != matrix_element_end;
74916       ++i, ++j) {
74917    const N& y_elem = *j;
74918    N& elem = *i;
74919    if (y_elem < elem) {
74920      Iterator k = std::lower_bound(first, last, elem);
74921      if (k != last) {
74922        if (elem < *k) {
74923          assign_r(elem, *k, ROUND_UP);
74924        }
74925      }
74926      else {
74927        assign_r(elem, PLUS_INFINITY, ROUND_NOT_NEEDED);
74928      }
74929    }
74930  }
74931
74932  reset_strongly_closed();
74933  PPL_ASSERT(OK());
74934}
74935
74936template <typename T>
74937void
74938Octagonal_Shape<T>
74939::get_limiting_octagon(const Constraint_System& cs,
74940                       Octagonal_Shape& limiting_octagon) const {
74941  const dimension_type cs_space_dim = cs.space_dimension();
74942  // Private method: the caller has to ensure the following.
74943  PPL_ASSERT(cs_space_dim <= space_dim);
74944
74945  strong_closure_assign();
74946  bool is_oct_changed = false;
74947
74948  // Allocate temporaries outside of the loop.
74949  PPL_DIRTY_TEMP_COEFFICIENT(coeff);
74950  PPL_DIRTY_TEMP_COEFFICIENT(term);
74951  PPL_DIRTY_TEMP(N, d);
74952
74953  for (Constraint_System::const_iterator cs_i = cs.begin(),
74954         cs_end = cs.end(); cs_i != cs_end; ++cs_i) {
74955    const Constraint& c = *cs_i;
74956    dimension_type num_vars = 0;
74957    dimension_type i = 0;
74958    dimension_type j = 0;
74959    // Constraints that are not octagonal differences are ignored.
74960    if (!Octagonal_Shape_Helper
74961      ::extract_octagonal_difference(c, cs_space_dim, num_vars, i, j,
74962                                     coeff, term)) {
74963      continue;
74964    }
74965
74966    typedef typename OR_Matrix<N>::const_row_iterator Row_iterator;
74967    typedef typename OR_Matrix<N>::const_row_reference_type Row_reference;
74968    typedef typename OR_Matrix<N>::row_iterator row_iterator;
74969    typedef typename OR_Matrix<N>::row_reference_type row_reference;
74970    Row_iterator m_begin = matrix.row_begin();
74971    // Select the cell to be modified for the "<=" part of the constraint.
74972    Row_iterator i_iter = m_begin + i;
74973    Row_reference m_i = *i_iter;
74974    OR_Matrix<N>& lo_mat = limiting_octagon.matrix;
74975    row_iterator lo_iter = lo_mat.row_begin() + i;
74976    row_reference lo_m_i = *lo_iter;
74977    N& lo_m_i_j = lo_m_i[j];
74978    if (coeff < 0) {
74979      neg_assign(coeff);
74980    }
74981    // Compute the bound for `m_i_j', rounding towards plus infinity.
74982    div_round_up(d, term, coeff);
74983    if (m_i[j] <= d) {
74984      if (c.is_inequality()) {
74985        if (lo_m_i_j > d) {
74986          lo_m_i_j = d;
74987          is_oct_changed = true;
74988        }
74989        else {
74990          // Select the right row of the cell.
74991          if (i % 2 == 0) {
74992            ++i_iter;
74993            ++lo_iter;
74994          }
74995          else {
74996            --i_iter;
74997            --lo_iter;
74998          }
74999          Row_reference m_ci = *i_iter;
75000          row_reference lo_m_ci = *lo_iter;
75001          // Select the right column of the cell.
75002          using namespace Implementation::Octagonal_Shapes;
75003          dimension_type cj = coherent_index(j);
75004          N& lo_m_ci_cj = lo_m_ci[cj];
75005          neg_assign(term);
75006          div_round_up(d, term, coeff);
75007          if (m_ci[cj] <= d && lo_m_ci_cj > d) {
75008            lo_m_ci_cj = d;
75009            is_oct_changed = true;
75010          }
75011        }
75012      }
75013    }
75014  }
75015  // In general, adding a constraint does not preserve the strongly
75016  // closure of the octagon.
75017  if (is_oct_changed && limiting_octagon.marked_strongly_closed()) {
75018    limiting_octagon.reset_strongly_closed();
75019  }
75020}
75021
75022template <typename T>
75023void
75024Octagonal_Shape<T>
75025::limited_CC76_extrapolation_assign(const Octagonal_Shape& y,
75026                                    const Constraint_System& cs,
75027                                    unsigned* tp) {
75028
75029  // Dimension-compatibility check.
75030  if (space_dim != y.space_dim) {
75031    throw_dimension_incompatible("limited_CC76_extrapolation_assign(y, cs)",
75032                                 y);
75033  }
75034  // `cs' must be dimension-compatible with the two octagons.
75035  const dimension_type cs_space_dim = cs.space_dimension();
75036  if (space_dim < cs_space_dim) {
75037    throw_constraint_incompatible("limited_CC76_extrapolation_assign(y, cs)");
75038  }
75039
75040  // Strict inequalities not allowed.
75041  if (cs.has_strict_inequalities()) {
75042    throw_constraint_incompatible("limited_CC76_extrapolation_assign(y, cs)");
75043  }
75044
75045  // The limited CC76-extrapolation between two octagons in a
75046  // zero-dimensional space is a octagon in a zero-dimensional
75047  // space, too.
75048  if (space_dim == 0) {
75049    return;
75050  }
75051
75052  // Assume `y' is contained in or equal to `*this'.
75053  PPL_EXPECT_HEAVY(copy_contains(*this, y));
75054
75055  // If `*this' is empty, since `*this' contains `y', `y' is empty too.
75056  if (marked_empty()) {
75057    return;
75058  }
75059
75060  // If `y' is empty, we return.
75061  if (y.marked_empty()) {
75062    return;
75063  }
75064
75065  Octagonal_Shape limiting_octagon(space_dim, UNIVERSE);
75066  get_limiting_octagon(cs, limiting_octagon);
75067  CC76_extrapolation_assign(y, tp);
75068  intersection_assign(limiting_octagon);
75069}
75070
75071template <typename T>
75072void
75073Octagonal_Shape<T>::BHMZ05_widening_assign(const Octagonal_Shape& y,
75074                                           unsigned* tp) {
75075  // Dimension-compatibility check.
75076  if (space_dim != y.space_dim) {
75077    throw_dimension_incompatible("BHMZ05_widening_assign(y)", y);
75078  }
75079
75080  // Assume `y' is contained in or equal to `*this'.
75081  PPL_EXPECT_HEAVY(copy_contains(*this, y));
75082
75083  // Compute the affine dimension of `y'.
75084  const dimension_type y_affine_dim = y.affine_dimension();
75085  // If the affine dimension of `y' is zero, then either `y' is
75086  // zero-dimensional, or it is empty, or it is a singleton.
75087  // In all cases, due to the inclusion hypothesis, the result is `*this'.
75088  if (y_affine_dim == 0) {
75089    return;
75090  }
75091
75092  // If the affine dimension has changed, due to the inclusion hypothesis,
75093  // the result is `*this'.
75094  const dimension_type x_affine_dim = affine_dimension();
75095  PPL_ASSERT(x_affine_dim >= y_affine_dim);
75096  if (x_affine_dim != y_affine_dim) {
75097    return;
75098  }
75099  // If there are tokens available, work on a temporary copy.
75100  if (tp != 0 && *tp > 0) {
75101    Octagonal_Shape x_tmp(*this);
75102    x_tmp.BHMZ05_widening_assign(y, 0);
75103    // If the widening was not precise, use one of the available tokens.
75104    if (!contains(x_tmp)) {
75105      --(*tp);
75106    }
75107    return;
75108  }
75109
75110  // Here no token is available.
75111  PPL_ASSERT(marked_strongly_closed() && y.marked_strongly_closed());
75112  // Minimize `y'.
75113  y.strong_reduction_assign();
75114
75115  // Extrapolate unstable bounds.
75116  typename OR_Matrix<N>::const_element_iterator j = y.matrix.element_begin();
75117  for (typename OR_Matrix<N>::element_iterator i = matrix.element_begin(),
75118       matrix_element_end = matrix.element_end();
75119       i != matrix_element_end;
75120       ++i, ++j) {
75121    N& elem = *i;
75122      // Note: in the following line the use of `!=' (as opposed to
75123      // the use of `<' that would seem -but is not- equivalent) is
75124      // intentional.
75125    if (*j != elem) {
75126      assign_r(elem, PLUS_INFINITY, ROUND_NOT_NEEDED);
75127    }
75128  }
75129  reset_strongly_closed();
75130  PPL_ASSERT(OK());
75131}
75132
75133template <typename T>
75134void
75135Octagonal_Shape<T>
75136::limited_BHMZ05_extrapolation_assign(const Octagonal_Shape& y,
75137                                      const Constraint_System& cs,
75138                                      unsigned* tp) {
75139
75140  // Dimension-compatibility check.
75141  if (space_dim != y.space_dim) {
75142    throw_dimension_incompatible("limited_BHMZ05_extrapolation_assign(y, cs)",
75143                                 y);
75144  }
75145
75146  // `cs' must be dimension-compatible with the two octagons.
75147  const dimension_type cs_space_dim = cs.space_dimension();
75148  if (space_dim < cs_space_dim) {
75149    throw_constraint_incompatible("limited_CH78_extrapolation_assign(y, cs)");
75150  }
75151
75152  // Strict inequalities not allowed.
75153  if (cs.has_strict_inequalities()) {
75154    throw_constraint_incompatible("limited_CH78_extrapolation_assign(y, cs)");
75155  }
75156
75157  // The limited BHMZ05-extrapolation between two octagons in a
75158  // zero-dimensional space is a octagon in a zero-dimensional
75159  // space, too.
75160  if (space_dim == 0) {
75161    return;
75162  }
75163
75164  // Assume `y' is contained in or equal to `*this'.
75165  PPL_EXPECT_HEAVY(copy_contains(*this, y));
75166
75167  // If `*this' is empty, since `*this' contains `y', `y' is empty too.
75168  if (marked_empty()) {
75169    return;
75170  }
75171  // If `y' is empty, we return.
75172  if (y.marked_empty()) {
75173    return;
75174  }
75175
75176  Octagonal_Shape limiting_octagon(space_dim, UNIVERSE);
75177  get_limiting_octagon(cs, limiting_octagon);
75178  BHMZ05_widening_assign(y, tp);
75179  intersection_assign(limiting_octagon);
75180}
75181
75182template <typename T>
75183void
75184Octagonal_Shape<T>::CC76_narrowing_assign(const Octagonal_Shape& y) {
75185  // Dimension-compatibility check.
75186  if (space_dim != y.space_dim) {
75187    throw_dimension_incompatible("CC76_narrowing_assign(y)", y);
75188  }
75189
75190  // Assume `*this' is contained in or equal to `y'.
75191  PPL_EXPECT_HEAVY(copy_contains(y, *this));
75192
75193  // If both octagons are zero-dimensional, since `*this' contains `y',
75194  // we simply return '*this'.
75195  if (space_dim == 0) {
75196    return;
75197  }
75198
75199  y.strong_closure_assign();
75200  // If `y' is empty, since `y' contains `*this', `*this' is empty too.
75201  if (y.marked_empty()) {
75202    return;
75203  }
75204
75205  strong_closure_assign();
75206  // If `*this' is empty, we return.
75207  if (marked_empty()) {
75208    return;
75209  }
75210
75211  // We consider a constraint of `*this', if its value is `plus_infinity',
75212  // we take the value of the corresponding constraint of `y'.
75213  bool is_oct_changed = false;
75214  typename OR_Matrix<N>::const_element_iterator j = y.matrix.element_begin();
75215  for (typename OR_Matrix<N>::element_iterator i = matrix.element_begin(),
75216         matrix_element_end = matrix.element_end();
75217       i != matrix_element_end;
75218       ++i, ++j) {
75219    if (!is_plus_infinity(*i)
75220        && !is_plus_infinity(*j)
75221        && *i != *j) {
75222      *i = *j;
75223      is_oct_changed = true;
75224    }
75225  }
75226
75227  if (is_oct_changed && marked_strongly_closed()) {
75228    reset_strongly_closed();
75229  }
75230  PPL_ASSERT(OK());
75231}
75232
75233template <typename T>
75234void
75235Octagonal_Shape<T>
75236::deduce_v_pm_u_bounds(const dimension_type v_id,
75237                       const dimension_type last_id,
75238                       const Linear_Expression& sc_expr,
75239                       Coefficient_traits::const_reference sc_denom,
75240                       const N& ub_v) {
75241  // Private method: the caller has to ensure the following.
75242  PPL_ASSERT(sc_denom > 0);
75243  PPL_ASSERT(!is_plus_infinity(ub_v));
75244
75245  PPL_DIRTY_TEMP(mpq_class, mpq_sc_denom);
75246  assign_r(mpq_sc_denom, sc_denom, ROUND_NOT_NEEDED);
75247
75248  // No need to consider indices greater than `last_id'.
75249  const dimension_type n_v = 2*v_id;
75250  typename OR_Matrix<N>::row_reference_type m_cv = matrix[n_v + 1];
75251
75252  // Speculatively allocate temporaries out of the loop.
75253  PPL_DIRTY_TEMP(N, half);
75254  PPL_DIRTY_TEMP(mpq_class, minus_lb_u);
75255  PPL_DIRTY_TEMP(mpq_class, q);
75256  PPL_DIRTY_TEMP(mpq_class, minus_q);
75257  PPL_DIRTY_TEMP(mpq_class, ub_u);
75258  PPL_DIRTY_TEMP(mpq_class, lb_u);
75259  PPL_DIRTY_TEMP(N, up_approx);
75260  PPL_DIRTY_TEMP_COEFFICIENT(minus_expr_u);
75261
75262  for (Linear_Expression::const_iterator u = sc_expr.begin(),
75263      u_end = sc_expr.lower_bound(Variable(last_id + 1)); u != u_end; ++u) {
75264    const dimension_type u_id = u.variable().id();
75265    // Skip the case when `u_id == v_id'.
75266    if (u_id == v_id) {
75267      continue;
75268    }
75269    const Coefficient& expr_u = *u;
75270
75271    const dimension_type n_u = u_id*2;
75272    // If `expr_u' is positive, we can improve `v - u'.
75273    if (expr_u > 0) {
75274      if (expr_u >= sc_denom) {
75275        // Here q >= 1: deducing `v - u <= ub_v - ub_u'.
75276        // We avoid to check if `ub_u' is plus infinity, because
75277        // it is used for the computation of `ub_v'.
75278        // Let half = m_cu_u / 2.
75279        div_2exp_assign_r(half, matrix[n_u + 1][n_u], 1, ROUND_UP);
75280        N& m_v_minus_u = (n_v < n_u) ? matrix[n_u][n_v] : m_cv[n_u + 1];
75281        sub_assign_r(m_v_minus_u, ub_v, half, ROUND_UP);
75282      }
75283      else {
75284        // Here 0 < q < 1.
75285        typename OR_Matrix<N>::row_reference_type m_u = matrix[n_u];
75286        const N& m_u_cu = m_u[n_u + 1];
75287        if (!is_plus_infinity(m_u_cu)) {
75288          // Let `ub_u' and `lb_u' be the known upper and lower bound
75289          // for `u', respectively. The upper bound for `v - u' is
75290          // computed as `ub_v - (q * ub_u + (1-q) * lb_u)',
75291          // i.e., `ub_v + (-lb_u) - q * (ub_u + (-lb_u))'.
75292          assign_r(minus_lb_u, m_u_cu, ROUND_NOT_NEEDED);
75293          div_2exp_assign_r(minus_lb_u, minus_lb_u, 1, ROUND_NOT_NEEDED);
75294          assign_r(q, expr_u, ROUND_NOT_NEEDED);
75295          div_assign_r(q, q, mpq_sc_denom, ROUND_NOT_NEEDED);
75296          assign_r(ub_u, matrix[n_u + 1][n_u], ROUND_NOT_NEEDED);
75297          div_2exp_assign_r(ub_u, ub_u, 1, ROUND_NOT_NEEDED);
75298          // Compute `ub_u - lb_u'.
75299          add_assign_r(ub_u, ub_u, minus_lb_u, ROUND_NOT_NEEDED);
75300          // Compute `(-lb_u) - q * (ub_u - lb_u)'.
75301          sub_mul_assign_r(minus_lb_u, q, ub_u, ROUND_NOT_NEEDED);
75302          assign_r(up_approx, minus_lb_u, ROUND_UP);
75303          // Deducing `v - u <= ub_v - (q * ub_u + (1-q) * lb_u)'.
75304          N& m_v_minus_u = (n_v < n_u) ? m_u[n_v] : m_cv[n_u + 1];
75305          add_assign_r(m_v_minus_u, ub_v, up_approx, ROUND_UP);
75306        }
75307      }
75308    }
75309    else {
75310      PPL_ASSERT(expr_u < 0);
75311      // If `expr_u' is negative, we can improve `v + u'.
75312      neg_assign(minus_expr_u, expr_u);
75313      if (minus_expr_u >= sc_denom) {
75314        // Here q <= -1: Deducing `v + u <= ub_v + lb_u'.
75315        // We avoid to check if `lb_u' is plus infinity, because
75316        // it is used for the computation of `ub_v'.
75317        // Let half = m_u_cu / 2.
75318        div_2exp_assign_r(half, matrix[n_u][n_u + 1], 1, ROUND_UP);
75319        N& m_v_plus_u = (n_v < n_u) ? matrix[n_u + 1][n_v] : m_cv[n_u];
75320        sub_assign_r(m_v_plus_u, ub_v, half, ROUND_UP);
75321      }
75322      else {
75323        // Here -1 < q < 0.
75324        typename OR_Matrix<N>::row_reference_type m_cu = matrix[n_u + 1];
75325        const N& m_cu_u = m_cu[n_u];
75326        if (!is_plus_infinity(m_cu_u)) {
75327          // Let `ub_u' and `lb_u' be the known upper and lower bound
75328          // for `u', respectively. The upper bound for `v + u' is
75329          // computed as `ub_v + ((-q) * lb_u + (1 + q) * ub_u)',
75330          // i.e., `ub_v + ub_u + (-q) * (lb_u - ub_u)'.
75331          assign_r(ub_u, m_cu[n_u], ROUND_NOT_NEEDED);
75332          div_2exp_assign_r(ub_u, ub_u, 1, ROUND_NOT_NEEDED);
75333          assign_r(minus_q, minus_expr_u, ROUND_NOT_NEEDED);
75334          div_assign_r(minus_q, minus_q, mpq_sc_denom, ROUND_NOT_NEEDED);
75335          assign_r(lb_u, matrix[n_u][n_u + 1], ROUND_NOT_NEEDED);
75336          div_2exp_assign_r(lb_u, lb_u, 1, ROUND_NOT_NEEDED);
75337          neg_assign_r(lb_u, lb_u, ROUND_NOT_NEEDED);
75338          // Compute `lb_u - ub_u'.
75339          sub_assign_r(lb_u, lb_u, ub_u, ROUND_NOT_NEEDED);
75340          // Compute `ub_u + (-q) * (lb_u - ub_u)'.
75341          add_mul_assign_r(ub_u, minus_q, lb_u, ROUND_NOT_NEEDED);
75342          assign_r(up_approx, ub_u, ROUND_UP);
75343          // Deducing `v + u <= ub_v + ((-q) * lb_u + (1 + q) * ub_u)'.
75344          N& m_v_plus_u = (n_v < n_u) ? m_cu[n_v] : m_cv[n_u];
75345          add_assign_r(m_v_plus_u, ub_v, up_approx, ROUND_UP);
75346        }
75347      }
75348    }
75349  }
75350}
75351
75352template <typename T>
75353void
75354Octagonal_Shape<T>
75355::deduce_minus_v_pm_u_bounds(const dimension_type v_id,
75356                             const dimension_type last_id,
75357                             const Linear_Expression& sc_expr,
75358                             Coefficient_traits::const_reference sc_denom,
75359                             const N& minus_lb_v) {
75360  // Private method: the caller has to ensure the following.
75361  PPL_ASSERT(sc_denom > 0);
75362  PPL_ASSERT(!is_plus_infinity(minus_lb_v));
75363
75364  PPL_DIRTY_TEMP(mpq_class, mpq_sc_denom);
75365  assign_r(mpq_sc_denom, sc_denom, ROUND_NOT_NEEDED);
75366
75367  // No need to consider indices greater than `last_id'.
75368  const dimension_type n_v = 2*v_id;
75369  typename OR_Matrix<N>::row_reference_type m_v = matrix[n_v];
75370
75371  // Speculatively allocate temporaries out of the loop.
75372  PPL_DIRTY_TEMP(N, half);
75373  PPL_DIRTY_TEMP(mpq_class, ub_u);
75374  PPL_DIRTY_TEMP(mpq_class, q);
75375  PPL_DIRTY_TEMP(mpq_class, minus_lb_u);
75376  PPL_DIRTY_TEMP(N, up_approx);
75377  PPL_DIRTY_TEMP_COEFFICIENT(minus_expr_u);
75378
75379  for (Linear_Expression::const_iterator u = sc_expr.begin(),
75380      u_end = sc_expr.lower_bound(Variable(last_id + 1)); u != u_end; ++u) {
75381    const dimension_type u_id = u.variable().id();
75382    // Skip the case when `u_id == v_id'.
75383    if (u_id == v_id) {
75384      continue;
75385    }
75386    const Coefficient& expr_u = *u;
75387
75388    const dimension_type n_u = u_id*2;
75389    // If `expr_u' is positive, we can improve `-v + u'.
75390    if (expr_u > 0) {
75391      if (expr_u >= sc_denom) {
75392        // Here q >= 1: deducing `-v + u <= lb_u - lb_v',
75393        // i.e., `u - v <= (-lb_v) - (-lb_u)'.
75394        // We avoid to check if `lb_u' is plus infinity, because
75395        // it is used for the computation of `lb_v'.
75396        // Let half = m_u_cu / 2.
75397        div_2exp_assign_r(half, matrix[n_u][n_u + 1], 1, ROUND_UP);
75398        N& m_u_minus_v = (n_v < n_u) ? matrix[n_u + 1][n_v + 1] : m_v[n_u];
75399        sub_assign_r(m_u_minus_v, minus_lb_v, half, ROUND_UP);
75400      }
75401      else {
75402        // Here 0 < q < 1.
75403        typename OR_Matrix<N>::row_reference_type m_cu = matrix[n_u + 1];
75404        const N& m_cu_u = m_cu[n_u];
75405        if (!is_plus_infinity(m_cu_u)) {
75406          // Let `ub_u' and `lb_u' be the known upper and lower bound
75407          // for `u', respectively. The upper bound for `u - v' is
75408          // computed as `(q * lb_u + (1-q) * ub_u) - lb_v',
75409          // i.e., `ub_u - q * (ub_u + (-lb_u)) + minus_lb_v'.
75410          assign_r(ub_u, m_cu[n_u], ROUND_NOT_NEEDED);
75411          div_2exp_assign_r(ub_u, ub_u, 1, ROUND_NOT_NEEDED);
75412          assign_r(q, expr_u, ROUND_NOT_NEEDED);
75413          div_assign_r(q, q, mpq_sc_denom, ROUND_NOT_NEEDED);
75414          assign_r(minus_lb_u, matrix[n_u][n_u + 1], ROUND_NOT_NEEDED);
75415          div_2exp_assign_r(minus_lb_u, minus_lb_u, 1, ROUND_NOT_NEEDED);
75416          // Compute `ub_u - lb_u'.
75417          add_assign_r(minus_lb_u, ub_u, minus_lb_u, ROUND_NOT_NEEDED);
75418          // Compute `ub_u - q * (ub_u - lb_u)'.
75419          sub_mul_assign_r(ub_u, q, minus_lb_u, ROUND_NOT_NEEDED);
75420          assign_r(up_approx, ub_u, ROUND_UP);
75421          // Deducing `u - v <= -lb_v - (q * lb_u + (1-q) * ub_u)'.
75422          N& m_u_minus_v = (n_v < n_u) ? m_cu[n_v + 1] : m_v[n_u];
75423          add_assign_r(m_u_minus_v, minus_lb_v, up_approx, ROUND_UP);
75424        }
75425      }
75426    }
75427    else {
75428      PPL_ASSERT(expr_u < 0);
75429      // If `expr_u' is negative, we can improve `-v - u'.
75430      neg_assign(minus_expr_u, expr_u);
75431      if (minus_expr_u >= sc_denom) {
75432        // Here q <= -1: Deducing `-v - u <= -lb_v - ub_u'.
75433        // We avoid to check if `ub_u' is plus infinity, because
75434        // it is used for the computation of `lb_v'.
75435        // Let half = m_cu_u / 2.
75436        div_2exp_assign_r(half, matrix[n_u + 1][n_u], 1, ROUND_UP);
75437        N& m_minus_v_minus_u = (n_v < n_u)
75438          ? matrix[n_u][n_v + 1]
75439          : m_v[n_u + 1];
75440        sub_assign_r(m_minus_v_minus_u, minus_lb_v, half, ROUND_UP);
75441      }
75442      else {
75443        // Here -1 < q < 0.
75444        typename OR_Matrix<N>::row_reference_type m_u = matrix[n_u];
75445        const N& m_u_cu = m_u[n_u + 1];
75446        if (!is_plus_infinity(m_u_cu)) {
75447          // Let `ub_u' and `lb_u' be the known upper and lower bound
75448          // for `u', respectively. The upper bound for `-v - u' is
75449          // computed as `-lb_v - ((-q)*ub_u + (1 + q)*lb_u)',
75450          // i.e., `minus_lb_v - lb_u + q*(ub_u - lb_u)'.
75451          assign_r(ub_u, matrix[n_u + 1][n_u], ROUND_NOT_NEEDED);
75452          div_2exp_assign_r(ub_u, ub_u, 1, ROUND_NOT_NEEDED);
75453          assign_r(q, expr_u, ROUND_NOT_NEEDED);
75454          div_assign_r(q, q, mpq_sc_denom, ROUND_NOT_NEEDED);
75455          assign_r(minus_lb_u, m_u[n_u + 1], ROUND_NOT_NEEDED);
75456          div_2exp_assign_r(minus_lb_u, minus_lb_u, 1, ROUND_NOT_NEEDED);
75457          // Compute `ub_u - lb_u'.
75458          add_assign_r(ub_u, ub_u, minus_lb_u, ROUND_NOT_NEEDED);
75459          // Compute `-lb_u + q*(ub_u - lb_u)'.
75460          add_mul_assign_r(minus_lb_u, q, ub_u, ROUND_NOT_NEEDED);
75461          assign_r(up_approx, minus_lb_u, ROUND_UP);
75462          // Deducing `-v - u <= -lb_v - ((-q) * ub_u + (1 + q) * lb_u)'.
75463          N& m_minus_v_minus_u = (n_v < n_u) ? m_u[n_v + 1] : m_v[n_u + 1];
75464          add_assign_r(m_minus_v_minus_u, minus_lb_v, up_approx, ROUND_UP);
75465        }
75466      }
75467    }
75468  }
75469}
75470
75471template <typename T>
75472void
75473Octagonal_Shape<T>
75474::forget_all_octagonal_constraints(const dimension_type v_id) {
75475  PPL_ASSERT(v_id < space_dim);
75476  const dimension_type n_v = 2*v_id;
75477  typename OR_Matrix<N>::row_iterator m_iter = matrix.row_begin() + n_v;
75478  typename OR_Matrix<N>::row_reference_type r_v = *m_iter;
75479  typename OR_Matrix<N>::row_reference_type r_cv = *(++m_iter);
75480  for (dimension_type h = m_iter.row_size(); h-- > 0; ) {
75481    assign_r(r_v[h], PLUS_INFINITY, ROUND_NOT_NEEDED);
75482    assign_r(r_cv[h], PLUS_INFINITY, ROUND_NOT_NEEDED);
75483  }
75484  ++m_iter;
75485  for (typename OR_Matrix<N>::row_iterator m_end = matrix.row_end();
75486       m_iter != m_end; ++m_iter) {
75487    typename OR_Matrix<N>::row_reference_type r = *m_iter;
75488    assign_r(r[n_v], PLUS_INFINITY, ROUND_NOT_NEEDED);
75489    assign_r(r[n_v + 1], PLUS_INFINITY, ROUND_NOT_NEEDED);
75490  }
75491}
75492
75493template <typename T>
75494void
75495Octagonal_Shape<T>
75496::forget_binary_octagonal_constraints(const dimension_type v_id) {
75497  PPL_ASSERT(v_id < space_dim);
75498  const dimension_type n_v = 2*v_id;
75499  typename OR_Matrix<N>::row_iterator m_iter = matrix.row_begin() + n_v;
75500  typename OR_Matrix<N>::row_reference_type r_v = *m_iter;
75501  typename OR_Matrix<N>::row_reference_type r_cv = *(++m_iter);
75502  for (dimension_type k = n_v; k-- > 0; ) {
75503    assign_r(r_v[k], PLUS_INFINITY, ROUND_NOT_NEEDED);
75504    assign_r(r_cv[k], PLUS_INFINITY, ROUND_NOT_NEEDED);
75505  }
75506  ++m_iter;
75507  for (typename OR_Matrix<N>::row_iterator m_end = matrix.row_end();
75508       m_iter != m_end; ++m_iter) {
75509    typename OR_Matrix<N>::row_reference_type r = *m_iter;
75510    assign_r(r[n_v], PLUS_INFINITY, ROUND_NOT_NEEDED);
75511    assign_r(r[n_v + 1], PLUS_INFINITY, ROUND_NOT_NEEDED);
75512  }
75513}
75514
75515template <typename T>
75516void
75517Octagonal_Shape<T>::unconstrain(const Variable var) {
75518  // Dimension-compatibility check.
75519  const dimension_type var_id = var.id();
75520  if (space_dimension() < var_id + 1) {
75521    throw_dimension_incompatible("unconstrain(var)", var_id + 1);
75522  }
75523
75524  // Enforce strong closure for precision.
75525  strong_closure_assign();
75526
75527  // If the shape is empty, this is a no-op.
75528  if (marked_empty()) {
75529    return;
75530  }
75531
75532  forget_all_octagonal_constraints(var_id);
75533  // Strong closure is preserved.
75534  PPL_ASSERT(OK());
75535}
75536
75537template <typename T>
75538void
75539Octagonal_Shape<T>::unconstrain(const Variables_Set& vars) {
75540  // The cylindrification with respect to no dimensions is a no-op.
75541  // This case captures the only legal cylindrification in a 0-dim space.
75542  if (vars.empty()) {
75543    return;
75544  }
75545
75546  // Dimension-compatibility check.
75547  const dimension_type min_space_dim = vars.space_dimension();
75548  if (space_dimension() < min_space_dim) {
75549    throw_dimension_incompatible("unconstrain(vs)", min_space_dim);
75550  }
75551
75552  // Enforce strong closure for precision.
75553  strong_closure_assign();
75554
75555  // If the shape is empty, this is a no-op.
75556  if (marked_empty()) {
75557    return;
75558  }
75559
75560  for (Variables_Set::const_iterator vsi = vars.begin(),
75561         vsi_end = vars.end(); vsi != vsi_end; ++vsi) {
75562    forget_all_octagonal_constraints(*vsi);
75563  }
75564  // Strong closure is preserved.
75565  PPL_ASSERT(OK());
75566}
75567
75568template <typename T>
75569void
75570Octagonal_Shape<T>::refine(const Variable var,
75571                           const Relation_Symbol relsym,
75572                           const Linear_Expression& expr,
75573                           Coefficient_traits::const_reference denominator) {
75574  PPL_ASSERT(denominator != 0);
75575  PPL_ASSERT(space_dim >= expr.space_dimension());
75576  const dimension_type var_id = var.id();
75577  PPL_ASSERT(var_id <= space_dim);
75578  PPL_ASSERT(expr.coefficient(var) == 0);
75579  PPL_ASSERT(relsym != LESS_THAN && relsym != GREATER_THAN);
75580
75581  const Coefficient& b = expr.inhomogeneous_term();
75582  // Number of non-zero coefficients in `expr': will be set to
75583  // 0, 1, or 2, the latter value meaning any value greater than 1.
75584  dimension_type t = 0;
75585
75586  // Variable index of the last non-zero coefficient in `expr', if any.
75587  dimension_type w_id = expr.last_nonzero();
75588
75589  if (w_id != 0) {
75590    ++t;
75591    if (!expr.all_zeroes(1, w_id)) {
75592      ++t;
75593    }
75594    --w_id;
75595  }
75596
75597  // Now we know the form of `expr':
75598  // - If t == 0, then expr == b, with `b' a constant;
75599  // - If t == 1, then expr == a*j + b, where `j != v';
75600  // - If t == 2, then `expr' is of the general form.
75601  typedef typename OR_Matrix<N>::row_iterator row_iterator;
75602  typedef typename OR_Matrix<N>::row_reference_type row_reference;
75603  typedef typename OR_Matrix<N>::const_row_iterator Row_iterator;
75604  typedef typename OR_Matrix<N>::const_row_reference_type Row_reference;
75605
75606  const row_iterator m_begin = matrix.row_begin();
75607  const dimension_type n_var = 2*var_id;
75608  PPL_DIRTY_TEMP_COEFFICIENT(minus_denom);
75609  neg_assign(minus_denom, denominator);
75610
75611  // Since we are only able to record octagonal differences, we can
75612  // precisely deal with the case of a single variable only if its
75613  // coefficient (taking into account the denominator) is 1.
75614  // If this is not the case, we fall back to the general case
75615  // so as to over-approximate the constraint.
75616  if (t == 1 && expr.coefficient(Variable(w_id)) != denominator
75617      && expr.coefficient(Variable(w_id)) != minus_denom) {
75618    t = 2;
75619  }
75620  if (t == 0) {
75621    // Case 1: expr == b.
75622    PPL_DIRTY_TEMP_COEFFICIENT(two_b);
75623    two_b = 2*b;
75624    switch (relsym) {
75625    case EQUAL:
75626      // Add the constraint `var == b/denominator'.
75627      add_octagonal_constraint(n_var + 1, n_var, two_b, denominator);
75628      add_octagonal_constraint(n_var, n_var + 1, two_b, minus_denom);
75629      break;
75630    case LESS_OR_EQUAL:
75631      // Add the constraint `var <= b/denominator'.
75632      add_octagonal_constraint(n_var + 1, n_var, two_b, denominator);
75633      break;
75634    case GREATER_OR_EQUAL:
75635      // Add the constraint `var >= b/denominator',
75636      // i.e., `-var <= -b/denominator',
75637      add_octagonal_constraint(n_var, n_var + 1, two_b, minus_denom);
75638      break;
75639    default:
75640      // We already dealt with the other cases.
75641      PPL_UNREACHABLE;
75642      break;
75643    }
75644  }
75645  else if (t == 1) {
75646    // Value of the one and only non-zero coefficient in `expr'.
75647    const Coefficient& w_coeff = expr.coefficient(Variable(w_id));
75648    const dimension_type n_w = 2*w_id;
75649    switch (relsym) {
75650    case EQUAL:
75651      if (w_coeff == denominator) {
75652        // Add the new constraint `var - w = b/denominator'.
75653        if (var_id < w_id) {
75654          add_octagonal_constraint(n_w, n_var, b, denominator);
75655          add_octagonal_constraint(n_w + 1, n_var + 1, b, minus_denom);
75656        }
75657        else {
75658          add_octagonal_constraint(n_var + 1, n_w + 1, b, denominator);
75659          add_octagonal_constraint(n_var, n_w, b, minus_denom);
75660        }
75661      }
75662      else {
75663        // Add the new constraint `var + w = b/denominator'.
75664        if (var_id < w_id) {
75665          add_octagonal_constraint(n_w + 1, n_var, b, denominator);
75666          add_octagonal_constraint(n_w, n_var + 1, b, minus_denom);
75667        }
75668        else {
75669          add_octagonal_constraint(n_var + 1, n_w, b, denominator);
75670          add_octagonal_constraint(n_var, n_w + 1, b, minus_denom);
75671        }
75672      }
75673      break;
75674    case LESS_OR_EQUAL:
75675      {
75676        PPL_DIRTY_TEMP(N, d);
75677        div_round_up(d, b, denominator);
75678        // Note that: `w_id != v', so that `expr' is of the form
75679        // w_coeff * w + b, with `w_id != v'.
75680        if (w_coeff == denominator) {
75681          // Add the new constraints `v - w <= b/denominator'.
75682          if (var_id < w_id) {
75683            add_octagonal_constraint(n_w, n_var, d);
75684          }
75685          else {
75686            add_octagonal_constraint(n_var + 1, n_w + 1, d);
75687          }
75688        }
75689        else if (w_coeff == minus_denom) {
75690          // Add the new constraints `v + w <= b/denominator'.
75691          if (var_id < w_id) {
75692            add_octagonal_constraint(n_w + 1, n_var, d);
75693          }
75694          else {
75695            add_octagonal_constraint(n_var + 1, n_w, d);
75696          }
75697        }
75698        break;
75699      }
75700
75701    case GREATER_OR_EQUAL:
75702      {
75703        PPL_DIRTY_TEMP(N, d);
75704        div_round_up(d, b, minus_denom);
75705        // Note that: `w_id != v', so that `expr' is of the form
75706        // w_coeff * w + b, with `w_id != v'.
75707        if (w_coeff == denominator) {
75708          // Add the new constraint `v - w >= b/denominator',
75709          // i.e.,  `-v + w <= -b/denominator'.
75710          if (var_id < w_id) {
75711            add_octagonal_constraint(n_w + 1, n_var + 1, d);
75712          }
75713          else {
75714            add_octagonal_constraint(n_var, n_w, d);
75715          }
75716        }
75717        else if (w_coeff == minus_denom) {
75718          // Add the new constraints `v + w >= b/denominator',
75719          // i.e.,  `-v - w <= -b/denominator'.
75720          if (var_id < w_id) {
75721            add_octagonal_constraint(n_w, n_var + 1, d);
75722          }
75723          else {
75724            add_octagonal_constraint(n_var, n_w + 1, d);
75725          }
75726        }
75727        break;
75728      }
75729
75730    default:
75731      // We already dealt with the other cases.
75732      PPL_UNREACHABLE;
75733      break;
75734    }
75735  }
75736  else {
75737    // Here t == 2, so that
75738    // expr == a_1*x_1 + a_2*x_2 + ... + a_n*x_n + b, where n >= 2.
75739    const bool is_sc = (denominator > 0);
75740    PPL_DIRTY_TEMP_COEFFICIENT(minus_b);
75741    neg_assign(minus_b, b);
75742    const Coefficient& sc_b = is_sc ? b : minus_b;
75743    const Coefficient& minus_sc_b = is_sc ? minus_b : b;
75744    const Coefficient& sc_denom = is_sc ? denominator : minus_denom;
75745    const Coefficient& minus_sc_denom = is_sc ? minus_denom : denominator;
75746    // NOTE: here, for optimization purposes, `minus_expr' is only assigned
75747    // when `denominator' is negative. Do not use it unless you are sure
75748    // it has been correctly assigned.
75749    Linear_Expression minus_expr;
75750    if (!is_sc) {
75751      minus_expr = -expr;
75752    }
75753    const Linear_Expression& sc_expr = is_sc ? expr : minus_expr;
75754
75755    PPL_DIRTY_TEMP(N, sum);
75756    // Index of variable that is unbounded in `this'.
75757    PPL_UNINITIALIZED(dimension_type, pinf_index);
75758    // Number of unbounded variables found.
75759    dimension_type pinf_count = 0;
75760
75761    switch (relsym) {
75762    case EQUAL:
75763      {
75764        PPL_DIRTY_TEMP(N, neg_sum);
75765        // Index of variable that is unbounded in `this'.
75766        PPL_UNINITIALIZED(dimension_type, neg_pinf_index);
75767        // Number of unbounded variables found.
75768        dimension_type neg_pinf_count = 0;
75769
75770        // Approximate the inhomogeneous term.
75771        assign_r(sum, sc_b, ROUND_UP);
75772        assign_r(neg_sum, minus_sc_b, ROUND_UP);
75773
75774        // Approximate the homogeneous part of `sc_expr'.
75775        PPL_DIRTY_TEMP(N, coeff_i);
75776        PPL_DIRTY_TEMP(N, half);
75777        PPL_DIRTY_TEMP_COEFFICIENT(minus_sc_i);
75778        PPL_DIRTY_TEMP(N, minus_coeff_i);
75779        // Note: indices above `w' can be disregarded, as they all have
75780        // a zero coefficient in `sc_expr'.
75781        for (Row_iterator m_iter = m_begin,
75782               m_iter_end = m_begin + (2 * w_id + 2);
75783             m_iter != m_iter_end; ) {
75784          const dimension_type n_i = m_iter.index();
75785          const dimension_type id = n_i/2;
75786          Row_reference m_i = *m_iter;
75787          ++m_iter;
75788          Row_reference m_ci = *m_iter;
75789          ++m_iter;
75790          const Coefficient& sc_i = sc_expr.coefficient(Variable(id));
75791          const int sign_i = sgn(sc_i);
75792          if (sign_i > 0) {
75793            assign_r(coeff_i, sc_i, ROUND_UP);
75794            // Approximating `sc_expr'.
75795            if (pinf_count <= 1) {
75796              const N& double_approx_i = m_ci[n_i];
75797              if (!is_plus_infinity(double_approx_i)) {
75798                // Let half = double_approx_i / 2.
75799                div_2exp_assign_r(half, double_approx_i, 1, ROUND_UP);
75800                add_mul_assign_r(sum, coeff_i, half, ROUND_UP);
75801              }
75802              else {
75803                ++pinf_count;
75804                pinf_index = id;
75805              }
75806            }
75807            // Approximating `-sc_expr'.
75808            if (neg_pinf_count <= 1) {
75809              const N& double_approx_minus_i = m_i[n_i + 1];
75810              if (!is_plus_infinity(double_approx_minus_i)) {
75811                // Let half = double_approx_minus_i / 2.
75812                div_2exp_assign_r(half, double_approx_minus_i, 1, ROUND_UP);
75813                add_mul_assign_r(neg_sum, coeff_i, half, ROUND_UP);
75814              }
75815              else {
75816                ++neg_pinf_count;
75817                neg_pinf_index = id;
75818              }
75819            }
75820          }
75821          else if (sign_i < 0) {
75822            neg_assign_r(minus_sc_i, sc_i, ROUND_NOT_NEEDED);
75823            assign_r(minus_coeff_i, minus_sc_i, ROUND_UP);
75824            // Approximating `sc_expr'.
75825            if (pinf_count <= 1) {
75826              const N& double_approx_minus_i = m_i[n_i + 1];
75827              if (!is_plus_infinity(double_approx_minus_i)) {
75828                // Let half = double_approx_minus_i / 2.
75829                div_2exp_assign_r(half, double_approx_minus_i, 1, ROUND_UP);
75830                add_mul_assign_r(sum, minus_coeff_i, half, ROUND_UP);
75831              }
75832              else {
75833                ++pinf_count;
75834                pinf_index = id;
75835              }
75836            }
75837            // Approximating `-sc_expr'.
75838            if (neg_pinf_count <= 1) {
75839              const N& double_approx_i = m_ci[n_i];
75840              if (!is_plus_infinity(double_approx_i)) {
75841                // Let half = double_approx_i / 2.
75842                div_2exp_assign_r(half, double_approx_i, 1, ROUND_UP);
75843                add_mul_assign_r(neg_sum, minus_coeff_i, half, ROUND_UP);
75844              }
75845              else {
75846                ++neg_pinf_count;
75847                neg_pinf_index = id;
75848              }
75849            }
75850          }
75851        }
75852        // Return immediately if no approximation could be computed.
75853        if (pinf_count > 1 && neg_pinf_count > 1) {
75854          PPL_ASSERT(OK());
75855          return;
75856        }
75857
75858        // In the following, strong closure will be definitely lost.
75859        reset_strongly_closed();
75860
75861        // Exploit the upper approximation, if possible.
75862        if (pinf_count <= 1) {
75863          // Compute quotient (if needed).
75864          if (sc_denom != 1) {
75865            // Before computing quotients, the denominator should be
75866            // approximated towards zero. Since `sc_denom' is known to be
75867            // positive, this amounts to rounding downwards, which is
75868            // achieved as usual by rounding upwards `minus_sc_denom'
75869            // and negating again the result.
75870            PPL_DIRTY_TEMP(N, down_sc_denom);
75871            assign_r(down_sc_denom, minus_sc_denom, ROUND_UP);
75872            neg_assign_r(down_sc_denom, down_sc_denom, ROUND_UP);
75873            div_assign_r(sum, sum, down_sc_denom, ROUND_UP);
75874          }
75875          // Add the upper bound constraint, if meaningful.
75876          if (pinf_count == 0) {
75877            // Add the constraint `v <= sum'.
75878            PPL_DIRTY_TEMP(N, double_sum);
75879            mul_2exp_assign_r(double_sum, sum, 1, ROUND_UP);
75880            matrix[n_var + 1][n_var] = double_sum;
75881            // Deduce constraints of the form `v +/- u', where `u != v'.
75882            deduce_v_pm_u_bounds(var_id, w_id, sc_expr, sc_denom, sum);
75883          }
75884          else {
75885            // Here `pinf_count == 1'.
75886            if (pinf_index != var_id) {
75887              const Coefficient& ppi
75888                = sc_expr.coefficient(Variable(pinf_index));
75889              if (ppi == sc_denom) {
75890                // Add the constraint `v - pinf_index <= sum'.
75891                if (var_id < pinf_index) {
75892                  matrix[2*pinf_index][n_var] = sum;
75893                }
75894                else {
75895                  matrix[n_var + 1][2*pinf_index + 1] = sum;
75896                }
75897              }
75898              else {
75899                if (ppi == minus_sc_denom) {
75900                  // Add the constraint `v + pinf_index <= sum'.
75901                  if (var_id < pinf_index) {
75902                    matrix[2*pinf_index + 1][n_var] = sum;
75903                  }
75904                  else {
75905                    matrix[n_var + 1][2*pinf_index] = sum;
75906                  }
75907                }
75908              }
75909            }
75910          }
75911        }
75912
75913        // Exploit the lower approximation, if possible.
75914        if (neg_pinf_count <= 1) {
75915          // Compute quotient (if needed).
75916          if (sc_denom != 1) {
75917            // Before computing quotients, the denominator should be
75918            // approximated towards zero. Since `sc_denom' is known to be
75919            // positive, this amounts to rounding downwards, which is
75920            // achieved as usual by rounding upwards `minus_sc_denom'
75921            // and negating again the result.
75922            PPL_DIRTY_TEMP(N, down_sc_denom);
75923            assign_r(down_sc_denom, minus_sc_denom, ROUND_UP);
75924            neg_assign_r(down_sc_denom, down_sc_denom, ROUND_UP);
75925            div_assign_r(neg_sum, neg_sum, down_sc_denom, ROUND_UP);
75926          }
75927          // Add the lower bound constraint, if meaningful.
75928          if (neg_pinf_count == 0) {
75929            // Add the constraint `v >= -neg_sum', i.e., `-v <= neg_sum'.
75930            PPL_DIRTY_TEMP(N, double_neg_sum);
75931            mul_2exp_assign_r(double_neg_sum, neg_sum, 1, ROUND_UP);
75932            matrix[n_var][n_var + 1] = double_neg_sum;
75933            // Deduce constraints of the form `-v +/- u', where `u != v'.
75934            deduce_minus_v_pm_u_bounds(var_id, w_id, sc_expr, sc_denom,
75935                                       neg_sum);
75936          }
75937          else {
75938            // Here `neg_pinf_count == 1'.
75939            if (neg_pinf_index != var_id) {
75940              const Coefficient& npi
75941                = sc_expr.coefficient(Variable(neg_pinf_index));
75942              if (npi == sc_denom) {
75943                // Add the constraint `v - neg_pinf_index >= -neg_sum',
75944                // i.e., `neg_pinf_index - v <= neg_sum'.
75945                if (neg_pinf_index < var_id) {
75946                  matrix[n_var][2*neg_pinf_index] = neg_sum;
75947                }
75948                else {
75949                  matrix[2*neg_pinf_index + 1][n_var + 1] = neg_sum;
75950                }
75951              }
75952              else {
75953                if (npi == minus_sc_denom) {
75954                  // Add the constraint `v + neg_pinf_index >= -neg_sum',
75955                  // i.e., `-neg_pinf_index - v <= neg_sum'.
75956                  if (neg_pinf_index < var_id) {
75957                    matrix[n_var][2*neg_pinf_index + 1] = neg_sum;
75958                  }
75959                  else {
75960                    matrix[2*neg_pinf_index][n_var + 1] = neg_sum;
75961                  }
75962                }
75963              }
75964            }
75965          }
75966        }
75967        break;
75968      }
75969
75970    case LESS_OR_EQUAL:
75971      {
75972        // Compute an upper approximation for `expr' into `sum',
75973        // taking into account the sign of `denominator'.
75974
75975        // Approximate the inhomogeneous term.
75976        assign_r(sum, sc_b, ROUND_UP);
75977
75978        // Approximate the homogeneous part of `sc_expr'.
75979        PPL_DIRTY_TEMP(N, coeff_i);
75980        PPL_DIRTY_TEMP(N, approx_i);
75981        PPL_DIRTY_TEMP_COEFFICIENT(minus_sc_i);
75982        // Note: indices above `w_id' can be disregarded, as they all have
75983        // a zero coefficient in `expr'.
75984        for (row_iterator m_iter = m_begin,
75985               m_iter_end = m_begin + (2 * w_id + 2);
75986             m_iter != m_iter_end; ) {
75987          const dimension_type n_i = m_iter.index();
75988          const dimension_type id = n_i/2;
75989          row_reference m_i = *m_iter;
75990          ++m_iter;
75991          row_reference m_ci = *m_iter;
75992          ++m_iter;
75993          const Coefficient& sc_i = sc_expr.coefficient(Variable(id));
75994          const int sign_i = sgn(sc_i);
75995          if (sign_i == 0) {
75996            continue;
75997          }
75998          // Choose carefully: we are approximating `sc_expr'.
75999          const N& double_approx_i = (sign_i > 0) ? m_ci[n_i] : m_i[n_i + 1];
76000          if (is_plus_infinity(double_approx_i)) {
76001            if (++pinf_count > 1) {
76002              break;
76003            }
76004            pinf_index = id;
76005            continue;
76006          }
76007          if (sign_i > 0) {
76008            assign_r(coeff_i, sc_i, ROUND_UP);
76009          }
76010          else {
76011            neg_assign(minus_sc_i, sc_i);
76012            assign_r(coeff_i, minus_sc_i, ROUND_UP);
76013          }
76014          div_2exp_assign_r(approx_i, double_approx_i, 1, ROUND_UP);
76015          add_mul_assign_r(sum, coeff_i, approx_i, ROUND_UP);
76016        }
76017        // Divide by the (sign corrected) denominator (if needed).
76018        if (sc_denom != 1) {
76019          // Before computing the quotient, the denominator should be
76020          // approximated towards zero. Since `sc_denom' is known to be
76021          // positive, this amounts to rounding downwards, which is achieved
76022          // by rounding upwards `minus_sc-denom' and negating again the result.
76023          PPL_DIRTY_TEMP(N, down_sc_denom);
76024          assign_r(down_sc_denom, minus_sc_denom, ROUND_UP);
76025          neg_assign_r(down_sc_denom, down_sc_denom, ROUND_UP);
76026          div_assign_r(sum, sum, down_sc_denom, ROUND_UP);
76027        }
76028
76029        if (pinf_count == 0) {
76030          // Add the constraint `v <= sum'.
76031          PPL_DIRTY_TEMP(N, double_sum);
76032          mul_2exp_assign_r(double_sum, sum, 1, ROUND_UP);
76033          add_octagonal_constraint(n_var + 1, n_var, double_sum);
76034          // Deduce constraints of the form `v +/- u', where `u != v'.
76035          deduce_v_pm_u_bounds(var_id, w_id, sc_expr, sc_denom, sum);
76036        }
76037        else if (pinf_count == 1) {
76038          dimension_type pinf_ind = 2*pinf_index;
76039          if (expr.coefficient(Variable(pinf_index)) == denominator ) {
76040            // Add the constraint `v - pinf_index <= sum'.
76041            if (var_id < pinf_index) {
76042              add_octagonal_constraint(pinf_ind, n_var, sum);
76043            }
76044            else {
76045              add_octagonal_constraint(n_var + 1, pinf_ind + 1, sum);
76046            }
76047          }
76048          else {
76049            if (expr.coefficient(Variable(pinf_index)) == minus_denom) {
76050              // Add the constraint `v + pinf_index <= sum'.
76051              if (var_id < pinf_index) {
76052                add_octagonal_constraint(pinf_ind + 1, n_var, sum);
76053              }
76054              else {
76055                add_octagonal_constraint(n_var + 1, pinf_ind, sum);
76056              }
76057            }
76058          }
76059        }
76060        break;
76061      }
76062
76063    case GREATER_OR_EQUAL:
76064      {
76065        // Compute an upper approximation for `-sc_expr' into `sum'.
76066        // Note: approximating `-sc_expr' from above and then negating the
76067        // result is the same as approximating `sc_expr' from below.
76068
76069        // Approximate the inhomogeneous term.
76070        assign_r(sum, minus_sc_b, ROUND_UP);
76071
76072        // Approximate the homogeneous part of `-sc_expr'.
76073        PPL_DIRTY_TEMP(N, coeff_i);
76074        PPL_DIRTY_TEMP(N, approx_i);
76075        PPL_DIRTY_TEMP_COEFFICIENT(minus_sc_i);
76076        for (row_iterator m_iter = m_begin,
76077               m_iter_end = m_begin + (2 * w_id + 2);
76078             m_iter != m_iter_end; ) {
76079          const dimension_type n_i = m_iter.index();
76080          const dimension_type id = n_i/2;
76081          row_reference m_i = *m_iter;
76082          ++m_iter;
76083          row_reference m_ci = *m_iter;
76084          ++m_iter;
76085          const Coefficient& sc_i = sc_expr.coefficient(Variable(id));
76086          const int sign_i = sgn(sc_i);
76087          if (sign_i == 0) {
76088            continue;
76089          }
76090          // Choose carefully: we are approximating `-sc_expr'.
76091          const N& double_approx_i = (sign_i > 0) ? m_i[n_i + 1] : m_ci[n_i];
76092          if (is_plus_infinity(double_approx_i)) {
76093            if (++pinf_count > 1) {
76094              break;
76095            }
76096            pinf_index = id;
76097            continue;
76098          }
76099          if (sign_i > 0) {
76100            assign_r(coeff_i, sc_i, ROUND_UP);
76101          }
76102          else {
76103            neg_assign(minus_sc_i, sc_i);
76104            assign_r(coeff_i, minus_sc_i, ROUND_UP);
76105          }
76106          div_2exp_assign_r(approx_i, double_approx_i, 1, ROUND_UP);
76107          add_mul_assign_r(sum, coeff_i, approx_i, ROUND_UP);
76108        }
76109
76110        // Divide by the (sign corrected) denominator (if needed).
76111        if (sc_denom != 1) {
76112          // Before computing the quotient, the denominator should be
76113          // approximated towards zero. Since `sc_denom' is known to be
76114          // positive, this amounts to rounding downwards, which is
76115          // achieved by rounding upwards `minus_sc_denom' and
76116          // negating again the result.
76117          PPL_DIRTY_TEMP(N, down_sc_denom);
76118          assign_r(down_sc_denom, minus_sc_denom, ROUND_UP);
76119          neg_assign_r(down_sc_denom, down_sc_denom, ROUND_UP);
76120          div_assign_r(sum, sum, down_sc_denom, ROUND_UP);
76121        }
76122
76123        if (pinf_count == 0) {
76124          // Add the constraint `v >= -neg_sum', i.e., `-v <= neg_sum'.
76125          PPL_DIRTY_TEMP(N, double_sum);
76126          mul_2exp_assign_r(double_sum, sum, 1, ROUND_UP);
76127          add_octagonal_constraint(n_var, n_var + 1, double_sum);
76128          // Deduce constraints of the form `-v +/- u', where `u != v'.
76129          deduce_minus_v_pm_u_bounds(var_id, pinf_index, sc_expr, sc_denom,
76130                                     sum);
76131        }
76132        else if (pinf_count == 1) {
76133          dimension_type pinf_ind = 2*pinf_index;
76134          if (expr.coefficient(Variable(pinf_index)) == denominator) {
76135            // Add the constraint `v - pinf_index >= -sum',
76136            // i.e., `pinf_index - v <= sum'.
76137            if (pinf_index < var_id) {
76138              add_octagonal_constraint(n_var, pinf_ind, sum);
76139            }
76140            else {
76141              add_octagonal_constraint(pinf_ind + 1, n_var, sum);
76142            }
76143          }
76144          else {
76145            if (expr.coefficient(Variable(pinf_index)) == minus_denom) {
76146              // Add the constraint `v + pinf_index >= -sum',
76147              // i.e., `-pinf_index - v <= sum'.
76148              if (pinf_index < var_id) {
76149                add_octagonal_constraint(n_var, pinf_ind + 1, sum);
76150              }
76151              else {
76152                add_octagonal_constraint(pinf_ind, n_var + 1, sum);
76153              }
76154            }
76155          }
76156        }
76157        break;
76158      }
76159
76160    default:
76161      // We already dealt with the other cases.
76162      PPL_UNREACHABLE;
76163      break;
76164    }
76165  }
76166}
76167
76168template <typename T>
76169void
76170Octagonal_Shape<T>::affine_image(const Variable var,
76171                                 const Linear_Expression& expr,
76172                                 Coefficient_traits::const_reference
76173                                 denominator) {
76174  // The denominator cannot be zero.
76175  if (denominator == 0) {
76176    throw_invalid_argument("affine_image(v, e, d)", "d == 0");
76177  }
76178
76179  // Dimension-compatibility checks.
76180  // The dimension of `expr' should not be greater than the dimension
76181  // of `*this'.
76182  const dimension_type expr_space_dim = expr.space_dimension();
76183  if (space_dim < expr_space_dim) {
76184    throw_dimension_incompatible("affine_image(v, e, d)", "e", expr);
76185  }
76186
76187  // `var' should be one of the dimensions of the octagon.
76188  const dimension_type var_id = var.id();
76189  if (space_dim < var_id + 1) {
76190    throw_dimension_incompatible("affine_image(v, e, d)", var_id + 1);
76191  }
76192
76193  strong_closure_assign();
76194  // The image of an empty octagon is empty too.
76195  if (marked_empty()) {
76196    return;
76197  }
76198
76199  // Number of non-zero coefficients in `expr': will be set to
76200  // 0, 1, or 2, the latter value meaning any value greater than 1.
76201  dimension_type t = 0;
76202  // Variable-index of the last non-zero coefficient in `expr', if any.
76203  dimension_type w_id = expr.last_nonzero();
76204
76205  if (w_id != 0) {
76206    ++t;
76207    if (!expr.all_zeroes(1, w_id)) {
76208      ++t;
76209    }
76210    --w_id;
76211  }
76212
76213  typedef typename OR_Matrix<N>::row_iterator row_iterator;
76214  typedef typename OR_Matrix<N>::row_reference_type row_reference;
76215  typedef typename OR_Matrix<N>::const_row_iterator Row_iterator;
76216  typedef typename OR_Matrix<N>::const_row_reference_type Row_reference;
76217  using std::swap;
76218
76219  const dimension_type n_var = 2*var_id;
76220  const Coefficient& b = expr.inhomogeneous_term();
76221  PPL_DIRTY_TEMP_COEFFICIENT(minus_denom);
76222  neg_assign_r(minus_denom, denominator, ROUND_NOT_NEEDED);
76223
76224  // `w' is the variable with index `w_id'.
76225  // Now we know the form of `expr':
76226  // - If t == 0, then expr == b, with `b' a constant;
76227  // - If t == 1, then expr == a*w + b, where `w' can be `v' or another
76228  //   variable; in this second case we have to check whether `a' is
76229  //   equal to `denominator' or `-denominator', since otherwise we have
76230  //   to fall back on the general form;
76231  // - If t == 2, the `expr' is of the general form.
76232
76233  if (t == 0) {
76234    // Case 1: expr == b.
76235    // Remove all constraints on `var'.
76236    forget_all_octagonal_constraints(var_id);
76237    PPL_DIRTY_TEMP_COEFFICIENT(two_b);
76238    two_b = 2*b;
76239    // Add the constraint `var == b/denominator'.
76240    add_octagonal_constraint(n_var + 1, n_var, two_b, denominator);
76241    add_octagonal_constraint(n_var, n_var + 1, two_b, minus_denom);
76242    PPL_ASSERT(OK());
76243    return;
76244  }
76245
76246  if (t == 1) {
76247    // The one and only non-zero homogeneous coefficient in `expr'.
76248    const Coefficient& w_coeff = expr.coefficient(Variable(w_id));
76249    if (w_coeff == denominator || w_coeff == minus_denom) {
76250      // Case 2: expr = w_coeff*w + b, with w_coeff = +/- denominator.
76251      if (w_id == var_id) {
76252        // Here `expr' is of the form: +/- denominator * v + b.
76253        const bool sign_symmetry = (w_coeff != denominator);
76254        if (!sign_symmetry && b == 0) {
76255          // The transformation is the identity function.
76256          return;
76257        }
76258        // Translate all the constraints on `var' adding or
76259        // subtracting the value `b/denominator'.
76260        PPL_DIRTY_TEMP(N, d);
76261        div_round_up(d, b, denominator);
76262        PPL_DIRTY_TEMP(N, minus_d);
76263        div_round_up(minus_d, b, minus_denom);
76264        if (sign_symmetry) {
76265          swap(d, minus_d);
76266        }
76267        const row_iterator m_begin = matrix.row_begin();
76268        const row_iterator m_end = matrix.row_end();
76269        row_iterator m_iter = m_begin + n_var;
76270        row_reference m_v = *m_iter;
76271        ++m_iter;
76272        row_reference m_cv = *m_iter;
76273        ++m_iter;
76274        // NOTE: delay update of unary constraints on `var'.
76275        for (dimension_type j = n_var; j-- > 0; ) {
76276          N& m_v_j = m_v[j];
76277          add_assign_r(m_v_j, m_v_j, minus_d, ROUND_UP);
76278          N& m_cv_j = m_cv[j];
76279          add_assign_r(m_cv_j, m_cv_j, d, ROUND_UP);
76280          if (sign_symmetry) {
76281            swap(m_v_j, m_cv_j);
76282          }
76283        }
76284        for ( ; m_iter != m_end; ++m_iter) {
76285          row_reference m_i = *m_iter;
76286          N& m_i_v = m_i[n_var];
76287          add_assign_r(m_i_v, m_i_v, d, ROUND_UP);
76288          N& m_i_cv = m_i[n_var + 1];
76289          add_assign_r(m_i_cv, m_i_cv, minus_d, ROUND_UP);
76290          if (sign_symmetry) {
76291            swap(m_i_v, m_i_cv);
76292          }
76293        }
76294        // Now update unary constraints on var.
76295        mul_2exp_assign_r(d, d, 1, ROUND_UP);
76296        N& m_cv_v = m_cv[n_var];
76297        add_assign_r(m_cv_v, m_cv_v, d, ROUND_UP);
76298        mul_2exp_assign_r(minus_d, minus_d, 1, ROUND_UP);
76299        N& m_v_cv = m_v[n_var + 1];
76300        add_assign_r(m_v_cv, m_v_cv, minus_d, ROUND_UP);
76301        if (sign_symmetry) {
76302          swap(m_cv_v, m_v_cv);
76303        }
76304        // Note: strong closure is preserved.
76305      }
76306      else {
76307        // Here `w != var', so that `expr' is of the form
76308        // +/-denominator * w + b.
76309        // Remove all constraints on `var'.
76310        forget_all_octagonal_constraints(var_id);
76311        const dimension_type n_w = 2*w_id;
76312        // Add the new constraint `var - w = b/denominator'.
76313        if (w_coeff == denominator) {
76314          if (var_id < w_id) {
76315            add_octagonal_constraint(n_w, n_var, b, denominator);
76316            add_octagonal_constraint(n_w + 1, n_var + 1, b, minus_denom);
76317          }
76318          else {
76319            add_octagonal_constraint(n_var + 1, n_w + 1, b, denominator);
76320            add_octagonal_constraint(n_var, n_w, b, minus_denom);
76321          }
76322        }
76323        else {
76324          // Add the new constraint `var + w = b/denominator'.
76325          if (var_id < w_id) {
76326            add_octagonal_constraint(n_w + 1, n_var, b, denominator);
76327            add_octagonal_constraint(n_w, n_var + 1, b, minus_denom);
76328          }
76329          else {
76330            add_octagonal_constraint(n_var + 1, n_w, b, denominator);
76331            add_octagonal_constraint(n_var, n_w + 1, b, minus_denom);
76332          }
76333        }
76334        incremental_strong_closure_assign(var);
76335      }
76336      PPL_ASSERT(OK());
76337      return;
76338    }
76339  }
76340
76341  // General case.
76342  // Either t == 2, so that
76343  // expr == a_1*x_1 + a_2*x_2 + ... + a_n*x_n + b, where n >= 2,
76344  // or t == 1, expr == a*w + b, but a <> +/- denominator.
76345  // We will remove all the constraints on `var' and add back
76346  // constraints providing upper and lower bounds for `var'.
76347
76348  // Compute upper approximations for `expr' and `-expr'
76349  // into `pos_sum' and `neg_sum', respectively, taking into account
76350  // the sign of `denominator'.
76351  // Note: approximating `-expr' from above and then negating the
76352  // result is the same as approximating `expr' from below.
76353  const bool is_sc = (denominator > 0);
76354  PPL_DIRTY_TEMP_COEFFICIENT(minus_b);
76355  neg_assign_r(minus_b, b, ROUND_NOT_NEEDED);
76356
76357  const Coefficient& sc_b = is_sc ? b : minus_b;
76358  const Coefficient& minus_sc_b = is_sc ? minus_b : b;
76359  const Coefficient& sc_denom = is_sc ? denominator : minus_denom;
76360  const Coefficient& minus_sc_denom = is_sc ? minus_denom : denominator;
76361  // NOTE: here, for optimization purposes, `minus_expr' is only assigned
76362  // when `denominator' is negative. Do not use it unless you are sure
76363  // it has been correctly assigned.
76364  Linear_Expression minus_expr;
76365  if (!is_sc) {
76366    minus_expr = -expr;
76367  }
76368  const Linear_Expression& sc_expr = is_sc ? expr : minus_expr;
76369
76370  PPL_DIRTY_TEMP(N, pos_sum);
76371  PPL_DIRTY_TEMP(N, neg_sum);
76372  // Indices of the variables that are unbounded in `this->matrix'.
76373  PPL_UNINITIALIZED(dimension_type, pos_pinf_index);
76374  PPL_UNINITIALIZED(dimension_type, neg_pinf_index);
76375  // Number of unbounded variables found.
76376  dimension_type pos_pinf_count = 0;
76377  dimension_type neg_pinf_count = 0;
76378
76379  // Approximate the inhomogeneous term.
76380  assign_r(pos_sum, sc_b, ROUND_UP);
76381  assign_r(neg_sum, minus_sc_b, ROUND_UP);
76382
76383  // Approximate the homogeneous part of `sc_expr'.
76384  PPL_DIRTY_TEMP(N, coeff_i);
76385  PPL_DIRTY_TEMP(N, minus_coeff_i);
76386  PPL_DIRTY_TEMP(N, half);
76387  PPL_DIRTY_TEMP_COEFFICIENT(minus_sc_i);
76388  // Note: indices above `w' can be disregarded, as they all have
76389  // a zero coefficient in `sc_expr'.
76390  const row_iterator m_begin = matrix.row_begin();
76391  for (Row_iterator m_iter = m_begin, m_iter_end = m_begin + (2 * w_id + 2);
76392       m_iter != m_iter_end; ) {
76393    const dimension_type n_i = m_iter.index();
76394    const dimension_type id = n_i/2;
76395    Row_reference m_i = *m_iter;
76396    ++m_iter;
76397    Row_reference m_ci = *m_iter;
76398    ++m_iter;
76399    const Coefficient& sc_i = sc_expr.coefficient(Variable(id));
76400    const int sign_i = sgn(sc_i);
76401    if (sign_i > 0) {
76402      assign_r(coeff_i, sc_i, ROUND_UP);
76403      // Approximating `sc_expr'.
76404      if (pos_pinf_count <= 1) {
76405        const N& double_up_approx_i = m_ci[n_i];
76406        if (!is_plus_infinity(double_up_approx_i)) {
76407          // Let half = double_up_approx_i / 2.
76408          div_2exp_assign_r(half, double_up_approx_i, 1, ROUND_UP);
76409          add_mul_assign_r(pos_sum, coeff_i, half, ROUND_UP);
76410        }
76411        else {
76412          ++pos_pinf_count;
76413          pos_pinf_index = id;
76414        }
76415      }
76416      // Approximating `-sc_expr'.
76417      if (neg_pinf_count <= 1) {
76418        const N& double_up_approx_minus_i = m_i[n_i + 1];
76419        if (!is_plus_infinity(double_up_approx_minus_i)) {
76420          // Let half = double_up_approx_minus_i / 2.
76421          div_2exp_assign_r(half, double_up_approx_minus_i, 1, ROUND_UP);
76422          add_mul_assign_r(neg_sum, coeff_i, half, ROUND_UP);
76423        }
76424        else {
76425          ++neg_pinf_count;
76426          neg_pinf_index = id;
76427        }
76428      }
76429    }
76430    else if (sign_i < 0) {
76431      neg_assign_r(minus_sc_i, sc_i, ROUND_NOT_NEEDED);
76432      assign_r(minus_coeff_i, minus_sc_i, ROUND_UP);
76433      // Approximating `sc_expr'.
76434      if (pos_pinf_count <= 1) {
76435        const N& double_up_approx_minus_i = m_i[n_i + 1];
76436        if (!is_plus_infinity(double_up_approx_minus_i)) {
76437          // Let half = double_up_approx_minus_i / 2.
76438          div_2exp_assign_r(half, double_up_approx_minus_i, 1, ROUND_UP);
76439          add_mul_assign_r(pos_sum, minus_coeff_i, half, ROUND_UP);
76440        }
76441        else {
76442          ++pos_pinf_count;
76443          pos_pinf_index = id;
76444        }
76445      }
76446      // Approximating `-sc_expr'.
76447      if (neg_pinf_count <= 1) {
76448        const N& double_up_approx_i = m_ci[n_i];
76449        if (!is_plus_infinity(double_up_approx_i)) {
76450          // Let half = double_up_approx_i / 2.
76451          div_2exp_assign_r(half, double_up_approx_i, 1, ROUND_UP);
76452          add_mul_assign_r(neg_sum, minus_coeff_i, half, ROUND_UP);
76453        }
76454        else {
76455          ++neg_pinf_count;
76456          neg_pinf_index = id;
76457        }
76458      }
76459    }
76460  }
76461
76462  // Remove all constraints on `var'.
76463  forget_all_octagonal_constraints(var_id);
76464  // Return immediately if no approximation could be computed.
76465  if (pos_pinf_count > 1 && neg_pinf_count > 1) {
76466    PPL_ASSERT(OK());
76467    return;
76468  }
76469
76470  // In the following, strong closure will be definitely lost.
76471  reset_strongly_closed();
76472
76473  // Exploit the upper approximation, if possible.
76474  if (pos_pinf_count <= 1) {
76475    // Compute quotient (if needed).
76476    if (sc_denom != 1) {
76477      // Before computing quotients, the denominator should be approximated
76478      // towards zero. Since `sc_denom' is known to be positive, this amounts to
76479      // rounding downwards, which is achieved as usual by rounding upwards
76480      // `minus_sc_denom' and negating again the result.
76481      PPL_DIRTY_TEMP(N, down_sc_denom);
76482      assign_r(down_sc_denom, minus_sc_denom, ROUND_UP);
76483      neg_assign_r(down_sc_denom, down_sc_denom, ROUND_UP);
76484      div_assign_r(pos_sum, pos_sum, down_sc_denom, ROUND_UP);
76485    }
76486    // Add the upper bound constraint, if meaningful.
76487    if (pos_pinf_count == 0) {
76488      // Add the constraint `v <= pos_sum'.
76489      PPL_DIRTY_TEMP(N, double_pos_sum);
76490      mul_2exp_assign_r(double_pos_sum, pos_sum, 1, ROUND_UP);
76491      matrix[n_var + 1][n_var] = double_pos_sum;
76492      // Deduce constraints of the form `v +/- u', where `u != v'.
76493      deduce_v_pm_u_bounds(var_id, w_id, sc_expr, sc_denom, pos_sum);
76494    }
76495    else {
76496      // Here `pos_pinf_count == 1'.
76497      if (pos_pinf_index != var_id) {
76498        const Coefficient& ppi = sc_expr.coefficient(Variable(pos_pinf_index));
76499        if (ppi == sc_denom) {
76500          // Add the constraint `v - pos_pinf_index <= pos_sum'.
76501          if (var_id < pos_pinf_index) {
76502            matrix[2*pos_pinf_index][n_var] = pos_sum;
76503          }
76504          else {
76505            matrix[n_var + 1][2*pos_pinf_index + 1] = pos_sum;
76506          }
76507        }
76508        else {
76509          if (ppi == minus_sc_denom) {
76510            // Add the constraint `v + pos_pinf_index <= pos_sum'.
76511            if (var_id < pos_pinf_index) {
76512              matrix[2*pos_pinf_index + 1][n_var] = pos_sum;
76513            }
76514            else {
76515              matrix[n_var + 1][2*pos_pinf_index] = pos_sum;
76516            }
76517          }
76518        }
76519      }
76520    }
76521  }
76522
76523  // Exploit the lower approximation, if possible.
76524  if (neg_pinf_count <= 1) {
76525    // Compute quotient (if needed).
76526    if (sc_denom != 1) {
76527      // Before computing quotients, the denominator should be approximated
76528      // towards zero. Since `sc_denom' is known to be positive, this amounts to
76529      // rounding downwards, which is achieved as usual by rounding upwards
76530      // `minus_sc_denom' and negating again the result.
76531      PPL_DIRTY_TEMP(N, down_sc_denom);
76532      assign_r(down_sc_denom, minus_sc_denom, ROUND_UP);
76533      neg_assign_r(down_sc_denom, down_sc_denom, ROUND_UP);
76534      div_assign_r(neg_sum, neg_sum, down_sc_denom, ROUND_UP);
76535    }
76536    // Add the lower bound constraint, if meaningful.
76537    if (neg_pinf_count == 0) {
76538      // Add the constraint `v >= -neg_sum', i.e., `-v <= neg_sum'.
76539      PPL_DIRTY_TEMP(N, double_neg_sum);
76540      mul_2exp_assign_r(double_neg_sum, neg_sum, 1, ROUND_UP);
76541      matrix[n_var][n_var + 1] = double_neg_sum;
76542      // Deduce constraints of the form `-v +/- u', where `u != v'.
76543      deduce_minus_v_pm_u_bounds(var_id, w_id, sc_expr, sc_denom, neg_sum);
76544    }
76545    else {
76546      // Here `neg_pinf_count == 1'.
76547      if (neg_pinf_index != var_id) {
76548        const Coefficient& npi = sc_expr.coefficient(Variable(neg_pinf_index));
76549        if (npi == sc_denom) {
76550          // Add the constraint `v - neg_pinf_index >= -neg_sum',
76551          // i.e., `neg_pinf_index - v <= neg_sum'.
76552          if (neg_pinf_index < var_id) {
76553            matrix[n_var][2*neg_pinf_index] = neg_sum;
76554          }
76555          else {
76556            matrix[2*neg_pinf_index + 1][n_var + 1] = neg_sum;
76557          }
76558        }
76559        else {
76560          if (npi == minus_sc_denom) {
76561            // Add the constraint `v + neg_pinf_index >= -neg_sum',
76562            // i.e., `-neg_pinf_index - v <= neg_sum'.
76563            if (neg_pinf_index < var_id) {
76564              matrix[n_var][2*neg_pinf_index + 1] = neg_sum;
76565            }
76566            else {
76567              matrix[2*neg_pinf_index][n_var + 1] = neg_sum;
76568            }
76569          }
76570        }
76571      }
76572    }
76573  }
76574
76575  incremental_strong_closure_assign(var);
76576  PPL_ASSERT(OK());
76577}
76578
76579template <typename T>
76580template <typename Interval_Info>
76581void
76582Octagonal_Shape<T>::affine_form_image(const Variable var,
76583                    const Linear_Form< Interval<T, Interval_Info> >& lf) {
76584  // Check that T is a floating point type.
76585  PPL_COMPILE_TIME_CHECK(!std::numeric_limits<T>::is_exact,
76586    "Octagonal_Shape<T>::affine_form_image(Variable, Linear_Form):"
76587    " T is not a floating point type.");
76588
76589  // Dimension-compatibility checks.
76590  // The dimension of `lf' should not be greater than the dimension
76591  // of `*this'.
76592  const dimension_type lf_space_dim = lf.space_dimension();
76593  if (space_dim < lf_space_dim) {
76594    throw_dimension_incompatible("affine_form_image(v, l)", "l", lf);
76595  }
76596
76597  // `var' should be one of the dimensions of the octagon.
76598  const dimension_type var_id = var.id();
76599  if (space_dim < var_id + 1) {
76600    throw_dimension_incompatible("affine_form_image(v, l)", var.id() + 1);
76601  }
76602
76603  strong_closure_assign();
76604  // The image of an empty octagon is empty too.
76605  if (marked_empty()) {
76606    return;
76607  }
76608
76609  // Number of non-zero coefficients in `lf': will be set to
76610  // 0, 1, or 2, the latter value meaning any value greater than 1.
76611  dimension_type t = 0;
76612  // Variable-index of the last non-zero coefficient in `lf', if any.
76613  dimension_type w_id = 0;
76614
76615  // Get information about the number of non-zero coefficients in `lf'.
76616  for (dimension_type i = lf_space_dim; i-- > 0; ) {
76617    if (lf.coefficient(Variable(i)) != 0) {
76618      if (t++ == 1) {
76619        break;
76620      }
76621      else {
76622        w_id = i;
76623      }
76624    }
76625  }
76626
76627  typedef typename OR_Matrix<N>::row_iterator row_iterator;
76628  typedef typename OR_Matrix<N>::row_reference_type row_reference;
76629  typedef Interval<T, Interval_Info> FP_Interval_Type;
76630  using std::swap;
76631
76632  const dimension_type n_var = 2*var_id;
76633  const FP_Interval_Type& b = lf.inhomogeneous_term();
76634
76635  // `w' is the variable with index `w_id'.
76636  // Now we know the form of `lf':
76637  // - If t == 0, then lf == [lb, ub];
76638  // - If t == 1, then lf == a*w + [lb, ub], where `w' can be `v' or another
76639  //   variable;
76640  // - If t == 2, the `lf' is of the general form.
76641
76642  PPL_DIRTY_TEMP(N, b_ub);
76643  assign_r(b_ub, b.upper(), ROUND_NOT_NEEDED);
76644  PPL_DIRTY_TEMP(N, b_mlb);
76645  neg_assign_r(b_mlb, b.lower(), ROUND_NOT_NEEDED);
76646
76647  if (t == 0) {
76648    // Case 1: lf = [lb, ub].
76649    forget_all_octagonal_constraints(var_id);
76650    mul_2exp_assign_r(b_mlb, b_mlb, 1, ROUND_UP);
76651    mul_2exp_assign_r(b_ub, b_ub, 1, ROUND_UP);
76652    // Add the constraint `var >= lb && var <= ub'.
76653    add_octagonal_constraint(n_var + 1, n_var, b_ub);
76654    add_octagonal_constraint(n_var, n_var + 1, b_mlb);
76655    PPL_ASSERT(OK());
76656    return;
76657  }
76658
76659  // True if `b' is in [0, 0].
76660  bool is_b_zero = (b_mlb == 0 && b_ub == 0);
76661
76662  if (t == 1) {
76663    // The one and only non-zero homogeneous coefficient in `lf'.
76664    const FP_Interval_Type& w_coeff = lf.coefficient(Variable(w_id));
76665    // True if `w_coeff' is in [1, 1].
76666    bool is_w_coeff_one = (w_coeff == 1);
76667    // True if `w_coeff' is in [-1, -1].
76668    bool is_w_coeff_minus_one = (w_coeff == -1);
76669    if (is_w_coeff_one || is_w_coeff_minus_one) {
76670      // Case 2: lf = w_coeff*w + b, with w_coeff = [+/-1, +/-1].
76671      if (w_id == var_id) {
76672        // Here lf = w_coeff*v + b, with w_coeff = [+/-1, +/-1].
76673        if (is_w_coeff_one && is_b_zero) {
76674          // The transformation is the identity function.
76675          return;
76676        }
76677        // Translate all the constraints on `var' by adding the value
76678        // `b_ub' or subtracting the value `b_lb'.
76679        if (is_w_coeff_minus_one) {
76680          swap(b_ub, b_mlb);
76681        }
76682        const row_iterator m_begin = matrix.row_begin();
76683        const row_iterator m_end = matrix.row_end();
76684        row_iterator m_iter = m_begin + n_var;
76685        row_reference m_v = *m_iter;
76686        ++m_iter;
76687        row_reference m_cv = *m_iter;
76688        ++m_iter;
76689        // NOTE: delay update of unary constraints on `var'.
76690        for (dimension_type j = n_var; j-- > 0; ) {
76691          N& m_v_j = m_v[j];
76692          add_assign_r(m_v_j, m_v_j, b_mlb, ROUND_UP);
76693          N& m_cv_j = m_cv[j];
76694          add_assign_r(m_cv_j, m_cv_j, b_ub, ROUND_UP);
76695          if (is_w_coeff_minus_one) {
76696            swap(m_v_j, m_cv_j);
76697          }
76698        }
76699        for ( ; m_iter != m_end; ++m_iter) {
76700          row_reference m_i = *m_iter;
76701          N& m_i_v = m_i[n_var];
76702          add_assign_r(m_i_v, m_i_v, b_ub, ROUND_UP);
76703          N& m_i_cv = m_i[n_var + 1];
76704          add_assign_r(m_i_cv, m_i_cv, b_mlb, ROUND_UP);
76705          if (is_w_coeff_minus_one) {
76706            swap(m_i_v, m_i_cv);
76707          }
76708        }
76709        // Now update unary constraints on var.
76710        mul_2exp_assign_r(b_ub, b_ub, 1, ROUND_UP);
76711        N& m_cv_v = m_cv[n_var];
76712        add_assign_r(m_cv_v, m_cv_v, b_ub, ROUND_UP);
76713        mul_2exp_assign_r(b_mlb, b_mlb, 1, ROUND_UP);
76714        N& m_v_cv = m_v[n_var + 1];
76715        add_assign_r(m_v_cv, m_v_cv, b_mlb, ROUND_UP);
76716        if (is_w_coeff_minus_one) {
76717          swap(m_cv_v, m_v_cv);
76718        }
76719        // Note: strong closure is preserved.
76720      }
76721      else {
76722        // Here `w != var', so that `lf' is of the form
76723        // [+/-1, +/-1] * w + b.
76724        // Remove all constraints on `var'.
76725        forget_all_octagonal_constraints(var_id);
76726        const dimension_type n_w = 2*w_id;
76727        if (is_w_coeff_one) {
76728          // Add the new constraints `var - w >= b_lb'
76729          // `and var - w <= b_ub'.
76730          if (var_id < w_id) {
76731            add_octagonal_constraint(n_w, n_var, b_ub);
76732            add_octagonal_constraint(n_w + 1, n_var + 1, b_mlb);
76733          }
76734          else {
76735            add_octagonal_constraint(n_var + 1, n_w + 1, b_ub);
76736            add_octagonal_constraint(n_var, n_w, b_mlb);
76737          }
76738        }
76739        else {
76740          // Add the new constraints `var + w >= b_lb'
76741          // `and var + w <= b_ub'.
76742          if (var_id < w_id) {
76743            add_octagonal_constraint(n_w + 1, n_var, b_ub);
76744            add_octagonal_constraint(n_w, n_var + 1, b_mlb);
76745          }
76746          else {
76747            add_octagonal_constraint(n_var + 1, n_w, b_ub);
76748            add_octagonal_constraint(n_var, n_w + 1, b_mlb);
76749          }
76750        }
76751        incremental_strong_closure_assign(var);
76752      }
76753      PPL_ASSERT(OK());
76754      return;
76755    }
76756  }
76757
76758  // General case.
76759  // Either t == 2, so that
76760  // expr == i_1*x_1 + i_2*x_2 + ... + i_n*x_n + b, where n >= 2,
76761  // or t == 1, expr == i*w + b, but i <> [+/-1, +/-1].
76762
76763  // In the following, strong closure will be definitely lost.
76764  reset_strongly_closed();
76765
76766  Linear_Form<FP_Interval_Type> minus_lf(lf);
76767  minus_lf.negate();
76768
76769  // Declare temporaries outside the loop.
76770  PPL_DIRTY_TEMP(N, upper_bound);
76771
76772  row_iterator m_iter = matrix.row_begin();
76773  m_iter += n_var;
76774  row_reference var_ite = *m_iter;
76775  ++m_iter;
76776  row_reference var_cv_ite = *m_iter;
76777  ++m_iter;
76778  row_iterator m_end = matrix.row_end();
76779
76780  // Update binary constraints on var FIRST.
76781  for (dimension_type curr_var = var_id,
76782         n_curr_var = n_var - 2; curr_var-- > 0; ) {
76783    Variable current(curr_var);
76784    linear_form_upper_bound(lf + current, upper_bound);
76785    assign_r(var_cv_ite[n_curr_var], upper_bound, ROUND_NOT_NEEDED);
76786    linear_form_upper_bound(lf - current, upper_bound);
76787    assign_r(var_cv_ite[n_curr_var + 1], upper_bound, ROUND_NOT_NEEDED);
76788    linear_form_upper_bound(minus_lf + current, upper_bound);
76789    assign_r(var_ite[n_curr_var], upper_bound, ROUND_NOT_NEEDED);
76790    linear_form_upper_bound(minus_lf - current, upper_bound);
76791    assign_r(var_ite[n_curr_var + 1], upper_bound, ROUND_NOT_NEEDED);
76792    n_curr_var -= 2;
76793  }
76794  for (dimension_type curr_var = var_id + 1; m_iter != m_end; ++m_iter) {
76795    row_reference m_v_ite = *m_iter;
76796    ++m_iter;
76797    row_reference m_cv_ite = *m_iter;
76798    Variable current(curr_var);
76799    linear_form_upper_bound(lf + current, upper_bound);
76800    assign_r(m_cv_ite[n_var], upper_bound, ROUND_NOT_NEEDED);
76801    linear_form_upper_bound(lf - current, upper_bound);
76802    assign_r(m_v_ite[n_var], upper_bound, ROUND_NOT_NEEDED);
76803    linear_form_upper_bound(minus_lf + current, upper_bound);
76804    assign_r(m_cv_ite[n_var + 1], upper_bound, ROUND_NOT_NEEDED);
76805    linear_form_upper_bound(minus_lf - current, upper_bound);
76806    assign_r(m_v_ite[n_var + 1], upper_bound, ROUND_NOT_NEEDED);
76807    ++curr_var;
76808  }
76809
76810  // Finally, update unary constraints on var.
76811  PPL_DIRTY_TEMP(N, lf_ub);
76812  linear_form_upper_bound(lf, lf_ub);
76813  PPL_DIRTY_TEMP(N, minus_lf_ub);
76814  linear_form_upper_bound(minus_lf, minus_lf_ub);
76815  mul_2exp_assign_r(lf_ub, lf_ub, 1, ROUND_UP);
76816  assign_r(matrix[n_var + 1][n_var], lf_ub, ROUND_NOT_NEEDED);
76817  mul_2exp_assign_r(minus_lf_ub, minus_lf_ub, 1, ROUND_UP);
76818  assign_r(matrix[n_var][n_var + 1], minus_lf_ub, ROUND_NOT_NEEDED);
76819
76820  PPL_ASSERT(OK());
76821}
76822
76823template <typename T>
76824template <typename Interval_Info>
76825void
76826Octagonal_Shape<T>::
76827linear_form_upper_bound(const Linear_Form< Interval<T, Interval_Info> >& lf,
76828                        N& result) const {
76829
76830  // Check that T is a floating point type.
76831  PPL_COMPILE_TIME_CHECK(!std::numeric_limits<T>::is_exact,
76832                     "Octagonal_Shape<T>::linear_form_upper_bound:"
76833                     " T not a floating point type.");
76834
76835  const dimension_type lf_space_dimension = lf.space_dimension();
76836  PPL_ASSERT(lf_space_dimension <= space_dim);
76837
76838  typedef Interval<T, Interval_Info> FP_Interval_Type;
76839
76840  PPL_DIRTY_TEMP(N, curr_lb);
76841  PPL_DIRTY_TEMP(N, curr_ub);
76842  PPL_DIRTY_TEMP(N, curr_var_ub);
76843  PPL_DIRTY_TEMP(N, curr_minus_var_ub);
76844
76845  PPL_DIRTY_TEMP(N, first_comparison_term);
76846  PPL_DIRTY_TEMP(N, second_comparison_term);
76847
76848  PPL_DIRTY_TEMP(N, negator);
76849
76850  assign_r(result, lf.inhomogeneous_term().upper(), ROUND_NOT_NEEDED);
76851
76852  for (dimension_type curr_var = 0, n_var = 0; curr_var < lf_space_dimension;
76853       ++curr_var) {
76854    const FP_Interval_Type& curr_coefficient =
76855                            lf.coefficient(Variable(curr_var));
76856    assign_r(curr_lb, curr_coefficient.lower(), ROUND_NOT_NEEDED);
76857    assign_r(curr_ub, curr_coefficient.upper(), ROUND_NOT_NEEDED);
76858    if (curr_lb != 0 || curr_ub != 0) {
76859      assign_r(curr_var_ub, matrix[n_var + 1][n_var], ROUND_NOT_NEEDED);
76860      div_2exp_assign_r(curr_var_ub, curr_var_ub, 1, ROUND_UP);
76861      neg_assign_r(curr_minus_var_ub, matrix[n_var][n_var + 1],
76862                   ROUND_NOT_NEEDED);
76863      div_2exp_assign_r(curr_minus_var_ub, curr_minus_var_ub, 1, ROUND_DOWN);
76864      // Optimize the most common case: curr = +/-[1, 1].
76865      if (curr_lb == 1 && curr_ub == 1) {
76866        add_assign_r(result, result, std::max(curr_var_ub, curr_minus_var_ub),
76867                     ROUND_UP);
76868      }
76869      else if (curr_lb == -1 && curr_ub == -1) {
76870        neg_assign_r(negator, std::min(curr_var_ub, curr_minus_var_ub),
76871                     ROUND_NOT_NEEDED);
76872        add_assign_r(result, result, negator, ROUND_UP);
76873      }
76874      else {
76875        // Next addend will be the maximum of four quantities.
76876        assign_r(first_comparison_term, 0, ROUND_NOT_NEEDED);
76877        assign_r(second_comparison_term, 0, ROUND_NOT_NEEDED);
76878        add_mul_assign_r(first_comparison_term, curr_var_ub, curr_ub,
76879                         ROUND_UP);
76880        add_mul_assign_r(second_comparison_term, curr_var_ub, curr_lb,
76881                         ROUND_UP);
76882        assign_r(first_comparison_term, std::max(first_comparison_term,
76883                                                 second_comparison_term),
76884                 ROUND_NOT_NEEDED);
76885        assign_r(second_comparison_term, 0, ROUND_NOT_NEEDED);
76886        add_mul_assign_r(second_comparison_term, curr_minus_var_ub, curr_ub,
76887                         ROUND_UP);
76888        assign_r(first_comparison_term, std::max(first_comparison_term,
76889                                                 second_comparison_term),
76890                 ROUND_NOT_NEEDED);
76891        assign_r(second_comparison_term, 0, ROUND_NOT_NEEDED);
76892        add_mul_assign_r(second_comparison_term, curr_minus_var_ub, curr_lb,
76893                         ROUND_UP);
76894        assign_r(first_comparison_term, std::max(first_comparison_term,
76895                                                 second_comparison_term),
76896                 ROUND_NOT_NEEDED);
76897
76898        add_assign_r(result, result, first_comparison_term, ROUND_UP);
76899      }
76900    }
76901
76902    n_var += 2;
76903  }
76904}
76905
76906template <typename T>
76907void
76908Octagonal_Shape<T>::
76909interval_coefficient_upper_bound(const N& var_ub, const N& minus_var_ub,
76910                                 const N& int_ub, const N& int_lb,
76911                                 N& result) {
76912
76913  // Check that T is a floating point type.
76914  PPL_COMPILE_TIME_CHECK(!std::numeric_limits<T>::is_exact,
76915                     "Octagonal_Shape<T>::interval_coefficient_upper_bound:"
76916                     " T not a floating point type.");
76917
76918  // NOTE: we store the first comparison term directly into result.
76919  PPL_DIRTY_TEMP(N, second_comparison_term);
76920  PPL_DIRTY_TEMP(N, third_comparison_term);
76921  PPL_DIRTY_TEMP(N, fourth_comparison_term);
76922
76923  assign_r(result, 0, ROUND_NOT_NEEDED);
76924  assign_r(second_comparison_term, 0, ROUND_NOT_NEEDED);
76925  assign_r(third_comparison_term, 0, ROUND_NOT_NEEDED);
76926  assign_r(fourth_comparison_term, 0, ROUND_NOT_NEEDED);
76927
76928  add_mul_assign_r(result, var_ub, int_ub, ROUND_UP);
76929  add_mul_assign_r(second_comparison_term, minus_var_ub, int_ub, ROUND_UP);
76930  add_mul_assign_r(third_comparison_term, var_ub, int_lb, ROUND_UP);
76931  add_mul_assign_r(fourth_comparison_term, minus_var_ub, int_lb, ROUND_UP);
76932
76933  assign_r(result, std::max(result, second_comparison_term), ROUND_NOT_NEEDED);
76934  assign_r(result, std::max(result, third_comparison_term), ROUND_NOT_NEEDED);
76935  assign_r(result, std::max(result, fourth_comparison_term), ROUND_NOT_NEEDED);
76936}
76937
76938template <typename T>
76939void
76940Octagonal_Shape<T>::affine_preimage(const Variable var,
76941                                    const Linear_Expression& expr,
76942                                    Coefficient_traits::const_reference
76943                                    denominator) {
76944
76945  // The denominator cannot be zero.
76946  if (denominator == 0) {
76947    throw_invalid_argument("affine_preimage(v, e, d)", "d == 0");
76948  }
76949
76950  // Dimension-compatibility checks.
76951  // The dimension of `expr' should not be greater than the dimension
76952  // of `*this'.
76953  const dimension_type expr_space_dim = expr.space_dimension();
76954  if (space_dim < expr_space_dim) {
76955    throw_dimension_incompatible("affine_preimage(v, e, d)", "e", expr);
76956  }
76957
76958  // `var' should be one of the dimensions of the octagon.
76959  dimension_type var_id = var.id();
76960  if (space_dim < var_id + 1) {
76961    throw_dimension_incompatible("affine_preimage(v, e, d)", var_id + 1);
76962  }
76963
76964  strong_closure_assign();
76965  // The image of an empty octagon is empty too.
76966  if (marked_empty()) {
76967    return;
76968  }
76969
76970  const Coefficient& b = expr.inhomogeneous_term();
76971
76972  // Number of non-zero coefficients in `expr': will be set to
76973  // 0, 1, or 2, the latter value meaning any value greater than 1.
76974  dimension_type t = 0;
76975
76976  // Variable-index of the last non-zero coefficient in `expr', if any.
76977  dimension_type w_id = expr.last_nonzero();
76978
76979  if (w_id != 0) {
76980    ++t;
76981    if (!expr.all_zeroes(1, w_id)) {
76982      ++t;
76983    }
76984    --w_id;
76985  }
76986
76987  // `w' is the variable with index `w_id'.
76988  // Now we know the form of `expr':
76989  // - If t == 0, then expr == b, with `b' a constant;
76990  // - If t == 1, then expr == a*w + b, where `w' can be `v' or another
76991  //   variable; in this second case we have to check whether `a' is
76992  //   equal to `denominator' or `-denominator', since otherwise we have
76993  //   to fall back on the general form;
76994  // - If t == 2, the `expr' is of the general form.
76995
76996  if (t == 0) {
76997    // Case 1: expr = n; remove all constraints on `var'.
76998    forget_all_octagonal_constraints(var_id);
76999    PPL_ASSERT(OK());
77000    return;
77001  }
77002
77003  if (t == 1) {
77004    // Value of the one and only non-zero coefficient in `expr'.
77005    const Coefficient& w_coeff = expr.coefficient(Variable(w_id));
77006    if (w_coeff == denominator || w_coeff == -denominator) {
77007      // Case 2: expr = w_coeff*w + b, with w_coeff = +/- denominator.
77008      if (w_id == var_id) {
77009        // Apply affine_image() on the inverse of this transformation.
77010        affine_image(var, denominator*var - b, w_coeff);
77011      }
77012      else {
77013        // `expr == w_coeff*w + b', where `w != var'.
77014        // Remove all constraints on `var'.
77015        forget_all_octagonal_constraints(var_id);
77016        PPL_ASSERT(OK());
77017      }
77018      return;
77019    }
77020  }
77021  // General case.
77022  // Either t == 2, so that
77023  // expr = a_1*x_1 + a_2*x_2 + ... + a_n*x_n + b, where n >= 2,
77024  // or t = 1, expr = a*w + b, but a <> +/- denominator.
77025  const Coefficient& coeff_v = expr.coefficient(var);
77026  if (coeff_v != 0) {
77027    if (coeff_v > 0) {
77028      // The transformation is invertible.
77029      Linear_Expression inverse = ((coeff_v + denominator)*var);
77030      inverse -= expr;
77031      affine_image(var, inverse, coeff_v);
77032    }
77033    else {
77034      // The transformation is invertible.
77035      PPL_DIRTY_TEMP_COEFFICIENT(minus_coeff_v);
77036      neg_assign(minus_coeff_v, coeff_v);
77037      Linear_Expression inverse = ((minus_coeff_v - denominator)*var);
77038      inverse += expr;
77039      affine_image(var, inverse, minus_coeff_v);
77040    }
77041  }
77042  else {
77043    // The transformation is not invertible: all constraints on `var' are lost.
77044    forget_all_octagonal_constraints(var_id);
77045    PPL_ASSERT(OK());
77046  }
77047}
77048
77049template <typename T>
77050void
77051Octagonal_Shape<T>
77052::generalized_affine_image(const Variable var,
77053                           const Relation_Symbol relsym,
77054                           const Linear_Expression&  expr ,
77055                           Coefficient_traits::const_reference denominator) {
77056  // The denominator cannot be zero.
77057  if (denominator == 0) {
77058    throw_invalid_argument("generalized_affine_image(v, r, e, d)", "d == 0");
77059  }
77060
77061  // Dimension-compatibility checks.
77062  // The dimension of `expr' should not be greater than the dimension
77063  // of `*this'.
77064  const dimension_type expr_space_dim = expr.space_dimension();
77065  if (space_dim < expr_space_dim) {
77066    throw_dimension_incompatible("generalized_affine_image(v, r, e, d)", "e",
77067                                 expr);
77068  }
77069
77070  // `var' should be one of the dimensions of the octagon.
77071  dimension_type var_id = var.id();
77072  if (space_dim < var_id + 1) {
77073    throw_dimension_incompatible("generalized_affine_image(v, r, e, d)",
77074                                 var_id + 1);
77075  }
77076
77077  // The relation symbol cannot be a strict relation symbol.
77078  if (relsym == LESS_THAN || relsym == GREATER_THAN) {
77079    throw_invalid_argument("generalized_affine_image(v, r, e, d)",
77080                           "r is a strict relation symbol");
77081  }
77082  // The relation symbol cannot be a disequality.
77083  if (relsym == NOT_EQUAL) {
77084    throw_invalid_argument("generalized_affine_image(v, r, e, d)",
77085                           "r is the disequality relation symbol");
77086  }
77087
77088  if (relsym == EQUAL) {
77089    // The relation symbol is "=":
77090    // this is just an affine image computation.
77091    affine_image(var, expr, denominator);
77092    return;
77093  }
77094
77095  strong_closure_assign();
77096  // The image of an empty octagon is empty too.
77097  if (marked_empty()) {
77098    return;
77099  }
77100
77101  // Number of non-zero coefficients in `expr': will be set to
77102  // 0, 1, or 2, the latter value meaning any value greater than 1.
77103  dimension_type t = 0;
77104  // Variable-index of the last non-zero coefficient in `expr', if any.
77105  dimension_type w_id = expr.last_nonzero();
77106
77107  if (w_id != 0) {
77108    ++t;
77109    if (!expr.all_zeroes(1, w_id)) {
77110      ++t;
77111    }
77112    --w_id;
77113  }
77114
77115  typedef typename OR_Matrix<N>::row_iterator row_iterator;
77116  typedef typename OR_Matrix<N>::row_reference_type row_reference;
77117  typedef typename OR_Matrix<N>::const_row_iterator Row_iterator;
77118  typedef typename OR_Matrix<N>::const_row_reference_type Row_reference;
77119
77120  const row_iterator m_begin = matrix.row_begin();
77121  const row_iterator m_end = matrix.row_end();
77122  const dimension_type n_var = 2*var_id;
77123  const Coefficient& b = expr.inhomogeneous_term();
77124  PPL_DIRTY_TEMP_COEFFICIENT(minus_denom);
77125  neg_assign_r(minus_denom, denominator, ROUND_NOT_NEEDED);
77126
77127  // `w' is the variable with index `w_id'.
77128  // Now we know the form of `expr':
77129  // - If t == 0, then expr == b, with `b' a constant;
77130  // - If t == 1, then expr == a*w + b, where `w' can be `v' or another
77131  //   variable; in this second case we have to check whether `a' is
77132  //   equal to `denominator' or `-denominator', since otherwise we have
77133  //   to fall back on the general form;
77134  // - If t == 2, the `expr' is of the general form.
77135
77136  if (t == 0) {
77137    // Case 1: expr = b.
77138    PPL_DIRTY_TEMP_COEFFICIENT(two_b);
77139    two_b = 2*b;
77140    // Remove all constraints on `var'.
77141    forget_all_octagonal_constraints(var_id);
77142    // Strong closure is lost.
77143    reset_strongly_closed();
77144    switch (relsym) {
77145    case LESS_OR_EQUAL:
77146      // Add the constraint `var <= b/denominator'.
77147      add_octagonal_constraint(n_var + 1, n_var, two_b, denominator);
77148      break;
77149    case GREATER_OR_EQUAL:
77150      // Add the constraint `var >= n/denominator',
77151      // i.e., `-var <= -b/denominator'.
77152      add_octagonal_constraint(n_var, n_var + 1, two_b, minus_denom);
77153      break;
77154    default:
77155      // We already dealt with the other cases.
77156      PPL_UNREACHABLE;
77157      break;
77158    }
77159    PPL_ASSERT(OK());
77160    return;
77161  }
77162
77163  if (t == 1) {
77164    // The one and only non-zero homogeneous coefficient in `expr'.
77165    const Coefficient& w_coeff = expr.coefficient(Variable(w_id));
77166    if (w_coeff == denominator || w_coeff == minus_denom) {
77167      // Case 2: expr == w_coeff*w + b, with w_coeff == +/- denominator.
77168      switch (relsym) {
77169      case LESS_OR_EQUAL:
77170        {
77171          PPL_DIRTY_TEMP(N, d);
77172          div_round_up(d, b, denominator);
77173          if (w_id == var_id) {
77174            // Here `expr' is of the form: +/- denominator * v + b.
77175            // Strong closure is not preserved.
77176            reset_strongly_closed();
77177            if (w_coeff == denominator) {
77178              // Translate all the constraints of the form `v - w <= cost'
77179              // into the constraint `v - w <= cost + b/denominator';
77180              // forget each constraint `w - v <= cost1'.
77181              row_iterator m_iter = m_begin + n_var;
77182              row_reference m_v = *m_iter;
77183              N& m_v_cv = m_v[n_var + 1];
77184              ++m_iter;
77185              row_reference m_cv = *m_iter;
77186              N& m_cv_v = m_cv[n_var];
77187              ++m_iter;
77188              // NOTE: delay update of m_v_cv and m_cv_v.
77189              for ( ; m_iter != m_end; ++m_iter) {
77190                row_reference m_i = *m_iter;
77191                N& m_i_v = m_i[n_var];
77192                add_assign_r(m_i_v, m_i_v, d, ROUND_UP);
77193                assign_r(m_i[n_var + 1], PLUS_INFINITY, ROUND_NOT_NEEDED);
77194              }
77195              for (dimension_type k = n_var; k-- > 0; ) {
77196                assign_r(m_v[k], PLUS_INFINITY, ROUND_NOT_NEEDED);
77197                add_assign_r(m_cv[k], m_cv[k], d, ROUND_UP);
77198              }
77199              mul_2exp_assign_r(d, d, 1, ROUND_UP);
77200              add_assign_r(m_cv_v, m_cv_v, d, ROUND_UP);
77201              assign_r(m_v_cv, PLUS_INFINITY, ROUND_NOT_NEEDED);
77202            }
77203            else {
77204              // Here `w_coeff == -denominator'.
77205              // `expr' is of the form: -a*var + b.
77206              N& m_v_cv = matrix[n_var][n_var + 1];
77207              mul_2exp_assign_r(d, d, 1, ROUND_UP);
77208              add_assign_r(matrix[n_var + 1][n_var], m_v_cv, d, ROUND_UP);
77209              assign_r(m_v_cv, PLUS_INFINITY, ROUND_NOT_NEEDED);
77210              forget_binary_octagonal_constraints(var_id);
77211            }
77212          }
77213          else {
77214            // Here `w != v', so that `expr' is the form
77215            // +/- denominator*w + b.
77216            // Remove all constraints on `v'.
77217            forget_all_octagonal_constraints(var_id);
77218            const dimension_type n_w = 2*w_id;
77219            if (w_coeff == denominator) {
77220              // Add the new constraint `v - w <= b/denominator'.
77221              if (var_id < w_id) {
77222                add_octagonal_constraint(n_w, n_var, b, denominator);
77223              }
77224              else {
77225                add_octagonal_constraint(n_var + 1, n_w + 1, b, denominator);
77226              }
77227            }
77228            else {
77229              // Add the new constraint `v + w <= b/denominator'.
77230              if (var_id < w_id) {
77231                add_octagonal_constraint(n_w + 1, n_var, b, denominator);
77232              }
77233              else {
77234                add_octagonal_constraint(n_var + 1, n_w, b, denominator);
77235              }
77236            }
77237          }
77238          break;
77239        }
77240
77241      case GREATER_OR_EQUAL:
77242        {
77243          PPL_DIRTY_TEMP(N, d);
77244          div_round_up(d, b, minus_denom);
77245          if (w_id == var_id) {
77246            // Here `expr' is of the form: +/- denominator * v + b.
77247            // Strong closure is not preserved.
77248            reset_strongly_closed();
77249            if (w_coeff == denominator) {
77250              // Translate each constraint `w - v <= cost'
77251              // into the constraint `w - v <= cost - b/denominator';
77252              // forget each constraint `v - w <= cost1'.
77253              row_iterator m_iter = m_begin + n_var;
77254              row_reference m_v = *m_iter;
77255              N& m_v_cv = m_v[n_var + 1];
77256              ++m_iter;
77257              row_reference m_cv = *m_iter;
77258              N& m_cv_v = m_cv[n_var];
77259              ++m_iter;
77260              // NOTE: delay update of m_v_cv and m_cv_v.
77261              for ( ; m_iter != m_end; ++m_iter) {
77262                row_reference m_i = *m_iter;
77263                assign_r(m_i[n_var], PLUS_INFINITY, ROUND_NOT_NEEDED);
77264                add_assign_r(m_i[n_var + 1], m_i[n_var + 1], d, ROUND_UP);
77265              }
77266              for (dimension_type k = n_var; k-- > 0; ) {
77267                add_assign_r(m_v[k], m_v[k], d, ROUND_UP);
77268                assign_r(m_cv[k], PLUS_INFINITY, ROUND_NOT_NEEDED);
77269              }
77270              mul_2exp_assign_r(d, d, 1, ROUND_UP);
77271              add_assign_r(m_v_cv, m_v_cv, d, ROUND_UP);
77272              assign_r(m_cv_v, PLUS_INFINITY, ROUND_NOT_NEEDED);
77273            }
77274            else {
77275              // Here `w_coeff == -denominator'.
77276              // `expr' is of the form: -a*var + b.
77277              N& m_cv_v = matrix[n_var + 1][n_var];
77278              mul_2exp_assign_r(d, d, 1, ROUND_UP);
77279              add_assign_r(matrix[n_var][n_var + 1], m_cv_v, d, ROUND_UP);
77280              assign_r(m_cv_v, PLUS_INFINITY, ROUND_NOT_NEEDED);
77281              forget_binary_octagonal_constraints(var_id);
77282            }
77283          }
77284          else {
77285            // Here `w != v', so that `expr' is of the form
77286            // +/-denominator * w + b, with `w != v'.
77287            // Remove all constraints on `v'.
77288            forget_all_octagonal_constraints(var_id);
77289            const dimension_type n_w = 2*w_id;
77290            // We have got an expression of the following form:
77291            // var1 + n, with `var1' != `var'.
77292            // We remove all constraints of the form `var (+/- var1) >= const'
77293            // and we add the new constraint `var +/- var1 >= n/denominator'.
77294            if (w_coeff == denominator) {
77295              // Add the new constraint `var - w >= b/denominator',
77296              // i.e., `w - var <= -b/denominator'.
77297              if (var_id < w_id) {
77298                add_octagonal_constraint(n_w + 1, n_var + 1, b, minus_denom);
77299              }
77300              else {
77301                add_octagonal_constraint(n_var, n_w, b, minus_denom);
77302              }
77303            }
77304            else {
77305              // Add the new constraint `var + w >= b/denominator',
77306              // i.e., `-w - var <= -b/denominator'.
77307              if (var_id < w_id) {
77308                add_octagonal_constraint(n_w, n_var + 1, b, minus_denom);
77309              }
77310              else {
77311                add_octagonal_constraint(n_var, n_w + 1, b, minus_denom);
77312              }
77313            }
77314          }
77315          break;
77316        }
77317
77318      default:
77319        // We already dealt with the other cases.
77320        PPL_UNREACHABLE;
77321        break;
77322      }
77323      PPL_ASSERT(OK());
77324      return;
77325    }
77326  }
77327
77328  // General case.
77329  // Either t == 2, so that
77330  // expr == a_1*x_1 + a_2*x_2 + ... + a_n*x_n + b, where n >= 2,
77331  // or t == 1, expr == a*w + b, but a <> +/- denominator.
77332  // We will remove all the constraints on `v' and add back
77333  // a constraint providing an upper or a lower bound for `v'
77334  // (depending on `relsym').
77335  const bool is_sc = (denominator > 0);
77336  PPL_DIRTY_TEMP_COEFFICIENT(minus_b);
77337  neg_assign(minus_b, b);
77338  const Coefficient& sc_b = is_sc ? b : minus_b;
77339  const Coefficient& minus_sc_b = is_sc ? minus_b : b;
77340  const Coefficient& sc_denom = is_sc ? denominator : minus_denom;
77341  const Coefficient& minus_sc_denom = is_sc ? minus_denom : denominator;
77342  // NOTE: here, for optimization purposes, `minus_expr' is only assigned
77343  // when `denominator' is negative. Do not use it unless you are sure
77344  // it has been correctly assigned.
77345  Linear_Expression minus_expr;
77346  if (!is_sc) {
77347    minus_expr = -expr;
77348  }
77349  const Linear_Expression& sc_expr = is_sc ? expr : minus_expr;
77350
77351  PPL_DIRTY_TEMP(N, sum);
77352  // Index of variable that is unbounded in `this->matrix'.
77353  PPL_UNINITIALIZED(dimension_type, pinf_index);
77354  // Number of unbounded variables found.
77355  dimension_type pinf_count = 0;
77356
77357  switch (relsym) {
77358  case LESS_OR_EQUAL:
77359    {
77360      // Compute an upper approximation for `sc_expr' into `sum'.
77361
77362      // Approximate the inhomogeneous term.
77363      assign_r(sum, sc_b, ROUND_UP);
77364      // Approximate the homogeneous part of `sc_expr'.
77365      PPL_DIRTY_TEMP(N, coeff_i);
77366      PPL_DIRTY_TEMP(N, approx_i);
77367      PPL_DIRTY_TEMP_COEFFICIENT(minus_sc_i);
77368      // Note: indices above `w' can be disregarded, as they all have
77369      // a zero coefficient in `sc_expr'.
77370      for (Row_iterator m_iter = m_begin, m_iter_end = m_begin + (2 * w_id + 2);
77371           m_iter != m_iter_end; ) {
77372        const dimension_type n_i = m_iter.index();
77373        const dimension_type id = n_i/2;
77374        Row_reference m_i = *m_iter;
77375        ++m_iter;
77376        Row_reference m_ci = *m_iter;
77377        ++m_iter;
77378        const Coefficient& sc_i = sc_expr.coefficient(Variable(id));
77379        const int sign_i = sgn(sc_i);
77380        if (sign_i == 0) {
77381          continue;
77382        }
77383        // Choose carefully: we are approximating `sc_expr'.
77384        const N& double_approx_i = (sign_i > 0) ? m_ci[n_i] : m_i[n_i + 1];
77385        if (is_plus_infinity(double_approx_i)) {
77386          if (++pinf_count > 1) {
77387            break;
77388          }
77389          pinf_index = id;
77390          continue;
77391        }
77392        if (sign_i > 0) {
77393          assign_r(coeff_i, sc_i, ROUND_UP);
77394        }
77395        else {
77396          neg_assign(minus_sc_i, sc_i);
77397          assign_r(coeff_i, minus_sc_i, ROUND_UP);
77398        }
77399        div_2exp_assign_r(approx_i, double_approx_i, 1, ROUND_UP);
77400        add_mul_assign_r(sum, coeff_i, approx_i, ROUND_UP);
77401      }
77402      // Remove all constraints on `v'.
77403      forget_all_octagonal_constraints(var_id);
77404      reset_strongly_closed();
77405      // Return immediately if no approximation could be computed.
77406      if (pinf_count > 1) {
77407        PPL_ASSERT(OK());
77408        return;
77409      }
77410
77411      // Divide by the (sign corrected) denominator (if needed).
77412      if (sc_denom != 1) {
77413        // Before computing the quotient, the denominator should be
77414        // approximated towards zero. Since `sc_denom' is known to be
77415        // positive, this amounts to rounding downwards, which is
77416        // achieved as usual by rounding upwards
77417        // `minus_sc_denom' and negating again the result.
77418        PPL_DIRTY_TEMP(N, down_sc_denom);
77419        assign_r(down_sc_denom, minus_sc_denom, ROUND_UP);
77420        neg_assign_r(down_sc_denom, down_sc_denom, ROUND_UP);
77421        div_assign_r(sum, sum, down_sc_denom, ROUND_UP);
77422      }
77423
77424      if (pinf_count == 0) {
77425        // Add the constraint `v <= pos_sum'.
77426        PPL_DIRTY_TEMP(N, double_sum);
77427        mul_2exp_assign_r(double_sum, sum, 1, ROUND_UP);
77428        matrix[n_var + 1][n_var] = double_sum;
77429        // Deduce constraints of the form `v +/- u', where `u != v'.
77430        deduce_v_pm_u_bounds(var_id, w_id, sc_expr, sc_denom, sum);
77431      }
77432      else if (pinf_count == 1) {
77433        if (pinf_index != var_id) {
77434          const Coefficient& pi = expr.coefficient(Variable(pinf_index));
77435          if (pi == denominator ) {
77436            // Add the constraint `v - pinf_index <= sum'.
77437            if (var_id < pinf_index) {
77438              matrix[2*pinf_index][n_var] = sum;
77439            }
77440            else {
77441              matrix[n_var + 1][2*pinf_index + 1] = sum;
77442            }
77443          }
77444          else {
77445            if (pi == minus_denom) {
77446              // Add the constraint `v + pinf_index <= sum'.
77447              if (var_id < pinf_index) {
77448                matrix[2*pinf_index + 1][n_var] = sum;
77449              }
77450              else {
77451                matrix[n_var + 1][2*pinf_index] = sum;
77452              }
77453            }
77454          }
77455        }
77456      }
77457      break;
77458    }
77459
77460  case GREATER_OR_EQUAL:
77461    {
77462      // Compute an upper approximation for `-sc_expr' into `sum'.
77463      // Note: approximating `-sc_expr' from above and then negating the
77464      // result is the same as approximating `sc_expr' from below.
77465
77466      // Approximate the inhomogeneous term.
77467      assign_r(sum, minus_sc_b, ROUND_UP);
77468      PPL_DIRTY_TEMP(N, coeff_i);
77469      PPL_DIRTY_TEMP_COEFFICIENT(minus_sc_i);
77470      PPL_DIRTY_TEMP(N, approx_i);
77471      // Approximate the homogeneous part of `-sc_expr'.
77472      for (Row_iterator m_iter = m_begin, m_iter_end = m_begin + (2 * w_id + 2);
77473           m_iter != m_iter_end; ) {
77474        const dimension_type n_i = m_iter.index();
77475        const dimension_type id = n_i/2;
77476        Row_reference m_i = *m_iter;
77477        ++m_iter;
77478        Row_reference m_ci = *m_iter;
77479        ++m_iter;
77480        const Coefficient& sc_i = sc_expr.coefficient(Variable(id));
77481        const int sign_i = sgn(sc_i);
77482        if (sign_i == 0) {
77483          continue;
77484        }
77485        // Choose carefully: we are approximating `-sc_expr'.
77486        const N& double_approx_i = (sign_i > 0) ? m_i[n_i + 1] : m_ci[n_i];
77487        if (is_plus_infinity(double_approx_i)) {
77488          if (++pinf_count > 1) {
77489            break;
77490          }
77491          pinf_index = id;
77492          continue;
77493        }
77494        if (sign_i > 0) {
77495          assign_r(coeff_i, sc_i, ROUND_UP);
77496        }
77497        else {
77498          neg_assign(minus_sc_i, sc_i);
77499          assign_r(coeff_i, minus_sc_i, ROUND_UP);
77500        }
77501        div_2exp_assign_r(approx_i, double_approx_i, 1, ROUND_UP);
77502        add_mul_assign_r(sum, coeff_i, approx_i, ROUND_UP);
77503      }
77504
77505      // Remove all constraints on `var'.
77506      forget_all_octagonal_constraints(var_id);
77507      reset_strongly_closed();
77508      // Return immediately if no approximation could be computed.
77509      if (pinf_count > 1) {
77510        PPL_ASSERT(OK());
77511        return;
77512      }
77513
77514      // Divide by the (sign corrected) denominator (if needed).
77515      if (sc_denom != 1) {
77516        // Before computing the quotient, the denominator should be
77517        // approximated towards zero. Since `sc_denom' is known to be
77518        // positive, this amounts to rounding downwards, which is
77519        // achieved as usual by rounding upwards
77520        // `minus_sc_denom' and negating again the result.
77521        PPL_DIRTY_TEMP(N, down_sc_denom);
77522        assign_r(down_sc_denom, minus_sc_denom, ROUND_UP);
77523        neg_assign_r(down_sc_denom, down_sc_denom, ROUND_UP);
77524        div_assign_r(sum, sum, down_sc_denom, ROUND_UP);
77525      }
77526
77527      if (pinf_count == 0) {
77528        // Add the constraint `v >= -neg_sum', i.e., `-v <= neg_sum'.
77529        PPL_DIRTY_TEMP(N, double_sum);
77530        mul_2exp_assign_r(double_sum, sum, 1, ROUND_UP);
77531        matrix[n_var][n_var + 1] = double_sum;
77532        // Deduce constraints of the form `-v +/- u', where `u != v'.
77533        deduce_minus_v_pm_u_bounds(var_id, pinf_index, sc_expr, sc_denom, sum);
77534      }
77535      else if (pinf_count == 1) {
77536        if (pinf_index != var_id) {
77537          const Coefficient& pi = expr.coefficient(Variable(pinf_index));
77538          if (pi == denominator) {
77539            // Add the constraint `v - pinf_index >= -sum',
77540            // i.e., `pinf_index - v <= sum'.
77541            if (pinf_index < var_id) {
77542              matrix[n_var][2*pinf_index] = sum;
77543            }
77544            else {
77545              matrix[2*pinf_index + 1][n_var + 1] = sum;
77546            }
77547          }
77548          else {
77549            if (pi == minus_denom) {
77550              // Add the constraint `v + pinf_index >= -sum',
77551              // i.e., `-pinf_index - v <= sum'.
77552              if (pinf_index < var_id) {
77553                matrix[n_var][2*pinf_index + 1] = sum;
77554              }
77555              else {
77556                matrix[2*pinf_index][n_var + 1] = sum;
77557              }
77558            }
77559          }
77560        }
77561      }
77562      break;
77563    }
77564
77565  default:
77566    // We already dealt with the other cases.
77567    PPL_UNREACHABLE;
77568    break;
77569  }
77570  incremental_strong_closure_assign(var);
77571  PPL_ASSERT(OK());
77572}
77573
77574template <typename T>
77575void
77576Octagonal_Shape<T>::generalized_affine_image(const Linear_Expression& lhs,
77577                                             const Relation_Symbol relsym,
77578                                             const Linear_Expression& rhs) {
77579  // Dimension-compatibility checks.
77580  // The dimension of `lhs' should not be greater than the dimension
77581  // of `*this'.
77582  dimension_type lhs_space_dim = lhs.space_dimension();
77583  if (space_dim < lhs_space_dim) {
77584    throw_dimension_incompatible("generalized_affine_image(e1, r, e2)",
77585                                 "e1", lhs);
77586  }
77587  // The dimension of `rhs' should not be greater than the dimension
77588  // of `*this'.
77589  const dimension_type rhs_space_dim = rhs.space_dimension();
77590  if (space_dim < rhs_space_dim) {
77591    throw_dimension_incompatible("generalized_affine_image(e1, r, e2)",
77592                                 "e2", rhs);
77593  }
77594
77595  // Strict relation symbols are not admitted for octagons.
77596  if (relsym == LESS_THAN || relsym == GREATER_THAN) {
77597    throw_invalid_argument("generalized_affine_image(e1, r, e2)",
77598                           "r is a strict relation symbol");
77599  }
77600  // The relation symbol cannot be a disequality.
77601  if (relsym == NOT_EQUAL) {
77602    throw_invalid_argument("generalized_affine_image(e1, r, e2)",
77603                           "r is the disequality relation symbol");
77604  }
77605
77606  strong_closure_assign();
77607  // The image of an empty octagon is empty.
77608  if (marked_empty()) {
77609    return;
77610  }
77611
77612  // Number of non-zero coefficients in `lhs': will be set to
77613  // 0, 1, or 2, the latter value meaning any value greater than 1.
77614  dimension_type t_lhs = 0;
77615  // Index of the last non-zero coefficient in `lhs', if any.
77616  dimension_type j_lhs = lhs.last_nonzero();
77617
77618  if (j_lhs != 0) {
77619    ++t_lhs;
77620    if (!lhs.all_zeroes(1, j_lhs)) {
77621      ++t_lhs;
77622    }
77623    --j_lhs;
77624  }
77625
77626  const Coefficient& b_lhs = lhs.inhomogeneous_term();
77627
77628  if (t_lhs == 0) {
77629    // `lhs' is a constant.
77630    // In principle, it is sufficient to add the constraint `lhs relsym rhs'.
77631    // Note that this constraint is an octagonal difference if `t_rhs <= 1'
77632    // or `t_rhs > 1' and `rhs == a*v - a*w + b_rhs' or
77633    // `rhs == a*v + a*w + b_rhs'. If `rhs' is of a
77634    // more general form, it will be simply ignored.
77635    // TODO: if it is not an octagonal difference, should we compute
77636    // approximations for this constraint?
77637    switch (relsym) {
77638    case LESS_OR_EQUAL:
77639      refine_no_check(lhs <= rhs);
77640      break;
77641    case EQUAL:
77642      refine_no_check(lhs == rhs);
77643      break;
77644    case GREATER_OR_EQUAL:
77645      refine_no_check(lhs >= rhs);
77646      break;
77647    default:
77648      // We already dealt with the other cases.
77649      PPL_UNREACHABLE;
77650      break;
77651    }
77652  }
77653
77654  else if (t_lhs == 1) {
77655    // Here `lhs == a_lhs * v + b_lhs'.
77656    // Independently from the form of `rhs', we can exploit the
77657    // method computing generalized affine images for a single variable.
77658    Variable v(j_lhs);
77659    // Compute a sign-corrected relation symbol.
77660    const Coefficient& denom = lhs.coefficient(v);
77661    Relation_Symbol new_relsym = relsym;
77662    if (denom < 0) {
77663      if (relsym == LESS_OR_EQUAL) {
77664        new_relsym = GREATER_OR_EQUAL;
77665      }
77666      else if (relsym == GREATER_OR_EQUAL) {
77667        new_relsym = LESS_OR_EQUAL;
77668      }
77669    }
77670    Linear_Expression expr = rhs - b_lhs;
77671    generalized_affine_image(v, new_relsym, expr, denom);
77672  }
77673  else {
77674    // Here `lhs' is of the general form, having at least two variables.
77675    // Compute the set of variables occurring in `lhs'.
77676    std::vector<Variable> lhs_vars;
77677    for (Linear_Expression::const_iterator i = lhs.begin(), i_end = lhs.end();
77678          i != i_end; ++i) {
77679      lhs_vars.push_back(i.variable());
77680    }
77681
77682    const dimension_type num_common_dims = std::min(lhs_space_dim, rhs_space_dim);
77683    if (!lhs.have_a_common_variable(rhs, Variable(0), Variable(num_common_dims))) {
77684      // `lhs' and `rhs' variables are disjoint.
77685      // Existentially quantify all variables in the lhs.
77686      for (dimension_type i = lhs_vars.size(); i-- > 0; ) {
77687        dimension_type lhs_vars_i = lhs_vars[i].id();
77688        forget_all_octagonal_constraints(lhs_vars_i);
77689      }
77690      // Constrain the left hand side expression so that it is related to
77691      // the right hand side expression as dictated by `relsym'.
77692      // TODO: if the following constraint is NOT an octagonal difference,
77693      // it will be simply ignored. Should we compute approximations for it?
77694      switch (relsym) {
77695      case LESS_OR_EQUAL:
77696        refine_no_check(lhs <= rhs);
77697        break;
77698      case EQUAL:
77699        refine_no_check(lhs == rhs);
77700        break;
77701      case GREATER_OR_EQUAL:
77702        refine_no_check(lhs >= rhs);
77703        break;
77704      default:
77705        // We already dealt with the other cases.
77706        PPL_UNREACHABLE;
77707        break;
77708      }
77709    }
77710    else {
77711      // Some variables in `lhs' also occur in `rhs'.
77712
77713#if 1 // Simplified computation (see the TODO note below).
77714
77715      for (dimension_type i = lhs_vars.size(); i-- > 0; ) {
77716        dimension_type lhs_vars_i = lhs_vars[i].id();
77717        forget_all_octagonal_constraints(lhs_vars_i);
77718      }
77719
77720#else // Currently unnecessarily complex computation.
77721
77722      // More accurate computation that is worth doing only if
77723      // the following TODO note is accurately dealt with.
77724
77725      // To ease the computation, we add an additional dimension.
77726      const Variable new_var(space_dim);
77727      add_space_dimensions_and_embed(1);
77728      // Constrain the new dimension to be equal to `rhs'.
77729      // NOTE: calling affine_image() instead of refine_no_check()
77730      // ensures some approximation is tried even when the constraint
77731      // is not an octagonal constraint.
77732      affine_image(new_var, rhs);
77733      // Existentially quantify all variables in the lhs.
77734      // NOTE: enforce strong closure for precision.
77735      strong_closure_assign();
77736      PPL_ASSERT(!marked_empty());
77737      for (dimension_type i = lhs_vars.size(); i-- > 0; ) {
77738        dimension_type lhs_vars_i = lhs_vars[i].id();
77739        forget_all_octagonal_constraints(lhs_vars_i);
77740      }
77741      // Constrain the new dimension so that it is related to
77742      // the left hand side as dictated by `relsym'.
77743      // TODO: each one of the following constraints is definitely NOT
77744      // an octagonal difference (since it has 3 variables at least).
77745      // Thus, the method refine_no_check() will simply ignore it.
77746      // Should we compute approximations for this constraint?
77747      switch (relsym) {
77748      case LESS_OR_EQUAL:
77749        refine_no_check(lhs <= new_var);
77750        break;
77751      case EQUAL:
77752        refine_no_check(lhs == new_var);
77753        break;
77754      case GREATER_OR_EQUAL:
77755        refine_no_check(lhs >= new_var);
77756        break;
77757      default:
77758        // We already dealt with the other cases.
77759        PPL_UNREACHABLE;
77760        break;
77761      }
77762      // Remove the temporarily added dimension.
77763      remove_higher_space_dimensions(space_dim-1);
77764#endif // Currently unnecessarily complex computation.
77765    }
77766  }
77767
77768  PPL_ASSERT(OK());
77769}
77770
77771template <typename T>
77772void
77773Octagonal_Shape<T>::bounded_affine_image(const Variable var,
77774                                         const Linear_Expression& lb_expr,
77775                                         const Linear_Expression& ub_expr,
77776                                         Coefficient_traits::const_reference
77777                                         denominator) {
77778  // The denominator cannot be zero.
77779  if (denominator == 0) {
77780    throw_invalid_argument("bounded_affine_image(v, lb, ub, d)", "d == 0");
77781  }
77782
77783  // `var' should be one of the dimensions of the octagon.
77784  const dimension_type var_id = var.id();
77785  if (space_dim < var_id + 1) {
77786    throw_dimension_incompatible("bounded_affine_image(v, lb, ub, d)",
77787                                 var_id + 1);
77788  }
77789
77790  // The dimension of `lb_expr' and `ub_expr' should not be
77791  // greater than the dimension of `*this'.
77792  const dimension_type lb_space_dim = lb_expr.space_dimension();
77793  if (space_dim < lb_space_dim) {
77794    throw_dimension_incompatible("bounded_affine_image(v, lb, ub, d)",
77795                                 "lb", lb_expr);
77796  }
77797  const dimension_type ub_space_dim = ub_expr.space_dimension();
77798  if (space_dim < ub_space_dim) {
77799    throw_dimension_incompatible("bounded_affine_image(v, lb, ub, d)",
77800                                 "ub", ub_expr);
77801  }
77802
77803  strong_closure_assign();
77804  // The image of an empty octagon is empty too.
77805  if (marked_empty()) {
77806    return;
77807  }
77808
77809  // Number of non-zero coefficients in `lb_expr': will be set to
77810  // 0, 1, or 2, the latter value meaning any value greater than 1.
77811  dimension_type t = 0;
77812  // Variable-index of the last non-zero coefficient in `lb_expr', if any.
77813  dimension_type w_id = lb_expr.last_nonzero();
77814
77815  if (w_id != 0) {
77816    ++t;
77817    if (!lb_expr.all_zeroes(1, w_id)) {
77818      ++t;
77819    }
77820    --w_id;
77821  }
77822
77823  typedef typename OR_Matrix<N>::row_iterator row_iterator;
77824  typedef typename OR_Matrix<N>::const_row_iterator Row_iterator;
77825  typedef typename OR_Matrix<N>::const_row_reference_type Row_reference;
77826
77827  const row_iterator m_begin = matrix.row_begin();
77828  const dimension_type n_var = 2*var_id;
77829  const Coefficient& b = lb_expr.inhomogeneous_term();
77830  PPL_DIRTY_TEMP_COEFFICIENT(minus_denom);
77831  neg_assign_r(minus_denom, denominator, ROUND_NOT_NEEDED);
77832
77833  // `w' is the variable with index `w_id'.
77834  // Now we know the form of `lb_expr':
77835  // - If t == 0, then lb_expr == b, with `b' a constant;
77836  // - If t == 1, then lb_expr == a*w + b, where `w' can be `v' or another
77837  //   variable; in this second case we have to check whether `a' is
77838  //   equal to `denominator' or `-denominator', since otherwise we have
77839  //   to fall back on the general form;
77840  // - If t == 2, the `lb_expr' is of the general form.
77841
77842  if (t == 0) {
77843    // Case 1: lb_expr == b.
77844    generalized_affine_image(var,
77845                             LESS_OR_EQUAL,
77846                             ub_expr,
77847                             denominator);
77848    PPL_DIRTY_TEMP_COEFFICIENT(two_b);
77849    two_b = 2*b;
77850    // Add the constraint `var >= b/denominator'.
77851    add_octagonal_constraint(n_var, n_var + 1, two_b, minus_denom);
77852    PPL_ASSERT(OK());
77853    return;
77854  }
77855
77856  if (t == 1) {
77857    // The one and only non-zero homogeneous coefficient in `lb_expr'.
77858    const Coefficient& w_coeff = lb_expr.coefficient(Variable(w_id));
77859    if (w_coeff == denominator || w_coeff == minus_denom) {
77860      // Case 2: lb_expr = w_coeff*w + b, with w_coeff = +/- denominator.
77861      if (w_id == var_id) {
77862        // Here `var' occurs in `lb_expr'.
77863        // To ease the computation, we add an additional dimension.
77864        const Variable new_var(space_dim);
77865        add_space_dimensions_and_embed(1);
77866        // Constrain the new dimension to be equal to `lb_expr'.
77867        // Here `lb_expr' is of the form: +/- denominator * v + b.
77868        affine_image(new_var, lb_expr, denominator);
77869        // Enforce the strong closure for precision.
77870        strong_closure_assign();
77871        PPL_ASSERT(!marked_empty());
77872        // Apply the affine upper bound.
77873        generalized_affine_image(var,
77874                                 LESS_OR_EQUAL,
77875                                 ub_expr,
77876                                 denominator);
77877        // Now apply the affine lower bound, as recorded in `new_var'
77878        refine_no_check(var >= new_var);
77879        // Remove the temporarily added dimension.
77880        remove_higher_space_dimensions(space_dim-1);
77881        return;
77882      }
77883      else {
77884        // Apply the affine upper bound.
77885        generalized_affine_image(var,
77886                                 LESS_OR_EQUAL,
77887                                 ub_expr,
77888                                 denominator);
77889        // Here `w != var', so that `lb_expr' is of the form
77890        // +/-denominator * w + b.
77891        const dimension_type n_w = 2*w_id;
77892        // Add the new constraint `var - w >= b/denominator'.
77893        if (w_coeff == denominator) {
77894          if (var_id < w_id) {
77895            add_octagonal_constraint(n_w + 1, n_var + 1, b, minus_denom);
77896          }
77897          else {
77898            add_octagonal_constraint(n_var, n_w, b, minus_denom);
77899          }
77900        }
77901        else {
77902          // Add the new constraint `var + w >= b/denominator'.
77903          if (var_id < w_id) {
77904            add_octagonal_constraint(n_w, n_var + 1, b, minus_denom);
77905          }
77906          else {
77907            add_octagonal_constraint(n_var, n_w + 1, b, minus_denom);
77908          }
77909        }
77910        PPL_ASSERT(OK());
77911        return;
77912      }
77913    }
77914  }
77915
77916  // General case.
77917  // Either t == 2, so that
77918  // expr == a_1*x_1 + a_2*x_2 + ... + a_n*x_n + b, where n >= 2,
77919  // or t == 1, expr == a*w + b, but a <> +/- denominator.
77920  // We will remove all the constraints on `var' and add back
77921  // constraints providing upper and lower bounds for `var'.
77922
77923  // Compute upper approximations for `expr' and `-expr'
77924  // into `pos_sum' and `neg_sum', respectively, taking into account
77925  // the sign of `denominator'.
77926  // Note: approximating `-expr' from above and then negating the
77927  // result is the same as approximating `expr' from below.
77928  const bool is_sc = (denominator > 0);
77929  PPL_DIRTY_TEMP_COEFFICIENT(minus_b);
77930  neg_assign_r(minus_b, b, ROUND_NOT_NEEDED);
77931
77932  const Coefficient& minus_sc_b = is_sc ? minus_b : b;
77933  const Coefficient& sc_denom = is_sc ? denominator : minus_denom;
77934  const Coefficient& minus_sc_denom = is_sc ? minus_denom : denominator;
77935  // NOTE: here, for optimization purposes, `minus_expr' is only assigned
77936  // when `denominator' is negative. Do not use it unless you are sure
77937  // it has been correctly assigned.
77938  Linear_Expression minus_expr;
77939  if (!is_sc) {
77940    minus_expr = -lb_expr;
77941  }
77942  const Linear_Expression& sc_expr = is_sc ? lb_expr : minus_expr;
77943
77944  PPL_DIRTY_TEMP(N, neg_sum);
77945  // Indices of the variables that are unbounded in `this->matrix'.
77946  PPL_UNINITIALIZED(dimension_type, neg_pinf_index);
77947  // Number of unbounded variables found.
77948  dimension_type neg_pinf_count = 0;
77949
77950  // Approximate the inhomogeneous term.
77951  assign_r(neg_sum, minus_sc_b, ROUND_UP);
77952
77953  // Approximate the homogeneous part of `sc_expr'.
77954  PPL_DIRTY_TEMP(N, coeff_i);
77955  PPL_DIRTY_TEMP(N, minus_coeff_i);
77956  PPL_DIRTY_TEMP(N, half);
77957  PPL_DIRTY_TEMP_COEFFICIENT(minus_sc_i);
77958  // Note: indices above `w' can be disregarded, as they all have
77959  // a zero coefficient in `sc_expr'.
77960  for (Row_iterator m_iter = m_begin, m_iter_end = m_begin + (2 * w_id + 2);
77961       m_iter != m_iter_end; ) {
77962    const dimension_type n_i = m_iter.index();
77963    const dimension_type id = n_i/2;
77964    Row_reference m_i = *m_iter;
77965    ++m_iter;
77966    Row_reference m_ci = *m_iter;
77967    ++m_iter;
77968    const Coefficient& sc_i = sc_expr.coefficient(Variable(id));
77969    const int sign_i = sgn(sc_i);
77970    if (sign_i > 0) {
77971      assign_r(coeff_i, sc_i, ROUND_UP);
77972      // Approximating `-sc_expr'.
77973      if (neg_pinf_count <= 1) {
77974        const N& double_up_approx_minus_i = m_i[n_i + 1];
77975        if (!is_plus_infinity(double_up_approx_minus_i)) {
77976          // Let half = double_up_approx_minus_i / 2.
77977          div_2exp_assign_r(half, double_up_approx_minus_i, 1, ROUND_UP);
77978          add_mul_assign_r(neg_sum, coeff_i, half, ROUND_UP);
77979        }
77980        else {
77981          ++neg_pinf_count;
77982          neg_pinf_index = id;
77983        }
77984      }
77985    }
77986    else if (sign_i < 0) {
77987      neg_assign_r(minus_sc_i, sc_i, ROUND_NOT_NEEDED);
77988      assign_r(minus_coeff_i, minus_sc_i, ROUND_UP);
77989      // Approximating `-sc_expr'.
77990      if (neg_pinf_count <= 1) {
77991        const N& double_up_approx_i = m_ci[n_i];
77992        if (!is_plus_infinity(double_up_approx_i)) {
77993          // Let half = double_up_approx_i / 2.
77994          div_2exp_assign_r(half, double_up_approx_i, 1, ROUND_UP);
77995          add_mul_assign_r(neg_sum, minus_coeff_i, half, ROUND_UP);
77996        }
77997        else {
77998          ++neg_pinf_count;
77999          neg_pinf_index = id;
78000        }
78001      }
78002    }
78003  }
78004
78005  // Apply the affine upper bound.
78006  generalized_affine_image(var,
78007                           LESS_OR_EQUAL,
78008                           ub_expr,
78009                           denominator);
78010
78011  // Return immediately if no approximation could be computed.
78012  if (neg_pinf_count > 1) {
78013    return;
78014  }
78015
78016  // In the following, strong closure will be definitely lost.
78017  reset_strongly_closed();
78018
78019  // Exploit the lower approximation, if possible.
78020  if (neg_pinf_count <= 1) {
78021    // Compute quotient (if needed).
78022    if (sc_denom != 1) {
78023      // Before computing quotients, the denominator should be approximated
78024      // towards zero. Since `sc_denom' is known to be positive, this amounts to
78025      // rounding downwards, which is achieved as usual by rounding upwards
78026      // `minus_sc_denom' and negating again the result.
78027      PPL_DIRTY_TEMP(N, down_sc_denom);
78028      assign_r(down_sc_denom, minus_sc_denom, ROUND_UP);
78029      neg_assign_r(down_sc_denom, down_sc_denom, ROUND_UP);
78030      div_assign_r(neg_sum, neg_sum, down_sc_denom, ROUND_UP);
78031    }
78032    // Add the lower bound constraint, if meaningful.
78033    if (neg_pinf_count == 0) {
78034      // Add the constraint `v >= -neg_sum', i.e., `-v <= neg_sum'.
78035      PPL_DIRTY_TEMP(N, double_neg_sum);
78036      mul_2exp_assign_r(double_neg_sum, neg_sum, 1, ROUND_UP);
78037      matrix[n_var][n_var + 1] = double_neg_sum;
78038      // Deduce constraints of the form `-v +/- u', where `u != v'.
78039      deduce_minus_v_pm_u_bounds(var_id, w_id, sc_expr, sc_denom, neg_sum);
78040    }
78041    else
78042      // Here `neg_pinf_count == 1'.
78043      if (neg_pinf_index != var_id) {
78044        const Coefficient& npi = sc_expr.coefficient(Variable(neg_pinf_index));
78045        if (npi == sc_denom) {
78046          // Add the constraint `v - neg_pinf_index >= -neg_sum',
78047          // i.e., `neg_pinf_index - v <= neg_sum'.
78048          if (neg_pinf_index < var_id) {
78049            matrix[n_var][2*neg_pinf_index] = neg_sum;
78050          }
78051          else {
78052            matrix[2*neg_pinf_index + 1][n_var + 1] = neg_sum;
78053          }
78054        }
78055        else {
78056          if (npi == minus_sc_denom) {
78057            // Add the constraint `v + neg_pinf_index >= -neg_sum',
78058            // i.e., `-neg_pinf_index - v <= neg_sum'.
78059            if (neg_pinf_index < var_id) {
78060              matrix[n_var][2*neg_pinf_index + 1] = neg_sum;
78061            }
78062            else {
78063              matrix[2*neg_pinf_index][n_var + 1] = neg_sum;
78064            }
78065          }
78066        }
78067      }
78068  }
78069
78070  PPL_ASSERT(OK());
78071}
78072
78073
78074template <typename T>
78075void
78076Octagonal_Shape<T>
78077::generalized_affine_preimage(const Variable var,
78078                              const Relation_Symbol relsym,
78079                              const Linear_Expression& expr,
78080                              Coefficient_traits::const_reference
78081                              denominator) {
78082  // The denominator cannot be zero.
78083  if (denominator == 0) {
78084    throw_invalid_argument("generalized_affine_preimage(v, r, e, d)", "d == 0");
78085  }
78086
78087  // Dimension-compatibility checks.
78088  // The dimension of `expr' should not be greater than the dimension
78089  // of `*this'.
78090  const dimension_type expr_space_dim = expr.space_dimension();
78091  if (space_dim < expr_space_dim) {
78092    throw_dimension_incompatible("generalized_affine_preimage(v, r, e, d)",
78093                                 "e", expr);
78094  }
78095
78096  // `var' should be one of the dimensions of the octagon.
78097  const dimension_type var_id = var.id();
78098  if (space_dim < var_id + 1) {
78099    throw_dimension_incompatible("generalized_affine_preimage(v, r, e, d)",
78100                                 var_id + 1);
78101  }
78102
78103  // The relation symbol cannot be a strict relation symbol.
78104  if (relsym == LESS_THAN || relsym == GREATER_THAN) {
78105    throw_invalid_argument("generalized_affine_preimage(v, r, e, d)",
78106                           "r is a strict relation symbol");
78107  }
78108  // The relation symbol cannot be a disequality.
78109  if (relsym == NOT_EQUAL) {
78110    throw_invalid_argument("generalized_affine_preimage(v, r, e, d)",
78111                           "r is the disequality relation symbol");
78112  }
78113
78114  if (relsym == EQUAL) {
78115    // The relation symbol is "=":
78116    // this is just an affine preimage computation.
78117    affine_preimage(var, expr, denominator);
78118    return;
78119  }
78120
78121  // The image of an empty octagon is empty too.
78122  strong_closure_assign();
78123  if (marked_empty()) {
78124    return;
78125  }
78126
78127  // Check whether the preimage of this affine relation can be easily
78128  // computed as the image of its inverse relation.
78129  const Coefficient& expr_v = expr.coefficient(var);
78130  if (expr_v != 0) {
78131    const Relation_Symbol reversed_relsym = (relsym == LESS_OR_EQUAL)
78132      ? GREATER_OR_EQUAL : LESS_OR_EQUAL;
78133    const Linear_Expression inverse
78134      = expr - (expr_v + denominator)*var;
78135    PPL_DIRTY_TEMP_COEFFICIENT(inverse_denom);
78136    neg_assign(inverse_denom, expr_v);
78137    const Relation_Symbol inverse_relsym
78138      = (sgn(denominator) == sgn(inverse_denom)) ? relsym : reversed_relsym;
78139    generalized_affine_image(var, inverse_relsym, inverse, inverse_denom);
78140    return;
78141  }
78142
78143  // Here `var_coefficient == 0', so that the preimage cannot
78144  // be easily computed by inverting the affine relation.
78145  // Shrink the Octagonal_Shape by adding the constraint induced
78146  // by the affine relation.
78147  refine(var, relsym, expr, denominator);
78148
78149  // If the shrunk OS is empty, its preimage is empty too; ...
78150  if (is_empty()) {
78151    return;
78152  }
78153  // ...  otherwise, since the relation was not invertible,
78154  // we just forget all constraints on `var'.
78155  forget_all_octagonal_constraints(var_id);
78156  PPL_ASSERT(OK());
78157}
78158
78159template <typename T>
78160void
78161Octagonal_Shape<T>
78162::generalized_affine_preimage(const Linear_Expression& lhs,
78163                              const Relation_Symbol relsym,
78164                              const Linear_Expression& rhs) {
78165  // Dimension-compatibility checks.
78166  // The dimension of `lhs' should not be greater than the dimension
78167  // of `*this'.
78168  dimension_type lhs_space_dim = lhs.space_dimension();
78169  if (space_dim < lhs_space_dim) {
78170    throw_dimension_incompatible("generalized_affine_preimage(e1, r, e2)",
78171                                 "e1", lhs);
78172  }
78173
78174  // The dimension of `rhs' should not be greater than the dimension
78175  // of `*this'.
78176  const dimension_type rhs_space_dim = rhs.space_dimension();
78177  if (space_dim < rhs_space_dim) {
78178    throw_dimension_incompatible("generalized_affine_preimage(e1, r, e2)",
78179                                 "e2", rhs);
78180  }
78181
78182  // Strict relation symbols are not admitted for octagons.
78183  if (relsym == LESS_THAN || relsym == GREATER_THAN) {
78184    throw_invalid_argument("generalized_affine_preimage(e1, r, e2)",
78185                           "r is a strict relation symbol");
78186  }
78187  // The relation symbol cannot be a disequality.
78188  if (relsym == NOT_EQUAL) {
78189    throw_invalid_argument("generalized_affine_preimage(e1, r, e2)",
78190                           "r is the disequality relation symbol");
78191  }
78192  strong_closure_assign();
78193  // The image of an empty octagon is empty.
78194  if (marked_empty()) {
78195    return;
78196  }
78197  // Number of non-zero coefficients in `lhs': will be set to
78198  // 0, 1, or 2, the latter value meaning any value greater than 1.
78199  dimension_type t_lhs = 0;
78200  // Index of the last non-zero coefficient in `lhs', if any.
78201  dimension_type j_lhs = lhs.last_nonzero();
78202
78203  if (j_lhs != 0) {
78204    ++t_lhs;
78205    if (!lhs.all_zeroes(1, j_lhs)) {
78206      ++t_lhs;
78207    }
78208    --j_lhs;
78209  }
78210
78211  const Coefficient& b_lhs = lhs.inhomogeneous_term();
78212
78213  // If all variables have a zero coefficient, then `lhs' is a constant:
78214  // in this case, preimage and image happen to be the same.
78215  if (t_lhs == 0) {
78216    generalized_affine_image(lhs, relsym, rhs);
78217    return;
78218  }
78219
78220  else if (t_lhs == 1) {
78221    // Here `lhs == a_lhs * v + b_lhs'.
78222    // Independently from the form of `rhs', we can exploit the
78223    // method computing generalized affine preimages for a single variable.
78224    Variable v(j_lhs);
78225    // Compute a sign-corrected relation symbol.
78226    const Coefficient& denom = lhs.coefficient(v);
78227    Relation_Symbol new_relsym = relsym;
78228    if (denom < 0) {
78229      if (relsym == LESS_OR_EQUAL) {
78230        new_relsym = GREATER_OR_EQUAL;
78231      }
78232      else if (relsym == GREATER_OR_EQUAL) {
78233        new_relsym = LESS_OR_EQUAL;
78234      }
78235    }
78236    Linear_Expression expr = rhs - b_lhs;
78237    generalized_affine_preimage(v, new_relsym, expr, denom);
78238  }
78239
78240  else {
78241    // Here `lhs' is of the general form, having at least two variables.
78242    // Compute the set of variables occurring in `lhs'.
78243    std::vector<Variable> lhs_vars;
78244    for (Linear_Expression::const_iterator i = lhs.begin(), i_end = lhs.end();
78245          i != i_end; ++i) {
78246      lhs_vars.push_back(i.variable());
78247    }
78248
78249    const dimension_type num_common_dims = std::min(lhs_space_dim, rhs_space_dim);
78250    if (!lhs.have_a_common_variable(rhs, Variable(0), Variable(num_common_dims))) {
78251      // `lhs' and `rhs' variables are disjoint.
78252      // Constrain the left hand side expression so that it is related to
78253      // the right hand side expression as dictated by `relsym'.
78254      // TODO: if the following constraint is NOT an octagonal difference,
78255      // it will be simply ignored. Should we compute approximations for it?
78256      switch (relsym) {
78257      case LESS_OR_EQUAL:
78258        refine_no_check(lhs <= rhs);
78259        break;
78260      case EQUAL:
78261        refine_no_check(lhs == rhs);
78262        break;
78263      case GREATER_OR_EQUAL:
78264        refine_no_check(lhs >= rhs);
78265        break;
78266      default:
78267        // We already dealt with the other cases.
78268        PPL_UNREACHABLE;
78269        break;
78270      }
78271
78272      // Any image of an empty octagon is empty.
78273      if (is_empty()) {
78274        return;
78275      }
78276      // Existentially quantify all variables in the lhs.
78277      for (dimension_type i = lhs_vars.size(); i-- > 0; ) {
78278        dimension_type lhs_vars_i = lhs_vars[i].id();
78279        forget_all_octagonal_constraints(lhs_vars_i);
78280      }
78281    }
78282    else {
78283      // Some variables in `lhs' also occur in `rhs'.
78284
78285      // More accurate computation that is worth doing only if
78286      // the following TODO note is accurately dealt with.
78287
78288      // To ease the computation, we add an additional dimension.
78289      const Variable new_var(space_dim);
78290      add_space_dimensions_and_embed(1);
78291      // Constrain the new dimension to be equal to `rhs'.
78292      // NOTE: calling affine_image() instead of refine_no_check()
78293      // ensures some approximation is tried even when the constraint
78294      // is not an octagonal difference.
78295      affine_image(new_var, lhs);
78296      // Existentially quantify all variables in the lhs.
78297      // NOTE: enforce strong closure for precision.
78298      strong_closure_assign();
78299      PPL_ASSERT(!marked_empty());
78300      for (dimension_type i = lhs_vars.size(); i-- > 0; ) {
78301        dimension_type lhs_vars_i = lhs_vars[i].id();
78302        forget_all_octagonal_constraints(lhs_vars_i);
78303      }
78304      // Constrain the new dimension so that it is related to
78305      // the left hand side as dictated by `relsym'.
78306      // Note: if `rhs == v + b_rhs' or `rhs == -v + b_rhs' or `rhs == b_rhs',
78307      // one of the following constraints will be added, because they
78308      // are octagonal differences.
78309      // Else the following constraints are NOT octagonal differences,
78310      // so the method refine_no_check() will ignore them.
78311      switch (relsym) {
78312      case LESS_OR_EQUAL:
78313        refine_no_check(new_var <= rhs);
78314        break;
78315      case EQUAL:
78316        refine_no_check(new_var == rhs);
78317        break;
78318      case GREATER_OR_EQUAL:
78319        refine_no_check(new_var >= rhs);
78320        break;
78321      default:
78322        // We already dealt with the other cases.
78323        PPL_UNREACHABLE;
78324        break;
78325      }
78326      // Remove the temporarily added dimension.
78327      remove_higher_space_dimensions(space_dim-1);
78328    }
78329  }
78330  PPL_ASSERT(OK());
78331}
78332
78333template <typename T>
78334void
78335Octagonal_Shape<T>::bounded_affine_preimage(const Variable var,
78336                                            const Linear_Expression& lb_expr,
78337                                            const Linear_Expression& ub_expr,
78338                                            Coefficient_traits::const_reference
78339                                            denominator) {
78340  // The denominator cannot be zero.
78341  if (denominator == 0) {
78342    throw_invalid_argument("bounded_affine_preimage(v, lb, ub, d)", "d == 0");
78343  }
78344
78345  // `var' should be one of the dimensions of the octagon.
78346  const dimension_type var_id = var.id();
78347  if (space_dim < var_id + 1) {
78348    throw_dimension_incompatible("bounded_affine_preimage(v, lb, ub, d)",
78349                                 var_id + 1);
78350  }
78351
78352  // The dimension of `lb_expr' and `ub_expr' should not be
78353  // greater than the dimension of `*this'.
78354  const dimension_type lb_space_dim = lb_expr.space_dimension();
78355  if (space_dim < lb_space_dim) {
78356    throw_dimension_incompatible("bounded_affine_preimage(v, lb, ub, d)",
78357                                 "lb", lb_expr);
78358  }
78359  const dimension_type ub_space_dim = ub_expr.space_dimension();
78360  if (space_dim < ub_space_dim) {
78361    throw_dimension_incompatible("bounded_affine_preimage(v, lb, ub, d)",
78362                                 "ub", ub_expr);
78363  }
78364
78365  strong_closure_assign();
78366  // The image of an empty octagon is empty too.
78367  if (marked_empty()) {
78368    return;
78369  }
78370
78371  if (ub_expr.coefficient(var) == 0) {
78372    refine(var, LESS_OR_EQUAL, ub_expr, denominator);
78373    generalized_affine_preimage(var, GREATER_OR_EQUAL,
78374                                lb_expr, denominator);
78375    return;
78376  }
78377  if (lb_expr.coefficient(var) == 0) {
78378    refine(var, GREATER_OR_EQUAL, lb_expr, denominator);
78379    generalized_affine_preimage(var, LESS_OR_EQUAL,
78380                                ub_expr, denominator);
78381    return;
78382  }
78383
78384  const Coefficient& expr_v = lb_expr.coefficient(var);
78385  // Here `var' occurs in `lb_expr' and `ub_expr'.
78386  // To ease the computation, we add an additional dimension.
78387  const Variable new_var(space_dim);
78388  add_space_dimensions_and_embed(1);
78389  const Linear_Expression lb_inverse
78390    = lb_expr - (expr_v + denominator)*var;
78391  PPL_DIRTY_TEMP_COEFFICIENT(inverse_denom);
78392  neg_assign(inverse_denom, expr_v);
78393  affine_image(new_var, lb_inverse, inverse_denom);
78394  strong_closure_assign();
78395  PPL_ASSERT(!marked_empty());
78396  generalized_affine_preimage(var, LESS_OR_EQUAL,
78397                              ub_expr, denominator);
78398  if (sgn(denominator) == sgn(inverse_denom)) {
78399    refine_no_check(var >= new_var) ;
78400  }
78401  else {
78402    refine_no_check(var <= new_var);
78403  }
78404  // Remove the temporarily added dimension.
78405  remove_higher_space_dimensions(space_dim-1);
78406}
78407
78408template <typename T>
78409Constraint_System
78410Octagonal_Shape<T>::constraints() const {
78411  Constraint_System cs;
78412  cs.set_space_dimension(space_dim);
78413
78414  if (space_dim == 0) {
78415    if (marked_empty()) {
78416      cs = Constraint_System::zero_dim_empty();
78417    }
78418    return cs;
78419  }
78420
78421  if (marked_empty()) {
78422    cs.insert(Constraint::zero_dim_false());
78423    return cs;
78424  }
78425
78426  typedef typename OR_Matrix<N>::const_row_iterator row_iterator;
78427  typedef typename OR_Matrix<N>::const_row_reference_type row_reference;
78428
78429  row_iterator m_begin = matrix.row_begin();
78430  row_iterator m_end = matrix.row_end();
78431
78432  PPL_DIRTY_TEMP_COEFFICIENT(a);
78433  PPL_DIRTY_TEMP_COEFFICIENT(b);
78434
78435  // Go through all the unary constraints in `matrix'.
78436  for (row_iterator i_iter = m_begin; i_iter != m_end; ) {
78437    const dimension_type i = i_iter.index();
78438    const Variable x(i/2);
78439    const N& c_i_ii = (*i_iter)[i + 1];
78440    ++i_iter;
78441    const N& c_ii_i = (*i_iter)[i];
78442    ++i_iter;
78443    // Go through unary constraints.
78444    if (is_additive_inverse(c_i_ii, c_ii_i)) {
78445      // We have a unary equality constraint.
78446      numer_denom(c_ii_i, b, a);
78447      a *= 2;
78448      cs.insert(a*x == b);
78449    }
78450    else {
78451      // We have 0, 1 or 2 inequality constraints.
78452      if (!is_plus_infinity(c_i_ii)) {
78453        numer_denom(c_i_ii, b, a);
78454        a *= 2;
78455        cs.insert(-a*x <= b);
78456      }
78457      if (!is_plus_infinity(c_ii_i)) {
78458        numer_denom(c_ii_i, b, a);
78459        a *= 2;
78460        cs.insert(a*x <= b);
78461      }
78462    }
78463  }
78464  //  Go through all the binary constraints in `matrix'.
78465  for (row_iterator i_iter = m_begin; i_iter != m_end; ) {
78466    const dimension_type i = i_iter.index();
78467    row_reference r_i = *i_iter;
78468    ++i_iter;
78469    row_reference r_ii = *i_iter;
78470    ++i_iter;
78471    const Variable y(i/2);
78472    for (dimension_type j = 0; j < i; j += 2) {
78473      const N& c_i_j = r_i[j];
78474      const N& c_ii_jj = r_ii[j + 1];
78475      const Variable x(j/2);
78476      if (is_additive_inverse(c_ii_jj, c_i_j)) {
78477        // We have an equality constraint of the form a*x - a*y = b.
78478        numer_denom(c_i_j, b, a);
78479        cs.insert(a*x - a*y == b);
78480      }
78481      else {
78482        // We have 0, 1 or 2 inequality constraints.
78483        if (!is_plus_infinity(c_i_j)) {
78484          numer_denom(c_i_j, b, a);
78485          cs.insert(a*x - a*y <= b);
78486        }
78487        if (!is_plus_infinity(c_ii_jj)) {
78488          numer_denom(c_ii_jj, b, a);
78489          cs.insert(a*y - a*x <= b);
78490        }
78491      }
78492
78493      const N& c_ii_j = r_ii[j];
78494      const N& c_i_jj = r_i[j + 1];
78495      if (is_additive_inverse(c_i_jj, c_ii_j)) {
78496        // We have an equality constraint of the form a*x + a*y = b.
78497        numer_denom(c_ii_j, b, a);
78498        cs.insert(a*x + a*y == b);
78499      }
78500      else {
78501        // We have 0, 1 or 2 inequality constraints.
78502        if (!is_plus_infinity(c_i_jj)) {
78503          numer_denom(c_i_jj, b, a);
78504          cs.insert(-a*x - a*y <= b);
78505        }
78506        if (!is_plus_infinity(c_ii_j)) {
78507          numer_denom(c_ii_j, b, a);
78508          cs.insert(a*x + a*y <= b);
78509        }
78510      }
78511    }
78512  }
78513  return cs;
78514}
78515
78516template <typename T>
78517void
78518Octagonal_Shape<T>::expand_space_dimension(Variable var, dimension_type m) {
78519  // `var' should be one of the dimensions of the vector space.
78520  const dimension_type var_id = var.id();
78521  if (var_id + 1 > space_dim) {
78522    throw_dimension_incompatible("expand_space_dimension(v, m)", var_id + 1);
78523  }
78524
78525  // The space dimension of the resulting octagon should not
78526  // overflow the maximum allowed space dimension.
78527  if (m > max_space_dimension() - space_dim) {
78528    throw_invalid_argument("expand_dimension(v, m)",
78529                           "adding m new space dimensions exceeds "
78530                           "the maximum allowed space dimension");
78531  }
78532  // Nothing to do, if no dimensions must be added.
78533  if (m == 0) {
78534    return;
78535  }
78536  // Keep track of the dimension before adding the new ones.
78537  const dimension_type old_num_rows = matrix.num_rows();
78538
78539  // Add the required new dimensions.
78540  add_space_dimensions_and_embed(m);
78541
78542  // For each constraints involving variable `var', we add a
78543  // similar constraint with the new variable substituted for
78544  // variable `var'.
78545  typedef typename OR_Matrix<N>::row_iterator row_iterator;
78546  typedef typename OR_Matrix<N>::row_reference_type row_reference;
78547  typedef typename OR_Matrix<N>::const_row_iterator Row_iterator;
78548  typedef typename OR_Matrix<N>::const_row_reference_type Row_reference;
78549
78550  const row_iterator m_begin = matrix.row_begin();
78551  const row_iterator m_end = matrix.row_end();
78552  const dimension_type n_var = 2*var_id;
78553  Row_iterator v_iter = m_begin + n_var;
78554  Row_reference m_v = *v_iter;
78555  Row_reference m_cv = *(v_iter + 1);
78556
78557  for (row_iterator i_iter = m_begin + old_num_rows; i_iter != m_end;
78558       i_iter += 2) {
78559    row_reference m_i = *i_iter;
78560    row_reference m_ci = *(i_iter + 1);
78561    const dimension_type i = i_iter.index();
78562    const dimension_type ci = i + 1;
78563    m_i[ci] = m_v[n_var + 1];
78564    m_ci[i] = m_cv[n_var];
78565    for (dimension_type j = 0; j < n_var; ++j) {
78566      m_i[j] = m_v[j];
78567      m_ci[j] = m_cv[j];
78568    }
78569    for (dimension_type j = n_var + 2; j < old_num_rows; ++j) {
78570      row_iterator j_iter = m_begin + j;
78571      row_reference m_cj = (j % 2 != 0) ? *(j_iter-1) : *(j_iter + 1);
78572      m_i[j] = m_cj[n_var + 1];
78573      m_ci[j] = m_cj[n_var];
78574    }
78575  }
78576  // In general, adding a constraint does not preserve the strong closure
78577  // of the octagon.
78578  if (marked_strongly_closed()) {
78579    reset_strongly_closed();
78580  }
78581  PPL_ASSERT(OK());
78582}
78583
78584template <typename T>
78585void
78586Octagonal_Shape<T>::fold_space_dimensions(const Variables_Set& vars,
78587                                          Variable dest) {
78588  // `dest' should be one of the dimensions of the octagon.
78589  if (dest.space_dimension() > space_dim) {
78590    throw_dimension_incompatible("fold_space_dimensions(vs, v)", "v", dest);
78591  }
78592  // The folding of no dimensions is a no-op.
78593  if (vars.empty()) {
78594    return;
78595  }
78596  // All variables in `vars' should be dimensions of the octagon.
78597  if (vars.space_dimension() > space_dim) {
78598    throw_dimension_incompatible("fold_space_dimensions(vs, v)",
78599                                 vars.space_dimension());
78600  }
78601
78602  // Moreover, `dest.id()' should not occur in `vars'.
78603  if (vars.find(dest.id()) != vars.end()) {
78604    throw_invalid_argument("fold_space_dimensions(vs, v)",
78605                           "v should not occur in vs");
78606  }
78607
78608  // Recompute the elements of the row and the column corresponding
78609  // to variable `dest' by taking the join of their value with the
78610  // value of the corresponding elements in the row and column of the
78611  // variable `vars'.
78612  typedef typename OR_Matrix<N>::row_iterator row_iterator;
78613  typedef typename OR_Matrix<N>::row_reference_type row_reference;
78614
78615  const row_iterator m_begin = matrix.row_begin();
78616
78617  strong_closure_assign();
78618  const dimension_type n_rows = matrix.num_rows();
78619  const dimension_type n_dest = 2*dest.id();
78620  row_iterator v_iter = m_begin + n_dest;
78621  row_reference m_v = *v_iter;
78622  row_reference m_cv = *(v_iter + 1);
78623  for (Variables_Set::const_iterator i = vars.begin(),
78624         vs_end = vars.end(); i != vs_end; ++i) {
78625    const dimension_type tbf_id = *i;
78626    const dimension_type tbf_var = 2*tbf_id;
78627    row_iterator tbf_iter = m_begin + tbf_var;
78628    row_reference m_tbf = *tbf_iter;
78629    row_reference m_ctbf = *(tbf_iter + 1);
78630    max_assign(m_v[n_dest + 1], m_tbf[tbf_var + 1]);
78631    max_assign(m_cv[n_dest], m_ctbf[tbf_var]);
78632
78633    const dimension_type min_id = std::min(n_dest, tbf_var);
78634    const dimension_type max_id = std::max(n_dest, tbf_var);
78635
78636    using namespace Implementation::Octagonal_Shapes;
78637    for (dimension_type j = 0; j < min_id; ++j) {
78638      const dimension_type cj = coherent_index(j);
78639      max_assign(m_v[j], m_tbf[j]);
78640      max_assign(m_cv[j], m_ctbf[j]);
78641      max_assign(m_cv[cj], m_ctbf[cj]);
78642      max_assign(m_v[cj], m_tbf[cj]);
78643    }
78644    for (dimension_type j = min_id + 2; j < max_id; ++j) {
78645      const dimension_type cj = coherent_index(j);
78646      row_iterator j_iter = m_begin + j;
78647      row_reference m_j = *j_iter;
78648      row_reference m_cj = (j % 2 != 0) ? *(j_iter-1) : *(j_iter + 1);
78649      if (n_dest == min_id) {
78650        max_assign(m_cj[n_dest + 1], m_tbf[j]);
78651        max_assign(m_cj[n_dest], m_ctbf[j]);
78652        max_assign(m_j[n_dest], m_ctbf[cj]);
78653        max_assign(m_j[n_dest + 1], m_tbf[cj]);
78654      }
78655      else {
78656        max_assign(m_v[j], m_cj[tbf_var + 1]);
78657        max_assign(m_cv[j], m_cj[tbf_var]);
78658        max_assign(m_cv[cj], m_j[tbf_var]);
78659        max_assign(m_v[cj], m_j[tbf_var + 1]);
78660      }
78661    }
78662    for (dimension_type j = max_id + 2; j < n_rows; ++j) {
78663      row_iterator j_iter = m_begin + j;
78664      row_reference m_j = *j_iter;
78665      row_reference m_cj = (j % 2 != 0) ? *(j_iter-1) : *(j_iter + 1);
78666      max_assign(m_cj[n_dest + 1], m_cj[tbf_var + 1]);
78667      max_assign(m_cj[n_dest], m_cj[tbf_var]);
78668      max_assign(m_j[n_dest], m_j[tbf_var]);
78669      max_assign(m_j[n_dest + 1], m_j[tbf_var + 1]);
78670    }
78671  }
78672  remove_space_dimensions(vars);
78673}
78674
78675template <typename T>
78676bool
78677Octagonal_Shape<T>::upper_bound_assign_if_exact(const Octagonal_Shape& y) {
78678  // FIXME, CHECKME: what about inexact computations?
78679
78680  // Declare a const reference to *this (to avoid accidental modifications).
78681  const Octagonal_Shape& x = *this;
78682  const dimension_type x_space_dim = x.space_dimension();
78683
78684  if (x_space_dim != y.space_dimension()) {
78685    throw_dimension_incompatible("upper_bound_assign_if_exact(y)", y);
78686  }
78687
78688  // The zero-dim case is trivial.
78689  if (x_space_dim == 0) {
78690    upper_bound_assign(y);
78691    return true;
78692  }
78693  // If `x' or `y' is (known to be) empty, the upper bound is exact.
78694  if (x.marked_empty()) {
78695    *this = y;
78696    return true;
78697  }
78698  else if (y.is_empty()) {
78699    return true;
78700  }
78701  else if (x.is_empty()) {
78702    *this = y;
78703    return true;
78704  }
78705
78706  // Here both `x' and `y' are known to be non-empty.
78707  PPL_ASSERT(x.marked_strongly_closed());
78708  PPL_ASSERT(y.marked_strongly_closed());
78709  // Pre-compute the upper bound of `x' and `y'.
78710  Octagonal_Shape<T> ub(x);
78711  ub.upper_bound_assign(y);
78712
78713  // Compute redundancy information for x and y.
78714  // TODO: provide a nicer data structure for redundancy.
78715  std::vector<Bit_Row> x_non_red;
78716  x.non_redundant_matrix_entries(x_non_red);
78717  std::vector<Bit_Row> y_non_red;
78718  y.non_redundant_matrix_entries(y_non_red);
78719
78720  PPL_DIRTY_TEMP(N, lhs);
78721  PPL_DIRTY_TEMP(N, lhs_copy);
78722  PPL_DIRTY_TEMP(N, rhs);
78723  PPL_DIRTY_TEMP(N, temp_zero);
78724  assign_r(temp_zero, 0, ROUND_NOT_NEEDED);
78725
78726  typedef typename OR_Matrix<N>::const_row_iterator row_iterator;
78727  typedef typename OR_Matrix<N>::const_row_reference_type row_reference;
78728  const dimension_type n_rows = x.matrix.num_rows();
78729  const row_iterator x_m_begin = x.matrix.row_begin();
78730  const row_iterator y_m_begin = y.matrix.row_begin();
78731  const row_iterator ub_m_begin = ub.matrix.row_begin();
78732
78733  for (dimension_type i = n_rows; i-- > 0; ) {
78734    const Bit_Row& x_non_red_i = x_non_red[i];
78735    using namespace Implementation::Octagonal_Shapes;
78736    const dimension_type ci = coherent_index(i);
78737    const dimension_type row_size_i = OR_Matrix<N>::row_size(i);
78738    row_reference x_i = *(x_m_begin + i);
78739    row_reference y_i = *(y_m_begin + i);
78740    row_reference ub_i = *(ub_m_begin + i);
78741    const N& ub_i_ci = ub_i[ci];
78742    for (dimension_type j = row_size_i; j-- > 0; ) {
78743      // Check redundancy of x_i_j.
78744      if (!x_non_red_i[j]) {
78745        continue;
78746      }
78747      const N& x_i_j = x_i[j];
78748      // Check 1st condition in BHZ09 theorem.
78749      if (x_i_j >= y_i[j]) {
78750        continue;
78751      }
78752
78753      const dimension_type cj = coherent_index(j);
78754      const dimension_type row_size_cj = OR_Matrix<N>::row_size(cj);
78755      row_reference ub_cj = *(ub_m_begin + cj);
78756      const N& ub_cj_j = ub_cj[j];
78757      for (dimension_type k = 0; k < n_rows; ++k) {
78758        const Bit_Row& y_non_red_k = y_non_red[k];
78759        const dimension_type ck = coherent_index(k);
78760        const dimension_type row_size_k = OR_Matrix<N>::row_size(k);
78761        row_reference x_k = *(x_m_begin + k);
78762        row_reference y_k = *(y_m_begin + k);
78763        row_reference ub_k = *(ub_m_begin + k);
78764        const N& ub_k_ck = ub_k[ck];
78765        // Be careful: for each index h, the diagonal element m[h][h]
78766        // is (by convention) +infty in our implementation; however,
78767        // BHZ09 theorem assumes that it is equal to 0.
78768        const N& ub_k_j
78769          = (k == j)
78770          ? temp_zero
78771          : ((j < row_size_k) ? ub_k[j] : ub_cj[ck]);
78772        const N& ub_i_ck
78773          = (i == ck)
78774          ? temp_zero
78775          : ((ck < row_size_i) ? ub_i[ck] : ub_k[ci]);
78776
78777        for (dimension_type ell = row_size_k; ell-- > 0; ) {
78778          // Check redundancy of y_k_ell.
78779          if (!y_non_red_k[ell]) {
78780            continue;
78781          }
78782          const N& y_k_ell = y_k[ell];
78783          // Check 2nd condition in BHZ09 theorem.
78784          if (y_k_ell >= x_k[ell]) {
78785            continue;
78786          }
78787          const dimension_type cell = coherent_index(ell);
78788          row_reference ub_cell = *(ub_m_begin + cell);
78789          const N& ub_i_ell
78790            = (i == ell)
78791            ? temp_zero
78792            : ((ell < row_size_i) ? ub_i[ell] : ub_cell[ci]);
78793          const N& ub_cj_ell
78794            = (cj == ell)
78795            ? temp_zero
78796            : ((ell < row_size_cj) ? ub_cj[ell] : ub_cell[j]);
78797          // Check 3rd condition in BHZ09 theorem.
78798          add_assign_r(lhs, x_i_j, y_k_ell, ROUND_UP);
78799          add_assign_r(rhs, ub_i_ell, ub_k_j, ROUND_UP);
78800          if (lhs >= rhs) {
78801            continue;
78802          }
78803          // Check 4th condition in BHZ09 theorem.
78804          add_assign_r(rhs, ub_i_ck, ub_cj_ell, ROUND_UP);
78805          if (lhs >= rhs) {
78806            continue;
78807          }
78808          // Check 5th condition in BHZ09 theorem.
78809          assign_r(lhs_copy, lhs, ROUND_NOT_NEEDED);
78810          add_assign_r(lhs, lhs_copy, x_i_j, ROUND_UP);
78811          add_assign_r(rhs, ub_i_ell, ub_i_ck, ROUND_UP);
78812          add_assign_r(rhs, rhs, ub_cj_j, ROUND_UP);
78813          if (lhs >= rhs) {
78814            continue;
78815          }
78816          // Check 6th condition in BHZ09 theorem.
78817          add_assign_r(rhs, ub_k_j, ub_cj_ell, ROUND_UP);
78818          add_assign_r(rhs, rhs, ub_i_ci, ROUND_UP);
78819          if (lhs >= rhs) {
78820            continue;
78821          }
78822          // Check 7th condition of BHZ09 theorem.
78823          add_assign_r(lhs, lhs_copy, y_k_ell, ROUND_UP);
78824          add_assign_r(rhs, ub_i_ell, ub_cj_ell, ROUND_UP);
78825          add_assign_r(rhs, rhs, ub_k_ck, ROUND_UP);
78826          if (lhs >= rhs) {
78827            continue;
78828          }
78829          // Check 8th (last) condition in BHZ09 theorem.
78830          add_assign_r(rhs, ub_k_j, ub_i_ck, ROUND_UP);
78831          add_assign_r(rhs, rhs, ub_cell[ell], ROUND_UP);
78832          if (lhs < rhs) {
78833            // All 8 conditions are satisfied:
78834            // upper bound is not exact.
78835            return false;
78836          }
78837        }
78838      }
78839    }
78840  }
78841
78842  // The upper bound of x and y is indeed exact.
78843  m_swap(ub);
78844  PPL_ASSERT(OK());
78845  return true;
78846}
78847
78848template <typename T>
78849bool
78850Octagonal_Shape<T>
78851::integer_upper_bound_assign_if_exact(const Octagonal_Shape& y) {
78852  PPL_COMPILE_TIME_CHECK(std::numeric_limits<T>::is_integer,
78853                         "Octagonal_Shape<T>::"
78854                         "integer_upper_bound_assign_if_exact(y):"
78855                         " T in not an integer datatype.");
78856  // Declare a const reference to *this (to avoid accidental modifications).
78857  const Octagonal_Shape& x = *this;
78858  const dimension_type x_space_dim = x.space_dimension();
78859
78860  if (x_space_dim != y.space_dimension()) {
78861    throw_dimension_incompatible("integer_upper_bound_assign_if_exact(y)", y);
78862  }
78863  // The zero-dim case is trivial.
78864  if (x_space_dim == 0) {
78865    upper_bound_assign(y);
78866    return true;
78867  }
78868
78869  // If `x' or `y' is (known to) contain no integral point,
78870  // then the integer upper bound can be computed exactly by tight closure.
78871  if (x.marked_empty()) {
78872    *this = y;
78873    tight_closure_assign();
78874    return true;
78875  }
78876  else if (y.marked_empty()) {
78877    tight_closure_assign();
78878    return true;
78879  }
78880  else if (x.is_empty() || x.tight_coherence_would_make_empty()) {
78881    *this = y;
78882    tight_closure_assign();
78883    return true;
78884  }
78885  else if (y.is_empty() || y.tight_coherence_would_make_empty()) {
78886    tight_closure_assign();
78887    return true;
78888  }
78889
78890  // Here both `x' and `y' are known to be non-empty (and Z-consistent).
78891  PPL_ASSERT(x.marked_strongly_closed());
78892  PPL_ASSERT(y.marked_strongly_closed());
78893  // Pre-compute the integer upper bound of `x' and `y':
78894  // have to take copies, since tight closure might modify the rational shape.
78895  Octagonal_Shape<T> tx(x);
78896  tx.tight_closure_assign();
78897  Octagonal_Shape<T> ty(y);
78898  ty.tight_closure_assign();
78899  Octagonal_Shape<T> ub(tx);
78900  ub.upper_bound_assign(ty);
78901
78902  // Compute redundancy information for tx and ty.
78903  // TODO: provide a nicer data structure for redundancy.
78904  // NOTE: there is no need to identify all redundancies, since this is
78905  // an optimization; hence we reuse the strong-reduction helper methods.
78906  std::vector<Bit_Row> tx_non_red;
78907  tx.non_redundant_matrix_entries(tx_non_red);
78908  std::vector<Bit_Row> ty_non_red;
78909  ty.non_redundant_matrix_entries(ty_non_red);
78910
78911  PPL_DIRTY_TEMP(N, lhs_i_j);
78912  PPL_DIRTY_TEMP(N, lhs_k_ell);
78913  PPL_DIRTY_TEMP(N, lhs);
78914  PPL_DIRTY_TEMP(N, lhs_copy);
78915  PPL_DIRTY_TEMP(N, rhs);
78916  PPL_DIRTY_TEMP(N, temp_zero);
78917  assign_r(temp_zero, 0, ROUND_NOT_NEEDED);
78918  PPL_DIRTY_TEMP(N, temp_one);
78919  assign_r(temp_one, 1, ROUND_NOT_NEEDED);
78920  PPL_DIRTY_TEMP(N, temp_two);
78921  assign_r(temp_two, 2, ROUND_NOT_NEEDED);
78922
78923  typedef typename OR_Matrix<N>::const_row_iterator row_iterator;
78924  typedef typename OR_Matrix<N>::const_row_reference_type row_reference;
78925  const dimension_type n_rows = tx.matrix.num_rows();
78926  const row_iterator tx_m_begin = tx.matrix.row_begin();
78927  const row_iterator ty_m_begin = ty.matrix.row_begin();
78928  const row_iterator ub_m_begin = ub.matrix.row_begin();
78929
78930  for (dimension_type i = n_rows; i-- > 0; ) {
78931    const Bit_Row& tx_non_red_i = tx_non_red[i];
78932    using namespace Implementation::Octagonal_Shapes;
78933    const dimension_type ci = coherent_index(i);
78934    const dimension_type row_size_i = OR_Matrix<N>::row_size(i);
78935    row_reference tx_i = *(tx_m_begin + i);
78936    row_reference ty_i = *(ty_m_begin + i);
78937    row_reference ub_i = *(ub_m_begin + i);
78938    const N& ub_i_ci = ub_i[ci];
78939    for (dimension_type j = row_size_i; j-- > 0; ) {
78940      // Check redundancy of tx_i_j.
78941      if (!tx_non_red_i[j]) {
78942        continue;
78943      }
78944      const N& tx_i_j = tx_i[j];
78945      const dimension_type cj = coherent_index(j);
78946      const N& eps_i_j = (i == cj) ? temp_two : temp_one;
78947      // Check condition 1a in BHZ09 Theorem 6.8.
78948      add_assign_r(lhs_i_j, tx_i_j, eps_i_j, ROUND_NOT_NEEDED);
78949      if (lhs_i_j > ty_i[j]) {
78950        continue;
78951      }
78952      const dimension_type row_size_cj = OR_Matrix<N>::row_size(cj);
78953      row_reference ub_cj = *(ub_m_begin + cj);
78954      const N& ub_cj_j = ub_cj[j];
78955      for (dimension_type k = 0; k < n_rows; ++k) {
78956        const Bit_Row& ty_non_red_k = ty_non_red[k];
78957        const dimension_type ck = coherent_index(k);
78958        const dimension_type row_size_k = OR_Matrix<N>::row_size(k);
78959        row_reference tx_k = *(tx_m_begin + k);
78960        row_reference ty_k = *(ty_m_begin + k);
78961        row_reference ub_k = *(ub_m_begin + k);
78962        const N& ub_k_ck = ub_k[ck];
78963        // Be careful: for each index h, the diagonal element m[h][h]
78964        // is (by convention) +infty in our implementation; however,
78965        // BHZ09 theorem assumes that it is equal to 0.
78966        const N& ub_k_j
78967          = (k == j)
78968          ? temp_zero
78969          : ((j < row_size_k) ? ub_k[j] : ub_cj[ck]);
78970        const N& ub_i_ck
78971          = (i == ck)
78972          ? temp_zero
78973          : ((ck < row_size_i) ? ub_i[ck] : ub_k[ci]);
78974
78975        for (dimension_type ell = row_size_k; ell-- > 0; ) {
78976          // Check redundancy of y_k_ell.
78977          if (!ty_non_red_k[ell]) {
78978            continue;
78979          }
78980          const N& ty_k_ell = ty_k[ell];
78981          const dimension_type cell = coherent_index(ell);
78982          const N& eps_k_ell = (k == cell) ? temp_two : temp_one;
78983          // Check condition 1b in BHZ09 Theorem 6.8.
78984          add_assign_r(lhs_k_ell, ty_k_ell, eps_k_ell, ROUND_NOT_NEEDED);
78985          if (lhs_k_ell > tx_k[ell]) {
78986            continue;
78987          }
78988          row_reference ub_cell = *(ub_m_begin + cell);
78989          const N& ub_i_ell
78990            = (i == ell)
78991            ? temp_zero
78992            : ((ell < row_size_i) ? ub_i[ell] : ub_cell[ci]);
78993          const N& ub_cj_ell
78994            = (cj == ell)
78995            ? temp_zero
78996            : ((ell < row_size_cj) ? ub_cj[ell] : ub_cell[j]);
78997          // Check condition 2a in BHZ09 Theorem 6.8.
78998          add_assign_r(lhs, lhs_i_j, lhs_k_ell, ROUND_NOT_NEEDED);
78999          add_assign_r(rhs, ub_i_ell, ub_k_j, ROUND_NOT_NEEDED);
79000          if (lhs > rhs) {
79001            continue;
79002          }
79003          // Check condition 2b in BHZ09 Theorem 6.8.
79004          add_assign_r(rhs, ub_i_ck, ub_cj_ell, ROUND_NOT_NEEDED);
79005          if (lhs > rhs) {
79006            continue;
79007          }
79008          // Check condition 3a in BHZ09 Theorem 6.8.
79009          assign_r(lhs_copy, lhs, ROUND_NOT_NEEDED);
79010          add_assign_r(lhs, lhs, lhs_i_j, ROUND_NOT_NEEDED);
79011          add_assign_r(rhs, ub_i_ell, ub_i_ck, ROUND_NOT_NEEDED);
79012          add_assign_r(rhs, rhs, ub_cj_j, ROUND_NOT_NEEDED);
79013          if (lhs > rhs) {
79014            continue;
79015          }
79016          // Check condition 3b in BHZ09 Theorem 6.8.
79017          add_assign_r(rhs, ub_k_j, ub_cj_ell, ROUND_NOT_NEEDED);
79018          add_assign_r(rhs, rhs, ub_i_ci, ROUND_NOT_NEEDED);
79019          if (lhs > rhs) {
79020            continue;
79021          }
79022          // Check condition 4a in BHZ09 Theorem 6.8.
79023          add_assign_r(lhs, lhs_copy, lhs_k_ell, ROUND_NOT_NEEDED);
79024          add_assign_r(rhs, ub_i_ell, ub_cj_ell, ROUND_NOT_NEEDED);
79025          add_assign_r(rhs, rhs, ub_k_ck, ROUND_NOT_NEEDED);
79026          if (lhs > rhs) {
79027            continue;
79028          }
79029          // Check condition 4b in BHZ09 Theorem 6.8.
79030          add_assign_r(rhs, ub_k_j, ub_i_ck, ROUND_NOT_NEEDED);
79031          add_assign_r(rhs, rhs, ub_cell[ell], ROUND_NOT_NEEDED);
79032          if (lhs <= rhs) {
79033            // All 8 conditions are satisfied:
79034            // integer upper bound is not exact.
79035            return false;
79036          }
79037        }
79038      }
79039    }
79040  }
79041
79042  // The upper bound of x and y is indeed exact.
79043  m_swap(ub);
79044  PPL_ASSERT(OK());
79045  return true;
79046}
79047
79048template <typename T>
79049void
79050Octagonal_Shape<T>::drop_some_non_integer_points(Complexity_Class) {
79051  if (std::numeric_limits<T>::is_integer) {
79052    return;
79053  }
79054
79055  strong_closure_assign();
79056  if (space_dim == 0 || marked_empty()) {
79057    return;
79058  }
79059
79060  for (typename OR_Matrix<N>::element_iterator i = matrix.element_begin(),
79061         i_end = matrix.element_end(); i != i_end; ++i) {
79062    drop_some_non_integer_points_helper(*i);
79063  }
79064
79065  // Unary constraints should have an even integer boundary.
79066  PPL_DIRTY_TEMP(N, temp_one);
79067  assign_r(temp_one, 1, ROUND_NOT_NEEDED);
79068  for (dimension_type i = 0; i < 2*space_dim; i += 2) {
79069    const dimension_type ci = i + 1;
79070    N& mat_i_ci = matrix[i][ci];
79071    if (!is_plus_infinity(mat_i_ci) && !is_even(mat_i_ci)) {
79072      sub_assign_r(mat_i_ci, mat_i_ci, temp_one, ROUND_UP);
79073      reset_strongly_closed();
79074    }
79075    N& mat_ci_i = matrix[ci][i];
79076    if (!is_plus_infinity(mat_ci_i) && !is_even(mat_ci_i)) {
79077      sub_assign_r(mat_ci_i, mat_ci_i, temp_one, ROUND_UP);
79078      reset_strongly_closed();
79079    }
79080  }
79081
79082  PPL_ASSERT(OK());
79083}
79084
79085template <typename T>
79086void
79087Octagonal_Shape<T>
79088::drop_some_non_integer_points(const Variables_Set& vars,
79089                               Complexity_Class) {
79090  // Dimension-compatibility check.
79091  const dimension_type min_space_dim = vars.space_dimension();
79092  if (space_dimension() < min_space_dim) {
79093    throw_dimension_incompatible("drop_some_non_integer_points(vs, cmpl)",
79094                                 min_space_dim);
79095  }
79096
79097  if (std::numeric_limits<T>::is_integer || min_space_dim == 0) {
79098    return;
79099  }
79100
79101  strong_closure_assign();
79102  if (marked_empty()) {
79103    return;
79104  }
79105
79106  PPL_DIRTY_TEMP(N, temp_one);
79107  assign_r(temp_one, 1, ROUND_NOT_NEEDED);
79108
79109  const Variables_Set::const_iterator v_begin = vars.begin();
79110  const Variables_Set::const_iterator v_end = vars.end();
79111  PPL_ASSERT(v_begin != v_end);
79112  typedef typename OR_Matrix<N>::row_reference_type row_reference;
79113  for (Variables_Set::const_iterator v_i = v_begin; v_i != v_end; ++v_i) {
79114    const dimension_type i = 2 * (*v_i);
79115    const dimension_type ci = i + 1;
79116    row_reference m_i = matrix[i];
79117    row_reference m_ci = matrix[ci];
79118
79119    // Unary constraints: should be even integers.
79120    N& m_i_ci = m_i[ci];
79121    if (!is_plus_infinity(m_i_ci)) {
79122      drop_some_non_integer_points_helper(m_i_ci);
79123      if (!is_even(m_i_ci)) {
79124        sub_assign_r(m_i_ci, m_i_ci, temp_one, ROUND_UP);
79125        reset_strongly_closed();
79126      }
79127    }
79128    N& m_ci_i = m_ci[i];
79129    if (!is_plus_infinity(m_ci_i)) {
79130      drop_some_non_integer_points_helper(m_ci_i);
79131      if (!is_even(m_ci_i)) {
79132        sub_assign_r(m_ci_i, m_ci_i, temp_one, ROUND_UP);
79133        reset_strongly_closed();
79134      }
79135    }
79136
79137    // Binary constraints (note: only consider j < i).
79138    for (Variables_Set::const_iterator v_j = v_begin; v_j != v_i; ++v_j) {
79139      const dimension_type j = 2 * (*v_j);
79140      const dimension_type cj = j + 1;
79141      drop_some_non_integer_points_helper(m_i[j]);
79142      drop_some_non_integer_points_helper(m_i[cj]);
79143      drop_some_non_integer_points_helper(m_ci[j]);
79144      drop_some_non_integer_points_helper(m_ci[cj]);
79145    }
79146  }
79147  PPL_ASSERT(OK());
79148}
79149
79150template <typename T>
79151template <typename U>
79152void
79153Octagonal_Shape<T>
79154::export_interval_constraints(U& dest) const {
79155  if (space_dim > dest.space_dimension()) {
79156    throw std::invalid_argument(
79157               "Octagonal_Shape<T>::export_interval_constraints");
79158  }
79159
79160  strong_closure_assign();
79161
79162  if (marked_empty()) {
79163    dest.set_empty();
79164    return;
79165  }
79166
79167  PPL_DIRTY_TEMP(N, lb);
79168  PPL_DIRTY_TEMP(N, ub);
79169  for (dimension_type i = space_dim; i-- > 0; ) {
79170    const dimension_type ii = 2*i;
79171    const dimension_type cii = ii + 1;
79172
79173    // Set the upper bound.
79174    const N& twice_ub = matrix[cii][ii];
79175    if (!is_plus_infinity(twice_ub)) {
79176      assign_r(ub, twice_ub, ROUND_NOT_NEEDED);
79177      div_2exp_assign_r(ub, ub, 1, ROUND_UP);
79178      // FIXME: passing a raw value may not be general enough.
79179      if (!dest.restrict_upper(i, ub.raw_value())) {
79180        return;
79181      }
79182    }
79183
79184    // Set the lower bound.
79185    const N& twice_lb = matrix[ii][cii];
79186    if (!is_plus_infinity(twice_lb)) {
79187      assign_r(lb, twice_lb, ROUND_NOT_NEEDED);
79188      neg_assign_r(lb, lb, ROUND_NOT_NEEDED);
79189      div_2exp_assign_r(lb, lb, 1, ROUND_DOWN);
79190      // FIXME: passing a raw value may not be general enough.
79191      if (!dest.restrict_lower(i, lb.raw_value())) {
79192        return;
79193      }
79194    }
79195  }
79196
79197}
79198
79199/*! \relates Parma_Polyhedra_Library::Octagonal_Shape */
79200template <typename T>
79201std::ostream&
79202IO_Operators::operator<<(std::ostream& s, const Octagonal_Shape<T>& oct) {
79203  // Handle special cases first.
79204  if (oct.marked_empty()) {
79205    s << "false";
79206    return s;
79207  }
79208  if (oct.is_universe()) {
79209    s << "true";
79210    return s;
79211  }
79212
79213  typedef typename Octagonal_Shape<T>::coefficient_type N;
79214  typedef typename OR_Matrix<N>::const_row_iterator row_iterator;
79215  typedef typename OR_Matrix<N>::const_row_reference_type row_reference;
79216
79217  // Records whether or not we still have to print the first constraint.
79218  bool first = true;
79219
79220  row_iterator m_begin = oct.matrix.row_begin();
79221  row_iterator m_end = oct.matrix.row_end();
79222
79223  // Temporaries.
79224  PPL_DIRTY_TEMP(N, negation);
79225  PPL_DIRTY_TEMP(N, half);
79226  // Go through all the unary constraints.
79227  // (Note: loop iterator is incremented in the loop body.)
79228  for (row_iterator i_iter = m_begin; i_iter != m_end; ) {
79229    const dimension_type i = i_iter.index();
79230    const Variable v_i(i/2);
79231    const N& c_i_ii = (*i_iter)[i + 1];
79232    ++i_iter;
79233    const N& c_ii_i = (*i_iter)[i];
79234    ++i_iter;
79235    // Check whether or not it is an equality constraint.
79236    if (is_additive_inverse(c_i_ii, c_ii_i)) {
79237      // It is an equality.
79238      PPL_ASSERT(!is_plus_infinity(c_i_ii) && !is_plus_infinity(c_ii_i));
79239      if (first) {
79240        first = false;
79241      }
79242      else {
79243        s << ", ";
79244      }
79245      // If the value bound can NOT be divided by 2 exactly,
79246      // then we output the constraint `2*v_i = bound'.
79247      if (div_2exp_assign_r(half, c_ii_i, 1,
79248                            ROUND_UP | ROUND_STRICT_RELATION)
79249          == V_EQ) {
79250        s << v_i << " = " << half;
79251      }
79252      else {
79253        s << "2*" << v_i << " = " << c_ii_i;
79254      }
79255    }
79256    else {
79257      // We will print unary non-strict inequalities, if any.
79258      if (!is_plus_infinity(c_i_ii)) {
79259        if (first) {
79260          first = false;
79261        }
79262        else {
79263          s << ", ";
79264        }
79265        neg_assign_r(negation, c_i_ii, ROUND_NOT_NEEDED);
79266        // If the value bound can NOT be divided by 2 exactly,
79267        // then we output the constraint `2*v_i >= negation'.
79268        if (div_2exp_assign_r(half, negation, 1,
79269                              ROUND_UP | ROUND_STRICT_RELATION)
79270            == V_EQ) {
79271          s << v_i << " >= " << half;
79272        }
79273        else {
79274          s << "2*" << v_i << " >= " << negation;
79275        }
79276      }
79277      if (!is_plus_infinity(c_ii_i)) {
79278        if (first) {
79279          first = false;
79280        }
79281        else {
79282          s << ", ";
79283        }
79284        // If the value bound can NOT be divided by 2 exactly,
79285        // then we output the constraint `2*v_i <= bound'.
79286        if (div_2exp_assign_r(half, c_ii_i, 1,
79287                              ROUND_UP | ROUND_STRICT_RELATION)
79288            == V_EQ) {
79289          s << v_i << " <= " << half;
79290        }
79291        else {
79292          s << "2*" << v_i << " <= " << c_ii_i;
79293        }
79294      }
79295    }
79296  }
79297
79298  // Go through all the binary constraints.
79299  // (Note: loop iterator is incremented in the loop body.)
79300  for (row_iterator i_iter = m_begin; i_iter != m_end; ) {
79301    const dimension_type i = i_iter.index();
79302    const Variable v_i(i/2);
79303    row_reference r_i = *i_iter;
79304    ++i_iter;
79305    row_reference r_ii = *i_iter;
79306    ++i_iter;
79307
79308    for (dimension_type j = 0; j < i; j += 2) {
79309      const Variable v_j(j/2);
79310      // Print binary differences.
79311      const N& c_ii_jj = r_ii[j + 1];
79312      const N& c_i_j = r_i[j];
79313      // Check whether or not it is an equality constraint.
79314      if (is_additive_inverse(c_ii_jj, c_i_j)) {
79315        // It is an equality.
79316        PPL_ASSERT(!is_plus_infinity(c_i_j) && !is_plus_infinity(c_ii_jj));
79317        if (first) {
79318          first = false;
79319        }
79320        else {
79321          s << ", ";
79322        }
79323        if (sgn(c_i_j) >= 0) {
79324          s << v_j << " - " << v_i << " = " << c_i_j;
79325        }
79326        else {
79327          s << v_i << " - " << v_j << " = " << c_ii_jj;
79328        }
79329      }
79330      else {
79331        // We will print non-strict inequalities, if any.
79332        if (!is_plus_infinity(c_i_j)) {
79333          if (first) {
79334            first = false;
79335          }
79336          else {
79337            s << ", ";
79338          }
79339          if (sgn(c_i_j) >= 0) {
79340            s << v_j << " - " << v_i << " <= " << c_i_j;
79341          }
79342          else {
79343            neg_assign_r(negation, c_i_j, ROUND_DOWN);
79344            s << v_i << " - " << v_j << " >= " << negation;
79345          }
79346        }
79347        if (!is_plus_infinity(c_ii_jj)) {
79348          if (first) {
79349            first = false;
79350          }
79351          else {
79352            s << ", ";
79353          }
79354          if (sgn(c_ii_jj) >= 0) {
79355            s << v_i << " - " << v_j << " <= " << c_ii_jj;
79356          }
79357          else {
79358            neg_assign_r(negation, c_ii_jj, ROUND_DOWN);
79359            s << v_j << " - " << v_i << " >= " << negation;
79360          }
79361        }
79362      }
79363      // Print binary sums.
79364      const N& c_i_jj = r_i[j + 1];
79365      const N& c_ii_j = r_ii[j];
79366      // Check whether or not it is an equality constraint.
79367      if (is_additive_inverse(c_i_jj, c_ii_j)) {
79368        // It is an equality.
79369        PPL_ASSERT(!is_plus_infinity(c_i_jj) && !is_plus_infinity(c_ii_j));
79370        if (first) {
79371          first = false;
79372        }
79373        else {
79374          s << ", ";
79375        }
79376        s << v_j << " + " << v_i << " = " << c_ii_j;
79377      }
79378      else {
79379        // We will print non-strict inequalities, if any.
79380        if (!is_plus_infinity(c_i_jj)) {
79381          if (first) {
79382            first = false;
79383          }
79384          else {
79385            s << ", ";
79386          }
79387          neg_assign_r(negation, c_i_jj, ROUND_DOWN);
79388          s << v_j << " + " << v_i << " >= " << negation;
79389        }
79390        if (!is_plus_infinity(c_ii_j)) {
79391          if (first) {
79392            first = false;
79393          }
79394          else {
79395            s << ", ";
79396          }
79397          s << v_j << " + " << v_i << " <= " << c_ii_j;
79398        }
79399      }
79400    }
79401  }
79402  return s;
79403}
79404
79405template <typename T>
79406void
79407Octagonal_Shape<T>::ascii_dump(std::ostream& s) const {
79408  s << "space_dim "
79409    << space_dim
79410    << "\n";
79411  status.ascii_dump(s);
79412  s << "\n";
79413  matrix.ascii_dump(s);
79414}
79415
79416PPL_OUTPUT_TEMPLATE_DEFINITIONS(T, Octagonal_Shape<T>)
79417
79418template <typename T>
79419bool
79420Octagonal_Shape<T>::ascii_load(std::istream& s) {
79421  std::string str;
79422
79423  if (!(s >> str) || str != "space_dim") {
79424    return false;
79425  }
79426
79427  if (!(s >> space_dim)) {
79428    return false;
79429  }
79430
79431  if (!status.ascii_load(s)) {
79432    return false;
79433  }
79434
79435  if (!matrix.ascii_load(s)) {
79436    return false;
79437  }
79438
79439  PPL_ASSERT(OK());
79440  return true;
79441}
79442
79443template <typename T>
79444memory_size_type
79445Octagonal_Shape<T>::external_memory_in_bytes() const {
79446  return matrix.external_memory_in_bytes();
79447}
79448
79449template <typename T>
79450bool
79451Octagonal_Shape<T>::OK() const {
79452  // Check whether the matrix is well-formed.
79453  if (!matrix.OK()) {
79454    return false;
79455  }
79456
79457  // Check whether the status information is legal.
79458  if (!status.OK()) {
79459    return false;
79460  }
79461
79462  // All empty octagons are OK.
79463  if (marked_empty()) {
79464    return true;
79465  }
79466
79467  // 0-dim universe octagon is OK.
79468  if (space_dim == 0) {
79469    return true;
79470  }
79471
79472  // MINUS_INFINITY cannot occur at all.
79473  for (typename OR_Matrix<N>::const_row_iterator i = matrix.row_begin(),
79474         matrix_row_end = matrix.row_end(); i != matrix_row_end; ++i) {
79475    typename OR_Matrix<N>::const_row_reference_type x_i = *i;
79476    for (dimension_type j = i.row_size(); j-- > 0; ) {
79477      if (is_minus_infinity(x_i[j])) {
79478#ifndef NDEBUG
79479        using namespace Parma_Polyhedra_Library::IO_Operators;
79480        std::cerr << "Octagonal_Shape::"
79481                  << "matrix[" << i.index() << "][" << j << "] = "
79482                  << x_i[j] << "!"
79483                  << std::endl;
79484#endif
79485        return false;
79486      }
79487    }
79488  }
79489
79490  // On the main diagonal only PLUS_INFINITY can occur.
79491  for (typename OR_Matrix<N>::const_row_iterator i = matrix.row_begin(),
79492         m_end = matrix.row_end(); i != m_end; ++i) {
79493    typename OR_Matrix<N>::const_row_reference_type r = *i;
79494    const N& m_i_i = r[i.index()];
79495    if (!is_plus_infinity(m_i_i)) {
79496#ifndef NDEBUG
79497      const dimension_type j = i.index();
79498      using namespace Parma_Polyhedra_Library::IO_Operators;
79499      std::cerr << "Octagonal_Shape::matrix[" << j << "][" << j << "] = "
79500                << m_i_i << "!  (+inf was expected.)\n";
79501#endif
79502      return false;
79503    }
79504  }
79505
79506  // The following tests might result in false alarms when using floating
79507  // point coefficients: they are only meaningful if the coefficient type
79508  // base is exact (since otherwise strong closure is approximated).
79509  if (std::numeric_limits<coefficient_type_base>::is_exact) {
79510
79511    // Check whether the closure information is legal.
79512    if (marked_strongly_closed()) {
79513      Octagonal_Shape x = *this;
79514      x.reset_strongly_closed();
79515      x.strong_closure_assign();
79516      if (x.matrix != matrix) {
79517#ifndef NDEBUG
79518        std::cerr << "Octagonal_Shape is marked as strongly closed "
79519                  << "but it is not!\n";
79520#endif
79521        return false;
79522      }
79523    }
79524
79525    // A closed octagon must be strong-coherent.
79526    if (marked_strongly_closed()) {
79527      if (!is_strong_coherent()) {
79528#ifndef NDEBUG
79529        std::cerr << "Octagonal_Shape is not strong-coherent!\n";
79530#endif
79531        return false;
79532      }
79533    }
79534  }
79535
79536  // All checks passed.
79537  return true;
79538}
79539
79540
79541template <typename T>
79542void
79543Octagonal_Shape<T>
79544::throw_dimension_incompatible(const char* method,
79545                               const Octagonal_Shape& y) const {
79546  std::ostringstream s;
79547  s << "PPL::Octagonal_Shape::" << method << ":\n"
79548    << "this->space_dimension() == " << space_dimension()
79549    << ", y->space_dimension() == " << y.space_dimension() << ".";
79550  throw std::invalid_argument(s.str());
79551}
79552
79553template <typename T>
79554void
79555Octagonal_Shape<T>
79556::throw_dimension_incompatible(const char* method,
79557                               dimension_type required_dim) const {
79558  std::ostringstream s;
79559  s << "PPL::Octagonal_Shape::" << method << ":\n"
79560    << "this->space_dimension() == " << space_dimension()
79561    << ", required dimension == " << required_dim << ".";
79562  throw std::invalid_argument(s.str());
79563}
79564
79565template <typename T>
79566void
79567Octagonal_Shape<T>::throw_dimension_incompatible(const char* method,
79568                                                 const Constraint& c) const {
79569  std::ostringstream s;
79570  s << "PPL::Octagonal_Shape::" << method << ":\n"
79571    << "this->space_dimension() == " << space_dimension()
79572    << ", c->space_dimension == " << c.space_dimension() << ".";
79573  throw std::invalid_argument(s.str());
79574}
79575
79576template <typename T>
79577void
79578Octagonal_Shape<T>::throw_dimension_incompatible(const char* method,
79579                                                 const Congruence& cg) const {
79580  std::ostringstream s;
79581  s << "PPL::Octagonal_Shape::" << method << ":\n"
79582    << "this->space_dimension() == " << space_dimension()
79583    << ", cg->space_dimension == " << cg.space_dimension() << ".";
79584  throw std::invalid_argument(s.str());
79585}
79586
79587template <typename T>
79588void
79589Octagonal_Shape<T>::throw_dimension_incompatible(const char* method,
79590                                                 const Generator& g) const {
79591  std::ostringstream s;
79592  s << "PPL::Octagonal_Shape::" << method << ":\n"
79593    << "this->space_dimension() == " << space_dimension()
79594    << ", g->space_dimension == " << g.space_dimension() << ".";
79595  throw std::invalid_argument(s.str());
79596}
79597
79598template <typename T>
79599void
79600Octagonal_Shape<T>::throw_constraint_incompatible(const char* method) {
79601  std::ostringstream s;
79602  s << "PPL::Octagonal_Shape::" << method << ":\n"
79603    << "the constraint is incompatible.";
79604  throw std::invalid_argument(s.str());
79605}
79606
79607template <typename T>
79608void
79609Octagonal_Shape<T>::throw_expression_too_complex(const char* method,
79610                                                 const Linear_Expression& le) {
79611  using namespace IO_Operators;
79612  std::ostringstream s;
79613  s << "PPL::Octagonal_Shape::" << method << ":\n"
79614    << le << " is too complex.";
79615  throw std::invalid_argument(s.str());
79616}
79617
79618template <typename T>
79619void
79620Octagonal_Shape<T>
79621::throw_dimension_incompatible(const char* method,
79622                               const char* le_name,
79623                               const Linear_Expression& le) const {
79624  std::ostringstream s;
79625  s << "PPL::Octagonal_Shape::" << method << ":\n"
79626    << "this->space_dimension() == " << space_dimension()
79627    << ", " << le_name << "->space_dimension() == "
79628    << le.space_dimension() << ".";
79629  throw std::invalid_argument(s.str());
79630}
79631
79632template <typename T>
79633template <typename C>
79634void
79635Octagonal_Shape<T>
79636::throw_dimension_incompatible(const char* method,
79637                               const char* lf_name,
79638                               const Linear_Form<C>& lf) const {
79639  std::ostringstream s;
79640  s << "PPL::Octagonal_Shape::" << method << ":\n"
79641    << "this->space_dimension() == " << space_dimension()
79642    << ", " << lf_name << "->space_dimension() == "
79643    << lf.space_dimension() << ".";
79644  throw std::invalid_argument(s.str());
79645}
79646
79647template <typename T>
79648void
79649Octagonal_Shape<T>::throw_invalid_argument(const char* method,
79650                                           const char* reason) {
79651  std::ostringstream s;
79652  s << "PPL::Octagonal_Shape::" << method << ":\n"
79653    << reason << ".";
79654  throw std::invalid_argument(s.str());
79655}
79656
79657} // namespace Parma_Polyhedra_Library
79658
79659/* Automatically generated from PPL source file ../src/Octagonal_Shape_defs.hh line 2329. */
79660
79661/* Automatically generated from PPL source file ../src/BD_Shape_inlines.hh line 38. */
79662#include <vector>
79663#include <iostream>
79664#include <algorithm>
79665
79666namespace Parma_Polyhedra_Library {
79667
79668template <typename T>
79669inline dimension_type
79670BD_Shape<T>::max_space_dimension() {
79671  // One dimension is reserved to have a value of type dimension_type
79672  // that does not represent a legal dimension.
79673  return std::min(DB_Matrix<N>::max_num_rows() - 1,
79674                  DB_Matrix<N>::max_num_columns() - 1);
79675}
79676
79677template <typename T>
79678inline bool
79679BD_Shape<T>::marked_zero_dim_univ() const {
79680  return status.test_zero_dim_univ();
79681}
79682
79683template <typename T>
79684inline bool
79685BD_Shape<T>::marked_empty() const {
79686  return status.test_empty();
79687}
79688
79689template <typename T>
79690inline bool
79691BD_Shape<T>::marked_shortest_path_closed() const {
79692  return status.test_shortest_path_closed();
79693}
79694
79695template <typename T>
79696inline bool
79697BD_Shape<T>::marked_shortest_path_reduced() const {
79698  return status.test_shortest_path_reduced();
79699}
79700
79701template <typename T>
79702inline void
79703BD_Shape<T>::set_zero_dim_univ() {
79704  status.set_zero_dim_univ();
79705}
79706
79707template <typename T>
79708inline void
79709BD_Shape<T>::set_empty() {
79710  status.set_empty();
79711}
79712
79713template <typename T>
79714inline void
79715BD_Shape<T>::set_shortest_path_closed() {
79716  status.set_shortest_path_closed();
79717}
79718
79719template <typename T>
79720inline void
79721BD_Shape<T>::set_shortest_path_reduced() {
79722  status.set_shortest_path_reduced();
79723}
79724
79725template <typename T>
79726inline void
79727BD_Shape<T>::reset_shortest_path_closed() {
79728  status.reset_shortest_path_closed();
79729}
79730
79731template <typename T>
79732inline void
79733BD_Shape<T>::reset_shortest_path_reduced() {
79734  status.reset_shortest_path_reduced();
79735}
79736
79737template <typename T>
79738inline
79739BD_Shape<T>::BD_Shape(const dimension_type num_dimensions,
79740                      const Degenerate_Element kind)
79741  : dbm(num_dimensions + 1), status(), redundancy_dbm() {
79742  if (kind == EMPTY) {
79743    set_empty();
79744  }
79745  else {
79746    if (num_dimensions > 0) {
79747      // A (non zero-dim) universe BDS is closed.
79748      set_shortest_path_closed();
79749    }
79750  }
79751  PPL_ASSERT(OK());
79752}
79753
79754template <typename T>
79755inline
79756BD_Shape<T>::BD_Shape(const BD_Shape& y, Complexity_Class)
79757  : dbm(y.dbm), status(y.status), redundancy_dbm() {
79758  if (y.marked_shortest_path_reduced()) {
79759    redundancy_dbm = y.redundancy_dbm;
79760  }
79761}
79762
79763template <typename T>
79764template <typename U>
79765inline
79766BD_Shape<T>::BD_Shape(const BD_Shape<U>& y, Complexity_Class)
79767  // For maximum precision, enforce shortest-path closure
79768  // before copying the DB matrix.
79769  : dbm((y.shortest_path_closure_assign(), y.dbm)),
79770    status(),
79771    redundancy_dbm() {
79772  // TODO: handle flags properly, possibly taking special cases into account.
79773  if (y.marked_empty()) {
79774    set_empty();
79775  }
79776  else if (y.marked_zero_dim_univ()) {
79777    set_zero_dim_univ();
79778  }
79779}
79780
79781template <typename T>
79782inline Congruence_System
79783BD_Shape<T>::congruences() const {
79784  return minimized_congruences();
79785}
79786
79787template <typename T>
79788inline void
79789BD_Shape<T>::add_constraints(const Constraint_System& cs) {
79790  for (Constraint_System::const_iterator i = cs.begin(),
79791         cs_end = cs.end(); i != cs_end; ++i) {
79792    add_constraint(*i);
79793  }
79794}
79795
79796template <typename T>
79797inline void
79798BD_Shape<T>::add_recycled_constraints(Constraint_System& cs) {
79799  add_constraints(cs);
79800}
79801
79802template <typename T>
79803inline void
79804BD_Shape<T>::add_congruences(const Congruence_System& cgs) {
79805  for (Congruence_System::const_iterator i = cgs.begin(),
79806         cgs_end = cgs.end(); i != cgs_end; ++i) {
79807    add_congruence(*i);
79808  }
79809}
79810
79811template <typename T>
79812inline void
79813BD_Shape<T>::add_recycled_congruences(Congruence_System& cgs) {
79814  add_congruences(cgs);
79815}
79816
79817template <typename T>
79818inline void
79819BD_Shape<T>::refine_with_constraint(const Constraint& c) {
79820  const dimension_type c_space_dim = c.space_dimension();
79821  // Dimension-compatibility check.
79822  if (c_space_dim > space_dimension()) {
79823    throw_dimension_incompatible("refine_with_constraint(c)", c);
79824  }
79825
79826  if (!marked_empty()) {
79827    refine_no_check(c);
79828  }
79829}
79830
79831template <typename T>
79832inline void
79833BD_Shape<T>::refine_with_constraints(const Constraint_System& cs) {
79834  // Dimension-compatibility check.
79835  if (cs.space_dimension() > space_dimension()) {
79836    throw_invalid_argument("refine_with_constraints(cs)",
79837                           "cs and *this are space-dimension incompatible");
79838  }
79839
79840  for (Constraint_System::const_iterator i = cs.begin(),
79841         cs_end = cs.end(); !marked_empty() && i != cs_end; ++i) {
79842    refine_no_check(*i);
79843  }
79844}
79845
79846template <typename T>
79847inline void
79848BD_Shape<T>::refine_with_congruence(const Congruence& cg) {
79849  const dimension_type cg_space_dim = cg.space_dimension();
79850  // Dimension-compatibility check.
79851  if (cg_space_dim > space_dimension()) {
79852    throw_dimension_incompatible("refine_with_congruence(cg)", cg);
79853  }
79854
79855  if (!marked_empty()) {
79856    refine_no_check(cg);
79857  }
79858}
79859
79860template <typename T>
79861void
79862BD_Shape<T>::refine_with_congruences(const Congruence_System& cgs) {
79863  // Dimension-compatibility check.
79864  if (cgs.space_dimension() > space_dimension()) {
79865    throw_invalid_argument("refine_with_congruences(cgs)",
79866                           "cgs and *this are space-dimension incompatible");
79867  }
79868
79869  for (Congruence_System::const_iterator i = cgs.begin(),
79870         cgs_end = cgs.end(); !marked_empty() && i != cgs_end; ++i) {
79871    refine_no_check(*i);
79872  }
79873}
79874
79875template <typename T>
79876inline void
79877BD_Shape<T>::refine_no_check(const Congruence& cg) {
79878  PPL_ASSERT(!marked_empty());
79879  PPL_ASSERT(cg.space_dimension() <= space_dimension());
79880
79881  if (cg.is_proper_congruence()) {
79882    if (cg.is_inconsistent()) {
79883      set_empty();
79884    }
79885    // Other proper congruences are just ignored.
79886    return;
79887  }
79888
79889  PPL_ASSERT(cg.is_equality());
79890  Constraint c(cg);
79891  refine_no_check(c);
79892}
79893
79894template <typename T>
79895inline bool
79896BD_Shape<T>::can_recycle_constraint_systems() {
79897  return false;
79898}
79899
79900
79901template <typename T>
79902inline bool
79903BD_Shape<T>::can_recycle_congruence_systems() {
79904  return false;
79905}
79906
79907template <typename T>
79908inline
79909BD_Shape<T>::BD_Shape(const Constraint_System& cs)
79910  : dbm(cs.space_dimension() + 1), status(), redundancy_dbm() {
79911  if (cs.space_dimension() > 0) {
79912    // A (non zero-dim) universe BDS is shortest-path closed.
79913    set_shortest_path_closed();
79914  }
79915  add_constraints(cs);
79916}
79917
79918template <typename T>
79919template <typename Interval>
79920inline
79921BD_Shape<T>::BD_Shape(const Box<Interval>& box,
79922                      Complexity_Class)
79923  : dbm(box.space_dimension() + 1), status(), redundancy_dbm() {
79924  // Check emptiness for maximum precision.
79925  if (box.is_empty()) {
79926    set_empty();
79927  }
79928  else if (box.space_dimension() > 0) {
79929    // A (non zero-dim) universe BDS is shortest-path closed.
79930    set_shortest_path_closed();
79931    refine_with_constraints(box.constraints());
79932  }
79933}
79934
79935template <typename T>
79936inline
79937BD_Shape<T>::BD_Shape(const Grid& grid,
79938                      Complexity_Class)
79939  : dbm(grid.space_dimension() + 1), status(), redundancy_dbm() {
79940  if (grid.space_dimension() > 0) {
79941    // A (non zero-dim) universe BDS is shortest-path closed.
79942    set_shortest_path_closed();
79943  }
79944  // Taking minimized congruences ensures maximum precision.
79945  refine_with_congruences(grid.minimized_congruences());
79946}
79947
79948template <typename T>
79949template <typename U>
79950inline
79951BD_Shape<T>::BD_Shape(const Octagonal_Shape<U>& os,
79952                      Complexity_Class)
79953  : dbm(os.space_dimension() + 1), status(), redundancy_dbm() {
79954  // Check for emptiness for maximum precision.
79955  if (os.is_empty()) {
79956    set_empty();
79957  }
79958  else if (os.space_dimension() > 0) {
79959    // A (non zero-dim) universe BDS is shortest-path closed.
79960    set_shortest_path_closed();
79961    refine_with_constraints(os.constraints());
79962    // After refining, shortest-path closure is possibly lost
79963    // (even when `os' was strongly closed: recall that U
79964    // is possibly different from T).
79965  }
79966}
79967
79968template <typename T>
79969inline BD_Shape<T>&
79970BD_Shape<T>::operator=(const BD_Shape& y) {
79971  dbm = y.dbm;
79972  status = y.status;
79973  if (y.marked_shortest_path_reduced()) {
79974    redundancy_dbm = y.redundancy_dbm;
79975  }
79976  return *this;
79977}
79978
79979template <typename T>
79980inline
79981BD_Shape<T>::~BD_Shape() {
79982}
79983
79984template <typename T>
79985inline void
79986BD_Shape<T>::m_swap(BD_Shape& y) {
79987  using std::swap;
79988  swap(dbm, y.dbm);
79989  swap(status, y.status);
79990  swap(redundancy_dbm, y.redundancy_dbm);
79991}
79992
79993template <typename T>
79994inline dimension_type
79995BD_Shape<T>::space_dimension() const {
79996  return dbm.num_rows() - 1;
79997}
79998
79999template <typename T>
80000inline bool
80001BD_Shape<T>::is_empty() const {
80002  shortest_path_closure_assign();
80003  return marked_empty();
80004}
80005
80006template <typename T>
80007inline bool
80008BD_Shape<T>::bounds_from_above(const Linear_Expression& expr) const {
80009  return bounds(expr, true);
80010}
80011
80012template <typename T>
80013inline bool
80014BD_Shape<T>::bounds_from_below(const Linear_Expression& expr) const {
80015  return bounds(expr, false);
80016}
80017
80018template <typename T>
80019inline bool
80020BD_Shape<T>::maximize(const Linear_Expression& expr,
80021                      Coefficient& sup_n, Coefficient& sup_d,
80022                      bool& maximum) const {
80023  return max_min(expr, true, sup_n, sup_d, maximum);
80024}
80025
80026template <typename T>
80027inline bool
80028BD_Shape<T>::maximize(const Linear_Expression& expr,
80029                      Coefficient& sup_n, Coefficient& sup_d, bool& maximum,
80030                      Generator& g) const {
80031  return max_min(expr, true, sup_n, sup_d, maximum, g);
80032}
80033
80034template <typename T>
80035inline bool
80036BD_Shape<T>::minimize(const Linear_Expression& expr,
80037                      Coefficient& inf_n, Coefficient& inf_d,
80038                      bool& minimum) const {
80039  return max_min(expr, false, inf_n, inf_d, minimum);
80040}
80041
80042template <typename T>
80043inline bool
80044BD_Shape<T>::minimize(const Linear_Expression& expr,
80045                      Coefficient& inf_n, Coefficient& inf_d, bool& minimum,
80046                      Generator& g) const {
80047  return max_min(expr, false, inf_n, inf_d, minimum, g);
80048}
80049
80050template <typename T>
80051inline bool
80052BD_Shape<T>::is_topologically_closed() const {
80053  return true;
80054}
80055
80056template <typename T>
80057inline bool
80058BD_Shape<T>::is_discrete() const {
80059  return affine_dimension() == 0;
80060}
80061
80062template <typename T>
80063inline void
80064BD_Shape<T>::topological_closure_assign() {
80065}
80066
80067/*! \relates BD_Shape */
80068template <typename T>
80069inline bool
80070operator==(const BD_Shape<T>& x, const BD_Shape<T>& y) {
80071  const dimension_type x_space_dim = x.space_dimension();
80072  // Dimension-compatibility check.
80073  if (x_space_dim != y.space_dimension()) {
80074    return false;
80075  }
80076
80077  // Zero-dim BDSs are equal if and only if they are both empty or universe.
80078  if (x_space_dim == 0) {
80079    if (x.marked_empty()) {
80080      return y.marked_empty();
80081    }
80082    else {
80083      return !y.marked_empty();
80084    }
80085  }
80086
80087  // The exact equivalence test requires shortest-path closure.
80088  x.shortest_path_closure_assign();
80089  y.shortest_path_closure_assign();
80090
80091  // If one of two BDSs is empty, then they are equal
80092  // if and only if the other BDS is empty too.
80093  if (x.marked_empty()) {
80094    return y.marked_empty();
80095  }
80096  if (y.marked_empty()) {
80097    return false;
80098  }
80099  // Check for syntactic equivalence of the two (shortest-path closed)
80100  // systems of bounded differences.
80101  return x.dbm == y.dbm;
80102}
80103
80104/*! \relates BD_Shape */
80105template <typename T>
80106inline bool
80107operator!=(const BD_Shape<T>& x, const BD_Shape<T>& y) {
80108  return !(x == y);
80109}
80110
80111/*! \relates BD_Shape */
80112template <typename Temp, typename To, typename T>
80113inline bool
80114rectilinear_distance_assign(Checked_Number<To, Extended_Number_Policy>& r,
80115                            const BD_Shape<T>& x,
80116                            const BD_Shape<T>& y,
80117                            const Rounding_Dir dir,
80118                            Temp& tmp0,
80119                            Temp& tmp1,
80120                            Temp& tmp2) {
80121  const dimension_type x_space_dim = x.space_dimension();
80122  // Dimension-compatibility check.
80123  if (x_space_dim != y.space_dimension()) {
80124    return false;
80125  }
80126
80127  // Zero-dim BDSs are equal if and only if they are both empty or universe.
80128  if (x_space_dim == 0) {
80129    if (x.marked_empty() == y.marked_empty()) {
80130      assign_r(r, 0, ROUND_NOT_NEEDED);
80131    }
80132    else {
80133      assign_r(r, PLUS_INFINITY, ROUND_NOT_NEEDED);
80134    }
80135    return true;
80136  }
80137
80138  // The distance computation requires shortest-path closure.
80139  x.shortest_path_closure_assign();
80140  y.shortest_path_closure_assign();
80141
80142  // If one of two BDSs is empty, then they are equal if and only if
80143  // the other BDS is empty too.
80144  if (x.marked_empty() ||  y.marked_empty()) {
80145    if (x.marked_empty() == y.marked_empty()) {
80146      assign_r(r, 0, ROUND_NOT_NEEDED);
80147    }
80148    else {
80149      assign_r(r, PLUS_INFINITY, ROUND_NOT_NEEDED);
80150    }
80151    return true;
80152  }
80153
80154  return rectilinear_distance_assign(r, x.dbm, y.dbm, dir, tmp0, tmp1, tmp2);
80155}
80156
80157/*! \relates BD_Shape */
80158template <typename Temp, typename To, typename T>
80159inline bool
80160rectilinear_distance_assign(Checked_Number<To, Extended_Number_Policy>& r,
80161                            const BD_Shape<T>& x,
80162                            const BD_Shape<T>& y,
80163                            const Rounding_Dir dir) {
80164  typedef Checked_Number<Temp, Extended_Number_Policy> Checked_Temp;
80165  PPL_DIRTY_TEMP(Checked_Temp, tmp0);
80166  PPL_DIRTY_TEMP(Checked_Temp, tmp1);
80167  PPL_DIRTY_TEMP(Checked_Temp, tmp2);
80168  return rectilinear_distance_assign(r, x, y, dir, tmp0, tmp1, tmp2);
80169}
80170
80171/*! \relates BD_Shape */
80172template <typename To, typename T>
80173inline bool
80174rectilinear_distance_assign(Checked_Number<To, Extended_Number_Policy>& r,
80175                            const BD_Shape<T>& x,
80176                            const BD_Shape<T>& y,
80177                            const Rounding_Dir dir) {
80178  return rectilinear_distance_assign<To, To, T>(r, x, y, dir);
80179}
80180
80181/*! \relates BD_Shape */
80182template <typename Temp, typename To, typename T>
80183inline bool
80184euclidean_distance_assign(Checked_Number<To, Extended_Number_Policy>& r,
80185                          const BD_Shape<T>& x,
80186                          const BD_Shape<T>& y,
80187                          const Rounding_Dir dir,
80188                          Temp& tmp0,
80189                          Temp& tmp1,
80190                          Temp& tmp2) {
80191  const dimension_type x_space_dim = x.space_dimension();
80192  // Dimension-compatibility check.
80193  if (x_space_dim != y.space_dimension()) {
80194    return false;
80195  }
80196
80197  // Zero-dim BDSs are equal if and only if they are both empty or universe.
80198  if (x_space_dim == 0) {
80199    if (x.marked_empty() == y.marked_empty()) {
80200      assign_r(r, 0, ROUND_NOT_NEEDED);
80201    }
80202    else {
80203      assign_r(r, PLUS_INFINITY, ROUND_NOT_NEEDED);
80204    }
80205    return true;
80206  }
80207
80208  // The distance computation requires shortest-path closure.
80209  x.shortest_path_closure_assign();
80210  y.shortest_path_closure_assign();
80211
80212  // If one of two BDSs is empty, then they are equal if and only if
80213  // the other BDS is empty too.
80214  if (x.marked_empty() ||  y.marked_empty()) {
80215    if (x.marked_empty() == y.marked_empty()) {
80216      assign_r(r, 0, ROUND_NOT_NEEDED);
80217    }
80218    else {
80219      assign_r(r, PLUS_INFINITY, ROUND_NOT_NEEDED);
80220    }
80221    return true;
80222  }
80223
80224  return euclidean_distance_assign(r, x.dbm, y.dbm, dir, tmp0, tmp1, tmp2);
80225}
80226
80227/*! \relates BD_Shape */
80228template <typename Temp, typename To, typename T>
80229inline bool
80230euclidean_distance_assign(Checked_Number<To, Extended_Number_Policy>& r,
80231                          const BD_Shape<T>& x,
80232                          const BD_Shape<T>& y,
80233                          const Rounding_Dir dir) {
80234  typedef Checked_Number<Temp, Extended_Number_Policy> Checked_Temp;
80235  PPL_DIRTY_TEMP(Checked_Temp, tmp0);
80236  PPL_DIRTY_TEMP(Checked_Temp, tmp1);
80237  PPL_DIRTY_TEMP(Checked_Temp, tmp2);
80238  return euclidean_distance_assign(r, x, y, dir, tmp0, tmp1, tmp2);
80239}
80240
80241/*! \relates BD_Shape */
80242template <typename To, typename T>
80243inline bool
80244euclidean_distance_assign(Checked_Number<To, Extended_Number_Policy>& r,
80245                          const BD_Shape<T>& x,
80246                          const BD_Shape<T>& y,
80247                          const Rounding_Dir dir) {
80248  return euclidean_distance_assign<To, To, T>(r, x, y, dir);
80249}
80250
80251/*! \relates BD_Shape */
80252template <typename Temp, typename To, typename T>
80253inline bool
80254l_infinity_distance_assign(Checked_Number<To, Extended_Number_Policy>& r,
80255                           const BD_Shape<T>& x,
80256                           const BD_Shape<T>& y,
80257                           const Rounding_Dir dir,
80258                           Temp& tmp0,
80259                           Temp& tmp1,
80260                           Temp& tmp2) {
80261  const dimension_type x_space_dim = x.space_dimension();
80262  // Dimension-compatibility check.
80263  if (x_space_dim != y.space_dimension()) {
80264    return false;
80265  }
80266  // Zero-dim BDSs are equal if and only if they are both empty or universe.
80267  if (x_space_dim == 0) {
80268    if (x.marked_empty() == y.marked_empty()) {
80269      assign_r(r, 0, ROUND_NOT_NEEDED);
80270    }
80271    else {
80272      assign_r(r, PLUS_INFINITY, ROUND_NOT_NEEDED);
80273    }
80274    return true;
80275  }
80276
80277  // The distance computation requires shortest-path closure.
80278  x.shortest_path_closure_assign();
80279  y.shortest_path_closure_assign();
80280
80281  // If one of two BDSs is empty, then they are equal if and only if
80282  // the other BDS is empty too.
80283  if (x.marked_empty() ||  y.marked_empty()) {
80284    if (x.marked_empty() == y.marked_empty()) {
80285      assign_r(r, 0, ROUND_NOT_NEEDED);
80286    }
80287    else {
80288      assign_r(r, PLUS_INFINITY, ROUND_NOT_NEEDED);
80289    }
80290    return true;
80291  }
80292
80293  return l_infinity_distance_assign(r, x.dbm, y.dbm, dir, tmp0, tmp1, tmp2);
80294}
80295
80296/*! \relates BD_Shape */
80297template <typename Temp, typename To, typename T>
80298inline bool
80299l_infinity_distance_assign(Checked_Number<To, Extended_Number_Policy>& r,
80300                           const BD_Shape<T>& x,
80301                           const BD_Shape<T>& y,
80302                           const Rounding_Dir dir) {
80303  typedef Checked_Number<Temp, Extended_Number_Policy> Checked_Temp;
80304  PPL_DIRTY_TEMP(Checked_Temp, tmp0);
80305  PPL_DIRTY_TEMP(Checked_Temp, tmp1);
80306  PPL_DIRTY_TEMP(Checked_Temp, tmp2);
80307  return l_infinity_distance_assign(r, x, y, dir, tmp0, tmp1, tmp2);
80308}
80309
80310/*! \relates BD_Shape */
80311template <typename To, typename T>
80312inline bool
80313l_infinity_distance_assign(Checked_Number<To, Extended_Number_Policy>& r,
80314                           const BD_Shape<T>& x,
80315                           const BD_Shape<T>& y,
80316                           const Rounding_Dir dir) {
80317  return l_infinity_distance_assign<To, To, T>(r, x, y, dir);
80318}
80319
80320template <typename T>
80321inline void
80322BD_Shape<T>::add_dbm_constraint(const dimension_type i,
80323                                const dimension_type j,
80324                                const N& k) {
80325  // Private method: the caller has to ensure the following.
80326  PPL_ASSERT(i <= space_dimension() && j <= space_dimension() && i != j);
80327  N& dbm_ij = dbm[i][j];
80328  if (dbm_ij > k) {
80329    dbm_ij = k;
80330    if (marked_shortest_path_closed()) {
80331      reset_shortest_path_closed();
80332    }
80333  }
80334}
80335
80336template <typename T>
80337inline void
80338BD_Shape<T>::add_dbm_constraint(const dimension_type i,
80339                                const dimension_type j,
80340                                Coefficient_traits::const_reference numer,
80341                                Coefficient_traits::const_reference denom) {
80342  // Private method: the caller has to ensure the following.
80343  PPL_ASSERT(i <= space_dimension() && j <= space_dimension() && i != j);
80344  PPL_ASSERT(denom != 0);
80345  PPL_DIRTY_TEMP(N, k);
80346  div_round_up(k, numer, denom);
80347  add_dbm_constraint(i, j, k);
80348}
80349
80350template <typename T>
80351inline void
80352BD_Shape<T>::time_elapse_assign(const BD_Shape& y) {
80353  // Dimension-compatibility check.
80354  if (space_dimension() != y.space_dimension()) {
80355    throw_dimension_incompatible("time_elapse_assign(y)", y);
80356  }
80357  // Compute time-elapse on polyhedra.
80358  // TODO: provide a direct implementation.
80359  C_Polyhedron ph_x(constraints());
80360  C_Polyhedron ph_y(y.constraints());
80361  ph_x.time_elapse_assign(ph_y);
80362  BD_Shape<T> x(ph_x);
80363  m_swap(x);
80364  PPL_ASSERT(OK());
80365}
80366
80367template <typename T>
80368inline bool
80369BD_Shape<T>::strictly_contains(const BD_Shape& y) const {
80370  const BD_Shape<T>& x = *this;
80371  return x.contains(y) && !y.contains(x);
80372}
80373
80374template <typename T>
80375inline bool
80376BD_Shape<T>::upper_bound_assign_if_exact(const BD_Shape& y) {
80377  if (space_dimension() != y.space_dimension()) {
80378    throw_dimension_incompatible("upper_bound_assign_if_exact(y)", y);
80379  }
80380#if 0
80381  return BFT00_upper_bound_assign_if_exact(y);
80382#else
80383  const bool integer_upper_bound = false;
80384  return BHZ09_upper_bound_assign_if_exact<integer_upper_bound>(y);
80385#endif
80386}
80387
80388template <typename T>
80389inline bool
80390BD_Shape<T>::integer_upper_bound_assign_if_exact(const BD_Shape& y) {
80391  PPL_COMPILE_TIME_CHECK(std::numeric_limits<T>::is_integer,
80392                         "BD_Shape<T>::integer_upper_bound_assign_if_exact(y):"
80393                         " T in not an integer datatype.");
80394  if (space_dimension() != y.space_dimension()) {
80395    throw_dimension_incompatible("integer_upper_bound_assign_if_exact(y)", y);
80396  }
80397  const bool integer_upper_bound = true;
80398  return BHZ09_upper_bound_assign_if_exact<integer_upper_bound>(y);
80399}
80400
80401template <typename T>
80402inline void
80403BD_Shape<T>
80404::remove_higher_space_dimensions(const dimension_type new_dimension) {
80405  // Dimension-compatibility check: the variable having
80406  // maximum index is the one occurring last in the set.
80407  const dimension_type space_dim = space_dimension();
80408  if (new_dimension > space_dim) {
80409    throw_dimension_incompatible("remove_higher_space_dimensions(nd)",
80410                                 new_dimension);
80411  }
80412
80413  // The removal of no dimensions from any BDS is a no-op.
80414  // Note that this case also captures the only legal removal of
80415  // dimensions from a zero-dim space BDS.
80416  if (new_dimension == space_dim) {
80417    PPL_ASSERT(OK());
80418    return;
80419  }
80420
80421  // Shortest-path closure is necessary as in remove_space_dimensions().
80422  shortest_path_closure_assign();
80423  dbm.resize_no_copy(new_dimension + 1);
80424
80425  // Shortest-path closure is maintained.
80426  // TODO: see whether or not reduction can be (efficiently!) maintained too.
80427  if (marked_shortest_path_reduced()) {
80428    reset_shortest_path_reduced();
80429  }
80430
80431  // If we removed _all_ dimensions from a non-empty BDS,
80432  // the zero-dim universe BDS has been obtained.
80433  if (new_dimension == 0 && !marked_empty()) {
80434    set_zero_dim_univ();
80435  }
80436  PPL_ASSERT(OK());
80437}
80438
80439template <typename T>
80440void
80441BD_Shape<T>::wrap_assign(const Variables_Set& vars,
80442                         Bounded_Integer_Type_Width w,
80443                         Bounded_Integer_Type_Representation r,
80444                         Bounded_Integer_Type_Overflow o,
80445                         const Constraint_System* cs_p,
80446                         unsigned complexity_threshold,
80447                         bool wrap_individually) {
80448  Implementation::wrap_assign(*this,
80449                              vars, w, r, o, cs_p,
80450                              complexity_threshold, wrap_individually,
80451                              "BD_Shape");
80452}
80453
80454template <typename T>
80455inline void
80456BD_Shape<T>::CC76_extrapolation_assign(const BD_Shape& y, unsigned* tp) {
80457  static N stop_points[] = {
80458    N(-2, ROUND_UP),
80459    N(-1, ROUND_UP),
80460    N( 0, ROUND_UP),
80461    N( 1, ROUND_UP),
80462    N( 2, ROUND_UP)
80463  };
80464  CC76_extrapolation_assign(y,
80465                            stop_points,
80466                            stop_points
80467                            + sizeof(stop_points)/sizeof(stop_points[0]),
80468                            tp);
80469}
80470
80471template <typename T>
80472inline void
80473BD_Shape<T>::H79_widening_assign(const BD_Shape& y, unsigned* tp) {
80474  // Compute the H79 widening on polyhedra.
80475  // TODO: provide a direct implementation.
80476  C_Polyhedron ph_x(constraints());
80477  C_Polyhedron ph_y(y.constraints());
80478  ph_x.H79_widening_assign(ph_y, tp);
80479  BD_Shape x(ph_x);
80480  m_swap(x);
80481  PPL_ASSERT(OK());
80482}
80483
80484template <typename T>
80485inline void
80486BD_Shape<T>::widening_assign(const BD_Shape& y, unsigned* tp) {
80487  H79_widening_assign(y, tp);
80488}
80489
80490template <typename T>
80491inline void
80492BD_Shape<T>::limited_H79_extrapolation_assign(const BD_Shape& y,
80493                                              const Constraint_System& cs,
80494                                              unsigned* tp) {
80495  // Compute the limited H79 extrapolation on polyhedra.
80496  // TODO: provide a direct implementation.
80497  C_Polyhedron ph_x(constraints());
80498  C_Polyhedron ph_y(y.constraints());
80499  ph_x.limited_H79_extrapolation_assign(ph_y, cs, tp);
80500  BD_Shape x(ph_x);
80501  m_swap(x);
80502  PPL_ASSERT(OK());
80503}
80504
80505template <typename T>
80506inline memory_size_type
80507BD_Shape<T>::total_memory_in_bytes() const {
80508  return sizeof(*this) + external_memory_in_bytes();
80509}
80510
80511template <typename T>
80512inline int32_t
80513BD_Shape<T>::hash_code() const {
80514  return hash_code_from_dimension(space_dimension());
80515}
80516
80517template <typename T>
80518template <typename Interval_Info>
80519inline void
80520BD_Shape<T>::generalized_refine_with_linear_form_inequality(
80521             const Linear_Form<Interval<T, Interval_Info> >& left,
80522             const Linear_Form<Interval<T, Interval_Info> >& right,
80523             const Relation_Symbol relsym) {
80524  switch (relsym) {
80525  case EQUAL:
80526    // TODO: see if we can handle this case more efficiently.
80527    refine_with_linear_form_inequality(left, right);
80528    refine_with_linear_form_inequality(right, left);
80529    break;
80530  case LESS_THAN:
80531  case LESS_OR_EQUAL:
80532    refine_with_linear_form_inequality(left, right);
80533    break;
80534  case GREATER_THAN:
80535  case GREATER_OR_EQUAL:
80536    refine_with_linear_form_inequality(right, left);
80537    break;
80538  case NOT_EQUAL:
80539    break;
80540  default:
80541    PPL_UNREACHABLE;
80542  }
80543}
80544
80545template <typename T>
80546template <typename Interval_Info>
80547inline void
80548BD_Shape<T>
80549::refine_fp_interval_abstract_store(Box<Interval<T, Interval_Info> >&
80550                                    store) const {
80551
80552  // Check that T is a floating point type.
80553  PPL_COMPILE_TIME_CHECK(!std::numeric_limits<T>::is_exact,
80554                     "BD_Shape<T>::refine_fp_interval_abstract_store:"
80555                     " T not a floating point type.");
80556
80557  typedef Interval<T, Interval_Info> FP_Interval_Type;
80558  store.intersection_assign(Box<FP_Interval_Type>(*this));
80559}
80560
80561template <typename T>
80562inline void
80563BD_Shape<T>::drop_some_non_integer_points_helper(N& elem) {
80564  if (!is_integer(elem)) {
80565    Result r = floor_assign_r(elem, elem, ROUND_DOWN);
80566    PPL_USED(r);
80567    PPL_ASSERT(r == V_EQ);
80568    reset_shortest_path_closed();
80569  }
80570}
80571
80572/*! \relates BD_Shape */
80573template <typename T>
80574inline void
80575swap(BD_Shape<T>& x, BD_Shape<T>& y) {
80576  x.m_swap(y);
80577}
80578
80579} // namespace Parma_Polyhedra_Library
80580
80581/* Automatically generated from PPL source file ../src/BD_Shape_templates.hh line 1. */
80582/* BD_Shape class implementation: non-inline template functions.
80583*/
80584
80585
80586/* Automatically generated from PPL source file ../src/BD_Shape_templates.hh line 40. */
80587#include <vector>
80588#include <deque>
80589#include <iostream>
80590#include <sstream>
80591#include <stdexcept>
80592#include <algorithm>
80593
80594namespace Parma_Polyhedra_Library {
80595
80596template <typename T>
80597BD_Shape<T>::BD_Shape(const Congruence_System& cgs)
80598  : dbm(cgs.space_dimension() + 1),
80599    status(),
80600    redundancy_dbm() {
80601  add_congruences(cgs);
80602}
80603
80604template <typename T>
80605BD_Shape<T>::BD_Shape(const Generator_System& gs)
80606  : dbm(gs.space_dimension() + 1), status(), redundancy_dbm() {
80607  const Generator_System::const_iterator gs_begin = gs.begin();
80608  const Generator_System::const_iterator gs_end = gs.end();
80609  if (gs_begin == gs_end) {
80610    // An empty generator system defines the empty BD shape.
80611    set_empty();
80612    return;
80613  }
80614
80615  const dimension_type space_dim = space_dimension();
80616  DB_Row<N>& dbm_0 = dbm[0];
80617  PPL_DIRTY_TEMP(N, tmp);
80618
80619  bool dbm_initialized = false;
80620  bool point_seen = false;
80621  // Going through all the points and closure points.
80622  for (Generator_System::const_iterator gs_i = gs_begin;
80623       gs_i != gs_end; ++gs_i) {
80624    const Generator& g = *gs_i;
80625    switch (g.type()) {
80626    case Generator::POINT:
80627      point_seen = true;
80628      // Intentionally fall through.
80629    case Generator::CLOSURE_POINT:
80630      if (!dbm_initialized) {
80631        // When handling the first (closure) point, we initialize the DBM.
80632        dbm_initialized = true;
80633        const Coefficient& d = g.divisor();
80634        // TODO: Check if the following loop can be optimized used
80635        // Generator::expr_type::const_iterator.
80636        for (dimension_type i = space_dim; i > 0; --i) {
80637          const Coefficient& g_i = g.expression().get(Variable(i - 1));
80638          DB_Row<N>& dbm_i = dbm[i];
80639          for (dimension_type j = space_dim; j > 0; --j) {
80640            if (i != j) {
80641              const Coefficient& g_j = g.expression().get(Variable(j - 1));
80642              div_round_up(dbm_i[j], g_j - g_i, d);
80643            }
80644          }
80645          div_round_up(dbm_i[0], -g_i, d);
80646        }
80647        for (dimension_type j = space_dim; j > 0; --j) {
80648          const Coefficient& g_j = g.expression().get(Variable(j - 1));
80649          div_round_up(dbm_0[j], g_j, d);
80650        }
80651        // Note: no need to initialize the first element of the main diagonal.
80652      }
80653      else {
80654        // This is not the first point: the DBM already contains
80655        // valid values and we must compute maxima.
80656        const Coefficient& d = g.divisor();
80657        // TODO: Check if the following loop can be optimized used
80658        // Generator::expr_type::const_iterator.
80659        for (dimension_type i = space_dim; i > 0; --i) {
80660          const Coefficient& g_i = g.expression().get(Variable(i - 1));
80661          DB_Row<N>& dbm_i = dbm[i];
80662          // The loop correctly handles the case when i == j.
80663          for (dimension_type j = space_dim; j > 0; --j) {
80664            const Coefficient& g_j = g.expression().get(Variable(j - 1));
80665            div_round_up(tmp, g_j - g_i, d);
80666            max_assign(dbm_i[j], tmp);
80667          }
80668          div_round_up(tmp, -g_i, d);
80669          max_assign(dbm_i[0], tmp);
80670        }
80671        for (dimension_type j = space_dim; j > 0; --j) {
80672          const Coefficient& g_j = g.expression().get(Variable(j - 1));
80673          div_round_up(tmp, g_j, d);
80674          max_assign(dbm_0[j], tmp);
80675        }
80676      }
80677      break;
80678    default:
80679      // Lines and rays temporarily ignored.
80680      break;
80681    }
80682  }
80683
80684  if (!point_seen) {
80685    // The generator system is not empty, but contains no points.
80686    throw_invalid_argument("BD_Shape(gs)",
80687                           "the non-empty generator system gs "
80688                           "contains no points.");
80689  }
80690
80691  // Going through all the lines and rays.
80692  for (Generator_System::const_iterator gs_i = gs_begin;
80693       gs_i != gs_end; ++gs_i) {
80694    const Generator& g = *gs_i;
80695    switch (g.type()) {
80696    case Generator::LINE:
80697      // TODO: Check if the following loop can be optimized used
80698      // Generator::expr_type::const_iterator.
80699      for (dimension_type i = space_dim; i > 0; --i) {
80700        const Coefficient& g_i = g.expression().get(Variable(i - 1));
80701        DB_Row<N>& dbm_i = dbm[i];
80702        // The loop correctly handles the case when i == j.
80703        for (dimension_type j = space_dim; j > 0; --j) {
80704          if (g_i != g.expression().get(Variable(j - 1))) {
80705            assign_r(dbm_i[j], PLUS_INFINITY, ROUND_NOT_NEEDED);
80706          }
80707        }
80708        if (g_i != 0) {
80709          assign_r(dbm_i[0], PLUS_INFINITY, ROUND_NOT_NEEDED);
80710        }
80711      }
80712      for (Generator::expr_type::const_iterator i = g.expression().begin(),
80713            i_end = g.expression().end(); i != i_end; ++i) {
80714        assign_r(dbm_0[i.variable().space_dimension()],
80715                 PLUS_INFINITY, ROUND_NOT_NEEDED);
80716      }
80717      break;
80718    case Generator::RAY:
80719      // TODO: Check if the following loop can be optimized used
80720      // Generator::expr_type::const_iterator.
80721      for (dimension_type i = space_dim; i > 0; --i) {
80722        const Coefficient& g_i = g.expression().get(Variable(i - 1));
80723        DB_Row<N>& dbm_i = dbm[i];
80724        // The loop correctly handles the case when i == j.
80725        for (dimension_type j = space_dim; j > 0; --j) {
80726          if (g_i < g.expression().get(Variable(j - 1))) {
80727            assign_r(dbm_i[j], PLUS_INFINITY, ROUND_NOT_NEEDED);
80728          }
80729        }
80730        if (g_i < 0) {
80731          assign_r(dbm_i[0], PLUS_INFINITY, ROUND_NOT_NEEDED);
80732        }
80733      }
80734      for (Generator::expr_type::const_iterator i = g.expression().begin(),
80735            i_end = g.expression().end(); i != i_end; ++i) {
80736        if (*i > 0) {
80737          assign_r(dbm_0[i.variable().space_dimension()],
80738                   PLUS_INFINITY, ROUND_NOT_NEEDED);
80739        }
80740      }
80741      break;
80742    default:
80743      // Points and closure points already dealt with.
80744      break;
80745    }
80746  }
80747  set_shortest_path_closed();
80748  PPL_ASSERT(OK());
80749}
80750
80751template <typename T>
80752BD_Shape<T>::BD_Shape(const Polyhedron& ph, const Complexity_Class complexity)
80753  : dbm(), status(), redundancy_dbm() {
80754  const dimension_type num_dimensions = ph.space_dimension();
80755
80756  if (ph.marked_empty()) {
80757    *this = BD_Shape<T>(num_dimensions, EMPTY);
80758    return;
80759  }
80760
80761  if (num_dimensions == 0) {
80762    *this = BD_Shape<T>(num_dimensions, UNIVERSE);
80763    return;
80764  }
80765
80766  // Build from generators when we do not care about complexity
80767  // or when the process has polynomial complexity.
80768  if (complexity == ANY_COMPLEXITY
80769      || (!ph.has_pending_constraints() && ph.generators_are_up_to_date())) {
80770    *this = BD_Shape<T>(ph.generators());
80771    return;
80772  }
80773
80774  // We cannot afford exponential complexity, we do not have a complete set
80775  // of generators for the polyhedron, and the polyhedron is not trivially
80776  // empty or zero-dimensional.  Constraints, however, are up to date.
80777  PPL_ASSERT(ph.constraints_are_up_to_date());
80778
80779  if (!ph.has_something_pending() && ph.constraints_are_minimized()) {
80780    // If the constraint system of the polyhedron is minimized,
80781    // the test `is_universe()' has polynomial complexity.
80782    if (ph.is_universe()) {
80783      *this = BD_Shape<T>(num_dimensions, UNIVERSE);
80784      return;
80785    }
80786  }
80787
80788  // See if there is at least one inconsistent constraint in `ph.con_sys'.
80789  for (Constraint_System::const_iterator i = ph.con_sys.begin(),
80790         cs_end = ph.con_sys.end(); i != cs_end; ++i) {
80791    if (i->is_inconsistent()) {
80792      *this = BD_Shape<T>(num_dimensions, EMPTY);
80793      return;
80794    }
80795  }
80796
80797  // If `complexity' allows it, use simplex to derive the exact (modulo
80798  // the fact that our BDSs are topologically closed) variable bounds.
80799  if (complexity == SIMPLEX_COMPLEXITY) {
80800    MIP_Problem lp(num_dimensions);
80801    lp.set_optimization_mode(MAXIMIZATION);
80802
80803    const Constraint_System& ph_cs = ph.constraints();
80804    if (!ph_cs.has_strict_inequalities()) {
80805      lp.add_constraints(ph_cs);
80806    }
80807    else {
80808      // Adding to `lp' a topologically closed version of `ph_cs'.
80809      for (Constraint_System::const_iterator i = ph_cs.begin(),
80810             ph_cs_end = ph_cs.end(); i != ph_cs_end; ++i) {
80811        const Constraint& c = *i;
80812        if (c.is_strict_inequality()) {
80813          Linear_Expression expr(c.expression());
80814          lp.add_constraint(expr >= 0);
80815        }
80816        else {
80817          lp.add_constraint(c);
80818        }
80819      }
80820    }
80821
80822    // Check for unsatisfiability.
80823    if (!lp.is_satisfiable()) {
80824      *this = BD_Shape<T>(num_dimensions, EMPTY);
80825      return;
80826    }
80827
80828    // Start with a universe BDS that will be refined by the simplex.
80829    *this = BD_Shape<T>(num_dimensions, UNIVERSE);
80830    // Get all the upper bounds.
80831    Generator g(point());
80832    PPL_DIRTY_TEMP_COEFFICIENT(numer);
80833    PPL_DIRTY_TEMP_COEFFICIENT(denom);
80834    for (dimension_type i = 1; i <= num_dimensions; ++i) {
80835      Variable x(i-1);
80836      // Evaluate optimal upper bound for `x <= ub'.
80837      lp.set_objective_function(x);
80838      if (lp.solve() == OPTIMIZED_MIP_PROBLEM) {
80839        g = lp.optimizing_point();
80840        lp.evaluate_objective_function(g, numer, denom);
80841        div_round_up(dbm[0][i], numer, denom);
80842      }
80843      // Evaluate optimal upper bound for `x - y <= ub'.
80844      for (dimension_type j = 1; j <= num_dimensions; ++j) {
80845        if (i == j) {
80846          continue;
80847        }
80848        Variable y(j-1);
80849        lp.set_objective_function(x - y);
80850        if (lp.solve() == OPTIMIZED_MIP_PROBLEM) {
80851          g = lp.optimizing_point();
80852          lp.evaluate_objective_function(g, numer, denom);
80853          div_round_up(dbm[j][i], numer, denom);
80854        }
80855      }
80856      // Evaluate optimal upper bound for `-x <= ub'.
80857      lp.set_objective_function(-x);
80858      if (lp.solve() == OPTIMIZED_MIP_PROBLEM) {
80859        g = lp.optimizing_point();
80860        lp.evaluate_objective_function(g, numer, denom);
80861        div_round_up(dbm[i][0], numer, denom);
80862      }
80863    }
80864    set_shortest_path_closed();
80865    PPL_ASSERT(OK());
80866    return;
80867  }
80868
80869  // Extract easy-to-find bounds from constraints.
80870  PPL_ASSERT(complexity == POLYNOMIAL_COMPLEXITY);
80871  *this = BD_Shape<T>(num_dimensions, UNIVERSE);
80872  refine_with_constraints(ph.constraints());
80873}
80874
80875template <typename T>
80876dimension_type
80877BD_Shape<T>::affine_dimension() const {
80878  const dimension_type space_dim = space_dimension();
80879  // A zero-space-dim shape always has affine dimension zero.
80880  if (space_dim == 0) {
80881    return 0;
80882  }
80883  // Shortest-path closure is necessary to detect emptiness
80884  // and all (possibly implicit) equalities.
80885  shortest_path_closure_assign();
80886  if (marked_empty()) {
80887    return 0;
80888  }
80889  // The vector `predecessor' is used to represent equivalence classes:
80890  // `predecessor[i] == i' if and only if `i' is the leader of its
80891  // equivalence class (i.e., the minimum index in the class).
80892  std::vector<dimension_type> predecessor;
80893  compute_predecessors(predecessor);
80894
80895  // Due to the fictitious variable `0', the affine dimension is one
80896  // less the number of equivalence classes.
80897  dimension_type affine_dim = 0;
80898  // Note: disregard the first equivalence class.
80899  for (dimension_type i = 1; i <= space_dim; ++i) {
80900    if (predecessor[i] == i) {
80901      ++affine_dim;
80902    }
80903  }
80904  return affine_dim;
80905}
80906
80907template <typename T>
80908Congruence_System
80909BD_Shape<T>::minimized_congruences() const {
80910  // Shortest-path closure is necessary to detect emptiness
80911  // and all (possibly implicit) equalities.
80912  shortest_path_closure_assign();
80913
80914  const dimension_type space_dim = space_dimension();
80915  Congruence_System cgs(space_dim);
80916
80917  if (space_dim == 0) {
80918    if (marked_empty()) {
80919      cgs = Congruence_System::zero_dim_empty();
80920    }
80921    return cgs;
80922  }
80923
80924  if (marked_empty()) {
80925    cgs.insert(Congruence::zero_dim_false());
80926    return cgs;
80927  }
80928
80929  PPL_DIRTY_TEMP_COEFFICIENT(numer);
80930  PPL_DIRTY_TEMP_COEFFICIENT(denom);
80931
80932  // Compute leader information.
80933  std::vector<dimension_type> leaders;
80934  compute_leaders(leaders);
80935
80936  // Go through the non-leaders to generate equality constraints.
80937  const DB_Row<N>& dbm_0 = dbm[0];
80938  for (dimension_type i = 1; i <= space_dim; ++i) {
80939    const dimension_type leader = leaders[i];
80940    if (i != leader) {
80941      // Generate the constraint relating `i' and its leader.
80942      if (leader == 0) {
80943        // A unary equality has to be generated.
80944        PPL_ASSERT(!is_plus_infinity(dbm_0[i]));
80945        numer_denom(dbm_0[i], numer, denom);
80946        cgs.insert(denom*Variable(i-1) == numer);
80947      }
80948      else {
80949        // A binary equality has to be generated.
80950        PPL_ASSERT(!is_plus_infinity(dbm[i][leader]));
80951        numer_denom(dbm[i][leader], numer, denom);
80952        cgs.insert(denom*Variable(leader-1) - denom*Variable(i-1) == numer);
80953      }
80954    }
80955  }
80956  return cgs;
80957}
80958
80959template <typename T>
80960void
80961BD_Shape<T>::add_constraint(const Constraint& c) {
80962  // Dimension-compatibility check.
80963  if (c.space_dimension() > space_dimension()) {
80964    throw_dimension_incompatible("add_constraint(c)", c);
80965  }
80966  // Get rid of strict inequalities.
80967  if (c.is_strict_inequality()) {
80968    if (c.is_inconsistent()) {
80969      set_empty();
80970      return;
80971    }
80972    if (c.is_tautological()) {
80973      return;
80974    }
80975    // Nontrivial strict inequalities are not allowed.
80976    throw_invalid_argument("add_constraint(c)",
80977                           "strict inequalities are not allowed");
80978  }
80979
80980  dimension_type num_vars = 0;
80981  dimension_type i = 0;
80982  dimension_type j = 0;
80983  PPL_DIRTY_TEMP_COEFFICIENT(coeff);
80984  // Constraints that are not bounded differences are not allowed.
80985  if (!BD_Shape_Helpers::extract_bounded_difference(c, num_vars, i, j, coeff)) {
80986    throw_invalid_argument("add_constraint(c)",
80987                           "c is not a bounded difference constraint");
80988  }
80989  const Coefficient& inhomo = c.inhomogeneous_term();
80990  if (num_vars == 0) {
80991    // Dealing with a trivial constraint (not a strict inequality).
80992    if (inhomo < 0
80993        || (inhomo != 0 && c.is_equality())) {
80994      set_empty();
80995    }
80996    return;
80997  }
80998
80999  // Select the cell to be modified for the "<=" part of the constraint,
81000  // and set `coeff' to the absolute value of itself.
81001  const bool negative = (coeff < 0);
81002  if (negative) {
81003    neg_assign(coeff);
81004  }
81005  bool changed = false;
81006  N& x = negative ? dbm[i][j] : dbm[j][i];
81007  // Compute the bound for `x', rounding towards plus infinity.
81008  PPL_DIRTY_TEMP(N, d);
81009  div_round_up(d, inhomo, coeff);
81010  if (x > d) {
81011    x = d;
81012    changed = true;
81013  }
81014
81015  if (c.is_equality()) {
81016    N& y = negative ? dbm[j][i] : dbm[i][j];
81017    // Also compute the bound for `y', rounding towards plus infinity.
81018    PPL_DIRTY_TEMP_COEFFICIENT(minus_c_term);
81019    neg_assign(minus_c_term, inhomo);
81020    div_round_up(d, minus_c_term, coeff);
81021    if (y > d) {
81022      y = d;
81023      changed = true;
81024    }
81025  }
81026
81027  // In general, adding a constraint does not preserve the shortest-path
81028  // closure or reduction of the bounded difference shape.
81029  if (changed && marked_shortest_path_closed()) {
81030    reset_shortest_path_closed();
81031  }
81032  PPL_ASSERT(OK());
81033}
81034
81035template <typename T>
81036void
81037BD_Shape<T>::add_congruence(const Congruence& cg) {
81038  const dimension_type cg_space_dim = cg.space_dimension();
81039  // Dimension-compatibility check:
81040  // the dimension of `cg' can not be greater than space_dim.
81041  if (space_dimension() < cg_space_dim) {
81042    throw_dimension_incompatible("add_congruence(cg)", cg);
81043  }
81044  // Handle the case of proper congruences first.
81045  if (cg.is_proper_congruence()) {
81046    if (cg.is_tautological()) {
81047      return;
81048    }
81049    if (cg.is_inconsistent()) {
81050      set_empty();
81051      return;
81052    }
81053    // Non-trivial and proper congruences are not allowed.
81054    throw_invalid_argument("add_congruence(cg)",
81055                           "cg is a non-trivial, proper congruence");
81056  }
81057
81058  PPL_ASSERT(cg.is_equality());
81059  Constraint c(cg);
81060  add_constraint(c);
81061}
81062
81063template <typename T>
81064void
81065BD_Shape<T>::refine_no_check(const Constraint& c) {
81066  PPL_ASSERT(!marked_empty());
81067  PPL_ASSERT(c.space_dimension() <= space_dimension());
81068
81069  dimension_type num_vars = 0;
81070  dimension_type i = 0;
81071  dimension_type j = 0;
81072  PPL_DIRTY_TEMP_COEFFICIENT(coeff);
81073  // Constraints that are not bounded differences are ignored.
81074  if (!BD_Shape_Helpers::extract_bounded_difference(c, num_vars, i, j, coeff)) {
81075    return;
81076  }
81077  const Coefficient& inhomo = c.inhomogeneous_term();
81078  if (num_vars == 0) {
81079    // Dealing with a trivial constraint (might be a strict inequality).
81080    if (inhomo < 0
81081        || (c.is_equality() && inhomo != 0)
81082        || (c.is_strict_inequality() && inhomo == 0)) {
81083      set_empty();
81084    }
81085    return;
81086  }
81087
81088  // Select the cell to be modified for the "<=" part of the constraint,
81089  // and set `coeff' to the absolute value of itself.
81090  const bool negative = (coeff < 0);
81091  N& x = negative ? dbm[i][j] : dbm[j][i];
81092  N& y = negative ? dbm[j][i] : dbm[i][j];
81093  if (negative) {
81094    neg_assign(coeff);
81095  }
81096  bool changed = false;
81097  // Compute the bound for `x', rounding towards plus infinity.
81098  PPL_DIRTY_TEMP(N, d);
81099  div_round_up(d, inhomo, coeff);
81100  if (x > d) {
81101    x = d;
81102    changed = true;
81103  }
81104
81105  if (c.is_equality()) {
81106    // Also compute the bound for `y', rounding towards plus infinity.
81107    PPL_DIRTY_TEMP_COEFFICIENT(minus_c_term);
81108    neg_assign(minus_c_term, inhomo);
81109    div_round_up(d, minus_c_term, coeff);
81110    if (y > d) {
81111      y = d;
81112      changed = true;
81113    }
81114  }
81115
81116  // In general, adding a constraint does not preserve the shortest-path
81117  // closure or reduction of the bounded difference shape.
81118  if (changed && marked_shortest_path_closed()) {
81119    reset_shortest_path_closed();
81120  }
81121  PPL_ASSERT(OK());
81122}
81123
81124template <typename T>
81125void
81126BD_Shape<T>::concatenate_assign(const BD_Shape& y) {
81127  BD_Shape& x = *this;
81128
81129  const dimension_type x_space_dim = x.space_dimension();
81130  const dimension_type y_space_dim = y.space_dimension();
81131
81132  // If `y' is an empty 0-dim space bounded difference shape,
81133  // let `*this' become empty.
81134  if (y_space_dim == 0 && y.marked_empty()) {
81135    set_empty();
81136    return;
81137  }
81138
81139  // If `x' is an empty 0-dim space BDS, then it is sufficient to adjust
81140  // the dimension of the vector space.
81141  if (x_space_dim == 0 && marked_empty()) {
81142    dbm.grow(y_space_dim + 1);
81143    PPL_ASSERT(OK());
81144    return;
81145  }
81146  // First we increase the space dimension of `x' by adding
81147  // `y.space_dimension()' new dimensions.
81148  // The matrix for the new system of constraints is obtained
81149  // by leaving the old system of constraints in the upper left-hand side
81150  // and placing the constraints of `y' in the lower right-hand side,
81151  // except the constraints as `y(i) >= cost' or `y(i) <= cost', that are
81152  // placed in the right position on the new matrix.
81153  add_space_dimensions_and_embed(y_space_dim);
81154  const dimension_type new_space_dim = x_space_dim + y_space_dim;
81155  for (dimension_type i = x_space_dim + 1; i <= new_space_dim; ++i) {
81156    DB_Row<N>& dbm_i = dbm[i];
81157    dbm_i[0] = y.dbm[i - x_space_dim][0];
81158    dbm[0][i] = y.dbm[0][i - x_space_dim];
81159    for (dimension_type j = x_space_dim + 1; j <= new_space_dim; ++j) {
81160      dbm_i[j] = y.dbm[i - x_space_dim][j - x_space_dim];
81161    }
81162  }
81163
81164  if (marked_shortest_path_closed()) {
81165    reset_shortest_path_closed();
81166  }
81167  PPL_ASSERT(OK());
81168}
81169
81170template <typename T>
81171bool
81172BD_Shape<T>::contains(const BD_Shape& y) const {
81173  const BD_Shape<T>& x = *this;
81174  const dimension_type x_space_dim = x.space_dimension();
81175
81176  // Dimension-compatibility check.
81177  if (x_space_dim != y.space_dimension()) {
81178    throw_dimension_incompatible("contains(y)", y);
81179  }
81180  if (x_space_dim == 0) {
81181    // The zero-dimensional empty shape only contains another
81182    // zero-dimensional empty shape.
81183    // The zero-dimensional universe shape contains any other
81184    // zero-dimensional shape.
81185    return marked_empty() ? y.marked_empty() : true;
81186  }
81187
81188  /*
81189    The `y' bounded difference shape must be closed.  As an example,
81190    consider the case where in `*this' we have the constraints
81191
81192    x1 - x2 <= 1,
81193    x1      <= 3,
81194    x2      <= 2,
81195
81196    and in `y' the constraints are
81197
81198    x1 - x2 <= 0,
81199    x2      <= 1.
81200
81201    Without closure the (erroneous) analysis of the inhomogeneous terms
81202    would conclude containment does not hold.  Closing `y' results into
81203    the "discovery" of the implicit constraint
81204
81205    x1      <= 1,
81206
81207    at which point the inhomogeneous terms can be examined to determine
81208    that containment does hold.
81209  */
81210  y.shortest_path_closure_assign();
81211  // An empty shape is contained in any other dimension-compatible shapes.
81212  if (y.marked_empty()) {
81213    return true;
81214  }
81215  // If `x' is empty it can not contain `y' (which is not empty).
81216  if (x.is_empty()) {
81217    return false;
81218  }
81219  // `*this' contains `y' if and only if every cell of `dbm'
81220  // is greater than or equal to the correspondent one of `y.dbm'.
81221  for (dimension_type i = x_space_dim + 1; i-- > 0; ) {
81222    const DB_Row<N>& x_dbm_i = x.dbm[i];
81223    const DB_Row<N>& y_dbm_i = y.dbm[i];
81224    for (dimension_type j = x_space_dim + 1; j-- > 0; ) {
81225      if (x_dbm_i[j] < y_dbm_i[j]) {
81226        return false;
81227      }
81228    }
81229  }
81230  return true;
81231}
81232
81233template <typename T>
81234bool
81235BD_Shape<T>::is_disjoint_from(const BD_Shape& y) const {
81236  const dimension_type space_dim = space_dimension();
81237  // Dimension-compatibility check.
81238  if (space_dim != y.space_dimension()) {
81239    throw_dimension_incompatible("is_disjoint_from(y)", y);
81240  }
81241  // If one of the two bounded difference shape is empty,
81242  // then the two bounded difference shape are disjoint.
81243  shortest_path_closure_assign();
81244  if (marked_empty()) {
81245    return true;
81246  }
81247  y.shortest_path_closure_assign();
81248  if (y.marked_empty()) {
81249    return true;
81250  }
81251  // Two BDSs are disjoint when their intersection is empty.
81252  // That is if and only if there exists at least a bounded difference
81253  // such that the upper bound of the bounded difference in the first
81254  // BD_Shape is strictly less than the lower bound of
81255  // the corresponding bounded difference in the second BD_Shape
81256  // or vice versa.
81257  // For example: let be
81258  // in `*this':    -a_j_i <= v_j - v_i <= a_i_j;
81259  // and in `y':    -b_j_i <= v_j - v_i <= b_i_j;
81260  // `*this' and `y' are disjoint if
81261  // 1.) a_i_j < -b_j_i or
81262  // 2.) b_i_j < -a_j_i.
81263  PPL_DIRTY_TEMP(N, tmp);
81264  for (dimension_type i = space_dim+1; i-- > 0; ) {
81265    const DB_Row<N>& x_i = dbm[i];
81266    for (dimension_type j = space_dim+1; j-- > 0; ) {
81267      neg_assign_r(tmp, y.dbm[j][i], ROUND_UP);
81268      if (x_i[j] < tmp) {
81269        return true;
81270      }
81271    }
81272  }
81273
81274  return false;
81275}
81276
81277template <typename T>
81278bool
81279BD_Shape<T>::is_universe() const {
81280  if (marked_empty()) {
81281    return false;
81282  }
81283  const dimension_type space_dim = space_dimension();
81284  // If the BDS is non-empty and zero-dimensional,
81285  // then it is necessarily the universe BDS.
81286  if (space_dim == 0) {
81287    return true;
81288  }
81289  // A bounded difference shape defining the universe BDS can only
81290  // contain trivial constraints.
81291  for (dimension_type i = space_dim + 1; i-- > 0; ) {
81292    const DB_Row<N>& dbm_i = dbm[i];
81293    for (dimension_type j = space_dim + 1; j-- > 0; ) {
81294      if (!is_plus_infinity(dbm_i[j])) {
81295        return false;
81296      }
81297    }
81298  }
81299  return true;
81300}
81301
81302template <typename T>
81303bool
81304BD_Shape<T>::is_bounded() const {
81305  shortest_path_closure_assign();
81306  const dimension_type space_dim = space_dimension();
81307  // A zero-dimensional or empty BDS is bounded.
81308  if (marked_empty() || space_dim == 0) {
81309    return true;
81310  }
81311  // A bounded difference shape defining the bounded BDS never can
81312  // contain trivial constraints.
81313  for (dimension_type i = space_dim + 1; i-- > 0; ) {
81314    const DB_Row<N>& dbm_i = dbm[i];
81315    for (dimension_type j = space_dim + 1; j-- > 0; ) {
81316      if (i != j) {
81317        if (is_plus_infinity(dbm_i[j])) {
81318          return false;
81319        }
81320      }
81321    }
81322  }
81323
81324  return true;
81325}
81326
81327template <typename T>
81328bool
81329BD_Shape<T>::contains_integer_point() const {
81330  // Force shortest-path closure.
81331  if (is_empty()) {
81332    return false;
81333  }
81334  const dimension_type space_dim = space_dimension();
81335  if (space_dim == 0) {
81336    return true;
81337  }
81338  // A non-empty BD_Shape defined by integer constraints
81339  // necessarily contains an integer point.
81340  if (std::numeric_limits<T>::is_integer) {
81341    return true;
81342  }
81343  // Build an integer BD_Shape z with bounds at least as tight as
81344  // those in *this and then recheck for emptiness.
81345  BD_Shape<mpz_class> bds_z(space_dim);
81346  typedef BD_Shape<mpz_class>::N Z;
81347  bds_z.reset_shortest_path_closed();
81348  PPL_DIRTY_TEMP(N, tmp);
81349  bool all_integers = true;
81350  for (dimension_type i = space_dim + 1; i-- > 0; ) {
81351    DB_Row<Z>& z_i = bds_z.dbm[i];
81352    const DB_Row<N>& dbm_i = dbm[i];
81353    for (dimension_type j = space_dim + 1; j-- > 0; ) {
81354      const N& dbm_i_j = dbm_i[j];
81355      if (is_plus_infinity(dbm_i_j)) {
81356        continue;
81357      }
81358      if (is_integer(dbm_i_j)) {
81359        assign_r(z_i[j], dbm_i_j, ROUND_NOT_NEEDED);
81360      }
81361      else {
81362        all_integers = false;
81363        Z& z_i_j = z_i[j];
81364        // Copy dbm_i_j into z_i_j, but rounding downwards.
81365        neg_assign_r(tmp, dbm_i_j, ROUND_NOT_NEEDED);
81366        assign_r(z_i_j, tmp, ROUND_UP);
81367        neg_assign_r(z_i_j, z_i_j, ROUND_NOT_NEEDED);
81368      }
81369    }
81370  }
81371  return all_integers || !bds_z.is_empty();
81372}
81373
81374template <typename T>
81375bool
81376BD_Shape<T>::frequency(const Linear_Expression& expr,
81377                       Coefficient& freq_n, Coefficient& freq_d,
81378                       Coefficient& val_n, Coefficient& val_d) const {
81379  dimension_type space_dim = space_dimension();
81380  // The dimension of `expr' must be at most the dimension of *this.
81381  if (space_dim < expr.space_dimension()) {
81382    throw_dimension_incompatible("frequency(e, ...)", "e", expr);
81383  }
81384  // Check if `expr' has a constant value.
81385  // If it is constant, set the frequency `freq_n' to 0
81386  // and return true. Otherwise the values for \p expr
81387  // are not discrete so return false.
81388
81389  // Space dimension is 0: if empty, then return false;
81390  // otherwise the frequency is 0 and the value is the inhomogeneous term.
81391  if (space_dim == 0) {
81392    if (is_empty()) {
81393      return false;
81394    }
81395    freq_n = 0;
81396    freq_d = 1;
81397    val_n = expr.inhomogeneous_term();
81398    val_d = 1;
81399    return true;
81400  }
81401
81402  shortest_path_closure_assign();
81403  // For an empty BD shape, we simply return false.
81404  if (marked_empty()) {
81405    return false;
81406  }
81407  // The BD shape has at least 1 dimension and is not empty.
81408  PPL_DIRTY_TEMP_COEFFICIENT(coeff);
81409  PPL_DIRTY_TEMP_COEFFICIENT(numer);
81410  PPL_DIRTY_TEMP_COEFFICIENT(denom);
81411  PPL_DIRTY_TEMP(N, tmp);
81412  Linear_Expression le = expr;
81413  // Boolean to keep track of a variable `v' in expression `le'.
81414  // If we can replace `v' by an expression using variables other
81415  // than `v' and are already in `le', then this is set to true.
81416
81417  PPL_DIRTY_TEMP_COEFFICIENT(val_denom);
81418  val_denom = 1;
81419
81420  // TODO: This loop can be optimized more, if needed, exploiting the
81421  // (possible) sparseness of le.
81422  for (dimension_type i = dbm.num_rows(); i-- > 1; ) {
81423    const Variable v(i-1);
81424    coeff = le.coefficient(v);
81425    if (coeff == 0) {
81426      continue;
81427    }
81428    const DB_Row<N>& dbm_i = dbm[i];
81429    // Check if `v' is constant in the BD shape.
81430    assign_r(tmp, dbm_i[0], ROUND_NOT_NEEDED);
81431    if (is_additive_inverse(dbm[0][i], tmp)) {
81432      // If `v' is constant, replace it in `le' by the value.
81433      numer_denom(tmp, numer, denom);
81434      sub_mul_assign(le, coeff, v);
81435      le *= denom;
81436      le -= numer*coeff;
81437      val_denom *= denom;
81438      continue;
81439    }
81440    // Check the bounded differences with the other dimensions that
81441    // have non-zero coefficient in `le'.
81442    else {
81443      bool constant_v = false;
81444      for (Linear_Expression::const_iterator j = le.begin(),
81445            j_end = le.lower_bound(Variable(i - 1)); j != j_end; ++j) {
81446        const Variable vj = j.variable();
81447        const dimension_type j_dim = vj.space_dimension();
81448        assign_r(tmp, dbm_i[j_dim], ROUND_NOT_NEEDED);
81449        if (is_additive_inverse(dbm[j_dim][i], tmp)) {
81450          // The coefficient for `vj' in `le' is not 0
81451          // and the difference with `v' in the BD shape is constant.
81452          // So apply this equality to eliminate `v' in `le'.
81453          numer_denom(tmp, numer, denom);
81454          // Modifying le invalidates the iterators, but it's not a problem
81455          // since we are going to exit the loop.
81456          sub_mul_assign(le, coeff, v);
81457          add_mul_assign(le, coeff, vj);
81458          le *= denom;
81459          le -= numer*coeff;
81460          val_denom *= denom;
81461          constant_v = true;
81462          break;
81463        }
81464      }
81465      if (!constant_v) {
81466        // The expression `expr' is not constant.
81467        return false;
81468      }
81469    }
81470  }
81471
81472  // The expression `expr' is constant.
81473  freq_n = 0;
81474  freq_d = 1;
81475
81476  // Reduce `val_n' and `val_d'.
81477  normalize2(le.inhomogeneous_term(), val_denom, val_n, val_d);
81478  return true;
81479}
81480
81481template <typename T>
81482bool
81483BD_Shape<T>::constrains(const Variable var) const {
81484  // `var' should be one of the dimensions of the BD shape.
81485  const dimension_type var_space_dim = var.space_dimension();
81486  if (space_dimension() < var_space_dim) {
81487    throw_dimension_incompatible("constrains(v)", "v", var);
81488  }
81489  shortest_path_closure_assign();
81490  // A BD shape known to be empty constrains all variables.
81491  // (Note: do not force emptiness check _yet_)
81492  if (marked_empty()) {
81493    return true;
81494  }
81495  // Check whether `var' is syntactically constrained.
81496  const DB_Row<N>& dbm_v = dbm[var_space_dim];
81497  for (dimension_type i = dbm.num_rows(); i-- > 0; ) {
81498    if (!is_plus_infinity(dbm_v[i])
81499        || !is_plus_infinity(dbm[i][var_space_dim])) {
81500      return true;
81501    }
81502  }
81503
81504  // `var' is not syntactically constrained:
81505  // now force an emptiness check.
81506  return is_empty();
81507}
81508
81509template <typename T>
81510void
81511BD_Shape<T>
81512::compute_predecessors(std::vector<dimension_type>& predecessor) const {
81513  PPL_ASSERT(!marked_empty() && marked_shortest_path_closed());
81514  PPL_ASSERT(predecessor.size() == 0);
81515  // Variables are ordered according to their index.
81516  // The vector `predecessor' is used to indicate which variable
81517  // immediately precedes a given one in the corresponding equivalence class.
81518  // The `leader' of an equivalence class is the element having minimum
81519  // index: leaders are their own predecessors.
81520  const dimension_type predecessor_size = dbm.num_rows();
81521  // Initially, each variable is leader of its own zero-equivalence class.
81522  predecessor.reserve(predecessor_size);
81523  for (dimension_type i = 0; i < predecessor_size; ++i) {
81524    predecessor.push_back(i);
81525  }
81526  // Now compute actual predecessors.
81527  for (dimension_type i = predecessor_size; i-- > 1; ) {
81528    if (i == predecessor[i]) {
81529      const DB_Row<N>& dbm_i = dbm[i];
81530      for (dimension_type j = i; j-- > 0; ) {
81531        if (j == predecessor[j]
81532            && is_additive_inverse(dbm[j][i], dbm_i[j])) {
81533          // Choose as predecessor the variable having the smaller index.
81534          predecessor[i] = j;
81535          break;
81536        }
81537      }
81538    }
81539  }
81540}
81541
81542template <typename T>
81543void
81544BD_Shape<T>::compute_leaders(std::vector<dimension_type>& leaders) const {
81545  PPL_ASSERT(!marked_empty() && marked_shortest_path_closed());
81546  PPL_ASSERT(leaders.size() == 0);
81547  // Compute predecessor information.
81548  compute_predecessors(leaders);
81549  // Flatten the predecessor chains so as to obtain leaders.
81550  PPL_ASSERT(leaders[0] == 0);
81551  for (dimension_type i = 1, l_size = leaders.size(); i != l_size; ++i) {
81552    const dimension_type leaders_i = leaders[i];
81553    PPL_ASSERT(leaders_i <= i);
81554    if (leaders_i != i) {
81555      const dimension_type leaders_leaders_i = leaders[leaders_i];
81556      PPL_ASSERT(leaders_leaders_i == leaders[leaders_leaders_i]);
81557      leaders[i] = leaders_leaders_i;
81558    }
81559  }
81560}
81561
81562template <typename T>
81563bool
81564BD_Shape<T>::is_shortest_path_reduced() const {
81565  // If the BDS is empty, it is also reduced.
81566  if (marked_empty()) {
81567    return true;
81568  }
81569  const dimension_type space_dim = space_dimension();
81570  // Zero-dimensional BDSs are necessarily reduced.
81571  if (space_dim == 0) {
81572    return true;
81573  }
81574  // A shortest-path reduced dbm is just a dbm with an indication of
81575  // those constraints that are redundant. If there is no indication
81576  // of the redundant constraints, then it cannot be reduced.
81577  if (!marked_shortest_path_reduced()) {
81578    return false;
81579  }
81580
81581  const BD_Shape x_copy = *this;
81582  x_copy.shortest_path_closure_assign();
81583  // If we just discovered emptiness, it cannot be reduced.
81584  if (x_copy.marked_empty()) {
81585    return false;
81586  }
81587  // The vector `leader' is used to indicate which variables are equivalent.
81588  std::vector<dimension_type> leader(space_dim + 1);
81589
81590  // We store the leader.
81591  for (dimension_type i = space_dim + 1; i-- > 0; ) {
81592    leader[i] = i;
81593  }
81594  // Step 1: we store really the leader with the corrected value.
81595  // We search for the equivalent or zero-equivalent variables.
81596  // The variable(i-1) and variable(j-1) are equivalent if and only if
81597  // m_i_j == -(m_j_i).
81598  for (dimension_type i = 0; i < space_dim; ++i) {
81599    const DB_Row<N>& x_copy_dbm_i = x_copy.dbm[i];
81600    for (dimension_type j = i + 1; j <= space_dim; ++j) {
81601      if (is_additive_inverse(x_copy.dbm[j][i], x_copy_dbm_i[j])) {
81602        // Two equivalent variables have got the same leader
81603        // (the smaller variable).
81604        leader[j] = leader[i];
81605      }
81606    }
81607  }
81608
81609  // Step 2: we check if there are redundant constraints in the zero_cycle
81610  // free bounded difference shape, considering only the leaders.
81611  // A constraint `c' is redundant, when there are two constraints such that
81612  // their sum is the same constraint with the inhomogeneous term
81613  // less than or equal to the `c' one.
81614  PPL_DIRTY_TEMP(N, c);
81615  for (dimension_type k = 0; k <= space_dim; ++k) {
81616    if (leader[k] == k) {
81617      const DB_Row<N>& x_k = x_copy.dbm[k];
81618      for (dimension_type i = 0; i <= space_dim; ++i) {
81619        if (leader[i] == i) {
81620          const DB_Row<N>& x_i = x_copy.dbm[i];
81621          const Bit_Row& redundancy_i = redundancy_dbm[i];
81622          const N& x_i_k = x_i[k];
81623          for (dimension_type j = 0; j <= space_dim; ++j) {
81624            if (leader[j] == j) {
81625              const N& x_i_j = x_i[j];
81626              if (!is_plus_infinity(x_i_j)) {
81627                add_assign_r(c, x_i_k, x_k[j], ROUND_UP);
81628                if (x_i_j >= c && !redundancy_i[j]) {
81629                  return false;
81630                }
81631              }
81632            }
81633          }
81634        }
81635      }
81636    }
81637  }
81638
81639  // The vector `var_conn' is used to check if there is a single cycle
81640  // that connected all zero-equivalent variables between them.
81641  // The value `space_dim + 1' is used to indicate that the equivalence
81642  // class contains a single variable.
81643  std::vector<dimension_type> var_conn(space_dim + 1);
81644  for (dimension_type i = space_dim + 1; i-- > 0; ) {
81645    var_conn[i] = space_dim + 1;
81646  }
81647  // Step 3: we store really the `var_conn' with the right value, putting
81648  // the variable with the selected variable is connected:
81649  // we check the row of each variable:
81650  // a- each leader could be connected with only zero-equivalent one,
81651  // b- each non-leader with only another zero-equivalent one.
81652  for (dimension_type i = 0; i <= space_dim; ++i) {
81653    // It count with how many variables the selected variable is
81654    // connected.
81655    dimension_type t = 0;
81656    dimension_type leader_i = leader[i];
81657    // Case a: leader.
81658    if (leader_i == i) {
81659      for (dimension_type j = 0; j <= space_dim; ++j) {
81660        dimension_type leader_j = leader[j];
81661        // Only the connectedness with equivalent variables
81662        // is considered.
81663        if (j != leader_j) {
81664          if (!redundancy_dbm[i][j]) {
81665            if (t == 1) {
81666              // Two non-leaders cannot be connected with the same leader.
81667              return false;
81668            }
81669            else {
81670              if (leader_j != i) {
81671                // The variables are not in the same equivalence class.
81672                return false;
81673              }
81674              else {
81675                ++t;
81676                var_conn[i] = j;
81677              }
81678            }
81679          }
81680        }
81681      }
81682    }
81683    // Case b: non-leader.
81684    else {
81685      for (dimension_type j = 0; j <= space_dim; ++j) {
81686        if (!redundancy_dbm[i][j]) {
81687          dimension_type leader_j = leader[j];
81688          if (leader_i != leader_j) {
81689            // The variables are not in the same equivalence class.
81690            return false;
81691          }
81692          else {
81693            if (t == 1) {
81694              // The variables cannot be connected with the same leader.
81695              return false;
81696            }
81697            else {
81698              ++t;
81699              var_conn[i] = j;
81700            }
81701          }
81702          // A non-leader must be connected with
81703          // another variable.
81704          if (t == 0) {
81705            return false;
81706          }
81707        }
81708      }
81709    }
81710  }
81711
81712  // The vector `just_checked' is used to check if
81713  // a variable is already checked.
81714  std::vector<bool> just_checked(space_dim + 1);
81715  for (dimension_type i = space_dim + 1; i-- > 0; ) {
81716    just_checked[i] = false;
81717  }
81718  // Step 4: we check if there are single cycles that
81719  // connected all the zero-equivalent variables between them.
81720  for (dimension_type i = 0; i <= space_dim; ++i) {
81721    // We do not re-check the already considered single cycles.
81722    if (!just_checked[i]) {
81723      dimension_type v_con = var_conn[i];
81724      // We consider only the equivalence classes with
81725      // 2 or plus variables.
81726      if (v_con != space_dim + 1) {
81727        // There is a single cycle if taken a variable,
81728        // we return to this same variable.
81729        while (v_con != i) {
81730          just_checked[v_con] = true;
81731          v_con = var_conn[v_con];
81732          // If we re-pass to an already considered variable,
81733          // then we haven't a single cycle.
81734          if (just_checked[v_con]) {
81735            return false;
81736          }
81737        }
81738      }
81739    }
81740    just_checked[i] = true;
81741  }
81742
81743  // The system bounded differences is just reduced.
81744  return true;
81745}
81746
81747template <typename T>
81748bool
81749BD_Shape<T>::bounds(const Linear_Expression& expr,
81750                    const bool from_above) const {
81751  // The dimension of `expr' should not be greater than the dimension
81752  // of `*this'.
81753  const dimension_type expr_space_dim = expr.space_dimension();
81754  const dimension_type space_dim = space_dimension();
81755  if (space_dim < expr_space_dim) {
81756    throw_dimension_incompatible((from_above
81757                                  ? "bounds_from_above(e)"
81758                                  : "bounds_from_below(e)"), "e", expr);
81759  }
81760  shortest_path_closure_assign();
81761  // A zero-dimensional or empty BDS bounds everything.
81762  if (space_dim == 0 || marked_empty()) {
81763    return true;
81764  }
81765  // The constraint `c' is used to check if `expr' is a difference
81766  // bounded and, in this case, to select the cell.
81767  const Constraint& c = from_above ? expr <= 0 : expr >= 0;
81768  dimension_type num_vars = 0;
81769  dimension_type i = 0;
81770  dimension_type j = 0;
81771  PPL_DIRTY_TEMP_COEFFICIENT(coeff);
81772  // Check if `c' is a BD constraint.
81773  if (BD_Shape_Helpers::extract_bounded_difference(c, num_vars, i, j, coeff)) {
81774    if (num_vars == 0) {
81775      // Dealing with a trivial constraint.
81776      return true;
81777    }
81778    // Select the cell to be checked.
81779    const N& x = (coeff < 0) ? dbm[i][j] : dbm[j][i];
81780    return !is_plus_infinity(x);
81781  }
81782  else {
81783    // Not a DB constraint: use the MIP solver.
81784    Optimization_Mode mode_bounds
81785      = from_above ? MAXIMIZATION : MINIMIZATION;
81786    MIP_Problem mip(space_dim, constraints(), expr, mode_bounds);
81787    // Problem is known to be feasible.
81788    return mip.solve() == OPTIMIZED_MIP_PROBLEM;
81789  }
81790}
81791
81792template <typename T>
81793bool
81794BD_Shape<T>::max_min(const Linear_Expression& expr,
81795                     const bool maximize,
81796                     Coefficient& ext_n, Coefficient& ext_d,
81797                     bool& included) const {
81798  // The dimension of `expr' should not be greater than the dimension
81799  // of `*this'.
81800  const dimension_type space_dim = space_dimension();
81801  const dimension_type expr_space_dim = expr.space_dimension();
81802  if (space_dim < expr_space_dim) {
81803    throw_dimension_incompatible((maximize
81804                                  ? "maximize(e, ...)"
81805                                  : "minimize(e, ...)"), "e", expr);
81806  }
81807  // Deal with zero-dim BDS first.
81808  if (space_dim == 0) {
81809    if (marked_empty()) {
81810      return false;
81811    }
81812    else {
81813      ext_n = expr.inhomogeneous_term();
81814      ext_d = 1;
81815      included = true;
81816      return true;
81817    }
81818  }
81819
81820  shortest_path_closure_assign();
81821  // For an empty BDS we simply return false.
81822  if (marked_empty()) {
81823    return false;
81824  }
81825  // The constraint `c' is used to check if `expr' is a difference
81826  // bounded and, in this case, to select the cell.
81827  const Constraint& c = maximize ? expr <= 0 : expr >= 0;
81828  dimension_type num_vars = 0;
81829  dimension_type i = 0;
81830  dimension_type j = 0;
81831  PPL_DIRTY_TEMP_COEFFICIENT(coeff);
81832  // Check if `c' is a BD constraint.
81833  if (!BD_Shape_Helpers::extract_bounded_difference(c, num_vars, i, j, coeff)) {
81834    Optimization_Mode mode_max_min
81835      = maximize ? MAXIMIZATION : MINIMIZATION;
81836    MIP_Problem mip(space_dim, constraints(), expr, mode_max_min);
81837    if (mip.solve() == OPTIMIZED_MIP_PROBLEM) {
81838      mip.optimal_value(ext_n, ext_d);
81839      included = true;
81840      return true;
81841    }
81842    else {
81843      // Here`expr' is unbounded in `*this'.
81844      return false;
81845    }
81846  }
81847  else {
81848    // Here `expr' is a bounded difference.
81849    if (num_vars == 0) {
81850      // Dealing with a trivial expression.
81851      ext_n = expr.inhomogeneous_term();
81852      ext_d = 1;
81853      included = true;
81854      return true;
81855    }
81856
81857    // Select the cell to be checked.
81858    const N& x = (coeff < 0) ? dbm[i][j] : dbm[j][i];
81859    if (!is_plus_infinity(x)) {
81860      // Compute the maximize/minimize of `expr'.
81861      PPL_DIRTY_TEMP(N, d);
81862      const Coefficient& b = expr.inhomogeneous_term();
81863      PPL_DIRTY_TEMP_COEFFICIENT(minus_b);
81864      neg_assign(minus_b, b);
81865      const Coefficient& sc_b = maximize ? b : minus_b;
81866      assign_r(d, sc_b, ROUND_UP);
81867      // Set `coeff_expr' to the absolute value of coefficient of
81868      // a variable in `expr'.
81869      PPL_DIRTY_TEMP(N, coeff_expr);
81870      PPL_ASSERT(i != 0);
81871      const Coefficient& coeff_i = expr.get(Variable(i - 1));
81872      const int sign_i = sgn(coeff_i);
81873      if (sign_i > 0) {
81874        assign_r(coeff_expr, coeff_i, ROUND_UP);
81875      }
81876      else {
81877        PPL_DIRTY_TEMP_COEFFICIENT(minus_coeff_i);
81878        neg_assign(minus_coeff_i, coeff_i);
81879        assign_r(coeff_expr, minus_coeff_i, ROUND_UP);
81880      }
81881      // Approximating the maximum/minimum of `expr'.
81882      add_mul_assign_r(d, coeff_expr, x, ROUND_UP);
81883      numer_denom(d, ext_n, ext_d);
81884      if (!maximize) {
81885        neg_assign(ext_n);
81886      }
81887      included = true;
81888      return true;
81889    }
81890
81891    // `expr' is unbounded.
81892    return false;
81893  }
81894}
81895
81896template <typename T>
81897bool
81898BD_Shape<T>::max_min(const Linear_Expression& expr,
81899                     const bool maximize,
81900                     Coefficient& ext_n, Coefficient& ext_d,
81901                     bool& included,
81902                     Generator& g) const {
81903  // The dimension of `expr' should not be greater than the dimension
81904  // of `*this'.
81905  const dimension_type space_dim = space_dimension();
81906  const dimension_type expr_space_dim = expr.space_dimension();
81907  if (space_dim < expr_space_dim) {
81908    throw_dimension_incompatible((maximize
81909                                  ? "maximize(e, ...)"
81910                                  : "minimize(e, ...)"), "e", expr);
81911  }
81912  // Deal with zero-dim BDS first.
81913  if (space_dim == 0) {
81914    if (marked_empty()) {
81915      return false;
81916    }
81917    else {
81918      ext_n = expr.inhomogeneous_term();
81919      ext_d = 1;
81920      included = true;
81921      g = point();
81922      return true;
81923    }
81924  }
81925
81926  shortest_path_closure_assign();
81927  // For an empty BDS we simply return false.
81928  if (marked_empty()) {
81929    return false;
81930  }
81931  Optimization_Mode mode_max_min
81932    = maximize ? MAXIMIZATION : MINIMIZATION;
81933  MIP_Problem mip(space_dim, constraints(), expr, mode_max_min);
81934  if (mip.solve() == OPTIMIZED_MIP_PROBLEM) {
81935    g = mip.optimizing_point();
81936    mip.evaluate_objective_function(g, ext_n, ext_d);
81937    included = true;
81938    return true;
81939  }
81940  // Here `expr' is unbounded in `*this'.
81941  return false;
81942}
81943
81944template <typename T>
81945Poly_Con_Relation
81946BD_Shape<T>::relation_with(const Congruence& cg) const {
81947  const dimension_type space_dim = space_dimension();
81948
81949  // Dimension-compatibility check.
81950  if (cg.space_dimension() > space_dim) {
81951    throw_dimension_incompatible("relation_with(cg)", cg);
81952  }
81953  // If the congruence is an equality, find the relation with
81954  // the equivalent equality constraint.
81955  if (cg.is_equality()) {
81956    Constraint c(cg);
81957    return relation_with(c);
81958  }
81959
81960  shortest_path_closure_assign();
81961
81962  if (marked_empty()) {
81963    return Poly_Con_Relation::saturates()
81964      && Poly_Con_Relation::is_included()
81965      && Poly_Con_Relation::is_disjoint();
81966  }
81967  if (space_dim == 0) {
81968    if (cg.is_inconsistent()) {
81969      return Poly_Con_Relation::is_disjoint();
81970    }
81971    else {
81972      return Poly_Con_Relation::saturates()
81973        && Poly_Con_Relation::is_included();
81974    }
81975  }
81976
81977  // Find the lower bound for a hyperplane with direction
81978  // defined by the congruence.
81979  Linear_Expression le = Linear_Expression(cg.expression());
81980  PPL_DIRTY_TEMP_COEFFICIENT(min_numer);
81981  PPL_DIRTY_TEMP_COEFFICIENT(min_denom);
81982  bool min_included;
81983  bool bounded_below = minimize(le, min_numer, min_denom, min_included);
81984
81985  // If there is no lower bound, then some of the hyperplanes defined by
81986  // the congruence will strictly intersect the shape.
81987  if (!bounded_below) {
81988    return Poly_Con_Relation::strictly_intersects();
81989  }
81990  // TODO: Consider adding a max_and_min() method, performing both
81991  // maximization and minimization so as to possibly exploit
81992  // incrementality of the MIP solver.
81993
81994  // Find the upper bound for a hyperplane with direction
81995  // defined by the congruence.
81996  PPL_DIRTY_TEMP_COEFFICIENT(max_numer);
81997  PPL_DIRTY_TEMP_COEFFICIENT(max_denom);
81998  bool max_included;
81999  bool bounded_above = maximize(le, max_numer, max_denom, max_included);
82000
82001  // If there is no upper bound, then some of the hyperplanes defined by
82002  // the congruence will strictly intersect the shape.
82003  if (!bounded_above) {
82004    return Poly_Con_Relation::strictly_intersects();
82005  }
82006  PPL_DIRTY_TEMP_COEFFICIENT(signed_distance);
82007
82008  // Find the position value for the hyperplane that satisfies the congruence
82009  // and is above the lower bound for the shape.
82010  PPL_DIRTY_TEMP_COEFFICIENT(min_value);
82011  min_value = min_numer / min_denom;
82012  const Coefficient& modulus = cg.modulus();
82013  signed_distance = min_value % modulus;
82014  min_value -= signed_distance;
82015  if (min_value * min_denom < min_numer) {
82016    min_value += modulus;
82017  }
82018  // Find the position value for the hyperplane that satisfies the congruence
82019  // and is below the upper bound for the shape.
82020  PPL_DIRTY_TEMP_COEFFICIENT(max_value);
82021  max_value = max_numer / max_denom;
82022  signed_distance = max_value % modulus;
82023  max_value += signed_distance;
82024  if (max_value * max_denom > max_numer) {
82025    max_value -= modulus;
82026  }
82027  // If the upper bound value is less than the lower bound value,
82028  // then there is an empty intersection with the congruence;
82029  // otherwise it will strictly intersect.
82030  if (max_value < min_value) {
82031    return Poly_Con_Relation::is_disjoint();
82032  }
82033  else {
82034    return Poly_Con_Relation::strictly_intersects();
82035  }
82036}
82037
82038
82039template <typename T>
82040Poly_Con_Relation
82041BD_Shape<T>::relation_with(const Constraint& c) const {
82042  const dimension_type c_space_dim = c.space_dimension();
82043  const dimension_type space_dim = space_dimension();
82044
82045  // Dimension-compatibility check.
82046  if (c_space_dim > space_dim) {
82047    throw_dimension_incompatible("relation_with(c)", c);
82048  }
82049  shortest_path_closure_assign();
82050
82051  if (marked_empty()) {
82052    return Poly_Con_Relation::saturates()
82053      && Poly_Con_Relation::is_included()
82054      && Poly_Con_Relation::is_disjoint();
82055  }
82056  if (space_dim == 0) {
82057    if ((c.is_equality() && c.inhomogeneous_term() != 0)
82058        || (c.is_inequality() && c.inhomogeneous_term() < 0)) {
82059      return Poly_Con_Relation::is_disjoint();
82060    }
82061    else if (c.is_strict_inequality() && c.inhomogeneous_term() == 0) {
82062      // The constraint 0 > 0 implicitly defines the hyperplane 0 = 0;
82063      // thus, the zero-dimensional point also saturates it.
82064      return Poly_Con_Relation::saturates()
82065        && Poly_Con_Relation::is_disjoint();
82066    }
82067    else if (c.is_equality() || c.inhomogeneous_term() == 0) {
82068      return Poly_Con_Relation::saturates()
82069        && Poly_Con_Relation::is_included();
82070    }
82071    else {
82072      // The zero-dimensional point saturates
82073      // neither the positivity constraint 1 >= 0,
82074      // nor the strict positivity constraint 1 > 0.
82075      return Poly_Con_Relation::is_included();
82076    }
82077  }
82078
82079  dimension_type num_vars = 0;
82080  dimension_type i = 0;
82081  dimension_type j = 0;
82082  PPL_DIRTY_TEMP_COEFFICIENT(coeff);
82083  if (!BD_Shape_Helpers::extract_bounded_difference(c, num_vars, i, j, coeff)) {
82084    // Constraints that are not bounded differences.
82085    // Use maximize() and minimize() to do much of the work.
82086
82087    // Find the linear expression for the constraint and use that to
82088    // find if the expression is bounded from above or below and if it
82089    // is, find the maximum and minimum values.
82090    Linear_Expression le(c.expression());
82091    le.set_inhomogeneous_term(Coefficient_zero());
82092
82093    PPL_DIRTY_TEMP_COEFFICIENT(max_numer);
82094    PPL_DIRTY_TEMP_COEFFICIENT(max_denom);
82095    bool max_included;
82096    PPL_DIRTY_TEMP_COEFFICIENT(min_numer);
82097    PPL_DIRTY_TEMP_COEFFICIENT(min_denom);
82098    bool min_included;
82099    bool bounded_above = maximize(le, max_numer, max_denom, max_included);
82100    bool bounded_below = minimize(le, min_numer, min_denom, min_included);
82101    if (!bounded_above) {
82102      if (!bounded_below) {
82103        return Poly_Con_Relation::strictly_intersects();
82104      }
82105      min_numer += c.inhomogeneous_term() * min_denom;
82106      switch (sgn(min_numer)) {
82107      case 1:
82108        if (c.is_equality()) {
82109          return Poly_Con_Relation::is_disjoint();
82110        }
82111        return Poly_Con_Relation::is_included();
82112      case 0:
82113        if (c.is_strict_inequality() || c.is_equality()) {
82114          return Poly_Con_Relation::strictly_intersects();
82115        }
82116        return Poly_Con_Relation::is_included();
82117      case -1:
82118        return Poly_Con_Relation::strictly_intersects();
82119      }
82120    }
82121    if (!bounded_below) {
82122      max_numer += c.inhomogeneous_term() * max_denom;
82123      switch (sgn(max_numer)) {
82124      case 1:
82125        return Poly_Con_Relation::strictly_intersects();
82126      case 0:
82127        if (c.is_strict_inequality()) {
82128          return Poly_Con_Relation::is_disjoint();
82129        }
82130        return Poly_Con_Relation::strictly_intersects();
82131      case -1:
82132        return Poly_Con_Relation::is_disjoint();
82133      }
82134    }
82135    else {
82136      max_numer += c.inhomogeneous_term() * max_denom;
82137      min_numer += c.inhomogeneous_term() * min_denom;
82138      switch (sgn(max_numer)) {
82139      case 1:
82140        switch (sgn(min_numer)) {
82141        case 1:
82142          if (c.is_equality()) {
82143            return Poly_Con_Relation::is_disjoint();
82144          }
82145          return Poly_Con_Relation::is_included();
82146        case 0:
82147          if (c.is_equality()) {
82148            return Poly_Con_Relation::strictly_intersects();
82149          }
82150          if (c.is_strict_inequality()) {
82151            return Poly_Con_Relation::strictly_intersects();
82152          }
82153          return Poly_Con_Relation::is_included();
82154        case -1:
82155          return Poly_Con_Relation::strictly_intersects();
82156        }
82157        PPL_UNREACHABLE;
82158        break;
82159      case 0:
82160        if (min_numer == 0) {
82161          if (c.is_strict_inequality()) {
82162            return Poly_Con_Relation::is_disjoint()
82163              && Poly_Con_Relation::saturates();
82164          }
82165          return Poly_Con_Relation::is_included()
82166            && Poly_Con_Relation::saturates();
82167        }
82168        if (c.is_strict_inequality()) {
82169          return Poly_Con_Relation::is_disjoint();
82170        }
82171        return Poly_Con_Relation::strictly_intersects();
82172      case -1:
82173        return Poly_Con_Relation::is_disjoint();
82174      }
82175    }
82176  }
82177
82178  // Constraints that are bounded differences.
82179  if (num_vars == 0) {
82180    // Dealing with a trivial constraint.
82181    switch (sgn(c.inhomogeneous_term())) {
82182    case -1:
82183      return Poly_Con_Relation::is_disjoint();
82184    case 0:
82185      if (c.is_strict_inequality()) {
82186        return Poly_Con_Relation::saturates()
82187          && Poly_Con_Relation::is_disjoint();
82188      }
82189      else {
82190        return Poly_Con_Relation::saturates()
82191          && Poly_Con_Relation::is_included();
82192      }
82193    case 1:
82194      if (c.is_equality()) {
82195        return Poly_Con_Relation::is_disjoint();
82196      }
82197      else {
82198        return Poly_Con_Relation::is_included();
82199      }
82200    }
82201  }
82202
82203  // Select the cell to be checked for the "<=" part of the constraint,
82204  // and set `coeff' to the absolute value of itself.
82205  const bool negative = (coeff < 0);
82206  const N& x = negative ? dbm[i][j] : dbm[j][i];
82207  const N& y = negative ? dbm[j][i] : dbm[i][j];
82208  if (negative) {
82209    neg_assign(coeff);
82210  }
82211  // Deduce the relation/s of the constraint `c' of the form
82212  // `coeff*v - coeff*u </<=/== c.inhomogeneous_term()'
82213  // with the respectively constraints in `*this'
82214  // `-y <= v - u <= x'.
82215  // Let `d == c.inhomogeneous_term()/coeff'
82216  // and `d1 == -c.inhomogeneous_term()/coeff'.
82217  // The following variables of mpq_class type are used to be precise
82218  // when the bds is defined by integer constraints.
82219  PPL_DIRTY_TEMP(mpq_class, q_x);
82220  PPL_DIRTY_TEMP(mpq_class, q_y);
82221  PPL_DIRTY_TEMP(mpq_class, d);
82222  PPL_DIRTY_TEMP(mpq_class, d1);
82223  PPL_DIRTY_TEMP(mpq_class, c_denom);
82224  PPL_DIRTY_TEMP(mpq_class, q_denom);
82225  assign_r(c_denom, coeff, ROUND_NOT_NEEDED);
82226  assign_r(d, c.inhomogeneous_term(), ROUND_NOT_NEEDED);
82227  neg_assign_r(d1, d, ROUND_NOT_NEEDED);
82228  div_assign_r(d, d, c_denom, ROUND_NOT_NEEDED);
82229  div_assign_r(d1, d1, c_denom, ROUND_NOT_NEEDED);
82230
82231  if (is_plus_infinity(x)) {
82232    if (!is_plus_infinity(y)) {
82233      // `*this' is in the following form:
82234      // `-y <= v - u'.
82235      // In this case `*this' is disjoint from `c' if
82236      // `-y > d' (`-y >= d' if c is a strict equality), i.e. if
82237      // `y < d1' (`y <= d1' if c is a strict equality).
82238      PPL_DIRTY_TEMP_COEFFICIENT(numer);
82239      PPL_DIRTY_TEMP_COEFFICIENT(denom);
82240      numer_denom(y, numer, denom);
82241      assign_r(q_denom, denom, ROUND_NOT_NEEDED);
82242      assign_r(q_y, numer, ROUND_NOT_NEEDED);
82243      div_assign_r(q_y, q_y, q_denom, ROUND_NOT_NEEDED);
82244      if (q_y < d1) {
82245        return Poly_Con_Relation::is_disjoint();
82246      }
82247      if (q_y == d1 && c.is_strict_inequality()) {
82248        return Poly_Con_Relation::is_disjoint();
82249      }
82250    }
82251
82252    // In all other cases `*this' intersects `c'.
82253    return Poly_Con_Relation::strictly_intersects();
82254  }
82255
82256  // Here `x' is not plus-infinity.
82257  PPL_DIRTY_TEMP_COEFFICIENT(numer);
82258  PPL_DIRTY_TEMP_COEFFICIENT(denom);
82259  numer_denom(x, numer, denom);
82260  assign_r(q_denom, denom, ROUND_NOT_NEEDED);
82261  assign_r(q_x, numer, ROUND_NOT_NEEDED);
82262  div_assign_r(q_x, q_x, q_denom, ROUND_NOT_NEEDED);
82263
82264  if (!is_plus_infinity(y)) {
82265    numer_denom(y, numer, denom);
82266    assign_r(q_denom, denom, ROUND_NOT_NEEDED);
82267    assign_r(q_y, numer, ROUND_NOT_NEEDED);
82268    div_assign_r(q_y, q_y, q_denom, ROUND_NOT_NEEDED);
82269    if (q_x == d && q_y == d1) {
82270      if (c.is_strict_inequality()) {
82271        return Poly_Con_Relation::saturates()
82272          && Poly_Con_Relation::is_disjoint();
82273      }
82274      else {
82275        return Poly_Con_Relation::saturates()
82276          && Poly_Con_Relation::is_included();
82277      }
82278    }
82279    // `*this' is disjoint from `c' when
82280    // `-y > d' (`-y >= d' if c is a strict equality), i.e. if
82281    // `y < d1' (`y <= d1' if c is a strict equality).
82282    if (q_y < d1) {
82283      return Poly_Con_Relation::is_disjoint();
82284    }
82285    if (q_y == d1 && c.is_strict_inequality()) {
82286      return Poly_Con_Relation::is_disjoint();
82287    }
82288  }
82289
82290  // Here `y' can be also plus-infinity.
82291  // If `c' is an equality, `*this' is disjoint from `c' if
82292  // `x < d'.
82293  if (d > q_x) {
82294    if (c.is_equality()) {
82295      return Poly_Con_Relation::is_disjoint();
82296    }
82297    else {
82298      return Poly_Con_Relation::is_included();
82299    }
82300  }
82301
82302  if (d == q_x && c.is_nonstrict_inequality()) {
82303    return Poly_Con_Relation::is_included();
82304  }
82305  // In all other cases `*this' intersects `c'.
82306  return Poly_Con_Relation::strictly_intersects();
82307}
82308
82309template <typename T>
82310Poly_Gen_Relation
82311BD_Shape<T>::relation_with(const Generator& g) const {
82312  const dimension_type space_dim = space_dimension();
82313  const dimension_type g_space_dim = g.space_dimension();
82314
82315  // Dimension-compatibility check.
82316  if (space_dim < g_space_dim) {
82317    throw_dimension_incompatible("relation_with(g)", g);
82318  }
82319  shortest_path_closure_assign();
82320  // The empty BDS cannot subsume a generator.
82321  if (marked_empty()) {
82322    return Poly_Gen_Relation::nothing();
82323  }
82324  // A universe BDS in a zero-dimensional space subsumes
82325  // all the generators of a zero-dimensional space.
82326  if (space_dim == 0) {
82327    return Poly_Gen_Relation::subsumes();
82328  }
82329  const bool is_line = g.is_line();
82330  const bool is_line_or_ray = g.is_line_or_ray();
82331
82332  // The relation between the BDS and the given generator is obtained
82333  // checking if the generator satisfies all the constraints in the BDS.
82334  // To check if the generator satisfies all the constraints it's enough
82335  // studying the sign of the scalar product between the generator and
82336  // all the constraints in the BDS.
82337
82338  // Allocation of temporaries done once and for all.
82339  PPL_DIRTY_TEMP_COEFFICIENT(numer);
82340  PPL_DIRTY_TEMP_COEFFICIENT(denom);
82341  PPL_DIRTY_TEMP_COEFFICIENT(product);
82342  // We find in `*this' all the constraints.
82343  // TODO: This loop can be optimized more, if needed.
82344  for (dimension_type i = 0; i <= space_dim; ++i) {
82345    const Coefficient& g_coeff_y = (i > g_space_dim || i == 0)
82346      ? Coefficient_zero() : g.coefficient(Variable(i-1));
82347    const DB_Row<N>& dbm_i = dbm[i];
82348    for (dimension_type j = i + 1; j <= space_dim; ++j) {
82349      const Coefficient& g_coeff_x = (j > g_space_dim)
82350        ? Coefficient_zero() : g.coefficient(Variable(j-1));
82351      const N& dbm_ij = dbm_i[j];
82352      const N& dbm_ji = dbm[j][i];
82353      if (is_additive_inverse(dbm_ji, dbm_ij)) {
82354        // We have one equality constraint: denom*x - denom*y = numer.
82355        // Compute the scalar product.
82356        numer_denom(dbm_ij, numer, denom);
82357        product = g_coeff_y;
82358        product -= g_coeff_x;
82359        product *= denom;
82360        if (!is_line_or_ray) {
82361          add_mul_assign(product, numer, g.divisor());
82362        }
82363        if (product != 0) {
82364          return Poly_Gen_Relation::nothing();
82365        }
82366      }
82367      else {
82368        // We have 0, 1 or 2 binary inequality constraint/s.
82369        if (!is_plus_infinity(dbm_ij)) {
82370          // We have the binary inequality constraint:
82371          // denom*x - denom*y <= numer.
82372          // Compute the scalar product.
82373          numer_denom(dbm_ij, numer, denom);
82374          product = g_coeff_y;
82375          product -= g_coeff_x;
82376          product *= denom;
82377          if (!is_line_or_ray) {
82378            add_mul_assign(product, numer, g.divisor());
82379          }
82380          if (is_line) {
82381            if (product != 0) {
82382              // Lines must saturate all constraints.
82383              return Poly_Gen_Relation::nothing();
82384            }
82385          }
82386          else {
82387            // `g' is either a ray, a point or a closure point.
82388            if (product < 0) {
82389              return Poly_Gen_Relation::nothing();
82390            }
82391          }
82392        }
82393
82394        if (!is_plus_infinity(dbm_ji)) {
82395          // We have the binary inequality constraint: denom*y - denom*x <= b.
82396          // Compute the scalar product.
82397          numer_denom(dbm_ji, numer, denom);
82398          product = 0;
82399          add_mul_assign(product, denom, g_coeff_x);
82400          add_mul_assign(product, -denom, g_coeff_y);
82401          if (!is_line_or_ray) {
82402            add_mul_assign(product, numer, g.divisor());
82403          }
82404          if (is_line) {
82405            if (product != 0) {
82406              // Lines must saturate all constraints.
82407              return Poly_Gen_Relation::nothing();
82408            }
82409          }
82410          else {
82411            // `g' is either a ray, a point or a closure point.
82412            if (product < 0) {
82413              return Poly_Gen_Relation::nothing();
82414            }
82415          }
82416        }
82417      }
82418    }
82419  }
82420
82421  // The generator satisfies all the constraints.
82422  return Poly_Gen_Relation::subsumes();
82423}
82424
82425template <typename T>
82426void
82427BD_Shape<T>::shortest_path_closure_assign() const {
82428  // Do something only if necessary.
82429  if (marked_empty() || marked_shortest_path_closed()) {
82430    return;
82431  }
82432  const dimension_type num_dimensions = space_dimension();
82433  // Zero-dimensional BDSs are necessarily shortest-path closed.
82434  if (num_dimensions == 0) {
82435    return;
82436  }
82437  // Even though the BDS will not change, its internal representation
82438  // is going to be modified by the Floyd-Warshall algorithm.
82439  BD_Shape& x = const_cast<BD_Shape<T>&>(*this);
82440
82441  // Fill the main diagonal with zeros.
82442  for (dimension_type h = num_dimensions + 1; h-- > 0; ) {
82443    PPL_ASSERT(is_plus_infinity(x.dbm[h][h]));
82444    assign_r(x.dbm[h][h], 0, ROUND_NOT_NEEDED);
82445  }
82446
82447  PPL_DIRTY_TEMP(N, sum);
82448  for (dimension_type k = num_dimensions + 1; k-- > 0; ) {
82449    const DB_Row<N>& x_dbm_k = x.dbm[k];
82450    for (dimension_type i = num_dimensions + 1; i-- > 0; ) {
82451      DB_Row<N>& x_dbm_i = x.dbm[i];
82452      const N& x_dbm_i_k = x_dbm_i[k];
82453      if (!is_plus_infinity(x_dbm_i_k)) {
82454        for (dimension_type j = num_dimensions + 1; j-- > 0; ) {
82455          const N& x_dbm_k_j = x_dbm_k[j];
82456          if (!is_plus_infinity(x_dbm_k_j)) {
82457            // Rounding upward for correctness.
82458            add_assign_r(sum, x_dbm_i_k, x_dbm_k_j, ROUND_UP);
82459            min_assign(x_dbm_i[j], sum);
82460          }
82461        }
82462      }
82463    }
82464  }
82465
82466  // Check for emptiness: the BDS is empty if and only if there is a
82467  // negative value on the main diagonal of `dbm'.
82468  for (dimension_type h = num_dimensions + 1; h-- > 0; ) {
82469    N& x_dbm_hh = x.dbm[h][h];
82470    if (sgn(x_dbm_hh) < 0) {
82471      x.set_empty();
82472      return;
82473    }
82474    else {
82475      PPL_ASSERT(sgn(x_dbm_hh) == 0);
82476      // Restore PLUS_INFINITY on the main diagonal.
82477      assign_r(x_dbm_hh, PLUS_INFINITY, ROUND_NOT_NEEDED);
82478    }
82479  }
82480
82481  // The BDS is not empty and it is now shortest-path closed.
82482  x.set_shortest_path_closed();
82483}
82484
82485template <typename T>
82486void
82487BD_Shape<T>::incremental_shortest_path_closure_assign(Variable var) const {
82488  // Do something only if necessary.
82489  if (marked_empty() || marked_shortest_path_closed()) {
82490    return;
82491  }
82492  const dimension_type num_dimensions = space_dimension();
82493  PPL_ASSERT(var.id() < num_dimensions);
82494
82495  // Even though the BDS will not change, its internal representation
82496  // is going to be modified by the incremental Floyd-Warshall algorithm.
82497  BD_Shape& x = const_cast<BD_Shape&>(*this);
82498
82499  // Fill the main diagonal with zeros.
82500  for (dimension_type h = num_dimensions + 1; h-- > 0; ) {
82501    PPL_ASSERT(is_plus_infinity(x.dbm[h][h]));
82502    assign_r(x.dbm[h][h], 0, ROUND_NOT_NEEDED);
82503  }
82504
82505  // Using the incremental Floyd-Warshall algorithm.
82506  PPL_DIRTY_TEMP(N, sum);
82507  const dimension_type v = var.id() + 1;
82508  DB_Row<N>& x_v = x.dbm[v];
82509  // Step 1: Improve all constraints on variable `var'.
82510  for (dimension_type k = num_dimensions + 1; k-- > 0; ) {
82511    DB_Row<N>& x_k = x.dbm[k];
82512    const N& x_v_k = x_v[k];
82513    const N& x_k_v = x_k[v];
82514    const bool x_v_k_finite = !is_plus_infinity(x_v_k);
82515    const bool x_k_v_finite = !is_plus_infinity(x_k_v);
82516    // Specialize inner loop based on finiteness info.
82517    if (x_v_k_finite) {
82518      if (x_k_v_finite) {
82519        // Here both x_v_k and x_k_v are finite.
82520        for (dimension_type i = num_dimensions + 1; i-- > 0; ) {
82521          DB_Row<N>& x_i = x.dbm[i];
82522          const N& x_i_k = x_i[k];
82523          if (!is_plus_infinity(x_i_k)) {
82524            add_assign_r(sum, x_i_k, x_k_v, ROUND_UP);
82525            min_assign(x_i[v], sum);
82526          }
82527          const N& x_k_i = x_k[i];
82528          if (!is_plus_infinity(x_k_i)) {
82529            add_assign_r(sum, x_v_k, x_k_i, ROUND_UP);
82530            min_assign(x_v[i], sum);
82531          }
82532        }
82533      }
82534      else {
82535        // Here x_v_k is finite, but x_k_v is not.
82536        for (dimension_type i = num_dimensions + 1; i-- > 0; ) {
82537          const N& x_k_i = x_k[i];
82538          if (!is_plus_infinity(x_k_i)) {
82539            add_assign_r(sum, x_v_k, x_k_i, ROUND_UP);
82540            min_assign(x_v[i], sum);
82541          }
82542        }
82543      }
82544    }
82545    else if (x_k_v_finite) {
82546      // Here x_v_k is infinite, but x_k_v is finite.
82547      for (dimension_type i = num_dimensions + 1; i-- > 0; ) {
82548        DB_Row<N>& x_i = x.dbm[i];
82549        const N& x_i_k = x_i[k];
82550        if (!is_plus_infinity(x_i_k)) {
82551          add_assign_r(sum, x_i_k, x_k_v, ROUND_UP);
82552          min_assign(x_i[v], sum);
82553        }
82554      }
82555    }
82556    else {
82557      // Here both x_v_k and x_k_v are infinite.
82558      continue;
82559    }
82560  }
82561
82562  // Step 2: improve the other bounds by using the precise bounds
82563  // for the constraints on `var'.
82564  for (dimension_type i = num_dimensions + 1; i-- > 0; ) {
82565    DB_Row<N>& x_i = x.dbm[i];
82566    const N& x_i_v = x_i[v];
82567    if (!is_plus_infinity(x_i_v)) {
82568      for (dimension_type j = num_dimensions + 1; j-- > 0; ) {
82569        const N& x_v_j = x_v[j];
82570        if (!is_plus_infinity(x_v_j)) {
82571          add_assign_r(sum, x_i_v, x_v_j, ROUND_UP);
82572          min_assign(x_i[j], sum);
82573        }
82574      }
82575    }
82576  }
82577
82578  // Check for emptiness: the BDS is empty if and only if there is a
82579  // negative value on the main diagonal of `dbm'.
82580  for (dimension_type h = num_dimensions + 1; h-- > 0; ) {
82581    N& x_dbm_hh = x.dbm[h][h];
82582    if (sgn(x_dbm_hh) < 0) {
82583      x.set_empty();
82584      return;
82585    }
82586    else {
82587      PPL_ASSERT(sgn(x_dbm_hh) == 0);
82588      // Restore PLUS_INFINITY on the main diagonal.
82589      assign_r(x_dbm_hh, PLUS_INFINITY, ROUND_NOT_NEEDED);
82590    }
82591  }
82592
82593  // The BDS is not empty and it is now shortest-path closed.
82594  x.set_shortest_path_closed();
82595}
82596
82597template <typename T>
82598void
82599BD_Shape<T>::shortest_path_reduction_assign() const {
82600  // Do something only if necessary.
82601  if (marked_shortest_path_reduced()) {
82602    return;
82603  }
82604  const dimension_type space_dim = space_dimension();
82605  // Zero-dimensional BDSs are necessarily reduced.
82606  if (space_dim == 0) {
82607    return;
82608  }
82609  // First find the tightest constraints for this BDS.
82610  shortest_path_closure_assign();
82611
82612  // If `*this' is empty, then there is nothing to reduce.
82613  if (marked_empty()) {
82614    return;
82615  }
82616  // Step 1: compute zero-equivalence classes.
82617  // Variables corresponding to indices `i' and `j' are zero-equivalent
82618  // if they lie on a zero-weight loop; since the matrix is shortest-path
82619  // closed, this happens if and only if dbm[i][j] == -dbm[j][i].
82620  std::vector<dimension_type> predecessor;
82621  compute_predecessors(predecessor);
82622  std::vector<dimension_type> leaders;
82623  compute_leader_indices(predecessor, leaders);
82624  const dimension_type num_leaders = leaders.size();
82625
82626  Bit_Matrix redundancy(space_dim + 1, space_dim + 1);
82627  // Init all constraints to be redundant.
82628  // TODO: provide an appropriate method to set multiple bits.
82629  Bit_Row& red_0 = redundancy[0];
82630  for (dimension_type j = space_dim + 1; j-- > 0; ) {
82631    red_0.set(j);
82632  }
82633  for (dimension_type i = space_dim + 1; i-- > 0; ) {
82634    redundancy[i] = red_0;
82635  }
82636  // Step 2: flag non-redundant constraints in the (zero-cycle-free)
82637  // subsystem of bounded differences having only leaders as variables.
82638  PPL_DIRTY_TEMP(N, c);
82639  for (dimension_type l_i = 0; l_i < num_leaders; ++l_i) {
82640    const dimension_type i = leaders[l_i];
82641    const DB_Row<N>& dbm_i = dbm[i];
82642    Bit_Row& redundancy_i = redundancy[i];
82643    for (dimension_type l_j = 0; l_j < num_leaders; ++l_j) {
82644      const dimension_type j = leaders[l_j];
82645      if (redundancy_i[j]) {
82646        const N& dbm_i_j = dbm_i[j];
82647        redundancy_i.clear(j);
82648        for (dimension_type l_k = 0; l_k < num_leaders; ++l_k) {
82649          const dimension_type k = leaders[l_k];
82650          add_assign_r(c, dbm_i[k], dbm[k][j], ROUND_UP);
82651          if (dbm_i_j >= c) {
82652            redundancy_i.set(j);
82653            break;
82654          }
82655        }
82656      }
82657    }
82658  }
82659
82660  // Step 3: flag non-redundant constraints in zero-equivalence classes.
82661  // Each equivalence class must have a single 0-cycle connecting
82662  // all the equivalent variables in increasing order.
82663  std::deque<bool> dealt_with(space_dim + 1, false);
82664  for (dimension_type i = space_dim + 1; i-- > 0; ) {
82665    // We only need to deal with non-singleton zero-equivalence classes
82666    // that haven't already been dealt with.
82667    if (i != predecessor[i] && !dealt_with[i]) {
82668      dimension_type j = i;
82669      while (true) {
82670        const dimension_type predecessor_j = predecessor[j];
82671        if (j == predecessor_j) {
82672          // We finally found the leader of `i'.
82673          PPL_ASSERT(redundancy[i][j]);
82674          redundancy[i].clear(j);
82675          // Here we dealt with `j' (i.e., `predecessor_j'), but it is useless
82676          // to update `dealt_with' because `j' is a leader.
82677          break;
82678        }
82679        // We haven't found the leader of `i' yet.
82680        PPL_ASSERT(redundancy[predecessor_j][j]);
82681        redundancy[predecessor_j].clear(j);
82682        dealt_with[predecessor_j] = true;
82683        j = predecessor_j;
82684      }
82685    }
82686  }
82687  // Even though shortest-path reduction is not going to change the BDS,
82688  // it might change its internal representation.
82689  BD_Shape<T>& x = const_cast<BD_Shape<T>&>(*this);
82690  using std::swap;
82691  swap(x.redundancy_dbm, redundancy);
82692  x.set_shortest_path_reduced();
82693
82694  PPL_ASSERT(is_shortest_path_reduced());
82695}
82696
82697template <typename T>
82698void
82699BD_Shape<T>::upper_bound_assign(const BD_Shape& y) {
82700  const dimension_type space_dim = space_dimension();
82701
82702  // Dimension-compatibility check.
82703  if (space_dim != y.space_dimension()) {
82704    throw_dimension_incompatible("upper_bound_assign(y)", y);
82705  }
82706  // The upper bound of a BD shape `bd' with an empty shape is `bd'.
82707  y.shortest_path_closure_assign();
82708  if (y.marked_empty()) {
82709    return;
82710  }
82711  shortest_path_closure_assign();
82712  if (marked_empty()) {
82713    *this = y;
82714    return;
82715  }
82716
82717  // The bds-hull consists in constructing `*this' with the maximum
82718  // elements selected from `*this' and `y'.
82719  PPL_ASSERT(space_dim == 0 || marked_shortest_path_closed());
82720  for (dimension_type i = space_dim + 1; i-- > 0; ) {
82721    DB_Row<N>& dbm_i = dbm[i];
82722    const DB_Row<N>& y_dbm_i = y.dbm[i];
82723    for (dimension_type j = space_dim + 1; j-- > 0; ) {
82724      N& dbm_ij = dbm_i[j];
82725      const N& y_dbm_ij = y_dbm_i[j];
82726      if (dbm_ij < y_dbm_ij) {
82727        dbm_ij = y_dbm_ij;
82728      }
82729    }
82730  }
82731  // Shortest-path closure is maintained (if it was holding).
82732  // TODO: see whether reduction can be (efficiently!) maintained too.
82733  if (marked_shortest_path_reduced()) {
82734    reset_shortest_path_reduced();
82735  }
82736  PPL_ASSERT(OK());
82737}
82738
82739template <typename T>
82740bool
82741BD_Shape<T>::BFT00_upper_bound_assign_if_exact(const BD_Shape& y) {
82742  // Declare a const reference to *this (to avoid accidental modifications).
82743  const BD_Shape& x = *this;
82744  const dimension_type x_space_dim = x.space_dimension();
82745
82746  // Private method: the caller must ensure the following.
82747  PPL_ASSERT(x_space_dim == y.space_dimension());
82748
82749  // The zero-dim case is trivial.
82750  if (x_space_dim == 0) {
82751    upper_bound_assign(y);
82752    return true;
82753  }
82754  // If `x' or `y' is (known to be) empty, the upper bound is exact.
82755  if (x.marked_empty()) {
82756    *this = y;
82757    return true;
82758  }
82759  else if (y.is_empty()) {
82760    return true;
82761  }
82762  else if (x.is_empty()) {
82763    *this = y;
82764    return true;
82765  }
82766
82767  // Here both `x' and `y' are known to be non-empty.
82768  // Implementation based on Algorithm 4.1 (page 6) in [BemporadFT00TR],
82769  // tailored to the special case of BD shapes.
82770
82771  Variable epsilon(x_space_dim);
82772  Linear_Expression zero_expr;
82773  zero_expr.set_space_dimension(x_space_dim + 1);
82774  Linear_Expression db_expr;
82775  PPL_DIRTY_TEMP_COEFFICIENT(numer);
82776  PPL_DIRTY_TEMP_COEFFICIENT(denom);
82777
82778  // Step 1: compute the constraint system for the envelope env(x,y)
82779  // and put into x_cs_removed and y_cs_removed those non-redundant
82780  // constraints that are not in the constraint system for env(x,y).
82781  // While at it, also add the additional space dimension (epsilon).
82782  Constraint_System env_cs;
82783  Constraint_System x_cs_removed;
82784  Constraint_System y_cs_removed;
82785  x.shortest_path_reduction_assign();
82786  y.shortest_path_reduction_assign();
82787  for (dimension_type i = x_space_dim + 1; i-- > 0; ) {
82788    const Bit_Row& x_red_i = x.redundancy_dbm[i];
82789    const Bit_Row& y_red_i = y.redundancy_dbm[i];
82790    const DB_Row<N>& x_dbm_i = x.dbm[i];
82791    const DB_Row<N>& y_dbm_i = y.dbm[i];
82792    for (dimension_type j = x_space_dim + 1; j-- > 0; ) {
82793      if (x_red_i[j] && y_red_i[j]) {
82794        continue;
82795      }
82796      if (!x_red_i[j]) {
82797        const N& x_dbm_ij = x_dbm_i[j];
82798        PPL_ASSERT(!is_plus_infinity(x_dbm_ij));
82799        numer_denom(x_dbm_ij, numer, denom);
82800        // Build skeleton DB constraint (having the right space dimension).
82801        db_expr = zero_expr;
82802        if (i > 0) {
82803          db_expr += Variable(i-1);
82804        }
82805        if (j > 0) {
82806          db_expr -= Variable(j-1);
82807        }
82808        if (denom != 1) {
82809          db_expr *= denom;
82810        }
82811        db_expr += numer;
82812        if (x_dbm_ij >= y_dbm_i[j]) {
82813          env_cs.insert(db_expr >= 0);
82814        }
82815        else {
82816          db_expr += epsilon;
82817          x_cs_removed.insert(db_expr == 0);
82818        }
82819      }
82820      if (!y_red_i[j]) {
82821        const N& y_dbm_ij = y_dbm_i[j];
82822        const N& x_dbm_ij = x_dbm_i[j];
82823        PPL_ASSERT(!is_plus_infinity(y_dbm_ij));
82824        numer_denom(y_dbm_ij, numer, denom);
82825        // Build skeleton DB constraint (having the right space dimension).
82826        db_expr = zero_expr;
82827        if (i > 0) {
82828          db_expr += Variable(i-1);
82829        }
82830        if (j > 0) {
82831          db_expr -= Variable(j-1);
82832        }
82833        if (denom != 1) {
82834          db_expr *= denom;
82835        }
82836        db_expr += numer;
82837        if (y_dbm_ij >= x_dbm_ij) {
82838          // Check if same constraint was added when considering x_dbm_ij.
82839          if (!x_red_i[j] && x_dbm_ij == y_dbm_ij) {
82840            continue;
82841          }
82842          env_cs.insert(db_expr >= 0);
82843        }
82844        else {
82845          db_expr += epsilon;
82846          y_cs_removed.insert(db_expr == 0);
82847        }
82848      }
82849    }
82850  }
82851
82852  if (x_cs_removed.empty()) {
82853    // No constraint of x was removed: y is included in x.
82854    return true;
82855  }
82856  if (y_cs_removed.empty()) {
82857    // No constraint of y was removed: x is included in y.
82858    *this = y;
82859    return true;
82860  }
82861
82862  // In preparation to Step 4: build the common part of LP problems,
82863  // i.e., the constraints corresponding to env(x,y),
82864  // where the additional space dimension (epsilon) has to be maximized.
82865  MIP_Problem env_lp(x_space_dim + 1, env_cs, epsilon, MAXIMIZATION);
82866  // Pre-solve `env_lp' to later exploit incrementality.
82867  env_lp.solve();
82868  PPL_ASSERT(env_lp.solve() != UNFEASIBLE_MIP_PROBLEM);
82869
82870  // Implementing loop in Steps 3-6.
82871  for (Constraint_System::const_iterator i = x_cs_removed.begin(),
82872         i_end = x_cs_removed.end(); i != i_end; ++i) {
82873    MIP_Problem lp_i(env_lp);
82874    lp_i.add_constraint(*i);
82875    // Pre-solve to exploit incrementality.
82876    if (lp_i.solve() == UNFEASIBLE_MIP_PROBLEM) {
82877      continue;
82878    }
82879    for (Constraint_System::const_iterator j = y_cs_removed.begin(),
82880           j_end = y_cs_removed.end(); j != j_end; ++j) {
82881      MIP_Problem lp_ij(lp_i);
82882      lp_ij.add_constraint(*j);
82883      // Solve and check for a positive optimal value.
82884      switch (lp_ij.solve()) {
82885      case UNFEASIBLE_MIP_PROBLEM:
82886        // CHECKME: is the following actually impossible?
82887        PPL_UNREACHABLE;
82888        return false;
82889      case UNBOUNDED_MIP_PROBLEM:
82890        return false;
82891      case OPTIMIZED_MIP_PROBLEM:
82892        lp_ij.optimal_value(numer, denom);
82893        if (numer > 0) {
82894          return false;
82895        }
82896        break;
82897      }
82898    }
82899  }
82900
82901  // The upper bound of x and y is indeed exact.
82902  upper_bound_assign(y);
82903  PPL_ASSERT(OK());
82904  return true;
82905}
82906
82907template <typename T>
82908template <bool integer_upper_bound>
82909bool
82910BD_Shape<T>::BHZ09_upper_bound_assign_if_exact(const BD_Shape& y) {
82911  PPL_COMPILE_TIME_CHECK(!integer_upper_bound
82912                         || std::numeric_limits<T>::is_integer,
82913                         "BD_Shape<T>::BHZ09_upper_bound_assign_if_exact(y):"
82914                         " instantiating for integer upper bound,"
82915                         " but T in not an integer datatype.");
82916
82917  // FIXME, CHECKME: what about inexact computations?
82918  // Declare a const reference to *this (to avoid accidental modifications).
82919  const BD_Shape& x = *this;
82920  const dimension_type x_space_dim = x.space_dimension();
82921
82922  // Private method: the caller must ensure the following.
82923  PPL_ASSERT(x_space_dim == y.space_dimension());
82924
82925  // The zero-dim case is trivial.
82926  if (x_space_dim == 0) {
82927    upper_bound_assign(y);
82928    return true;
82929  }
82930  // If `x' or `y' is (known to be) empty, the upper bound is exact.
82931  if (x.marked_empty()) {
82932    *this = y;
82933    return true;
82934  }
82935  else if (y.is_empty()) {
82936    return true;
82937  }
82938  else if (x.is_empty()) {
82939    *this = y;
82940    return true;
82941  }
82942
82943  // Here both `x' and `y' are known to be non-empty.
82944  x.shortest_path_reduction_assign();
82945  y.shortest_path_reduction_assign();
82946  PPL_ASSERT(x.marked_shortest_path_closed());
82947  PPL_ASSERT(y.marked_shortest_path_closed());
82948  // Pre-compute the upper bound of `x' and `y'.
82949  BD_Shape<T> ub(x);
82950  ub.upper_bound_assign(y);
82951
82952  PPL_DIRTY_TEMP(N, lhs);
82953  PPL_DIRTY_TEMP(N, rhs);
82954  PPL_DIRTY_TEMP(N, temp_zero);
82955  assign_r(temp_zero, 0, ROUND_NOT_NEEDED);
82956  PPL_DIRTY_TEMP(N, temp_one);
82957  if (integer_upper_bound) {
82958    assign_r(temp_one, 1, ROUND_NOT_NEEDED);
82959  }
82960  for (dimension_type i = x_space_dim + 1; i-- > 0; ) {
82961    const DB_Row<N>& x_i = x.dbm[i];
82962    const Bit_Row& x_red_i = x.redundancy_dbm[i];
82963    const DB_Row<N>& y_i = y.dbm[i];
82964    const DB_Row<N>& ub_i = ub.dbm[i];
82965    for (dimension_type j = x_space_dim + 1; j-- > 0; ) {
82966      // Check redundancy of x_i_j.
82967      if (x_red_i[j]) {
82968        continue;
82969      }
82970      // By non-redundancy, we know that i != j.
82971      PPL_ASSERT(i != j);
82972      const N& x_i_j = x_i[j];
82973      if (x_i_j < y_i[j]) {
82974        for (dimension_type k = x_space_dim + 1; k-- > 0; ) {
82975          const DB_Row<N>& x_k = x.dbm[k];
82976          const DB_Row<N>& y_k = y.dbm[k];
82977          const Bit_Row& y_red_k = y.redundancy_dbm[k];
82978          const DB_Row<N>& ub_k = ub.dbm[k];
82979          const N& ub_k_j = (k == j) ? temp_zero : ub_k[j];
82980          for (dimension_type ell = x_space_dim + 1; ell-- > 0; ) {
82981            // Check redundancy of y_k_ell.
82982            if (y_red_k[ell]) {
82983              continue;
82984            }
82985            // By non-redundancy, we know that k != ell.
82986            PPL_ASSERT(k != ell);
82987            const N& y_k_ell = y_k[ell];
82988            if (y_k_ell < x_k[ell]) {
82989              // The first condition in BHZ09 theorem holds;
82990              // now check for the second condition.
82991              add_assign_r(lhs, x_i_j, y_k_ell, ROUND_UP);
82992              const N& ub_i_ell = (i == ell) ? temp_zero : ub_i[ell];
82993              add_assign_r(rhs, ub_i_ell, ub_k_j, ROUND_UP);
82994              if (integer_upper_bound) {
82995                // Note: adding 1 rather than 2 (as in Theorem 5.3)
82996                // so as to later test for < rather than <=.
82997                add_assign_r(lhs, lhs, temp_one, ROUND_NOT_NEEDED);
82998              }
82999              // Testing for < in both the rational and integer case.
83000              if (lhs < rhs) {
83001                return false;
83002              }
83003            }
83004          }
83005        }
83006      }
83007    }
83008  }
83009  // The upper bound of x and y is indeed exact.
83010  m_swap(ub);
83011  PPL_ASSERT(OK());
83012  return true;
83013}
83014
83015template <typename T>
83016void
83017BD_Shape<T>::difference_assign(const BD_Shape& y) {
83018  const dimension_type space_dim = space_dimension();
83019
83020  // Dimension-compatibility check.
83021  if (space_dim != y.space_dimension()) {
83022    throw_dimension_incompatible("difference_assign(y)", y);
83023  }
83024  BD_Shape new_bd_shape(space_dim, EMPTY);
83025
83026  BD_Shape& x = *this;
83027
83028  x.shortest_path_closure_assign();
83029  // The difference of an empty bounded difference shape
83030  // and of a bounded difference shape `p' is empty.
83031  if (x.marked_empty()) {
83032    return;
83033  }
83034  y.shortest_path_closure_assign();
83035  // The difference of a bounded difference shape `p'
83036  // and an empty bounded difference shape is `p'.
83037  if (y.marked_empty()) {
83038    return;
83039  }
83040  // If both bounded difference shapes are zero-dimensional,
83041  // then at this point they are necessarily universe system of
83042  // bounded differences, so that their difference is empty.
83043  if (space_dim == 0) {
83044    x.set_empty();
83045    return;
83046  }
83047
83048  // TODO: This is just an executable specification.
83049  //       Have to find a more efficient method.
83050  if (y.contains(x)) {
83051    x.set_empty();
83052    return;
83053  }
83054
83055  // We take a constraint of the system y at the time and we
83056  // consider its complementary. Then we intersect the union
83057  // of these complementary constraints with the system x.
83058  const Constraint_System& y_cs = y.constraints();
83059  for (Constraint_System::const_iterator i = y_cs.begin(),
83060         y_cs_end = y_cs.end(); i != y_cs_end; ++i) {
83061    const Constraint& c = *i;
83062    // If the bounded difference shape `x' is included
83063    // in the bounded difference shape defined by `c',
83064    // then `c' _must_ be skipped, as adding its complement to `x'
83065    // would result in the empty bounded difference shape,
83066    // and as we would obtain a result that is less precise
83067    // than the bds-difference.
83068    if (x.relation_with(c).implies(Poly_Con_Relation::is_included())) {
83069      continue;
83070    }
83071    BD_Shape z = x;
83072    const Linear_Expression e(c.expression());
83073    z.add_constraint(e <= 0);
83074    if (!z.is_empty()) {
83075      new_bd_shape.upper_bound_assign(z);
83076    }
83077    if (c.is_equality()) {
83078      z = x;
83079      z.add_constraint(e >= 0);
83080      if (!z.is_empty()) {
83081        new_bd_shape.upper_bound_assign(z);
83082      }
83083    }
83084  }
83085  *this = new_bd_shape;
83086  PPL_ASSERT(OK());
83087}
83088
83089template <typename T>
83090bool
83091BD_Shape<T>::simplify_using_context_assign(const BD_Shape& y) {
83092  BD_Shape& x = *this;
83093  const dimension_type dim = x.space_dimension();
83094  // Dimension-compatibility check.
83095  if (dim != y.space_dimension()) {
83096    throw_dimension_incompatible("simplify_using_context_assign(y)", y);
83097  }
83098  // Filter away the zero-dimensional case.
83099  if (dim == 0) {
83100    if (y.marked_empty()) {
83101      x.set_zero_dim_univ();
83102      return false;
83103    }
83104    else {
83105      return !x.marked_empty();
83106    }
83107  }
83108
83109  // Filter away the case where `x' contains `y'
83110  // (this subsumes the case when `y' is empty).
83111  y.shortest_path_closure_assign();
83112  if (x.contains(y)) {
83113    BD_Shape<T> res(dim, UNIVERSE);
83114    x.m_swap(res);
83115    return false;
83116  }
83117
83118  // Filter away the case where `x' is empty.
83119  x.shortest_path_closure_assign();
83120  if (x.marked_empty()) {
83121    // Search for a constraint of `y' that is not a tautology.
83122    dimension_type i;
83123    dimension_type j;
83124    // Prefer unary constraints.
83125    i = 0;
83126    const DB_Row<N>& y_dbm_0 = y.dbm[0];
83127    for (j = 1; j <= dim; ++j) {
83128      if (!is_plus_infinity(y_dbm_0[j])) {
83129        // FIXME: if N is a float or bounded integer type, then
83130        // we also need to check that we are actually able to construct
83131        // a constraint inconsistent with respect to this one.
83132        goto found;
83133      }
83134    }
83135    j = 0;
83136    for (i = 1; i <= dim; ++i) {
83137      if (!is_plus_infinity(y.dbm[i][0])) {
83138        // FIXME: if N is a float or bounded integer type, then
83139        // we also need to check that we are actually able to construct
83140        // a constraint inconsistent with respect to this one.
83141        goto found;
83142      }
83143    }
83144    // Then search binary constraints.
83145    for (i = 1; i <= dim; ++i) {
83146      const DB_Row<N>& y_dbm_i = y.dbm[i];
83147      for (j = 1; j <= dim; ++j) {
83148        if (!is_plus_infinity(y_dbm_i[j])) {
83149          // FIXME: if N is a float or bounded integer type, then
83150          // we also need to check that we are actually able to construct
83151          // a constraint inconsistent with respect to this one.
83152          goto found;
83153        }
83154      }
83155    }
83156    // Not found: we were not able to build a constraint contradicting
83157    // one of the constraints in `y': `x' cannot be enlarged.
83158    return false;
83159
83160  found:
83161    // Found: build a new BDS contradicting the constraint found.
83162    PPL_ASSERT(i <= dim && j <= dim && (i > 0 || j > 0));
83163    BD_Shape<T> res(dim, UNIVERSE);
83164    PPL_DIRTY_TEMP(N, tmp);
83165    assign_r(tmp, 1, ROUND_UP);
83166    add_assign_r(tmp, tmp, y.dbm[i][j], ROUND_UP);
83167    PPL_ASSERT(!is_plus_infinity(tmp));
83168    // CHECKME: round down is really meant.
83169    neg_assign_r(res.dbm[j][i], tmp, ROUND_DOWN);
83170    x.m_swap(res);
83171    return false;
83172  }
83173
83174  // Here `x' and `y' are not empty and shortest-path closed;
83175  // also, `x' does not contain `y'.
83176  // Let `target' be the intersection of `x' and `y'.
83177  BD_Shape<T> target = x;
83178  target.intersection_assign(y);
83179  const bool bool_result = !target.is_empty();
83180
83181  // Compute a reduced dbm for `x' and ...
83182  x.shortest_path_reduction_assign();
83183  // ... count the non-redundant constraints.
83184  dimension_type x_num_non_redundant = (dim+1)*(dim+1);
83185  for (dimension_type i = dim + 1; i-- > 0; ) {
83186    x_num_non_redundant -= x.redundancy_dbm[i].count_ones();
83187  }
83188  PPL_ASSERT(x_num_non_redundant > 0);
83189
83190  // Let `yy' be a copy of `y': we will keep adding to `yy'
83191  // the non-redundant constraints of `x',
83192  // stopping as soon as `yy' becomes equal to `target'.
83193  BD_Shape<T> yy = y;
83194
83195  // The constraints added to `yy' will be recorded in `res' ...
83196  BD_Shape<T> res(dim, UNIVERSE);
83197  // ... and we will count them too.
83198  dimension_type res_num_non_redundant = 0;
83199
83200  // Compute leader information for `x'.
83201  std::vector<dimension_type> x_leaders;
83202  x.compute_leaders(x_leaders);
83203
83204  // First go through the unary equality constraints.
83205  const DB_Row<N>& x_dbm_0 = x.dbm[0];
83206  DB_Row<N>& yy_dbm_0 = yy.dbm[0];
83207  DB_Row<N>& res_dbm_0 = res.dbm[0];
83208  for (dimension_type j = 1; j <= dim; ++j) {
83209    // Unary equality constraints are encoded in entries dbm_0j and dbm_j0
83210    // provided index j has special variable index 0 as its leader.
83211    if (x_leaders[j] != 0) {
83212      continue;
83213    }
83214    PPL_ASSERT(!is_plus_infinity(x_dbm_0[j]));
83215    if (x_dbm_0[j] < yy_dbm_0[j]) {
83216      res_dbm_0[j] = x_dbm_0[j];
83217      ++res_num_non_redundant;
83218      // Tighten context `yy' using the newly added constraint.
83219      yy_dbm_0[j] = x_dbm_0[j];
83220      yy.reset_shortest_path_closed();
83221    }
83222    PPL_ASSERT(!is_plus_infinity(x.dbm[j][0]));
83223    if (x.dbm[j][0] < yy.dbm[j][0]) {
83224      res.dbm[j][0] = x.dbm[j][0];
83225      ++res_num_non_redundant;
83226      // Tighten context `yy' using the newly added constraint.
83227      yy.dbm[j][0] = x.dbm[j][0];
83228      yy.reset_shortest_path_closed();
83229    }
83230    // Restore shortest-path closure, if it was lost.
83231    if (!yy.marked_shortest_path_closed()) {
83232      Variable var_j(j-1);
83233      yy.incremental_shortest_path_closure_assign(var_j);
83234      if (target.contains(yy)) {
83235        // Target reached: swap `x' and `res' if needed.
83236        if (res_num_non_redundant < x_num_non_redundant) {
83237          res.reset_shortest_path_closed();
83238          x.m_swap(res);
83239        }
83240        return bool_result;
83241      }
83242    }
83243  }
83244
83245  // Go through the binary equality constraints.
83246  // Note: no need to consider the case i == 1.
83247  for (dimension_type i = 2; i <= dim; ++i) {
83248    const dimension_type j = x_leaders[i];
83249    if (j == i || j == 0) {
83250      continue;
83251    }
83252    PPL_ASSERT(!is_plus_infinity(x.dbm[i][j]));
83253    if (x.dbm[i][j] < yy.dbm[i][j]) {
83254      res.dbm[i][j] = x.dbm[i][j];
83255      ++res_num_non_redundant;
83256      // Tighten context `yy' using the newly added constraint.
83257      yy.dbm[i][j] = x.dbm[i][j];
83258      yy.reset_shortest_path_closed();
83259    }
83260    PPL_ASSERT(!is_plus_infinity(x.dbm[j][i]));
83261    if (x.dbm[j][i] < yy.dbm[j][i]) {
83262      res.dbm[j][i] = x.dbm[j][i];
83263      ++res_num_non_redundant;
83264      // Tighten context `yy' using the newly added constraint.
83265      yy.dbm[j][i] = x.dbm[j][i];
83266      yy.reset_shortest_path_closed();
83267    }
83268    // Restore shortest-path closure, if it was lost.
83269    if (!yy.marked_shortest_path_closed()) {
83270      Variable var_j(j-1);
83271      yy.incremental_shortest_path_closure_assign(var_j);
83272      if (target.contains(yy)) {
83273        // Target reached: swap `x' and `res' if needed.
83274        if (res_num_non_redundant < x_num_non_redundant) {
83275          res.reset_shortest_path_closed();
83276          x.m_swap(res);
83277        }
83278        return bool_result;
83279      }
83280    }
83281  }
83282
83283  // Finally go through the (proper) inequality constraints:
83284  // both indices i and j should be leaders.
83285  for (dimension_type i = 0; i <= dim; ++i) {
83286    if (i != x_leaders[i]) {
83287      continue;
83288    }
83289    const DB_Row<N>& x_dbm_i = x.dbm[i];
83290    const Bit_Row& x_redundancy_dbm_i = x.redundancy_dbm[i];
83291    DB_Row<N>& yy_dbm_i = yy.dbm[i];
83292    DB_Row<N>& res_dbm_i = res.dbm[i];
83293    for (dimension_type j = 0; j <= dim; ++j) {
83294      if (j != x_leaders[j] || x_redundancy_dbm_i[j]) {
83295        continue;
83296      }
83297      N& yy_dbm_ij = yy_dbm_i[j];
83298      const N& x_dbm_ij = x_dbm_i[j];
83299      if (x_dbm_ij < yy_dbm_ij) {
83300        res_dbm_i[j] = x_dbm_ij;
83301        ++res_num_non_redundant;
83302        // Tighten context `yy' using the newly added constraint.
83303        yy_dbm_ij = x_dbm_ij;
83304        yy.reset_shortest_path_closed();
83305        PPL_ASSERT(i > 0 || j > 0);
83306        Variable var(((i > 0) ? i : j) - 1);
83307        yy.incremental_shortest_path_closure_assign(var);
83308        if (target.contains(yy)) {
83309          // Target reached: swap `x' and `res' if needed.
83310          if (res_num_non_redundant < x_num_non_redundant) {
83311            res.reset_shortest_path_closed();
83312            x.m_swap(res);
83313          }
83314          return bool_result;
83315        }
83316      }
83317    }
83318  }
83319  // This point should be unreachable.
83320  PPL_UNREACHABLE;
83321  return false;
83322}
83323
83324template <typename T>
83325void
83326BD_Shape<T>::add_space_dimensions_and_embed(const dimension_type m) {
83327  // Adding no dimensions is a no-op.
83328  if (m == 0) {
83329    return;
83330  }
83331  const dimension_type space_dim = space_dimension();
83332  const dimension_type new_space_dim = space_dim + m;
83333  const bool was_zero_dim_univ = (!marked_empty() && space_dim == 0);
83334
83335  // To embed an n-dimension space BDS in a (n+m)-dimension space,
83336  // we just add `m' rows and columns in the bounded difference shape,
83337  // initialized to PLUS_INFINITY.
83338  dbm.grow(new_space_dim + 1);
83339
83340  // Shortest-path closure is maintained (if it was holding).
83341  // TODO: see whether reduction can be (efficiently!) maintained too.
83342  if (marked_shortest_path_reduced()) {
83343    reset_shortest_path_reduced();
83344  }
83345  // If `*this' was the zero-dim space universe BDS,
83346  // the we can set the shortest-path closure flag.
83347  if (was_zero_dim_univ) {
83348    set_shortest_path_closed();
83349  }
83350  PPL_ASSERT(OK());
83351}
83352
83353template <typename T>
83354void
83355BD_Shape<T>::add_space_dimensions_and_project(const dimension_type m) {
83356  // Adding no dimensions is a no-op.
83357  if (m == 0) {
83358    return;
83359  }
83360  const dimension_type space_dim = space_dimension();
83361
83362  // If `*this' was zero-dimensional, then we add `m' rows and columns.
83363  // If it also was non-empty, then we zero all the added elements
83364  // and set the flag for shortest-path closure.
83365  if (space_dim == 0) {
83366    dbm.grow(m + 1);
83367    if (!marked_empty()) {
83368      for (dimension_type i = m + 1; i-- > 0; ) {
83369        DB_Row<N>& dbm_i = dbm[i];
83370        for (dimension_type j = m + 1; j-- > 0; ) {
83371          if (i != j) {
83372            assign_r(dbm_i[j], 0, ROUND_NOT_NEEDED);
83373          }
83374        }
83375      }
83376      set_shortest_path_closed();
83377    }
83378    PPL_ASSERT(OK());
83379    return;
83380  }
83381
83382  // To project an n-dimension space bounded difference shape
83383  // in a (n+m)-dimension space, we add `m' rows and columns.
83384  // In the first row and column of the matrix we add `zero' from
83385  // the (n+1)-th position to the end.
83386  const dimension_type new_space_dim = space_dim + m;
83387  dbm.grow(new_space_dim + 1);
83388
83389  // Bottom of the matrix and first row.
83390  DB_Row<N>& dbm_0 = dbm[0];
83391  for (dimension_type i = space_dim + 1; i <= new_space_dim; ++i) {
83392    assign_r(dbm[i][0], 0, ROUND_NOT_NEEDED);
83393    assign_r(dbm_0[i], 0, ROUND_NOT_NEEDED);
83394  }
83395
83396  if (marked_shortest_path_closed()) {
83397    reset_shortest_path_closed();
83398  }
83399  PPL_ASSERT(OK());
83400}
83401
83402template <typename T>
83403void
83404BD_Shape<T>::remove_space_dimensions(const Variables_Set& vars) {
83405  // The removal of no dimensions from any BDS is a no-op.
83406  // Note that this case also captures the only legal removal of
83407  // space dimensions from a BDS in a 0-dim space.
83408  if (vars.empty()) {
83409    PPL_ASSERT(OK());
83410    return;
83411  }
83412
83413  const dimension_type old_space_dim = space_dimension();
83414
83415  // Dimension-compatibility check.
83416  const dimension_type min_space_dim = vars.space_dimension();
83417  if (old_space_dim < min_space_dim) {
83418    throw_dimension_incompatible("remove_space_dimensions(vs)", min_space_dim);
83419  }
83420  // Shortest-path closure is necessary to keep precision.
83421  shortest_path_closure_assign();
83422
83423  // When removing _all_ dimensions from a BDS, we obtain the
83424  // zero-dimensional BDS.
83425  const dimension_type new_space_dim = old_space_dim - vars.size();
83426  if (new_space_dim == 0) {
83427    dbm.resize_no_copy(1);
83428    if (!marked_empty()) {
83429      // We set the zero_dim_univ flag.
83430      set_zero_dim_univ();
83431    }
83432    PPL_ASSERT(OK());
83433    return;
83434  }
83435
83436  // Handle the case of an empty BD_Shape.
83437  if (marked_empty()) {
83438    dbm.resize_no_copy(new_space_dim + 1);
83439    PPL_ASSERT(OK());
83440    return;
83441  }
83442
83443  // Shortest-path closure is maintained.
83444  // TODO: see whether reduction can be (efficiently!) maintained too.
83445  if (marked_shortest_path_reduced()) {
83446    reset_shortest_path_reduced();
83447  }
83448  // For each variable to remove, we fill the corresponding column and
83449  // row by shifting respectively left and above those
83450  // columns and rows, that will not be removed.
83451  Variables_Set::const_iterator vsi = vars.begin();
83452  Variables_Set::const_iterator vsi_end = vars.end();
83453  dimension_type dst = *vsi + 1;
83454  dimension_type src = dst + 1;
83455  for (++vsi; vsi != vsi_end; ++vsi) {
83456    const dimension_type vsi_next = *vsi + 1;
83457    // All other columns and rows are moved respectively to the left
83458    // and above.
83459    while (src < vsi_next) {
83460      using std::swap;
83461      swap(dbm[dst], dbm[src]);
83462      for (dimension_type i = old_space_dim + 1; i-- > 0; ) {
83463        DB_Row<N>& dbm_i = dbm[i];
83464        assign_or_swap(dbm_i[dst], dbm_i[src]);
83465      }
83466      ++dst;
83467      ++src;
83468    }
83469    ++src;
83470  }
83471
83472  // Moving the remaining rows and columns.
83473  while (src <= old_space_dim) {
83474    using std::swap;
83475    swap(dbm[dst], dbm[src]);
83476    for (dimension_type i = old_space_dim + 1; i-- > 0; ) {
83477      DB_Row<N>& dbm_i = dbm[i];
83478      assign_or_swap(dbm_i[dst], dbm_i[src]);
83479    }
83480    ++src;
83481    ++dst;
83482  }
83483
83484  // Update the space dimension.
83485  dbm.resize_no_copy(new_space_dim + 1);
83486  PPL_ASSERT(OK());
83487}
83488
83489template <typename T>
83490template <typename Partial_Function>
83491void
83492BD_Shape<T>::map_space_dimensions(const Partial_Function& pfunc) {
83493  const dimension_type space_dim = space_dimension();
83494  // TODO: this implementation is just an executable specification.
83495  if (space_dim == 0) {
83496    return;
83497  }
83498  if (pfunc.has_empty_codomain()) {
83499    // All dimensions vanish: the BDS becomes zero_dimensional.
83500    remove_higher_space_dimensions(0);
83501    return;
83502  }
83503
83504  const dimension_type new_space_dim = pfunc.max_in_codomain() + 1;
83505  // If we are going to actually reduce the space dimension,
83506  // then shortest-path closure is required to keep precision.
83507  if (new_space_dim < space_dim) {
83508    shortest_path_closure_assign();
83509  }
83510  // If the BDS is empty, then it is sufficient to adjust the
83511  // space dimension of the bounded difference shape.
83512  if (marked_empty()) {
83513    remove_higher_space_dimensions(new_space_dim);
83514    return;
83515  }
83516
83517  // Shortest-path closure is maintained (if it was holding).
83518  // TODO: see whether reduction can be (efficiently!) maintained too.
83519  if (marked_shortest_path_reduced()) {
83520    reset_shortest_path_reduced();
83521  }
83522  // We create a new matrix with the new space dimension.
83523  DB_Matrix<N> x(new_space_dim+1);
83524  // First of all we must map the unary constraints, because
83525  // there is the fictitious variable `zero', that can't be mapped
83526  // at all.
83527  DB_Row<N>& dbm_0 = dbm[0];
83528  DB_Row<N>& x_0 = x[0];
83529  for (dimension_type j = 1; j <= space_dim; ++j) {
83530    dimension_type new_j;
83531    if (pfunc.maps(j - 1, new_j)) {
83532      assign_or_swap(x_0[new_j + 1], dbm_0[j]);
83533      assign_or_swap(x[new_j + 1][0], dbm[j][0]);
83534    }
83535  }
83536  // Now we map the binary constraints, exchanging the indexes.
83537  for (dimension_type i = 1; i <= space_dim; ++i) {
83538    dimension_type new_i;
83539    if (pfunc.maps(i - 1, new_i)) {
83540      DB_Row<N>& dbm_i = dbm[i];
83541      ++new_i;
83542      DB_Row<N>& x_new_i = x[new_i];
83543      for (dimension_type j = i+1; j <= space_dim; ++j) {
83544        dimension_type new_j;
83545        if (pfunc.maps(j - 1, new_j)) {
83546          ++new_j;
83547          assign_or_swap(x_new_i[new_j], dbm_i[j]);
83548          assign_or_swap(x[new_j][new_i], dbm[j][i]);
83549        }
83550      }
83551    }
83552  }
83553
83554  using std::swap;
83555  swap(dbm, x);
83556  PPL_ASSERT(OK());
83557}
83558
83559template <typename T>
83560void
83561BD_Shape<T>::intersection_assign(const BD_Shape& y) {
83562  const dimension_type space_dim = space_dimension();
83563
83564  // Dimension-compatibility check.
83565  if (space_dim != y.space_dimension()) {
83566    throw_dimension_incompatible("intersection_assign(y)", y);
83567  }
83568  // If one of the two bounded difference shapes is empty,
83569  // the intersection is empty.
83570  if (marked_empty()) {
83571    return;
83572  }
83573  if (y.marked_empty()) {
83574    set_empty();
83575    return;
83576  }
83577
83578  // If both bounded difference shapes are zero-dimensional,
83579  // then at this point they are necessarily non-empty,
83580  // so that their intersection is non-empty too.
83581  if (space_dim == 0) {
83582    return;
83583  }
83584  // To intersect two bounded difference shapes we compare
83585  // the constraints and we choose the less values.
83586  bool changed = false;
83587  for (dimension_type i = space_dim + 1; i-- > 0; ) {
83588    DB_Row<N>& dbm_i = dbm[i];
83589    const DB_Row<N>& y_dbm_i = y.dbm[i];
83590    for (dimension_type j = space_dim + 1; j-- > 0; ) {
83591      N& dbm_ij = dbm_i[j];
83592      const N& y_dbm_ij = y_dbm_i[j];
83593      if (dbm_ij > y_dbm_ij) {
83594        dbm_ij = y_dbm_ij;
83595        changed = true;
83596      }
83597    }
83598  }
83599
83600  if (changed && marked_shortest_path_closed()) {
83601    reset_shortest_path_closed();
83602  }
83603  PPL_ASSERT(OK());
83604}
83605
83606template <typename T>
83607template <typename Iterator>
83608void
83609BD_Shape<T>::CC76_extrapolation_assign(const BD_Shape& y,
83610                                       Iterator first, Iterator last,
83611                                       unsigned* tp) {
83612  const dimension_type space_dim = space_dimension();
83613
83614  // Dimension-compatibility check.
83615  if (space_dim != y.space_dimension()) {
83616    throw_dimension_incompatible("CC76_extrapolation_assign(y)", y);
83617  }
83618  // We assume that `y' is contained in or equal to `*this'.
83619  PPL_EXPECT_HEAVY(copy_contains(*this, y));
83620
83621  // If both bounded difference shapes are zero-dimensional,
83622  // since `*this' contains `y', we simply return `*this'.
83623  if (space_dim == 0) {
83624    return;
83625  }
83626  shortest_path_closure_assign();
83627  // If `*this' is empty, since `*this' contains `y', `y' is empty too.
83628  if (marked_empty()) {
83629    return;
83630  }
83631  y.shortest_path_closure_assign();
83632  // If `y' is empty, we return.
83633  if (y.marked_empty()) {
83634    return;
83635  }
83636  // If there are tokens available, work on a temporary copy.
83637  if (tp != 0 && *tp > 0) {
83638    BD_Shape<T> x_tmp(*this);
83639    x_tmp.CC76_extrapolation_assign(y, first, last, 0);
83640    // If the widening was not precise, use one of the available tokens.
83641    if (!contains(x_tmp)) {
83642      --(*tp);
83643    }
83644    return;
83645  }
83646
83647  // Compare each constraint in `y' to the corresponding one in `*this'.
83648  // The constraint in `*this' is kept as is if it is stronger than or
83649  // equal to the constraint in `y'; otherwise, the inhomogeneous term
83650  // of the constraint in `*this' is further compared with elements taken
83651  // from a sorted container (the stop-points, provided by the user), and
83652  // is replaced by the first entry, if any, which is greater than or equal
83653  // to the inhomogeneous term. If no such entry exists, the constraint
83654  // is removed altogether.
83655  for (dimension_type i = space_dim + 1; i-- > 0; ) {
83656    DB_Row<N>& dbm_i = dbm[i];
83657    const DB_Row<N>& y_dbm_i = y.dbm[i];
83658    for (dimension_type j = space_dim + 1; j-- > 0; ) {
83659      N& dbm_ij = dbm_i[j];
83660      const N& y_dbm_ij = y_dbm_i[j];
83661      if (y_dbm_ij < dbm_ij) {
83662        Iterator k = std::lower_bound(first, last, dbm_ij);
83663        if (k != last) {
83664          if (dbm_ij < *k) {
83665            assign_r(dbm_ij, *k, ROUND_UP);
83666          }
83667        }
83668        else {
83669          assign_r(dbm_ij, PLUS_INFINITY, ROUND_NOT_NEEDED);
83670        }
83671      }
83672    }
83673  }
83674  reset_shortest_path_closed();
83675  PPL_ASSERT(OK());
83676}
83677
83678template <typename T>
83679void
83680BD_Shape<T>::get_limiting_shape(const Constraint_System& cs,
83681                                BD_Shape& limiting_shape) const {
83682  // Private method: the caller has to ensure the following.
83683  PPL_ASSERT(cs.space_dimension() <= space_dimension());
83684
83685  shortest_path_closure_assign();
83686  bool changed = false;
83687  PPL_DIRTY_TEMP_COEFFICIENT(coeff);
83688  PPL_DIRTY_TEMP_COEFFICIENT(minus_c_term);
83689  PPL_DIRTY_TEMP(N, d);
83690  PPL_DIRTY_TEMP(N, d1);
83691  for (Constraint_System::const_iterator cs_i = cs.begin(),
83692         cs_end = cs.end(); cs_i != cs_end; ++cs_i) {
83693    const Constraint& c = *cs_i;
83694    dimension_type num_vars = 0;
83695    dimension_type i = 0;
83696    dimension_type j = 0;
83697    // Constraints that are not bounded differences are ignored.
83698    if (BD_Shape_Helpers::extract_bounded_difference(c, num_vars, i, j, coeff)) {
83699      // Select the cell to be modified for the "<=" part of the constraint,
83700      // and set `coeff' to the absolute value of itself.
83701      const bool negative = (coeff < 0);
83702      const N& x = negative ? dbm[i][j] : dbm[j][i];
83703      const N& y = negative ? dbm[j][i] : dbm[i][j];
83704      DB_Matrix<N>& ls_dbm = limiting_shape.dbm;
83705      if (negative) {
83706        neg_assign(coeff);
83707      }
83708      // Compute the bound for `x', rounding towards plus infinity.
83709      div_round_up(d, c.inhomogeneous_term(), coeff);
83710      if (x <= d) {
83711        if (c.is_inequality()) {
83712          N& ls_x = negative ? ls_dbm[i][j] : ls_dbm[j][i];
83713          if (ls_x > d) {
83714            ls_x = d;
83715            changed = true;
83716          }
83717        }
83718        else {
83719          // Compute the bound for `y', rounding towards plus infinity.
83720          neg_assign(minus_c_term, c.inhomogeneous_term());
83721          div_round_up(d1, minus_c_term, coeff);
83722          if (y <= d1) {
83723            N& ls_x = negative ? ls_dbm[i][j] : ls_dbm[j][i];
83724            N& ls_y = negative ? ls_dbm[j][i] : ls_dbm[i][j];
83725            if ((ls_x >= d && ls_y > d1) || (ls_x > d && ls_y >= d1)) {
83726              ls_x = d;
83727              ls_y = d1;
83728              changed = true;
83729            }
83730          }
83731        }
83732      }
83733    }
83734  }
83735
83736  // In general, adding a constraint does not preserve the shortest-path
83737  // closure of the bounded difference shape.
83738  if (changed && limiting_shape.marked_shortest_path_closed()) {
83739    limiting_shape.reset_shortest_path_closed();
83740  }
83741}
83742
83743template <typename T>
83744void
83745BD_Shape<T>::limited_CC76_extrapolation_assign(const BD_Shape& y,
83746                                               const Constraint_System& cs,
83747                                               unsigned* tp) {
83748  // Dimension-compatibility check.
83749  const dimension_type space_dim = space_dimension();
83750  if (space_dim != y.space_dimension()) {
83751    throw_dimension_incompatible("limited_CC76_extrapolation_assign(y, cs)",
83752                                 y);
83753  }
83754  // `cs' must be dimension-compatible with the two systems
83755  // of bounded differences.
83756  const dimension_type cs_space_dim = cs.space_dimension();
83757  if (space_dim < cs_space_dim) {
83758    throw_invalid_argument("limited_CC76_extrapolation_assign(y, cs)",
83759                           "cs is space_dimension incompatible");
83760  }
83761
83762  // Strict inequalities not allowed.
83763  if (cs.has_strict_inequalities()) {
83764    throw_invalid_argument("limited_CC76_extrapolation_assign(y, cs)",
83765                           "cs has strict inequalities");
83766  }
83767  // The limited CC76-extrapolation between two systems of bounded
83768  // differences in a zero-dimensional space is a system of bounded
83769  // differences in a zero-dimensional space, too.
83770  if (space_dim == 0) {
83771    return;
83772  }
83773  // We assume that `y' is contained in or equal to `*this'.
83774  PPL_EXPECT_HEAVY(copy_contains(*this, y));
83775
83776  // If `*this' is empty, since `*this' contains `y', `y' is empty too.
83777  if (marked_empty()) {
83778    return;
83779  }
83780  // If `y' is empty, we return.
83781  if (y.marked_empty()) {
83782    return;
83783  }
83784  BD_Shape<T> limiting_shape(space_dim, UNIVERSE);
83785  get_limiting_shape(cs, limiting_shape);
83786  CC76_extrapolation_assign(y, tp);
83787  intersection_assign(limiting_shape);
83788}
83789
83790template <typename T>
83791void
83792BD_Shape<T>::BHMZ05_widening_assign(const BD_Shape& y, unsigned* tp) {
83793  const dimension_type space_dim = space_dimension();
83794
83795  // Dimension-compatibility check.
83796  if (space_dim != y.space_dimension()) {
83797    throw_dimension_incompatible("BHMZ05_widening_assign(y)", y);
83798  }
83799  // We assume that `y' is contained in or equal to `*this'.
83800  PPL_EXPECT_HEAVY(copy_contains(*this, y));
83801
83802  // Compute the affine dimension of `y'.
83803  const dimension_type y_affine_dim = y.affine_dimension();
83804  // If the affine dimension of `y' is zero, then either `y' is
83805  // zero-dimensional, or it is empty, or it is a singleton.
83806  // In all cases, due to the inclusion hypothesis, the result is `*this'.
83807  if (y_affine_dim == 0) {
83808    return;
83809  }
83810  // If the affine dimension has changed, due to the inclusion hypothesis,
83811  // the result is `*this'.
83812  const dimension_type x_affine_dim = affine_dimension();
83813  PPL_ASSERT(x_affine_dim >= y_affine_dim);
83814  if (x_affine_dim != y_affine_dim) {
83815    return;
83816  }
83817  // If there are tokens available, work on a temporary copy.
83818  if (tp != 0 && *tp > 0) {
83819    BD_Shape<T> x_tmp(*this);
83820    x_tmp.BHMZ05_widening_assign(y, 0);
83821    // If the widening was not precise, use one of the available tokens.
83822    if (!contains(x_tmp)) {
83823      --(*tp);
83824    }
83825    return;
83826  }
83827
83828  // Here no token is available.
83829  PPL_ASSERT(marked_shortest_path_closed() && y.marked_shortest_path_closed());
83830  // Minimize `y'.
83831  y.shortest_path_reduction_assign();
83832
83833  // Extrapolate unstable bounds, taking into account redundancy in `y'.
83834  for (dimension_type i = space_dim + 1; i-- > 0; ) {
83835    DB_Row<N>& dbm_i = dbm[i];
83836    const DB_Row<N>& y_dbm_i = y.dbm[i];
83837    const Bit_Row& y_redundancy_i = y.redundancy_dbm[i];
83838    for (dimension_type j = space_dim + 1; j-- > 0; ) {
83839      N& dbm_ij = dbm_i[j];
83840      // Note: in the following line the use of `!=' (as opposed to
83841      // the use of `<' that would seem -but is not- equivalent) is
83842      // intentional.
83843      if (y_redundancy_i[j] || y_dbm_i[j] != dbm_ij) {
83844        assign_r(dbm_ij, PLUS_INFINITY, ROUND_NOT_NEEDED);
83845      }
83846    }
83847  }
83848  // NOTE: this will also reset the shortest-path reduction flag,
83849  // even though the dbm is still in reduced form. However, the
83850  // current implementation invariant requires that any reduced dbm
83851  // is closed too.
83852  reset_shortest_path_closed();
83853  PPL_ASSERT(OK());
83854}
83855
83856template <typename T>
83857void
83858BD_Shape<T>::limited_BHMZ05_extrapolation_assign(const BD_Shape& y,
83859                                                 const Constraint_System& cs,
83860                                                 unsigned* tp) {
83861  // Dimension-compatibility check.
83862  const dimension_type space_dim = space_dimension();
83863  if (space_dim != y.space_dimension()) {
83864    throw_dimension_incompatible("limited_BHMZ05_extrapolation_assign(y, cs)",
83865                                 y);
83866  }
83867  // `cs' must be dimension-compatible with the two systems
83868  // of bounded differences.
83869  const dimension_type cs_space_dim = cs.space_dimension();
83870  if (space_dim < cs_space_dim) {
83871    throw_invalid_argument("limited_BHMZ05_extrapolation_assign(y, cs)",
83872                           "cs is space-dimension incompatible");
83873  }
83874  // Strict inequalities are not allowed.
83875  if (cs.has_strict_inequalities()) {
83876    throw_invalid_argument("limited_BHMZ05_extrapolation_assign(y, cs)",
83877                           "cs has strict inequalities");
83878  }
83879  // The limited BHMZ05-extrapolation between two systems of bounded
83880  // differences in a zero-dimensional space is a system of bounded
83881  // differences in a zero-dimensional space, too.
83882  if (space_dim == 0) {
83883    return;
83884  }
83885  // We assume that `y' is contained in or equal to `*this'.
83886  PPL_EXPECT_HEAVY(copy_contains(*this, y));
83887
83888  // If `*this' is empty, since `*this' contains `y', `y' is empty too.
83889  if (marked_empty()) {
83890    return;
83891  }
83892  // If `y' is empty, we return.
83893  if (y.marked_empty()) {
83894    return;
83895  }
83896  BD_Shape<T> limiting_shape(space_dim, UNIVERSE);
83897  get_limiting_shape(cs, limiting_shape);
83898  BHMZ05_widening_assign(y, tp);
83899  intersection_assign(limiting_shape);
83900}
83901
83902template <typename T>
83903void
83904BD_Shape<T>::CC76_narrowing_assign(const BD_Shape& y) {
83905  const dimension_type space_dim = space_dimension();
83906
83907  // Dimension-compatibility check.
83908  if (space_dim != y.space_dimension()) {
83909    throw_dimension_incompatible("CC76_narrowing_assign(y)", y);
83910  }
83911  // We assume that `*this' is contained in or equal to `y'.
83912  PPL_EXPECT_HEAVY(copy_contains(y, *this));
83913
83914  // If both bounded difference shapes are zero-dimensional,
83915  // since `y' contains `*this', we simply return `*this'.
83916  if (space_dim == 0) {
83917    return;
83918  }
83919  y.shortest_path_closure_assign();
83920  // If `y' is empty, since `y' contains `this', `*this' is empty too.
83921  if (y.marked_empty()) {
83922    return;
83923  }
83924  shortest_path_closure_assign();
83925  // If `*this' is empty, we return.
83926  if (marked_empty()) {
83927    return;
83928  }
83929  // Replace each constraint in `*this' by the corresponding constraint
83930  // in `y' if the corresponding inhomogeneous terms are both finite.
83931  bool changed = false;
83932  for (dimension_type i = space_dim + 1; i-- > 0; ) {
83933    DB_Row<N>& dbm_i = dbm[i];
83934    const DB_Row<N>& y_dbm_i = y.dbm[i];
83935    for (dimension_type j = space_dim + 1; j-- > 0; ) {
83936      N& dbm_ij = dbm_i[j];
83937      const N& y_dbm_ij = y_dbm_i[j];
83938      if (!is_plus_infinity(dbm_ij)
83939          && !is_plus_infinity(y_dbm_ij)
83940          && dbm_ij != y_dbm_ij) {
83941        dbm_ij = y_dbm_ij;
83942        changed = true;
83943      }
83944    }
83945  }
83946  if (changed && marked_shortest_path_closed()) {
83947    reset_shortest_path_closed();
83948  }
83949  PPL_ASSERT(OK());
83950}
83951
83952template <typename T>
83953void
83954BD_Shape<T>
83955::deduce_v_minus_u_bounds(const dimension_type v,
83956                          const dimension_type last_v,
83957                          const Linear_Expression& sc_expr,
83958                          Coefficient_traits::const_reference sc_denom,
83959                          const N& ub_v) {
83960  PPL_ASSERT(sc_denom > 0);
83961  PPL_ASSERT(!is_plus_infinity(ub_v));
83962  // Deduce constraints of the form `v - u', where `u != v'.
83963  // Note: the shortest-path closure is able to deduce the constraint
83964  // `v - u <= ub_v - lb_u'. We can be more precise if variable `u'
83965  // played an active role in the computation of the upper bound for `v',
83966  // i.e., if the corresponding coefficient `q == expr_u/denom' is
83967  // greater than zero. In particular:
83968  // if `q >= 1',    then `v - u <= ub_v - ub_u';
83969  // if `0 < q < 1', then `v - u <= ub_v - (q*ub_u + (1-q)*lb_u)'.
83970  PPL_DIRTY_TEMP(mpq_class, mpq_sc_denom);
83971  assign_r(mpq_sc_denom, sc_denom, ROUND_NOT_NEEDED);
83972  const DB_Row<N>& dbm_0 = dbm[0];
83973  // Speculative allocation of temporaries to be used in the following loop.
83974  PPL_DIRTY_TEMP(mpq_class, minus_lb_u);
83975  PPL_DIRTY_TEMP(mpq_class, q);
83976  PPL_DIRTY_TEMP(mpq_class, ub_u);
83977  PPL_DIRTY_TEMP(N, up_approx);
83978  for (Linear_Expression::const_iterator u = sc_expr.begin(),
83979        u_end = sc_expr.lower_bound(Variable(last_v)); u != u_end; ++u) {
83980    const dimension_type u_dim = u.variable().space_dimension();
83981    if (u_dim == v) {
83982      continue;
83983    }
83984    const Coefficient& expr_u = *u;
83985    if (expr_u < 0) {
83986      continue;
83987    }
83988    PPL_ASSERT(expr_u > 0);
83989    if (expr_u >= sc_denom) {
83990      // Deducing `v - u <= ub_v - ub_u'.
83991      sub_assign_r(dbm[u_dim][v], ub_v, dbm_0[u_dim], ROUND_UP);
83992    }
83993    else {
83994      DB_Row<N>& dbm_u = dbm[u_dim];
83995      const N& dbm_u0 = dbm_u[0];
83996      if (!is_plus_infinity(dbm_u0)) {
83997        // Let `ub_u' and `lb_u' be the known upper and lower bound
83998        // for `u', respectively. Letting `q = expr_u/sc_denom' be the
83999        // rational coefficient of `u' in `sc_expr/sc_denom',
84000        // the upper bound for `v - u' is computed as
84001        // `ub_v - (q * ub_u + (1-q) * lb_u)', i.e.,
84002        // `ub_v + (-lb_u) - q * (ub_u + (-lb_u))'.
84003        assign_r(minus_lb_u, dbm_u0, ROUND_NOT_NEEDED);
84004        assign_r(q, expr_u, ROUND_NOT_NEEDED);
84005        div_assign_r(q, q, mpq_sc_denom, ROUND_NOT_NEEDED);
84006        assign_r(ub_u, dbm_0[u_dim], ROUND_NOT_NEEDED);
84007        // Compute `ub_u - lb_u'.
84008        add_assign_r(ub_u, ub_u, minus_lb_u, ROUND_NOT_NEEDED);
84009        // Compute `(-lb_u) - q * (ub_u - lb_u)'.
84010        sub_mul_assign_r(minus_lb_u, q, ub_u, ROUND_NOT_NEEDED);
84011        assign_r(up_approx, minus_lb_u, ROUND_UP);
84012        // Deducing `v - u <= ub_v - (q * ub_u + (1-q) * lb_u)'.
84013        add_assign_r(dbm_u[v], ub_v, up_approx, ROUND_UP);
84014      }
84015    }
84016  }
84017}
84018
84019template <typename T>
84020void
84021BD_Shape<T>
84022::deduce_u_minus_v_bounds(const dimension_type v,
84023                          const dimension_type last_v,
84024                          const Linear_Expression& sc_expr,
84025                          Coefficient_traits::const_reference sc_denom,
84026                          const N& minus_lb_v) {
84027  PPL_ASSERT(sc_denom > 0);
84028  PPL_ASSERT(!is_plus_infinity(minus_lb_v));
84029  // Deduce constraints of the form `u - v', where `u != v'.
84030  // Note: the shortest-path closure is able to deduce the constraint
84031  // `u - v <= ub_u - lb_v'. We can be more precise if variable `u'
84032  // played an active role in the computation of the lower bound for `v',
84033  // i.e., if the corresponding coefficient `q == expr_u/denom' is
84034  // greater than zero. In particular:
84035  // if `q >= 1',    then `u - v <= lb_u - lb_v';
84036  // if `0 < q < 1', then `u - v <= (q*lb_u + (1-q)*ub_u) - lb_v'.
84037  PPL_DIRTY_TEMP(mpq_class, mpq_sc_denom);
84038  assign_r(mpq_sc_denom, sc_denom, ROUND_NOT_NEEDED);
84039  DB_Row<N>& dbm_0 = dbm[0];
84040  DB_Row<N>& dbm_v = dbm[v];
84041  // Speculative allocation of temporaries to be used in the following loop.
84042  PPL_DIRTY_TEMP(mpq_class, ub_u);
84043  PPL_DIRTY_TEMP(mpq_class, q);
84044  PPL_DIRTY_TEMP(mpq_class, minus_lb_u);
84045  PPL_DIRTY_TEMP(N, up_approx);
84046  // No need to consider indices greater than `last_v'.
84047  for (Linear_Expression::const_iterator u = sc_expr.begin(),
84048        u_end = sc_expr.lower_bound(Variable(last_v)); u != u_end; ++u) {
84049    const Variable u_var = u.variable();
84050    const dimension_type u_dim = u_var.space_dimension();
84051    if (u_var.space_dimension() == v) {
84052      continue;
84053    }
84054    const Coefficient& expr_u = *u;
84055    if (expr_u < 0) {
84056      continue;
84057    }
84058    PPL_ASSERT(expr_u > 0);
84059    if (expr_u >= sc_denom) {
84060      // Deducing `u - v <= lb_u - lb_v',
84061      // i.e., `u - v <= (-lb_v) - (-lb_u)'.
84062      sub_assign_r(dbm_v[u_dim], minus_lb_v, dbm[u_dim][0], ROUND_UP);
84063    }
84064    else {
84065      const N& dbm_0u = dbm_0[u_dim];
84066      if (!is_plus_infinity(dbm_0u)) {
84067        // Let `ub_u' and `lb_u' be the known upper and lower bound
84068        // for `u', respectively. Letting `q = expr_u/sc_denom' be the
84069        // rational coefficient of `u' in `sc_expr/sc_denom',
84070        // the upper bound for `u - v' is computed as
84071        // `(q * lb_u + (1-q) * ub_u) - lb_v', i.e.,
84072        // `ub_u - q * (ub_u + (-lb_u)) + minus_lb_v'.
84073        assign_r(ub_u, dbm_0u, ROUND_NOT_NEEDED);
84074        assign_r(q, expr_u, ROUND_NOT_NEEDED);
84075        div_assign_r(q, q, mpq_sc_denom, ROUND_NOT_NEEDED);
84076        assign_r(minus_lb_u, dbm[u_dim][0], ROUND_NOT_NEEDED);
84077        // Compute `ub_u - lb_u'.
84078        add_assign_r(minus_lb_u, minus_lb_u, ub_u, ROUND_NOT_NEEDED);
84079        // Compute `ub_u - q * (ub_u - lb_u)'.
84080        sub_mul_assign_r(ub_u, q, minus_lb_u, ROUND_NOT_NEEDED);
84081        assign_r(up_approx, ub_u, ROUND_UP);
84082        // Deducing `u - v <= (q*lb_u + (1-q)*ub_u) - lb_v'.
84083        add_assign_r(dbm_v[u_dim], up_approx, minus_lb_v, ROUND_UP);
84084      }
84085    }
84086  }
84087}
84088
84089template <typename T>
84090void
84091BD_Shape<T>::forget_all_dbm_constraints(const dimension_type v) {
84092  PPL_ASSERT(0 < v && v <= dbm.num_rows());
84093  DB_Row<N>& dbm_v = dbm[v];
84094  for (dimension_type i = dbm.num_rows(); i-- > 0; ) {
84095    assign_r(dbm_v[i], PLUS_INFINITY, ROUND_NOT_NEEDED);
84096    assign_r(dbm[i][v], PLUS_INFINITY, ROUND_NOT_NEEDED);
84097  }
84098}
84099
84100template <typename T>
84101void
84102BD_Shape<T>::forget_binary_dbm_constraints(const dimension_type v) {
84103  PPL_ASSERT(0 < v && v <= dbm.num_rows());
84104  DB_Row<N>& dbm_v = dbm[v];
84105  for (dimension_type i = dbm.num_rows()-1; i > 0; --i) {
84106    assign_r(dbm_v[i], PLUS_INFINITY, ROUND_NOT_NEEDED);
84107    assign_r(dbm[i][v], PLUS_INFINITY, ROUND_NOT_NEEDED);
84108  }
84109}
84110
84111template <typename T>
84112void
84113BD_Shape<T>::unconstrain(const Variable var) {
84114  // Dimension-compatibility check.
84115  const dimension_type var_space_dim = var.space_dimension();
84116  if (space_dimension() < var_space_dim) {
84117    throw_dimension_incompatible("unconstrain(var)", var_space_dim);
84118  }
84119  // Shortest-path closure is necessary to detect emptiness
84120  // and all (possibly implicit) constraints.
84121  shortest_path_closure_assign();
84122
84123  // If the shape is empty, this is a no-op.
84124  if (marked_empty()) {
84125    return;
84126  }
84127  forget_all_dbm_constraints(var_space_dim);
84128  // Shortest-path closure is preserved, but not reduction.
84129  reset_shortest_path_reduced();
84130  PPL_ASSERT(OK());
84131}
84132
84133template <typename T>
84134void
84135BD_Shape<T>::unconstrain(const Variables_Set& vars) {
84136  // The cylindrification with respect to no dimensions is a no-op.
84137  // This case captures the only legal cylindrification in a 0-dim space.
84138  if (vars.empty()) {
84139    return;
84140  }
84141  // Dimension-compatibility check.
84142  const dimension_type min_space_dim = vars.space_dimension();
84143  if (space_dimension() < min_space_dim) {
84144    throw_dimension_incompatible("unconstrain(vs)", min_space_dim);
84145  }
84146  // Shortest-path closure is necessary to detect emptiness
84147  // and all (possibly implicit) constraints.
84148  shortest_path_closure_assign();
84149
84150  // If the shape is empty, this is a no-op.
84151  if (marked_empty()) {
84152    return;
84153  }
84154  for (Variables_Set::const_iterator vsi = vars.begin(),
84155         vsi_end = vars.end(); vsi != vsi_end; ++vsi) {
84156    forget_all_dbm_constraints(*vsi + 1);
84157  }
84158  // Shortest-path closure is preserved, but not reduction.
84159  reset_shortest_path_reduced();
84160  PPL_ASSERT(OK());
84161}
84162
84163template <typename T>
84164void
84165BD_Shape<T>::refine(const Variable var,
84166                    const Relation_Symbol relsym,
84167                    const Linear_Expression& expr,
84168                    Coefficient_traits::const_reference denominator) {
84169  PPL_ASSERT(denominator != 0);
84170  PPL_ASSERT(space_dimension() >= expr.space_dimension());
84171  const dimension_type v = var.id() + 1;
84172  PPL_ASSERT(v <= space_dimension());
84173  PPL_ASSERT(expr.coefficient(var) == 0);
84174  PPL_ASSERT(relsym != LESS_THAN && relsym != GREATER_THAN);
84175
84176  const Coefficient& b = expr.inhomogeneous_term();
84177  // Number of non-zero coefficients in `expr': will be set to
84178  // 0, 1, or 2, the latter value meaning any value greater than 1.
84179  dimension_type t = 0;
84180  // Index of the last non-zero coefficient in `expr', if any.
84181  dimension_type w = expr.last_nonzero();
84182
84183  if (w != 0) {
84184    ++t;
84185    if (!expr.all_zeroes(1, w)) {
84186      ++t;
84187    }
84188  }
84189
84190  // Since we are only able to record bounded differences, we can
84191  // precisely deal with the case of a single variable only if its
84192  // coefficient (taking into account the denominator) is 1.
84193  // If this is not the case, we fall back to the general case
84194  // so as to over-approximate the constraint.
84195  if (t == 1 && expr.get(Variable(w - 1)) != denominator) {
84196    t = 2;
84197  }
84198  // Now we know the form of `expr':
84199  // - If t == 0, then expr == b, with `b' a constant;
84200  // - If t == 1, then expr == a*w + b, where `w != v' and `a == denominator';
84201  // - If t == 2, the `expr' is of the general form.
84202  const DB_Row<N>& dbm_0 = dbm[0];
84203  PPL_DIRTY_TEMP_COEFFICIENT(minus_denom);
84204  neg_assign(minus_denom, denominator);
84205
84206  if (t == 0) {
84207    // Case 1: expr == b.
84208    switch (relsym) {
84209    case EQUAL:
84210      // Add the constraint `var == b/denominator'.
84211      add_dbm_constraint(0, v, b, denominator);
84212      add_dbm_constraint(v, 0, b, minus_denom);
84213      break;
84214    case LESS_OR_EQUAL:
84215      // Add the constraint `var <= b/denominator'.
84216      add_dbm_constraint(0, v, b, denominator);
84217      break;
84218    case GREATER_OR_EQUAL:
84219      // Add the constraint `var >= b/denominator',
84220      // i.e., `-var <= -b/denominator',
84221      add_dbm_constraint(v, 0, b, minus_denom);
84222      break;
84223    default:
84224      // We already dealt with the other cases.
84225      PPL_UNREACHABLE;
84226      break;
84227    }
84228    return;
84229  }
84230
84231  if (t == 1) {
84232    // Case 2: expr == a*w + b, w != v, a == denominator.
84233    PPL_ASSERT(expr.get(Variable(w - 1)) == denominator);
84234    PPL_DIRTY_TEMP(N, d);
84235    switch (relsym) {
84236    case EQUAL:
84237      // Add the new constraint `v - w <= b/denominator'.
84238      div_round_up(d, b, denominator);
84239      add_dbm_constraint(w, v, d);
84240      // Add the new constraint `v - w >= b/denominator',
84241      // i.e., `w - v <= -b/denominator'.
84242      div_round_up(d, b, minus_denom);
84243      add_dbm_constraint(v, w, d);
84244      break;
84245    case LESS_OR_EQUAL:
84246      // Add the new constraint `v - w <= b/denominator'.
84247      div_round_up(d, b, denominator);
84248      add_dbm_constraint(w, v, d);
84249      break;
84250    case GREATER_OR_EQUAL:
84251      // Add the new constraint `v - w >= b/denominator',
84252      // i.e., `w - v <= -b/denominator'.
84253      div_round_up(d, b, minus_denom);
84254      add_dbm_constraint(v, w, d);
84255      break;
84256    default:
84257      // We already dealt with the other cases.
84258      PPL_UNREACHABLE;
84259      break;
84260    }
84261    return;
84262  }
84263
84264  // Here t == 2, so that either
84265  // expr == a_1*x_1 + a_2*x_2 + ... + a_n*x_n + b, where n >= 2, or
84266  // expr == a*w + b, w != v and a != denominator.
84267  const bool is_sc = (denominator > 0);
84268  PPL_DIRTY_TEMP_COEFFICIENT(minus_b);
84269  neg_assign(minus_b, b);
84270  const Coefficient& sc_b = is_sc ? b : minus_b;
84271  const Coefficient& minus_sc_b = is_sc ? minus_b : b;
84272  const Coefficient& sc_denom = is_sc ? denominator : minus_denom;
84273  const Coefficient& minus_sc_denom = is_sc ? minus_denom : denominator;
84274  // NOTE: here, for optimization purposes, `minus_expr' is only assigned
84275  // when `denominator' is negative. Do not use it unless you are sure
84276  // it has been correctly assigned.
84277  Linear_Expression minus_expr;
84278  if (!is_sc) {
84279    minus_expr = -expr;
84280  }
84281  const Linear_Expression& sc_expr = is_sc ? expr : minus_expr;
84282
84283  PPL_DIRTY_TEMP(N, sum);
84284  // Indices of the variables that are unbounded in `this->dbm'.
84285  PPL_UNINITIALIZED(dimension_type, pinf_index);
84286  // Number of unbounded variables found.
84287  dimension_type pinf_count = 0;
84288
84289  // Speculative allocation of temporaries that are used in most
84290  // of the computational traces starting from this point (also loops).
84291  PPL_DIRTY_TEMP_COEFFICIENT(minus_sc_i);
84292  PPL_DIRTY_TEMP(N, coeff_i);
84293
84294  switch (relsym) {
84295  case EQUAL:
84296    {
84297      PPL_DIRTY_TEMP(N, neg_sum);
84298      // Indices of the variables that are unbounded in `this->dbm'.
84299      PPL_UNINITIALIZED(dimension_type, neg_pinf_index);
84300      // Number of unbounded variables found.
84301      dimension_type neg_pinf_count = 0;
84302
84303      // Compute an upper approximation for `expr' into `sum',
84304      // taking into account the sign of `denominator'.
84305
84306      // Approximate the inhomogeneous term.
84307      assign_r(sum, sc_b, ROUND_UP);
84308      assign_r(neg_sum, minus_sc_b, ROUND_UP);
84309
84310      // Approximate the homogeneous part of `sc_expr'.
84311      // Note: indices above `w' can be disregarded, as they all have
84312      // a zero coefficient in `expr'.
84313      for (Linear_Expression::const_iterator i = sc_expr.begin(),
84314            i_end = sc_expr.lower_bound(Variable(w)); i != i_end; ++i) {
84315        const dimension_type i_dim = i.variable().space_dimension();
84316        const Coefficient& sc_i = *i;
84317        const int sign_i = sgn(sc_i);
84318        PPL_ASSERT(sign_i != 0);
84319        if (sign_i > 0) {
84320          assign_r(coeff_i, sc_i, ROUND_UP);
84321          // Approximating `sc_expr'.
84322          if (pinf_count <= 1) {
84323            const N& approx_i = dbm_0[i_dim];
84324            if (!is_plus_infinity(approx_i)) {
84325              add_mul_assign_r(sum, coeff_i, approx_i, ROUND_UP);
84326            }
84327            else {
84328              ++pinf_count;
84329              pinf_index = i_dim;
84330            }
84331          }
84332          // Approximating `-sc_expr'.
84333          if (neg_pinf_count <= 1) {
84334            const N& approx_minus_i = dbm[i_dim][0];
84335            if (!is_plus_infinity(approx_minus_i)) {
84336              add_mul_assign_r(neg_sum, coeff_i, approx_minus_i, ROUND_UP);
84337            }
84338            else {
84339              ++neg_pinf_count;
84340              neg_pinf_index = i_dim;
84341            }
84342          }
84343        }
84344        else {
84345          PPL_ASSERT(sign_i < 0);
84346          neg_assign(minus_sc_i, sc_i);
84347          // Note: using temporary named `coeff_i' to store -coeff_i.
84348          assign_r(coeff_i, minus_sc_i, ROUND_UP);
84349          // Approximating `sc_expr'.
84350          if (pinf_count <= 1) {
84351            const N& approx_minus_i = dbm[i_dim][0];
84352            if (!is_plus_infinity(approx_minus_i)) {
84353              add_mul_assign_r(sum, coeff_i, approx_minus_i, ROUND_UP);
84354            }
84355            else {
84356              ++pinf_count;
84357              pinf_index = i_dim;
84358            }
84359          }
84360          // Approximating `-sc_expr'.
84361          if (neg_pinf_count <= 1) {
84362            const N& approx_i = dbm_0[i_dim];
84363            if (!is_plus_infinity(approx_i)) {
84364              add_mul_assign_r(neg_sum, coeff_i, approx_i, ROUND_UP);
84365            }
84366            else {
84367              ++neg_pinf_count;
84368              neg_pinf_index = i_dim;
84369            }
84370          }
84371        }
84372      }
84373      // Return immediately if no approximation could be computed.
84374      if (pinf_count > 1 && neg_pinf_count > 1) {
84375        PPL_ASSERT(OK());
84376        return;
84377      }
84378
84379      // In the following, shortest-path closure will be definitely lost.
84380      reset_shortest_path_closed();
84381
84382      // Before computing quotients, the denominator should be approximated
84383      // towards zero. Since `sc_denom' is known to be positive, this amounts to
84384      // rounding downwards, which is achieved as usual by rounding upwards
84385      // `minus_sc_denom' and negating again the result.
84386      PPL_DIRTY_TEMP(N, down_sc_denom);
84387      assign_r(down_sc_denom, minus_sc_denom, ROUND_UP);
84388      neg_assign_r(down_sc_denom, down_sc_denom, ROUND_UP);
84389
84390      // Exploit the upper approximation, if possible.
84391      if (pinf_count <= 1) {
84392        // Compute quotient (if needed).
84393        if (down_sc_denom != 1) {
84394          div_assign_r(sum, sum, down_sc_denom, ROUND_UP);
84395        }
84396        // Add the upper bound constraint, if meaningful.
84397        if (pinf_count == 0) {
84398          // Add the constraint `v <= sum'.
84399          dbm[0][v] = sum;
84400          // Deduce constraints of the form `v - u', where `u != v'.
84401          deduce_v_minus_u_bounds(v, w, sc_expr, sc_denom, sum);
84402        }
84403        else {
84404          // Here `pinf_count == 1'.
84405          if (pinf_index != v
84406              && sc_expr.get(Variable(pinf_index - 1)) == sc_denom) {
84407            // Add the constraint `v - pinf_index <= sum'.
84408            dbm[pinf_index][v] = sum;
84409          }
84410        }
84411      }
84412
84413      // Exploit the lower approximation, if possible.
84414      if (neg_pinf_count <= 1) {
84415        // Compute quotient (if needed).
84416        if (down_sc_denom != 1) {
84417          div_assign_r(neg_sum, neg_sum, down_sc_denom, ROUND_UP);
84418        }
84419        // Add the lower bound constraint, if meaningful.
84420        if (neg_pinf_count == 0) {
84421          // Add the constraint `v >= -neg_sum', i.e., `-v <= neg_sum'.
84422          DB_Row<N>& dbm_v = dbm[v];
84423          dbm_v[0] = neg_sum;
84424          // Deduce constraints of the form `u - v', where `u != v'.
84425          deduce_u_minus_v_bounds(v, w, sc_expr, sc_denom, neg_sum);
84426        }
84427        // Here `neg_pinf_count == 1'.
84428        else if (neg_pinf_index != v
84429              && sc_expr.get(Variable(neg_pinf_index - 1)) == sc_denom) {
84430            // Add the constraint `v - neg_pinf_index >= -neg_sum',
84431            // i.e., `neg_pinf_index - v <= neg_sum'.
84432            dbm[v][neg_pinf_index] = neg_sum;
84433        }
84434      }
84435    }
84436    break;
84437
84438  case LESS_OR_EQUAL:
84439    // Compute an upper approximation for `expr' into `sum',
84440    // taking into account the sign of `denominator'.
84441
84442    // Approximate the inhomogeneous term.
84443    assign_r(sum, sc_b, ROUND_UP);
84444
84445    // Approximate the homogeneous part of `sc_expr'.
84446    // Note: indices above `w' can be disregarded, as they all have
84447    // a zero coefficient in `expr'.
84448    for (Linear_Expression::const_iterator i = sc_expr.begin(),
84449          i_end = sc_expr.lower_bound(Variable(w)); i != i_end; ++i) {
84450      const Coefficient& sc_i = *i;
84451      const dimension_type i_dim = i.variable().space_dimension();
84452      const int sign_i = sgn(sc_i);
84453      PPL_ASSERT(sign_i != 0);
84454      // Choose carefully: we are approximating `sc_expr'.
84455      const N& approx_i = (sign_i > 0) ? dbm_0[i_dim] : dbm[i_dim][0];
84456      if (is_plus_infinity(approx_i)) {
84457        if (++pinf_count > 1) {
84458          break;
84459        }
84460        pinf_index = i_dim;
84461        continue;
84462      }
84463      if (sign_i > 0) {
84464        assign_r(coeff_i, sc_i, ROUND_UP);
84465      }
84466      else {
84467        neg_assign(minus_sc_i, sc_i);
84468        assign_r(coeff_i, minus_sc_i, ROUND_UP);
84469      }
84470      add_mul_assign_r(sum, coeff_i, approx_i, ROUND_UP);
84471    }
84472
84473    // Divide by the (sign corrected) denominator (if needed).
84474    if (sc_denom != 1) {
84475      // Before computing the quotient, the denominator should be
84476      // approximated towards zero. Since `sc_denom' is known to be
84477      // positive, this amounts to rounding downwards, which is achieved
84478      // by rounding upwards `minus_sc - denom' and negating again the result.
84479      PPL_DIRTY_TEMP(N, down_sc_denom);
84480      assign_r(down_sc_denom, minus_sc_denom, ROUND_UP);
84481      neg_assign_r(down_sc_denom, down_sc_denom, ROUND_UP);
84482      div_assign_r(sum, sum, down_sc_denom, ROUND_UP);
84483    }
84484
84485    if (pinf_count == 0) {
84486      // Add the constraint `v <= sum'.
84487      add_dbm_constraint(0, v, sum);
84488      // Deduce constraints of the form `v - u', where `u != v'.
84489      deduce_v_minus_u_bounds(v, w, sc_expr, sc_denom, sum);
84490    }
84491    else if (pinf_count == 1) {
84492      if (expr.get(Variable(pinf_index - 1)) == denominator) {
84493        // Add the constraint `v - pinf_index <= sum'.
84494        add_dbm_constraint(pinf_index, v, sum);
84495      }
84496    }
84497    break;
84498
84499  case GREATER_OR_EQUAL:
84500    // Compute an upper approximation for `-sc_expr' into `sum'.
84501    // Note: approximating `-sc_expr' from above and then negating the
84502    // result is the same as approximating `sc_expr' from below.
84503
84504    // Approximate the inhomogeneous term.
84505    assign_r(sum, minus_sc_b, ROUND_UP);
84506
84507    // Approximate the homogeneous part of `-sc_expr'.
84508    for (Linear_Expression::const_iterator i = sc_expr.begin(),
84509          i_end = sc_expr.lower_bound(Variable(w)); i != i_end; ++i) {
84510      const Coefficient& sc_i = *i;
84511      const dimension_type i_dim = i.variable().space_dimension();
84512      const int sign_i = sgn(sc_i);
84513      PPL_ASSERT(sign_i != 0);
84514      // Choose carefully: we are approximating `-sc_expr'.
84515      const N& approx_i = (sign_i > 0) ? dbm[i_dim][0] : dbm_0[i_dim];
84516      if (is_plus_infinity(approx_i)) {
84517        if (++pinf_count > 1) {
84518          break;
84519        }
84520        pinf_index = i_dim;
84521        continue;
84522      }
84523      if (sign_i > 0) {
84524        assign_r(coeff_i, sc_i, ROUND_UP);
84525      }
84526      else {
84527        neg_assign(minus_sc_i, sc_i);
84528        assign_r(coeff_i, minus_sc_i, ROUND_UP);
84529      }
84530      add_mul_assign_r(sum, coeff_i, approx_i, ROUND_UP);
84531    }
84532
84533    // Divide by the (sign corrected) denominator (if needed).
84534    if (sc_denom != 1) {
84535      // Before computing the quotient, the denominator should be
84536      // approximated towards zero. Since `sc_denom' is known to be positive,
84537      // this amounts to rounding downwards, which is achieved by rounding
84538      // upwards `minus_sc_denom' and negating again the result.
84539      PPL_DIRTY_TEMP(N, down_sc_denom);
84540      assign_r(down_sc_denom, minus_sc_denom, ROUND_UP);
84541      neg_assign_r(down_sc_denom, down_sc_denom, ROUND_UP);
84542      div_assign_r(sum, sum, down_sc_denom, ROUND_UP);
84543    }
84544
84545    if (pinf_count == 0) {
84546      // Add the constraint `v >= -sum', i.e., `-v <= sum'.
84547      add_dbm_constraint(v, 0, sum);
84548      // Deduce constraints of the form `u - v', where `u != v'.
84549      deduce_u_minus_v_bounds(v, w, sc_expr, sc_denom, sum);
84550    }
84551    else if (pinf_count == 1) {
84552      if (pinf_index != v
84553          && expr.get(Variable(pinf_index - 1)) == denominator) {
84554        // Add the constraint `v - pinf_index >= -sum',
84555        // i.e., `pinf_index - v <= sum'.
84556        add_dbm_constraint(v, pinf_index, sum);
84557      }
84558    }
84559    break;
84560
84561  default:
84562    // We already dealt with the other cases.
84563    PPL_UNREACHABLE;
84564    break;
84565  }
84566
84567  PPL_ASSERT(OK());
84568}
84569
84570template <typename T>
84571void
84572BD_Shape<T>::affine_image(const Variable var,
84573                          const Linear_Expression& expr,
84574                          Coefficient_traits::const_reference denominator) {
84575  // The denominator cannot be zero.
84576  if (denominator == 0) {
84577    throw_invalid_argument("affine_image(v, e, d)", "d == 0");
84578  }
84579  // Dimension-compatibility checks.
84580  // The dimension of `expr' should not be greater than the dimension
84581  // of `*this'.
84582  const dimension_type space_dim = space_dimension();
84583  const dimension_type expr_space_dim = expr.space_dimension();
84584  if (space_dim < expr_space_dim) {
84585    throw_dimension_incompatible("affine_image(v, e, d)", "e", expr);
84586  }
84587  // `var' should be one of the dimensions of the shape.
84588  const dimension_type v = var.id() + 1;
84589  if (v > space_dim) {
84590    throw_dimension_incompatible("affine_image(v, e, d)", var.id());
84591  }
84592  // The image of an empty BDS is empty too.
84593  shortest_path_closure_assign();
84594  if (marked_empty()) {
84595    return;
84596  }
84597  const Coefficient& b = expr.inhomogeneous_term();
84598  // Number of non-zero coefficients in `expr': will be set to
84599  // 0, 1, or 2, the latter value meaning any value greater than 1.
84600  dimension_type t = 0;
84601  // Index of the last non-zero coefficient in `expr', if any.
84602  dimension_type w = expr.last_nonzero();
84603
84604  if (w != 0) {
84605    ++t;
84606    if (!expr.all_zeroes(1, w)) {
84607      ++t;
84608    }
84609  }
84610
84611  // Now we know the form of `expr':
84612  // - If t == 0, then expr == b, with `b' a constant;
84613  // - If t == 1, then expr == a*w + b, where `w' can be `v' or another
84614  //   variable; in this second case we have to check whether `a' is
84615  //   equal to `denominator' or `-denominator', since otherwise we have
84616  //   to fall back on the general form;
84617  // - If t == 2, the `expr' is of the general form.
84618  PPL_DIRTY_TEMP_COEFFICIENT(minus_denom);
84619  neg_assign(minus_denom, denominator);
84620
84621  if (t == 0) {
84622    // Case 1: expr == b.
84623    // Remove all constraints on `var'.
84624    forget_all_dbm_constraints(v);
84625    // Shortest-path closure is preserved, but not reduction.
84626    if (marked_shortest_path_reduced()) {
84627      reset_shortest_path_reduced();
84628    }
84629    // Add the constraint `var == b/denominator'.
84630    add_dbm_constraint(0, v, b, denominator);
84631    add_dbm_constraint(v, 0, b, minus_denom);
84632    PPL_ASSERT(OK());
84633    return;
84634  }
84635
84636  if (t == 1) {
84637    // Value of the one and only non-zero coefficient in `expr'.
84638    const Coefficient& a = expr.get(Variable(w - 1));
84639    if (a == denominator || a == minus_denom) {
84640      // Case 2: expr == a*w + b, with a == +/- denominator.
84641      if (w == v) {
84642        // `expr' is of the form: a*v + b.
84643        if (a == denominator) {
84644          if (b == 0) {
84645            // The transformation is the identity function.
84646            return;
84647          }
84648          else {
84649            // Translate all the constraints on `var',
84650            // adding or subtracting the value `b/denominator'.
84651            PPL_DIRTY_TEMP(N, d);
84652            div_round_up(d, b, denominator);
84653            PPL_DIRTY_TEMP(N, c);
84654            div_round_up(c, b, minus_denom);
84655            DB_Row<N>& dbm_v = dbm[v];
84656            for (dimension_type i = space_dim + 1; i-- > 0; ) {
84657              N& dbm_vi = dbm_v[i];
84658              add_assign_r(dbm_vi, dbm_vi, c, ROUND_UP);
84659              N& dbm_iv = dbm[i][v];
84660              add_assign_r(dbm_iv, dbm_iv, d, ROUND_UP);
84661            }
84662            // Both shortest-path closure and reduction are preserved.
84663          }
84664        }
84665        else {
84666          // Here `a == -denominator'.
84667          // Remove the binary constraints on `var'.
84668          forget_binary_dbm_constraints(v);
84669          // Swap the unary constraints on `var'.
84670          using std::swap;
84671          swap(dbm[v][0], dbm[0][v]);
84672          // Shortest-path closure is not preserved.
84673          reset_shortest_path_closed();
84674          if (b != 0) {
84675            // Translate the unary constraints on `var',
84676            // adding or subtracting the value `b/denominator'.
84677            PPL_DIRTY_TEMP(N, c);
84678            div_round_up(c, b, minus_denom);
84679            N& dbm_v0 = dbm[v][0];
84680            add_assign_r(dbm_v0, dbm_v0, c, ROUND_UP);
84681            PPL_DIRTY_TEMP(N, d);
84682            div_round_up(d, b, denominator);
84683            N& dbm_0v = dbm[0][v];
84684            add_assign_r(dbm_0v, dbm_0v, d, ROUND_UP);
84685          }
84686        }
84687      }
84688      else {
84689        // Here `w != v', so that `expr' is of the form
84690        // +/-denominator * w + b.
84691        // Remove all constraints on `var'.
84692        forget_all_dbm_constraints(v);
84693        // Shortest-path closure is preserved, but not reduction.
84694        if (marked_shortest_path_reduced()) {
84695          reset_shortest_path_reduced();
84696        }
84697        if (a == denominator) {
84698          // Add the new constraint `v - w == b/denominator'.
84699          add_dbm_constraint(w, v, b, denominator);
84700          add_dbm_constraint(v, w, b, minus_denom);
84701        }
84702        else {
84703          // Here a == -denominator, so that we should be adding
84704          // the constraint `v + w == b/denominator'.
84705          // Approximate it by computing lower and upper bounds for `w'.
84706          const N& dbm_w0 = dbm[w][0];
84707          if (!is_plus_infinity(dbm_w0)) {
84708            // Add the constraint `v <= b/denominator - lower_w'.
84709            PPL_DIRTY_TEMP(N, d);
84710            div_round_up(d, b, denominator);
84711            add_assign_r(dbm[0][v], d, dbm_w0, ROUND_UP);
84712            reset_shortest_path_closed();
84713          }
84714          const N& dbm_0w = dbm[0][w];
84715          if (!is_plus_infinity(dbm_0w)) {
84716            // Add the constraint `v >= b/denominator - upper_w'.
84717            PPL_DIRTY_TEMP(N, c);
84718            div_round_up(c, b, minus_denom);
84719            add_assign_r(dbm[v][0], dbm_0w, c, ROUND_UP);
84720            reset_shortest_path_closed();
84721          }
84722        }
84723      }
84724      PPL_ASSERT(OK());
84725      return;
84726    }
84727  }
84728
84729  // General case.
84730  // Either t == 2, so that
84731  // expr == a_1*x_1 + a_2*x_2 + ... + a_n*x_n + b, where n >= 2,
84732  // or t == 1, expr == a*w + b, but a <> +/- denominator.
84733  // We will remove all the constraints on `var' and add back
84734  // constraints providing upper and lower bounds for `var'.
84735
84736  // Compute upper approximations for `expr' and `-expr'
84737  // into `pos_sum' and `neg_sum', respectively, taking into account
84738  // the sign of `denominator'.
84739  // Note: approximating `-expr' from above and then negating the
84740  // result is the same as approximating `expr' from below.
84741  const bool is_sc = (denominator > 0);
84742  PPL_DIRTY_TEMP_COEFFICIENT(minus_b);
84743  neg_assign(minus_b, b);
84744  const Coefficient& sc_b = is_sc ? b : minus_b;
84745  const Coefficient& minus_sc_b = is_sc ? minus_b : b;
84746  const Coefficient& sc_denom = is_sc ? denominator : minus_denom;
84747  const Coefficient& minus_sc_denom = is_sc ? minus_denom : denominator;
84748  // NOTE: here, for optimization purposes, `minus_expr' is only assigned
84749  // when `denominator' is negative. Do not use it unless you are sure
84750  // it has been correctly assigned.
84751  Linear_Expression minus_expr;
84752  if (!is_sc) {
84753    minus_expr = -expr;
84754  }
84755  const Linear_Expression& sc_expr = is_sc ? expr : minus_expr;
84756
84757  PPL_DIRTY_TEMP(N, pos_sum);
84758  PPL_DIRTY_TEMP(N, neg_sum);
84759  // Indices of the variables that are unbounded in `this->dbm'.
84760  PPL_UNINITIALIZED(dimension_type, pos_pinf_index);
84761  PPL_UNINITIALIZED(dimension_type, neg_pinf_index);
84762  // Number of unbounded variables found.
84763  dimension_type pos_pinf_count = 0;
84764  dimension_type neg_pinf_count = 0;
84765
84766  // Approximate the inhomogeneous term.
84767  assign_r(pos_sum, sc_b, ROUND_UP);
84768  assign_r(neg_sum, minus_sc_b, ROUND_UP);
84769
84770  // Approximate the homogeneous part of `sc_expr'.
84771  const DB_Row<N>& dbm_0 = dbm[0];
84772  // Speculative allocation of temporaries to be used in the following loop.
84773  PPL_DIRTY_TEMP(N, coeff_i);
84774  PPL_DIRTY_TEMP_COEFFICIENT(minus_sc_i);
84775
84776  // Note: indices above `w' can be disregarded, as they all have
84777  // a zero coefficient in `sc_expr'.
84778  for (Linear_Expression::const_iterator i = sc_expr.begin(),
84779        i_end = sc_expr.lower_bound(Variable(w)); i != i_end; ++i) {
84780    const Coefficient& sc_i = *i;
84781    const dimension_type i_dim = i.variable().space_dimension();
84782    const int sign_i = sgn(sc_i);
84783    if (sign_i > 0) {
84784      assign_r(coeff_i, sc_i, ROUND_UP);
84785      // Approximating `sc_expr'.
84786      if (pos_pinf_count <= 1) {
84787        const N& up_approx_i = dbm_0[i_dim];
84788        if (!is_plus_infinity(up_approx_i)) {
84789          add_mul_assign_r(pos_sum, coeff_i, up_approx_i, ROUND_UP);
84790        }
84791        else {
84792          ++pos_pinf_count;
84793          pos_pinf_index = i_dim;
84794        }
84795      }
84796      // Approximating `-sc_expr'.
84797      if (neg_pinf_count <= 1) {
84798        const N& up_approx_minus_i = dbm[i_dim][0];
84799        if (!is_plus_infinity(up_approx_minus_i)) {
84800          add_mul_assign_r(neg_sum, coeff_i, up_approx_minus_i, ROUND_UP);
84801        }
84802        else {
84803          ++neg_pinf_count;
84804          neg_pinf_index = i_dim;
84805        }
84806      }
84807    }
84808    else {
84809      PPL_ASSERT(sign_i < 0);
84810      neg_assign(minus_sc_i, sc_i);
84811      // Note: using temporary named `coeff_i' to store -coeff_i.
84812      assign_r(coeff_i, minus_sc_i, ROUND_UP);
84813      // Approximating `sc_expr'.
84814      if (pos_pinf_count <= 1) {
84815        const N& up_approx_minus_i = dbm[i_dim][0];
84816        if (!is_plus_infinity(up_approx_minus_i)) {
84817          add_mul_assign_r(pos_sum, coeff_i, up_approx_minus_i, ROUND_UP);
84818        }
84819        else {
84820          ++pos_pinf_count;
84821          pos_pinf_index = i_dim;
84822        }
84823      }
84824      // Approximating `-sc_expr'.
84825      if (neg_pinf_count <= 1) {
84826        const N& up_approx_i = dbm_0[i_dim];
84827        if (!is_plus_infinity(up_approx_i)) {
84828          add_mul_assign_r(neg_sum, coeff_i, up_approx_i, ROUND_UP);
84829        }
84830        else {
84831          ++neg_pinf_count;
84832          neg_pinf_index = i_dim;
84833        }
84834      }
84835    }
84836  }
84837
84838  // Remove all constraints on 'v'.
84839  forget_all_dbm_constraints(v);
84840  // Shortest-path closure is maintained, but not reduction.
84841  if (marked_shortest_path_reduced()) {
84842    reset_shortest_path_reduced();
84843  }
84844  // Return immediately if no approximation could be computed.
84845  if (pos_pinf_count > 1 && neg_pinf_count > 1) {
84846    PPL_ASSERT(OK());
84847    return;
84848  }
84849
84850  // In the following, shortest-path closure will be definitely lost.
84851  reset_shortest_path_closed();
84852
84853  // Exploit the upper approximation, if possible.
84854  if (pos_pinf_count <= 1) {
84855    // Compute quotient (if needed).
84856    if (sc_denom != 1) {
84857      // Before computing quotients, the denominator should be approximated
84858      // towards zero. Since `sc_denom' is known to be positive, this amounts to
84859      // rounding downwards, which is achieved as usual by rounding upwards
84860      // `minus_sc_denom' and negating again the result.
84861      PPL_DIRTY_TEMP(N, down_sc_denom);
84862      assign_r(down_sc_denom, minus_sc_denom, ROUND_UP);
84863      neg_assign_r(down_sc_denom, down_sc_denom, ROUND_UP);
84864      div_assign_r(pos_sum, pos_sum, down_sc_denom, ROUND_UP);
84865    }
84866    // Add the upper bound constraint, if meaningful.
84867    if (pos_pinf_count == 0) {
84868      // Add the constraint `v <= pos_sum'.
84869      dbm[0][v] = pos_sum;
84870      // Deduce constraints of the form `v - u', where `u != v'.
84871      deduce_v_minus_u_bounds(v, w, sc_expr, sc_denom, pos_sum);
84872    }  // Here `pos_pinf_count == 1'.
84873    else if (pos_pinf_index != v
84874          && sc_expr.get(Variable(pos_pinf_index - 1)) == sc_denom) {
84875        // Add the constraint `v - pos_pinf_index <= pos_sum'.
84876        dbm[pos_pinf_index][v] = pos_sum;
84877      }
84878  }
84879
84880  // Exploit the lower approximation, if possible.
84881  if (neg_pinf_count <= 1) {
84882    // Compute quotient (if needed).
84883    if (sc_denom != 1) {
84884      // Before computing quotients, the denominator should be approximated
84885      // towards zero. Since `sc_denom' is known to be positive, this amounts to
84886      // rounding downwards, which is achieved as usual by rounding upwards
84887      // `minus_sc_denom' and negating again the result.
84888      PPL_DIRTY_TEMP(N, down_sc_denom);
84889      assign_r(down_sc_denom, minus_sc_denom, ROUND_UP);
84890      neg_assign_r(down_sc_denom, down_sc_denom, ROUND_UP);
84891      div_assign_r(neg_sum, neg_sum, down_sc_denom, ROUND_UP);
84892    }
84893    // Add the lower bound constraint, if meaningful.
84894    if (neg_pinf_count == 0) {
84895      // Add the constraint `v >= -neg_sum', i.e., `-v <= neg_sum'.
84896      DB_Row<N>& dbm_v = dbm[v];
84897      dbm_v[0] = neg_sum;
84898      // Deduce constraints of the form `u - v', where `u != v'.
84899      deduce_u_minus_v_bounds(v, w, sc_expr, sc_denom, neg_sum);
84900    }
84901    // Here `neg_pinf_count == 1'.
84902    else if (neg_pinf_index != v
84903          && sc_expr.get(Variable(neg_pinf_index - 1)) == sc_denom) {
84904        // Add the constraint `v - neg_pinf_index >= -neg_sum',
84905        // i.e., `neg_pinf_index - v <= neg_sum'.
84906        dbm[v][neg_pinf_index] = neg_sum;
84907    }
84908  }
84909
84910  PPL_ASSERT(OK());
84911}
84912
84913template <typename T>
84914template <typename Interval_Info>
84915void
84916BD_Shape<T>::affine_form_image(const Variable var,
84917                    const Linear_Form< Interval<T, Interval_Info> >& lf) {
84918
84919  // Check that T is a floating point type.
84920  PPL_COMPILE_TIME_CHECK(!std::numeric_limits<T>::is_exact,
84921                    "BD_Shape<T>::affine_form_image(Variable, Linear_Form):"
84922                    " T not a floating point type.");
84923
84924  // Dimension-compatibility checks.
84925  // The dimension of `lf' should not be greater than the dimension
84926  // of `*this'.
84927  const dimension_type space_dim = space_dimension();
84928  const dimension_type lf_space_dim = lf.space_dimension();
84929  if (space_dim < lf_space_dim) {
84930    throw_dimension_incompatible("affine_form_image(var_id, l)", "l", lf);
84931  }
84932  // `var' should be one of the dimensions of the shape.
84933  const dimension_type var_id = var.id() + 1;
84934  if (space_dim < var_id) {
84935    throw_dimension_incompatible("affine_form_image(var_id, l)", var.id());
84936  }
84937  // The image of an empty BDS is empty too.
84938  shortest_path_closure_assign();
84939  if (marked_empty()) {
84940    return;
84941  }
84942  // Number of non-zero coefficients in `lf': will be set to
84943  // 0, 1, or 2, the latter value meaning any value greater than 1.
84944  dimension_type t = 0;
84945  // Index of the last non-zero coefficient in `lf', if any.
84946  dimension_type w_id = 0;
84947  // Get information about the number of non-zero coefficients in `lf'.
84948  for (dimension_type i = lf_space_dim; i-- > 0; ) {
84949    if (lf.coefficient(Variable(i)) != 0) {
84950      if (t++ == 1) {
84951        break;
84952      }
84953      else {
84954        w_id = i + 1;
84955      }
84956    }
84957  }
84958  typedef Interval<T, Interval_Info> FP_Interval_Type;
84959
84960  const FP_Interval_Type& b = lf.inhomogeneous_term();
84961
84962  // Now we know the form of `lf':
84963  // - If t == 0, then lf == b, with `b' a constant;
84964  // - If t == 1, then lf == a*w + b, where `w' can be `v' or another
84965  //   variable;
84966  // - If t == 2, the linear form 'lf' is of the general form.
84967
84968  if (t == 0) {
84969    inhomogeneous_affine_form_image(var_id, b);
84970    PPL_ASSERT(OK());
84971    return;
84972  }
84973  else if (t == 1) {
84974    const FP_Interval_Type& w_coeff = lf.coefficient(Variable(w_id - 1));
84975    if (w_coeff == 1 || w_coeff == -1) {
84976      one_variable_affine_form_image(var_id, b, w_coeff, w_id, space_dim);
84977      PPL_ASSERT(OK());
84978      return;
84979    }
84980  }
84981  two_variables_affine_form_image(var_id, lf, space_dim);
84982  PPL_ASSERT(OK());
84983}
84984
84985// Case 1: var = b, where b = [-b_mlb, b_ub]
84986template <typename T>
84987template <typename Interval_Info>
84988void
84989BD_Shape<T>
84990::inhomogeneous_affine_form_image(const dimension_type& var_id,
84991                                  const Interval<T, Interval_Info>& b) {
84992  PPL_DIRTY_TEMP(N, b_ub);
84993  assign_r(b_ub, b.upper(), ROUND_NOT_NEEDED);
84994  PPL_DIRTY_TEMP(N, b_mlb);
84995  neg_assign_r(b_mlb, b.lower(), ROUND_NOT_NEEDED);
84996
84997  // Remove all constraints on `var'.
84998  forget_all_dbm_constraints(var_id);
84999  // Shortest-path closure is preserved, but not reduction.
85000  if (marked_shortest_path_reduced()) {
85001    reset_shortest_path_reduced();
85002  }
85003  // Add the constraint `var >= lb && var <= ub'.
85004  add_dbm_constraint(0, var_id, b_ub);
85005  add_dbm_constraint(var_id, 0, b_mlb);
85006  return;
85007}
85008
85009// case 2: var = (+/-1) * w + [-b_mlb, b_ub], where `w' can be `var'
85010// or another variable.
85011template <typename T>
85012template <typename Interval_Info>
85013void BD_Shape<T>
85014::one_variable_affine_form_image(const dimension_type& var_id,
85015                            const Interval<T, Interval_Info>& b,
85016                            const Interval<T, Interval_Info>& w_coeff,
85017                            const dimension_type& w_id,
85018                            const dimension_type& space_dim) {
85019
85020  PPL_DIRTY_TEMP(N, b_ub);
85021  assign_r(b_ub, b.upper(), ROUND_NOT_NEEDED);
85022  PPL_DIRTY_TEMP(N, b_mlb);
85023  neg_assign_r(b_mlb, b.lower(), ROUND_NOT_NEEDED);
85024
85025  // True if `w_coeff' is in [1, 1].
85026  bool is_w_coeff_one = (w_coeff == 1);
85027
85028  if (w_id == var_id) {
85029    // True if `b' is in [b_mlb, b_ub] and that is [0, 0].
85030    bool is_b_zero = (b_mlb == 0 && b_ub == 0);
85031    // Here `lf' is of the form: [+/-1, +/-1] * v + b.
85032    if (is_w_coeff_one) {
85033      if (is_b_zero) {
85034        // The transformation is the identity function.
85035        return;
85036      }
85037      else {
85038        // Translate all the constraints on `var' by adding the value
85039        // `b_ub' or subtracting the value `b_mlb'.
85040        DB_Row<N>& dbm_v = dbm[var_id];
85041        for (dimension_type i = space_dim + 1; i-- > 0; ) {
85042          N& dbm_vi = dbm_v[i];
85043          add_assign_r(dbm_vi, dbm_vi, b_mlb, ROUND_UP);
85044          N& dbm_iv = dbm[i][var_id];
85045          add_assign_r(dbm_iv, dbm_iv, b_ub, ROUND_UP);
85046        }
85047        // Both shortest-path closure and reduction are preserved.
85048      }
85049    }
85050    else {
85051      // Here `w_coeff = [-1, -1].
85052      // Remove the binary constraints on `var'.
85053      forget_binary_dbm_constraints(var_id);
85054      using std::swap;
85055      swap(dbm[var_id][0], dbm[0][var_id]);
85056      // Shortest-path closure is not preserved.
85057      reset_shortest_path_closed();
85058      if (!is_b_zero) {
85059        // Translate the unary constraints on `var' by adding the value
85060        // `b_ub' or subtracting the value `b_mlb'.
85061        N& dbm_v0 = dbm[var_id][0];
85062        add_assign_r(dbm_v0, dbm_v0, b_mlb, ROUND_UP);
85063        N& dbm_0v = dbm[0][var_id];
85064        add_assign_r(dbm_0v, dbm_0v, b_ub, ROUND_UP);
85065      }
85066    }
85067  }
85068  else {
85069    // Here `w != var', so that `lf' is of the form
85070    // [+/-1, +/-1] * w + b.
85071    // Remove all constraints on `var'.
85072    forget_all_dbm_constraints(var_id);
85073    // Shortest-path closure is preserved, but not reduction.
85074    if (marked_shortest_path_reduced()) {
85075      reset_shortest_path_reduced();
85076    }
85077    if (is_w_coeff_one) {
85078      // Add the new constraints `var - w >= b_mlb'
85079      // `and var - w <= b_ub'.
85080      add_dbm_constraint(w_id, var_id, b_ub);
85081      add_dbm_constraint(var_id, w_id, b_mlb);
85082    }
85083    else {
85084      // We have to add the constraint `v + w == b', over-approximating it
85085      // by computing lower and upper bounds for `w'.
85086      const N& mlb_w = dbm[w_id][0];
85087      if (!is_plus_infinity(mlb_w)) {
85088        // Add the constraint `v <= ub - lb_w'.
85089        add_assign_r(dbm[0][var_id], b_ub, mlb_w, ROUND_UP);
85090        reset_shortest_path_closed();
85091      }
85092      const N& ub_w = dbm[0][w_id];
85093      if (!is_plus_infinity(ub_w)) {
85094        // Add the constraint `v >= lb - ub_w'.
85095        add_assign_r(dbm[var_id][0], ub_w, b_mlb, ROUND_UP);
85096        reset_shortest_path_closed();
85097      }
85098    }
85099  }
85100  return;
85101}
85102
85103// General case.
85104// Either t == 2, so that
85105// lf == i_1*x_1 + i_2*x_2 + ... + i_n*x_n + b, where n >= 2,
85106// or t == 1, lf == i*w + b, but i <> [+/-1, +/-1].
85107template <typename T>
85108template <typename Interval_Info>
85109void BD_Shape<T>
85110::two_variables_affine_form_image(const dimension_type& var_id,
85111           const Linear_Form< Interval<T, Interval_Info> >& lf,
85112                             const dimension_type& space_dim) {
85113  // Shortest-path closure is maintained, but not reduction.
85114  if (marked_shortest_path_reduced()) {
85115    reset_shortest_path_reduced();
85116  }
85117  reset_shortest_path_closed();
85118
85119  Linear_Form< Interval<T, Interval_Info> > minus_lf(lf);
85120  minus_lf.negate();
85121
85122  // Declare temporaries outside the loop.
85123  PPL_DIRTY_TEMP(N, upper_bound);
85124
85125  // Update binary constraints on var FIRST.
85126  for (dimension_type curr_var = 1; curr_var < var_id; ++curr_var) {
85127    Variable current(curr_var - 1);
85128    linear_form_upper_bound(lf - current, upper_bound);
85129    assign_r(dbm[curr_var][var_id], upper_bound, ROUND_NOT_NEEDED);
85130    linear_form_upper_bound(minus_lf + current, upper_bound);
85131    assign_r(dbm[var_id][curr_var], upper_bound, ROUND_NOT_NEEDED);
85132  }
85133  for (dimension_type curr_var = var_id + 1; curr_var <= space_dim;
85134                                                      ++curr_var) {
85135    Variable current(curr_var - 1);
85136    linear_form_upper_bound(lf - current, upper_bound);
85137    assign_r(dbm[curr_var][var_id], upper_bound, ROUND_NOT_NEEDED);
85138    linear_form_upper_bound(minus_lf + current, upper_bound);
85139    assign_r(dbm[var_id][curr_var], upper_bound, ROUND_NOT_NEEDED);
85140  }
85141  // Finally, update unary constraints on var.
85142  PPL_DIRTY_TEMP(N, lf_ub);
85143  linear_form_upper_bound(lf, lf_ub);
85144  PPL_DIRTY_TEMP(N, minus_lf_ub);
85145  linear_form_upper_bound(minus_lf, minus_lf_ub);
85146  assign_r(dbm[0][var_id], lf_ub, ROUND_NOT_NEEDED);
85147  assign_r(dbm[var_id][0], minus_lf_ub, ROUND_NOT_NEEDED);
85148}
85149
85150template <typename T>
85151template <typename Interval_Info>
85152void BD_Shape<T>::refine_with_linear_form_inequality(
85153                   const Linear_Form< Interval<T, Interval_Info> >& left,
85154                   const Linear_Form< Interval<T, Interval_Info> >& right) {
85155    // Check that T is a floating point type.
85156    PPL_COMPILE_TIME_CHECK(!std::numeric_limits<T>::is_exact,
85157                    "Octagonal_Shape<T>::refine_with_linear_form_inequality:"
85158                    " T not a floating point type.");
85159
85160    //We assume that the analyzer will not try to apply an unreachable filter.
85161    PPL_ASSERT(!marked_empty());
85162
85163    // Dimension-compatibility checks.
85164    // The dimensions of `left' and `right' should not be greater than the
85165    // dimension of `*this'.
85166    const dimension_type left_space_dim = left.space_dimension();
85167    const dimension_type space_dim = space_dimension();
85168    if (space_dim < left_space_dim) {
85169      throw_dimension_incompatible(
85170          "refine_with_linear_form_inequality(left, right)", "left", left);
85171    }
85172    const dimension_type right_space_dim = right.space_dimension();
85173    if (space_dim < right_space_dim) {
85174      throw_dimension_incompatible(
85175          "refine_with_linear_form_inequality(left, right)", "right", right);
85176    }
85177  // Number of non-zero coefficients in `left': will be set to
85178  // 0, 1, or 2, the latter value meaning any value greater than 1.
85179  dimension_type left_t = 0;
85180  // Variable-index of the last non-zero coefficient in `left', if any.
85181  dimension_type left_w_id = 0;
85182  // Number of non-zero coefficients in `right': will be set to
85183  // 0, 1, or 2, the latter value meaning any value greater than 1.
85184  dimension_type right_t = 0;
85185  // Variable-index of the last non-zero coefficient in `right', if any.
85186  dimension_type right_w_id = 0;
85187
85188  typedef Interval<T, Interval_Info> FP_Interval_Type;
85189
85190  // Get information about the number of non-zero coefficients in `left'.
85191  for (dimension_type i = left_space_dim; i-- > 0; ) {
85192    if (left.coefficient(Variable(i)) != 0) {
85193      if (left_t++ == 1) {
85194        break;
85195      }
85196      else {
85197        left_w_id = i;
85198      }
85199    }
85200  }
85201
85202  // Get information about the number of non-zero coefficients in `right'.
85203  for (dimension_type i = right_space_dim; i-- > 0; ) {
85204    if (right.coefficient(Variable(i)) != 0) {
85205      if (right_t++ == 1) {
85206        break;
85207      }
85208      else {
85209        right_w_id = i;
85210      }
85211    }
85212  }
85213
85214  const FP_Interval_Type& left_w_coeff =
85215          left.coefficient(Variable(left_w_id));
85216  const FP_Interval_Type& right_w_coeff =
85217          right.coefficient(Variable(right_w_id));
85218
85219  if (left_t == 0) {
85220    if (right_t == 0) {
85221      // The constraint involves constants only. Ignore it: it is up to
85222      // the analyzer to handle it.
85223      PPL_ASSERT(OK());
85224      return;
85225    }
85226    else if (right_w_coeff == 1 || right_w_coeff == -1) {
85227      left_inhomogeneous_refine(right_t, right_w_id, left, right);
85228      PPL_ASSERT(OK());
85229      return;
85230    }
85231  }
85232  else if (left_t == 1) {
85233    if (left_w_coeff == 1 || left_w_coeff == -1) {
85234      if (right_t == 0 || (right_w_coeff == 1 || right_w_coeff == -1)) {
85235        left_one_var_refine(left_w_id, right_t, right_w_id, left, right);
85236        PPL_ASSERT(OK());
85237        return;
85238      }
85239    }
85240  }
85241
85242  // General case.
85243  general_refine(left_w_id, right_w_id, left, right);
85244  PPL_ASSERT(OK());
85245} // end of refine_with_linear_form_inequality
85246
85247template <typename T>
85248template <typename U>
85249void
85250BD_Shape<T>
85251::export_interval_constraints(U& dest) const {
85252  const dimension_type space_dim = space_dimension();
85253  if (space_dim > dest.space_dimension()) {
85254    throw std::invalid_argument(
85255               "BD_Shape<T>::export_interval_constraints");
85256  }
85257
85258  // Expose all the interval constraints.
85259  shortest_path_closure_assign();
85260
85261  if (marked_empty()) {
85262    dest.set_empty();
85263    PPL_ASSERT(OK());
85264    return;
85265  }
85266
85267  PPL_DIRTY_TEMP(N, tmp);
85268  const DB_Row<N>& dbm_0 = dbm[0];
85269  for (dimension_type i = space_dim; i-- > 0; ) {
85270    // Set the upper bound.
85271    const N& u = dbm_0[i+1];
85272    if (!is_plus_infinity(u)) {
85273      if (!dest.restrict_upper(i, u.raw_value())) {
85274        return;
85275      }
85276    }
85277    // Set the lower bound.
85278    const N& negated_l = dbm[i+1][0];
85279    if (!is_plus_infinity(negated_l)) {
85280      neg_assign_r(tmp, negated_l, ROUND_DOWN);
85281      if (!dest.restrict_lower(i, tmp.raw_value())) {
85282        return;
85283      }
85284    }
85285  }
85286
85287  PPL_ASSERT(OK());
85288}
85289
85290template <typename T>
85291template <typename Interval_Info>
85292void
85293BD_Shape<T>::left_inhomogeneous_refine(const dimension_type& right_t,
85294                                       const dimension_type& right_w_id,
85295                    const Linear_Form< Interval<T, Interval_Info> >& left,
85296                    const Linear_Form< Interval<T, Interval_Info> >& right) {
85297
85298  typedef Interval<T, Interval_Info> FP_Interval_Type;
85299
85300  if (right_t == 1) {
85301    // The constraint has the form [a-, a+] <= [b-, b+] + [c-, c+] * x.
85302    // Reduce it to the constraint +/-x <= b+ - a- if [c-, c+] = +/-[1, 1].
85303      const FP_Interval_Type& right_w_coeff =
85304                              right.coefficient(Variable(right_w_id));
85305      if (right_w_coeff == 1) {
85306        PPL_DIRTY_TEMP(N, b_plus_minus_a_minus);
85307        const FP_Interval_Type& left_a = left.inhomogeneous_term();
85308        const FP_Interval_Type& right_b = right.inhomogeneous_term();
85309        sub_assign_r(b_plus_minus_a_minus, right_b.upper(), left_a.lower(),
85310                     ROUND_UP);
85311        add_dbm_constraint(right_w_id+1, 0, b_plus_minus_a_minus);
85312        return;
85313      }
85314
85315      if (right_w_coeff == -1) {
85316        PPL_DIRTY_TEMP(N, b_plus_minus_a_minus);
85317        const FP_Interval_Type& left_a = left.inhomogeneous_term();
85318        const FP_Interval_Type& right_b = right.inhomogeneous_term();
85319        sub_assign_r(b_plus_minus_a_minus, right_b.upper(), left_a.lower(),
85320                     ROUND_UP);
85321        add_dbm_constraint(0, right_w_id+1, b_plus_minus_a_minus);
85322        return;
85323      }
85324    }
85325} // end of left_inhomogeneous_refine
85326
85327
85328template <typename T>
85329template <typename Interval_Info>
85330void
85331BD_Shape<T>
85332::left_one_var_refine(const dimension_type& left_w_id,
85333                      const dimension_type& right_t,
85334                      const dimension_type& right_w_id,
85335                const Linear_Form< Interval<T, Interval_Info> >& left,
85336                const Linear_Form< Interval<T, Interval_Info> >& right) {
85337
85338  typedef Interval<T, Interval_Info> FP_Interval_Type;
85339
85340    if (right_t == 0) {
85341      // The constraint has the form [b-, b+] + [c-, c+] * x <= [a-, a+]
85342      // Reduce it to the constraint +/-x <= a+ - b- if [c-, c+] = +/-[1, 1].
85343      const FP_Interval_Type& left_w_coeff =
85344        left.coefficient(Variable(left_w_id));
85345
85346      if (left_w_coeff == 1) {
85347        PPL_DIRTY_TEMP(N, a_plus_minus_b_minus);
85348        const FP_Interval_Type& left_b = left.inhomogeneous_term();
85349        const FP_Interval_Type& right_a = right.inhomogeneous_term();
85350        sub_assign_r(a_plus_minus_b_minus, right_a.upper(), left_b.lower(),
85351                     ROUND_UP);
85352        add_dbm_constraint(0, left_w_id+1, a_plus_minus_b_minus);
85353        return;
85354      }
85355
85356      if (left_w_coeff == -1) {
85357        PPL_DIRTY_TEMP(N, a_plus_minus_b_minus);
85358        const FP_Interval_Type& left_b = left.inhomogeneous_term();
85359        const FP_Interval_Type& right_a = right.inhomogeneous_term();
85360        sub_assign_r(a_plus_minus_b_minus, right_a.upper(), left_b.lower(),
85361                     ROUND_UP);
85362        add_dbm_constraint(left_w_id+1, 0, a_plus_minus_b_minus);
85363        return;
85364      }
85365    }
85366    else if (right_t == 1) {
85367      // The constraint has the form
85368      // [a-, a+] + [b-, b+] * x <= [c-, c+] + [d-, d+] * y.
85369      // Reduce it to the constraint +/-x +/-y <= c+ - a-
85370      // if [b-, b+] = +/-[1, 1] and [d-, d+] = +/-[1, 1].
85371      const FP_Interval_Type& left_w_coeff =
85372                              left.coefficient(Variable(left_w_id));
85373
85374      const FP_Interval_Type& right_w_coeff =
85375                              right.coefficient(Variable(right_w_id));
85376
85377      bool is_left_coeff_one = (left_w_coeff == 1);
85378      bool is_left_coeff_minus_one = (left_w_coeff == -1);
85379      bool is_right_coeff_one = (right_w_coeff == 1);
85380      bool is_right_coeff_minus_one = (right_w_coeff == -1);
85381      if (left_w_id == right_w_id) {
85382        if ((is_left_coeff_one && is_right_coeff_one)
85383            ||
85384            (is_left_coeff_minus_one && is_right_coeff_minus_one)) {
85385          // Here we have an identity or a constants-only constraint.
85386          return;
85387        }
85388        if (is_left_coeff_one && is_right_coeff_minus_one) {
85389          // We fall back to a previous case.
85390          PPL_DIRTY_TEMP(N, a_plus_minus_b_minus);
85391          const FP_Interval_Type& left_b = left.inhomogeneous_term();
85392          const FP_Interval_Type& right_a = right.inhomogeneous_term();
85393          sub_assign_r(a_plus_minus_b_minus, right_a.upper(), left_b.lower(),
85394                       ROUND_UP);
85395          div_2exp_assign_r(a_plus_minus_b_minus, a_plus_minus_b_minus, 1,
85396                            ROUND_UP);
85397          add_dbm_constraint(0, left_w_id + 1, a_plus_minus_b_minus);
85398          return;
85399        }
85400        if (is_left_coeff_minus_one && is_right_coeff_one) {
85401          // We fall back to a previous case.
85402          PPL_DIRTY_TEMP(N, a_plus_minus_b_minus);
85403          const FP_Interval_Type& left_b = left.inhomogeneous_term();
85404          const FP_Interval_Type& right_a = right.inhomogeneous_term();
85405          sub_assign_r(a_plus_minus_b_minus, right_a.upper(), left_b.lower(),
85406                       ROUND_UP);
85407          div_2exp_assign_r(a_plus_minus_b_minus, a_plus_minus_b_minus, 1,
85408                            ROUND_UP);
85409          add_dbm_constraint(right_w_id + 1, 0, a_plus_minus_b_minus);
85410          return;
85411        }
85412      }
85413      else if (is_left_coeff_minus_one && is_right_coeff_one) {
85414        // over-approximate (if is it possible) the inequality
85415        // -B + [b1, b2] <= A + [a1, a2] by adding the constraints
85416        // -B <= upper_bound(A) + (a2 - b1) and
85417        // -A <= upper_bound(B) + (a2 - b1)
85418        PPL_DIRTY_TEMP(N, a_plus_minus_b_minus);
85419        const FP_Interval_Type& left_b = left.inhomogeneous_term();
85420        const FP_Interval_Type& right_a = right.inhomogeneous_term();
85421        sub_assign_r(a_plus_minus_b_minus, right_a.upper(), left_b.lower(),
85422                       ROUND_UP);
85423        PPL_DIRTY_TEMP(N, ub);
85424        ub = dbm[0][right_w_id + 1];
85425        if (!is_plus_infinity(ub)) {
85426          add_assign_r(ub, ub, a_plus_minus_b_minus, ROUND_UP);
85427          add_dbm_constraint(left_w_id + 1, 0, ub);
85428        }
85429        ub = dbm[0][left_w_id + 1];
85430        if (!is_plus_infinity(ub)) {
85431          add_assign_r(ub, ub, a_plus_minus_b_minus, ROUND_UP);
85432          add_dbm_constraint(right_w_id + 1, 0, ub);
85433        }
85434        return;
85435      }
85436      if (is_left_coeff_one && is_right_coeff_minus_one) {
85437        // over-approximate (if is it possible) the inequality
85438        // B + [b1, b2] <= -A + [a1, a2] by adding the constraints
85439        // B <= upper_bound(-A) + (a2 - b1) and
85440        // A <= upper_bound(-B) + (a2 - b1)
85441        PPL_DIRTY_TEMP(N, a_plus_minus_b_minus);
85442        const FP_Interval_Type& left_b = left.inhomogeneous_term();
85443        const FP_Interval_Type& right_a = right.inhomogeneous_term();
85444        sub_assign_r(a_plus_minus_b_minus, right_a.upper(), left_b.lower(),
85445                       ROUND_UP);
85446        PPL_DIRTY_TEMP(N, ub);
85447        ub = dbm[right_w_id + 1][0];
85448        if (!is_plus_infinity(ub)) {
85449          add_assign_r(ub, ub, a_plus_minus_b_minus, ROUND_UP);
85450          add_dbm_constraint(0, left_w_id + 1, ub);
85451        }
85452        ub = dbm[left_w_id + 1][0];
85453        if (!is_plus_infinity(ub)) {
85454          add_assign_r(ub, ub, a_plus_minus_b_minus, ROUND_UP);
85455          add_dbm_constraint(0, right_w_id + 1, ub);
85456        }
85457            return;
85458      }
85459      if (is_left_coeff_one && is_right_coeff_one) {
85460        PPL_DIRTY_TEMP(N, c_plus_minus_a_minus);
85461        const FP_Interval_Type& left_a = left.inhomogeneous_term();
85462        const FP_Interval_Type& right_c = right.inhomogeneous_term();
85463        sub_assign_r(c_plus_minus_a_minus, right_c.upper(), left_a.lower(),
85464                     ROUND_UP);
85465        add_dbm_constraint(right_w_id+1, left_w_id+1, c_plus_minus_a_minus);
85466        return;
85467      }
85468      if (is_left_coeff_minus_one && is_right_coeff_minus_one) {
85469        PPL_DIRTY_TEMP(N, c_plus_minus_a_minus);
85470        const FP_Interval_Type& left_a = left.inhomogeneous_term();
85471        const FP_Interval_Type& right_c = right.inhomogeneous_term();
85472        sub_assign_r(c_plus_minus_a_minus, right_c.upper(), left_a.lower(),
85473                     ROUND_UP);
85474        add_dbm_constraint(left_w_id+1, right_w_id+1, c_plus_minus_a_minus);
85475        return;
85476      }
85477    }
85478}
85479
85480template <typename T>
85481template <typename Interval_Info>
85482void
85483BD_Shape<T>
85484::general_refine(const dimension_type& left_w_id,
85485                 const dimension_type& right_w_id,
85486                 const Linear_Form< Interval<T, Interval_Info> >& left,
85487                 const Linear_Form< Interval<T, Interval_Info> >& right) {
85488
85489  typedef Interval<T, Interval_Info> FP_Interval_Type;
85490  Linear_Form<FP_Interval_Type> right_minus_left(right);
85491  right_minus_left -= left;
85492
85493  // Declare temporaries outside of the loop.
85494  PPL_DIRTY_TEMP(N, low_coeff);
85495  PPL_DIRTY_TEMP(N, high_coeff);
85496  PPL_DIRTY_TEMP(N, upper_bound);
85497
85498  dimension_type max_w_id = std::max(left_w_id, right_w_id);
85499
85500  for (dimension_type first_v = 0; first_v < max_w_id; ++first_v) {
85501    for (dimension_type second_v = first_v+1;
85502         second_v <= max_w_id; ++second_v) {
85503      const FP_Interval_Type& lfv_coefficient =
85504        left.coefficient(Variable(first_v));
85505      const FP_Interval_Type& lsv_coefficient =
85506        left.coefficient(Variable(second_v));
85507      const FP_Interval_Type& rfv_coefficient =
85508        right.coefficient(Variable(first_v));
85509      const FP_Interval_Type& rsv_coefficient =
85510        right.coefficient(Variable(second_v));
85511      // We update the constraints only when both variables appear in at
85512      // least one argument.
85513      bool do_update = false;
85514      assign_r(low_coeff, lfv_coefficient.lower(), ROUND_NOT_NEEDED);
85515      assign_r(high_coeff, lfv_coefficient.upper(), ROUND_NOT_NEEDED);
85516      if (low_coeff != 0 || high_coeff != 0) {
85517        assign_r(low_coeff, lsv_coefficient.lower(), ROUND_NOT_NEEDED);
85518        assign_r(high_coeff, lsv_coefficient.upper(), ROUND_NOT_NEEDED);
85519        if (low_coeff != 0 || high_coeff != 0) {
85520          do_update = true;
85521        }
85522        else {
85523          assign_r(low_coeff, rsv_coefficient.lower(), ROUND_NOT_NEEDED);
85524          assign_r(high_coeff, rsv_coefficient.upper(), ROUND_NOT_NEEDED);
85525          if (low_coeff != 0 || high_coeff != 0) {
85526            do_update = true;
85527          }
85528        }
85529      }
85530      else {
85531        assign_r(low_coeff, rfv_coefficient.lower(), ROUND_NOT_NEEDED);
85532        assign_r(high_coeff, rfv_coefficient.upper(), ROUND_NOT_NEEDED);
85533        if (low_coeff != 0 || high_coeff != 0) {
85534          assign_r(low_coeff, lsv_coefficient.lower(), ROUND_NOT_NEEDED);
85535          assign_r(high_coeff, lsv_coefficient.upper(), ROUND_NOT_NEEDED);
85536          if (low_coeff != 0 || high_coeff != 0) {
85537            do_update = true;
85538          }
85539          else {
85540            assign_r(low_coeff, rsv_coefficient.lower(), ROUND_NOT_NEEDED);
85541            assign_r(high_coeff, rsv_coefficient.upper(), ROUND_NOT_NEEDED);
85542            if (low_coeff != 0 || high_coeff != 0) {
85543              do_update = true;
85544            }
85545          }
85546        }
85547      }
85548
85549      if (do_update) {
85550        Variable first(first_v);
85551        Variable second(second_v);
85552        dimension_type n_first_var = first_v +1 ;
85553        dimension_type n_second_var = second_v + 1;
85554        linear_form_upper_bound(right_minus_left - first + second,
85555                                upper_bound);
85556        add_dbm_constraint(n_first_var, n_second_var, upper_bound);
85557        linear_form_upper_bound(right_minus_left + first - second,
85558                                upper_bound);
85559        add_dbm_constraint(n_second_var, n_first_var, upper_bound);
85560      }
85561    }
85562  }
85563
85564  // Finally, update the unary constraints.
85565  for (dimension_type v = 0; v < max_w_id; ++v) {
85566    const FP_Interval_Type& lv_coefficient =
85567      left.coefficient(Variable(v));
85568    const FP_Interval_Type& rv_coefficient =
85569      right.coefficient(Variable(v));
85570    // We update the constraints only if v appears in at least one of the
85571    // two arguments.
85572    bool do_update = false;
85573    assign_r(low_coeff, lv_coefficient.lower(), ROUND_NOT_NEEDED);
85574    assign_r(high_coeff, lv_coefficient.upper(), ROUND_NOT_NEEDED);
85575    if (low_coeff != 0 || high_coeff != 0) {
85576      do_update = true;
85577    }
85578    else {
85579      assign_r(low_coeff, rv_coefficient.lower(), ROUND_NOT_NEEDED);
85580      assign_r(high_coeff, rv_coefficient.upper(), ROUND_NOT_NEEDED);
85581      if (low_coeff != 0 || high_coeff != 0) {
85582        do_update = true;
85583      }
85584    }
85585
85586    if (do_update) {
85587      Variable var(v);
85588      dimension_type n_var = v + 1;
85589      linear_form_upper_bound(right_minus_left + var, upper_bound);
85590      add_dbm_constraint(0, n_var, upper_bound);
85591      linear_form_upper_bound(right_minus_left - var, upper_bound);
85592      add_dbm_constraint(n_var, 0, upper_bound);
85593    }
85594  }
85595
85596}
85597
85598template <typename T>
85599template <typename Interval_Info>
85600void
85601BD_Shape<T>::
85602linear_form_upper_bound(const Linear_Form< Interval<T, Interval_Info> >& lf,
85603                        N& result) const {
85604
85605  // Check that T is a floating point type.
85606  PPL_COMPILE_TIME_CHECK(!std::numeric_limits<T>::is_exact,
85607                     "BD_Shape<T>::linear_form_upper_bound:"
85608                     " T not a floating point type.");
85609
85610  const dimension_type lf_space_dimension = lf.space_dimension();
85611  PPL_ASSERT(lf_space_dimension <= space_dimension());
85612
85613  typedef Interval<T, Interval_Info> FP_Interval_Type;
85614
85615  PPL_DIRTY_TEMP(N, curr_lb);
85616  PPL_DIRTY_TEMP(N, curr_ub);
85617  PPL_DIRTY_TEMP(N, curr_var_ub);
85618  PPL_DIRTY_TEMP(N, curr_minus_var_ub);
85619
85620  PPL_DIRTY_TEMP(N, first_comparison_term);
85621  PPL_DIRTY_TEMP(N, second_comparison_term);
85622
85623  PPL_DIRTY_TEMP(N, negator);
85624
85625  assign_r(result, lf.inhomogeneous_term().upper(), ROUND_NOT_NEEDED);
85626
85627  for (dimension_type curr_var = 0, n_var = 0; curr_var < lf_space_dimension;
85628       ++curr_var) {
85629    n_var = curr_var + 1;
85630    const FP_Interval_Type&
85631      curr_coefficient = lf.coefficient(Variable(curr_var));
85632    assign_r(curr_lb, curr_coefficient.lower(), ROUND_NOT_NEEDED);
85633    assign_r(curr_ub, curr_coefficient.upper(), ROUND_NOT_NEEDED);
85634    if (curr_lb != 0 || curr_ub != 0) {
85635      assign_r(curr_var_ub, dbm[0][n_var], ROUND_NOT_NEEDED);
85636      neg_assign_r(curr_minus_var_ub, dbm[n_var][0], ROUND_NOT_NEEDED);
85637      // Optimize the most commons cases: curr = +/-[1, 1].
85638      if (curr_lb == 1 && curr_ub == 1) {
85639        add_assign_r(result, result, std::max(curr_var_ub, curr_minus_var_ub),
85640                     ROUND_UP);
85641      }
85642      else if (curr_lb == -1 && curr_ub == -1) {
85643        neg_assign_r(negator, std::min(curr_var_ub, curr_minus_var_ub),
85644                     ROUND_NOT_NEEDED);
85645        add_assign_r(result, result, negator, ROUND_UP);
85646      }
85647      else {
85648        // Next addend will be the maximum of four quantities.
85649        assign_r(first_comparison_term, 0, ROUND_NOT_NEEDED);
85650        assign_r(second_comparison_term, 0, ROUND_NOT_NEEDED);
85651        add_mul_assign_r(first_comparison_term, curr_var_ub, curr_ub,
85652                         ROUND_UP);
85653        add_mul_assign_r(second_comparison_term, curr_var_ub, curr_lb,
85654                         ROUND_UP);
85655        assign_r(first_comparison_term, std::max(first_comparison_term,
85656                                                 second_comparison_term),
85657                 ROUND_NOT_NEEDED);
85658        assign_r(second_comparison_term, 0, ROUND_NOT_NEEDED);
85659        add_mul_assign_r(second_comparison_term, curr_minus_var_ub, curr_ub,
85660                         ROUND_UP);
85661        assign_r(first_comparison_term, std::max(first_comparison_term,
85662                                                 second_comparison_term),
85663                 ROUND_NOT_NEEDED);
85664        assign_r(second_comparison_term, 0, ROUND_NOT_NEEDED);
85665        add_mul_assign_r(second_comparison_term, curr_minus_var_ub, curr_lb,
85666                         ROUND_UP);
85667        assign_r(first_comparison_term, std::max(first_comparison_term,
85668                                                 second_comparison_term),
85669                 ROUND_NOT_NEEDED);
85670
85671        add_assign_r(result, result, first_comparison_term, ROUND_UP);
85672      }
85673    }
85674  }
85675}
85676
85677template <typename T>
85678void
85679BD_Shape<T>::affine_preimage(const Variable var,
85680                             const Linear_Expression& expr,
85681                             Coefficient_traits::const_reference denominator) {
85682  // The denominator cannot be zero.
85683  if (denominator == 0) {
85684    throw_invalid_argument("affine_preimage(v, e, d)", "d == 0");
85685  }
85686  // Dimension-compatibility checks.
85687  // The dimension of `expr' should not be greater than the dimension
85688  // of `*this'.
85689  const dimension_type space_dim = space_dimension();
85690  const dimension_type expr_space_dim = expr.space_dimension();
85691  if (space_dim < expr_space_dim) {
85692    throw_dimension_incompatible("affine_preimage(v, e, d)", "e", expr);
85693  }
85694  // `var' should be one of the dimensions of
85695  // the bounded difference shapes.
85696  const dimension_type v = var.id() + 1;
85697  if (v > space_dim) {
85698    throw_dimension_incompatible("affine_preimage(v, e, d)", var.id());
85699  }
85700  // The image of an empty BDS is empty too.
85701  shortest_path_closure_assign();
85702  if (marked_empty()) {
85703    return;
85704  }
85705  const Coefficient& b = expr.inhomogeneous_term();
85706  // Number of non-zero coefficients in `expr': will be set to
85707  // 0, 1, or 2, the latter value meaning any value greater than 1.
85708  dimension_type t = 0;
85709  // Index of the last non-zero coefficient in `expr', if any.
85710  dimension_type j = expr.last_nonzero();
85711
85712  if (j != 0) {
85713    ++t;
85714    if (!expr.all_zeroes(1, j)) {
85715      ++t;
85716    }
85717  }
85718
85719  // Now we know the form of `expr':
85720  // - If t == 0, then expr = b, with `b' a constant;
85721  // - If t == 1, then expr = a*w + b, where `w' can be `v' or another
85722  //   variable; in this second case we have to check whether `a' is
85723  //   equal to `denominator' or `-denominator', since otherwise we have
85724  //   to fall back on the general form;
85725  // - If t > 1, the `expr' is of the general form.
85726  if (t == 0) {
85727    // Case 1: expr = n; remove all constraints on `var'.
85728    forget_all_dbm_constraints(v);
85729    // Shortest-path closure is preserved, but not reduction.
85730    if (marked_shortest_path_reduced()) {
85731      reset_shortest_path_reduced();
85732    }
85733    PPL_ASSERT(OK());
85734    return;
85735  }
85736
85737  if (t == 1) {
85738    // Value of the one and only non-zero coefficient in `expr'.
85739    const Coefficient& a = expr.get(Variable(j - 1));
85740    if (a == denominator || a == -denominator) {
85741      // Case 2: expr = a*w + b, with a = +/- denominator.
85742      if (j == var.space_dimension()) {
85743        // Apply affine_image() on the inverse of this transformation.
85744        affine_image(var, denominator*var - b, a);
85745      }
85746      else {
85747        // `expr == a*w + b', where `w != v'.
85748        // Remove all constraints on `var'.
85749        forget_all_dbm_constraints(v);
85750        // Shortest-path closure is preserved, but not reduction.
85751        if (marked_shortest_path_reduced()) {
85752          reset_shortest_path_reduced();
85753        }
85754        PPL_ASSERT(OK());
85755      }
85756      return;
85757    }
85758  }
85759
85760  // General case.
85761  // Either t == 2, so that
85762  // expr = a_1*x_1 + a_2*x_2 + ... + a_n*x_n + b, where n >= 2,
85763  // or t = 1, expr = a*w + b, but a <> +/- denominator.
85764  const Coefficient& expr_v = expr.coefficient(var);
85765  if (expr_v != 0) {
85766    // The transformation is invertible.
85767    Linear_Expression inverse((expr_v + denominator)*var);
85768    inverse -= expr;
85769    affine_image(var, inverse, expr_v);
85770  }
85771  else {
85772    // Transformation not invertible: all constraints on `var' are lost.
85773    forget_all_dbm_constraints(v);
85774    // Shortest-path closure is preserved, but not reduction.
85775    if (marked_shortest_path_reduced()) {
85776      reset_shortest_path_reduced();
85777    }
85778  }
85779  PPL_ASSERT(OK());
85780}
85781
85782template <typename T>
85783void
85784BD_Shape<T>
85785::bounded_affine_image(const Variable var,
85786                       const Linear_Expression& lb_expr,
85787                       const Linear_Expression& ub_expr,
85788                       Coefficient_traits::const_reference denominator) {
85789  // The denominator cannot be zero.
85790  if (denominator == 0) {
85791    throw_invalid_argument("bounded_affine_image(v, lb, ub, d)", "d == 0");
85792  }
85793  // Dimension-compatibility checks.
85794  // `var' should be one of the dimensions of the BD_Shape.
85795  const dimension_type bds_space_dim = space_dimension();
85796  const dimension_type v = var.id() + 1;
85797  if (v > bds_space_dim) {
85798    throw_dimension_incompatible("bounded_affine_image(v, lb, ub, d)",
85799                                 "v", var);
85800  }
85801  // The dimension of `lb_expr' and `ub_expr' should not be
85802  // greater than the dimension of `*this'.
85803  const dimension_type lb_space_dim = lb_expr.space_dimension();
85804  if (bds_space_dim < lb_space_dim) {
85805    throw_dimension_incompatible("bounded_affine_image(v, lb, ub, d)",
85806                                 "lb", lb_expr);
85807  }
85808  const dimension_type ub_space_dim = ub_expr.space_dimension();
85809  if (bds_space_dim < ub_space_dim) {
85810    throw_dimension_incompatible("bounded_affine_image(v, lb, ub, d)",
85811                                 "ub", ub_expr);
85812  }
85813  // Any image of an empty BDS is empty.
85814  shortest_path_closure_assign();
85815  if (marked_empty()) {
85816    return;
85817  }
85818  const Coefficient& b = ub_expr.inhomogeneous_term();
85819  // Number of non-zero coefficients in `ub_expr': will be set to
85820  // 0, 1, or 2, the latter value meaning any value greater than 1.
85821  dimension_type t = 0;
85822  // Index of the last non-zero coefficient in `ub_expr', if any.
85823  dimension_type w = ub_expr.last_nonzero();
85824
85825  if (w != 0) {
85826    ++t;
85827    if (!ub_expr.all_zeroes(1, w)) {
85828      ++t;
85829    }
85830  }
85831
85832  // Now we know the form of `ub_expr':
85833  // - If t == 0, then ub_expr == b, with `b' a constant;
85834  // - If t == 1, then ub_expr == a*w + b, where `w' can be `v' or another
85835  //   variable; in this second case we have to check whether `a' is
85836  //   equal to `denominator' or `-denominator', since otherwise we have
85837  //   to fall back on the general form;
85838  // - If t == 2, the `ub_expr' is of the general form.
85839  PPL_DIRTY_TEMP_COEFFICIENT(minus_denom);
85840  neg_assign(minus_denom, denominator);
85841
85842  if (t == 0) {
85843    // Case 1: ub_expr == b.
85844    generalized_affine_image(var,
85845                             GREATER_OR_EQUAL,
85846                             lb_expr,
85847                             denominator);
85848    // Add the constraint `var <= b/denominator'.
85849    add_dbm_constraint(0, v, b, denominator);
85850    PPL_ASSERT(OK());
85851    return;
85852  }
85853
85854  if (t == 1) {
85855    // Value of the one and only non-zero coefficient in `ub_expr'.
85856    const Coefficient& a = ub_expr.get(Variable(w - 1));
85857    if (a == denominator || a == minus_denom) {
85858      // Case 2: expr == a*w + b, with a == +/- denominator.
85859      if (w == v) {
85860        // Here `var' occurs in `ub_expr'.
85861        // To ease the computation, we add an additional dimension.
85862        const Variable new_var(bds_space_dim);
85863        add_space_dimensions_and_embed(1);
85864        // Constrain the new dimension to be equal to `ub_expr'.
85865        affine_image(new_var, ub_expr, denominator);
85866        // NOTE: enforce shortest-path closure for precision.
85867        shortest_path_closure_assign();
85868        PPL_ASSERT(!marked_empty());
85869        // Apply the affine lower bound.
85870        generalized_affine_image(var,
85871                                 GREATER_OR_EQUAL,
85872                                 lb_expr,
85873                                 denominator);
85874        // Now apply the affine upper bound, as recorded in `new_var'.
85875        add_constraint(var <= new_var);
85876        // Remove the temporarily added dimension.
85877        remove_higher_space_dimensions(bds_space_dim);
85878        return;
85879      }
85880      else {
85881        // Here `w != v', so that `expr' is of the form
85882        // +/-denominator * w + b.
85883        // Apply the affine lower bound.
85884        generalized_affine_image(var,
85885                                 GREATER_OR_EQUAL,
85886                                 lb_expr,
85887                                 denominator);
85888        if (a == denominator) {
85889          // Add the new constraint `v - w == b/denominator'.
85890          add_dbm_constraint(w, v, b, denominator);
85891        }
85892        else {
85893          // Here a == -denominator, so that we should be adding
85894          // the constraint `v + w == b/denominator'.
85895          // Approximate it by computing lower and upper bounds for `w'.
85896          const N& dbm_w0 = dbm[w][0];
85897          if (!is_plus_infinity(dbm_w0)) {
85898            // Add the constraint `v <= b/denominator - lower_w'.
85899            PPL_DIRTY_TEMP(N, d);
85900            div_round_up(d, b, denominator);
85901            add_assign_r(dbm[0][v], d, dbm_w0, ROUND_UP);
85902            reset_shortest_path_closed();
85903          }
85904        }
85905        PPL_ASSERT(OK());
85906        return;
85907      }
85908    }
85909  }
85910
85911  // General case.
85912  // Either t == 2, so that
85913  // ub_expr == a_1*x_1 + a_2*x_2 + ... + a_n*x_n + b, where n >= 2,
85914  // or t == 1, ub_expr == a*w + b, but a <> +/- denominator.
85915  // We will remove all the constraints on `var' and add back
85916  // constraints providing upper and lower bounds for `var'.
85917
85918  // Compute upper approximations for `ub_expr' into `pos_sum'
85919  // taking into account the sign of `denominator'.
85920  const bool is_sc = (denominator > 0);
85921  PPL_DIRTY_TEMP_COEFFICIENT(minus_b);
85922  neg_assign(minus_b, b);
85923  const Coefficient& sc_b = is_sc ? b : minus_b;
85924  const Coefficient& sc_denom = is_sc ? denominator : minus_denom;
85925  const Coefficient& minus_sc_denom = is_sc ? minus_denom : denominator;
85926  // NOTE: here, for optimization purposes, `minus_expr' is only assigned
85927  // when `denominator' is negative. Do not use it unless you are sure
85928  // it has been correctly assigned.
85929  Linear_Expression minus_expr;
85930  if (!is_sc) {
85931    minus_expr = -ub_expr;
85932  }
85933  const Linear_Expression& sc_expr = is_sc ? ub_expr : minus_expr;
85934
85935  PPL_DIRTY_TEMP(N, pos_sum);
85936  // Index of the variable that are unbounded in `this->dbm'.
85937  PPL_UNINITIALIZED(dimension_type, pos_pinf_index);
85938  // Number of unbounded variables found.
85939  dimension_type pos_pinf_count = 0;
85940
85941  // Approximate the inhomogeneous term.
85942  assign_r(pos_sum, sc_b, ROUND_UP);
85943
85944  // Approximate the homogeneous part of `sc_expr'.
85945  const DB_Row<N>& dbm_0 = dbm[0];
85946  // Speculative allocation of temporaries to be used in the following loop.
85947  PPL_DIRTY_TEMP(N, coeff_i);
85948  PPL_DIRTY_TEMP_COEFFICIENT(minus_sc_i);
85949  // Note: indices above `w' can be disregarded, as they all have
85950  // a zero coefficient in `sc_expr'.
85951  for (Linear_Expression::const_iterator i = sc_expr.begin(),
85952        i_end = sc_expr.lower_bound(Variable(w)); i != i_end; ++i) {
85953    const Coefficient& sc_i = *i;
85954    const dimension_type i_dim = i.variable().space_dimension();
85955    const int sign_i = sgn(sc_i);
85956    if (sign_i > 0) {
85957      assign_r(coeff_i, sc_i, ROUND_UP);
85958      // Approximating `sc_expr'.
85959      if (pos_pinf_count <= 1) {
85960        const N& up_approx_i = dbm_0[i_dim];
85961        if (!is_plus_infinity(up_approx_i)) {
85962          add_mul_assign_r(pos_sum, coeff_i, up_approx_i, ROUND_UP);
85963        }
85964        else {
85965          ++pos_pinf_count;
85966          pos_pinf_index = i_dim;
85967        }
85968      }
85969    }
85970    else {
85971      PPL_ASSERT(sign_i < 0);
85972      neg_assign(minus_sc_i, sc_i);
85973      // Note: using temporary named `coeff_i' to store -coeff_i.
85974      assign_r(coeff_i, minus_sc_i, ROUND_UP);
85975      // Approximating `sc_expr'.
85976      if (pos_pinf_count <= 1) {
85977        const N& up_approx_minus_i = dbm[i_dim][0];
85978        if (!is_plus_infinity(up_approx_minus_i)) {
85979          add_mul_assign_r(pos_sum, coeff_i, up_approx_minus_i, ROUND_UP);
85980        }
85981        else {
85982          ++pos_pinf_count;
85983          pos_pinf_index = i_dim;
85984        }
85985      }
85986    }
85987  }
85988  // Apply the affine lower bound.
85989  generalized_affine_image(var,
85990                           GREATER_OR_EQUAL,
85991                           lb_expr,
85992                           denominator);
85993  // Return immediately if no approximation could be computed.
85994  if (pos_pinf_count > 1) {
85995    return;
85996  }
85997
85998  // In the following, shortest-path closure will be definitely lost.
85999  reset_shortest_path_closed();
86000
86001  // Exploit the upper approximation, if possible.
86002  if (pos_pinf_count <= 1) {
86003    // Compute quotient (if needed).
86004    if (sc_denom != 1) {
86005      // Before computing quotients, the denominator should be approximated
86006      // towards zero. Since `sc_denom' is known to be positive, this amounts to
86007      // rounding downwards, which is achieved as usual by rounding upwards
86008      // `minus_sc_denom' and negating again the result.
86009      PPL_DIRTY_TEMP(N, down_sc_denom);
86010      assign_r(down_sc_denom, minus_sc_denom, ROUND_UP);
86011      neg_assign_r(down_sc_denom, down_sc_denom, ROUND_UP);
86012      div_assign_r(pos_sum, pos_sum, down_sc_denom, ROUND_UP);
86013    }
86014    // Add the upper bound constraint, if meaningful.
86015    if (pos_pinf_count == 0) {
86016      // Add the constraint `v <= pos_sum'.
86017      dbm[0][v] = pos_sum;
86018      // Deduce constraints of the form `v - u', where `u != v'.
86019      deduce_v_minus_u_bounds(v, w, sc_expr, sc_denom, pos_sum);
86020    }
86021    // Here `pos_pinf_count == 1'.
86022    else if (pos_pinf_index != v
86023             && sc_expr.get(Variable(pos_pinf_index - 1)) == sc_denom) {
86024        // Add the constraint `v - pos_pinf_index <= pos_sum'.
86025        dbm[pos_pinf_index][v] = pos_sum;
86026      }
86027  }
86028  PPL_ASSERT(OK());
86029}
86030
86031template <typename T>
86032void
86033BD_Shape<T>
86034::bounded_affine_preimage(const Variable var,
86035                          const Linear_Expression& lb_expr,
86036                          const Linear_Expression& ub_expr,
86037                          Coefficient_traits::const_reference denominator) {
86038  // The denominator cannot be zero.
86039  if (denominator == 0) {
86040    throw_invalid_argument("bounded_affine_preimage(v, lb, ub, d)", "d == 0");
86041  }
86042  // Dimension-compatibility checks.
86043  // `var' should be one of the dimensions of the BD_Shape.
86044  const dimension_type space_dim = space_dimension();
86045  const dimension_type v = var.id() + 1;
86046  if (v > space_dim) {
86047    throw_dimension_incompatible("bounded_affine_preimage(v, lb, ub, d)",
86048                                 "v", var);
86049  }
86050  // The dimension of `lb_expr' and `ub_expr' should not be
86051  // greater than the dimension of `*this'.
86052  const dimension_type lb_space_dim = lb_expr.space_dimension();
86053  if (space_dim < lb_space_dim) {
86054    throw_dimension_incompatible("bounded_affine_preimage(v, lb, ub, d)",
86055                                 "lb", lb_expr);
86056  }
86057  const dimension_type ub_space_dim = ub_expr.space_dimension();
86058  if (space_dim < ub_space_dim) {
86059    throw_dimension_incompatible("bounded_affine_preimage(v, lb, ub, d)",
86060                                 "ub", ub_expr);
86061  }
86062  // Any preimage of an empty BDS is empty.
86063  shortest_path_closure_assign();
86064  if (marked_empty()) {
86065    return;
86066  }
86067  if (ub_expr.coefficient(var) == 0) {
86068    refine(var, LESS_OR_EQUAL, ub_expr, denominator);
86069    generalized_affine_preimage(var, GREATER_OR_EQUAL,
86070                                lb_expr, denominator);
86071    return;
86072  }
86073  if (lb_expr.coefficient(var) == 0) {
86074    refine(var, GREATER_OR_EQUAL, lb_expr, denominator);
86075    generalized_affine_preimage(var, LESS_OR_EQUAL,
86076                                ub_expr, denominator);
86077    return;
86078  }
86079
86080  const Coefficient& lb_expr_v = lb_expr.coefficient(var);
86081  // Here `var' occurs in `lb_expr' and `ub_expr'.
86082  // To ease the computation, we add an additional dimension.
86083  const Variable new_var(space_dim);
86084  add_space_dimensions_and_embed(1);
86085  const Linear_Expression lb_inverse
86086    = lb_expr - (lb_expr_v + denominator)*var;
86087  PPL_DIRTY_TEMP_COEFFICIENT(lb_inverse_denom);
86088  neg_assign(lb_inverse_denom, lb_expr_v);
86089  affine_image(new_var, lb_inverse, lb_inverse_denom);
86090  shortest_path_closure_assign();
86091  PPL_ASSERT(!marked_empty());
86092  generalized_affine_preimage(var, LESS_OR_EQUAL,
86093                              ub_expr, denominator);
86094  if (sgn(denominator) == sgn(lb_inverse_denom)) {
86095    add_constraint(var >= new_var);
86096  }
86097  else {
86098    add_constraint(var <= new_var);
86099  }
86100  // Remove the temporarily added dimension.
86101  remove_higher_space_dimensions(space_dim);
86102}
86103
86104template <typename T>
86105void
86106BD_Shape<T>::generalized_affine_image(const Variable var,
86107                                      const Relation_Symbol relsym,
86108                                      const Linear_Expression& expr,
86109                                      Coefficient_traits::const_reference
86110                                      denominator) {
86111  // The denominator cannot be zero.
86112  if (denominator == 0) {
86113    throw_invalid_argument("generalized_affine_image(v, r, e, d)", "d == 0");
86114  }
86115  // Dimension-compatibility checks.
86116  // The dimension of `expr' should not be greater than the dimension
86117  // of `*this'.
86118  const dimension_type space_dim = space_dimension();
86119  const dimension_type expr_space_dim = expr.space_dimension();
86120  if (space_dim < expr_space_dim) {
86121    throw_dimension_incompatible("generalized_affine_image(v, r, e, d)",
86122                                 "e", expr);
86123  }
86124  // `var' should be one of the dimensions of the BDS.
86125  const dimension_type v = var.id() + 1;
86126  if (v > space_dim) {
86127    throw_dimension_incompatible("generalized_affine_image(v, r, e, d)",
86128                                 var.id());
86129  }
86130  // The relation symbol cannot be a strict relation symbol.
86131  if (relsym == LESS_THAN || relsym == GREATER_THAN) {
86132    throw_invalid_argument("generalized_affine_image(v, r, e, d)",
86133                           "r is a strict relation symbol");
86134  }
86135  // The relation symbol cannot be a disequality.
86136  if (relsym == NOT_EQUAL) {
86137    throw_invalid_argument("generalized_affine_image(v, r, e, d)",
86138                           "r is the disequality relation symbol");
86139  }
86140  if (relsym == EQUAL) {
86141    // The relation symbol is "=":
86142    // this is just an affine image computation.
86143    affine_image(var, expr, denominator);
86144    return;
86145  }
86146
86147  // The image of an empty BDS is empty too.
86148  shortest_path_closure_assign();
86149  if (marked_empty()) {
86150    return;
86151  }
86152  const Coefficient& b = expr.inhomogeneous_term();
86153  // Number of non-zero coefficients in `expr': will be set to
86154  // 0, 1, or 2, the latter value meaning any value greater than 1.
86155  dimension_type t = 0;
86156  // Index of the last non-zero coefficient in `expr', if any.
86157  dimension_type w = expr.last_nonzero();
86158
86159  if (w != 0) {
86160    ++t;
86161    if (!expr.all_zeroes(1, w)) {
86162      ++t;
86163    }
86164  }
86165
86166  // Now we know the form of `expr':
86167  // - If t == 0, then expr == b, with `b' a constant;
86168  // - If t == 1, then expr == a*w + b, where `w' can be `v' or another
86169  //   variable; in this second case we have to check whether `a' is
86170  //   equal to `denominator' or `-denominator', since otherwise we have
86171  //   to fall back on the general form;
86172  // - If t == 2, the `expr' is of the general form.
86173  DB_Row<N>& dbm_0 = dbm[0];
86174  DB_Row<N>& dbm_v = dbm[v];
86175  PPL_DIRTY_TEMP_COEFFICIENT(minus_denom);
86176  neg_assign(minus_denom, denominator);
86177
86178  if (t == 0) {
86179    // Case 1: expr == b.
86180    // Remove all constraints on `var'.
86181    forget_all_dbm_constraints(v);
86182    // Both shortest-path closure and reduction are lost.
86183    reset_shortest_path_closed();
86184    switch (relsym) {
86185    case LESS_OR_EQUAL:
86186      // Add the constraint `var <= b/denominator'.
86187      add_dbm_constraint(0, v, b, denominator);
86188      break;
86189    case GREATER_OR_EQUAL:
86190      // Add the constraint `var >= b/denominator',
86191      // i.e., `-var <= -b/denominator',
86192      add_dbm_constraint(v, 0, b, minus_denom);
86193      break;
86194    default:
86195      // We already dealt with the other cases.
86196      PPL_UNREACHABLE;
86197      break;
86198    }
86199    PPL_ASSERT(OK());
86200    return;
86201  }
86202
86203  if (t == 1) {
86204    // Value of the one and only non-zero coefficient in `expr'.
86205    const Coefficient& a = expr.get(Variable(w - 1));
86206    if (a == denominator || a == minus_denom) {
86207      // Case 2: expr == a*w + b, with a == +/- denominator.
86208      PPL_DIRTY_TEMP(N, d);
86209      switch (relsym) {
86210      case LESS_OR_EQUAL:
86211        div_round_up(d, b, denominator);
86212        if (w == v) {
86213          // `expr' is of the form: a*v + b.
86214          // Shortest-path closure and reduction are not preserved.
86215          reset_shortest_path_closed();
86216          if (a == denominator) {
86217            // Translate each constraint `v - w <= dbm_wv'
86218            // into the constraint `v - w <= dbm_wv + b/denominator';
86219            // forget each constraint `w - v <= dbm_vw'.
86220            for (dimension_type i = space_dim + 1; i-- > 0; ) {
86221              N& dbm_iv = dbm[i][v];
86222              add_assign_r(dbm_iv, dbm_iv, d, ROUND_UP);
86223              assign_r(dbm_v[i], PLUS_INFINITY, ROUND_NOT_NEEDED);
86224            }
86225          }
86226          else {
86227            // Here `a == -denominator'.
86228            // Translate the constraint `0 - v <= dbm_v0'
86229            // into the constraint `0 - v <= dbm_v0 + b/denominator'.
86230            N& dbm_v0 = dbm_v[0];
86231            add_assign_r(dbm_0[v], dbm_v0, d, ROUND_UP);
86232            // Forget all the other constraints on `v'.
86233            assign_r(dbm_v0, PLUS_INFINITY, ROUND_NOT_NEEDED);
86234            forget_binary_dbm_constraints(v);
86235          }
86236        }
86237        else {
86238          // Here `w != v', so that `expr' is of the form
86239          // +/-denominator * w + b, with `w != v'.
86240          // Remove all constraints on `v'.
86241          forget_all_dbm_constraints(v);
86242          // Shortest-path closure is preserved, but not reduction.
86243          if (marked_shortest_path_reduced()) {
86244            reset_shortest_path_reduced();
86245          }
86246          if (a == denominator) {
86247            // Add the new constraint `v - w <= b/denominator'.
86248            add_dbm_constraint(w, v, d);
86249          }
86250          else {
86251            // Here a == -denominator, so that we should be adding
86252            // the constraint `v <= b/denominator - w'.
86253            // Approximate it by computing a lower bound for `w'.
86254            const N& dbm_w0 = dbm[w][0];
86255            if (!is_plus_infinity(dbm_w0)) {
86256              // Add the constraint `v <= b/denominator - lb_w'.
86257              add_assign_r(dbm_0[v], d, dbm_w0, ROUND_UP);
86258              // Shortest-path closure is not preserved.
86259              reset_shortest_path_closed();
86260            }
86261          }
86262        }
86263        break;
86264
86265      case GREATER_OR_EQUAL:
86266        div_round_up(d, b, minus_denom);
86267        if (w == v) {
86268          // `expr' is of the form: a*w + b.
86269          // Shortest-path closure and reduction are not preserved.
86270          reset_shortest_path_closed();
86271          if (a == denominator) {
86272            // Translate each constraint `w - v <= dbm_vw'
86273            // into the constraint `w - v <= dbm_vw - b/denominator';
86274            // forget each constraint `v - w <= dbm_wv'.
86275            for (dimension_type i = space_dim + 1; i-- > 0; ) {
86276              N& dbm_vi = dbm_v[i];
86277              add_assign_r(dbm_vi, dbm_vi, d, ROUND_UP);
86278              assign_r(dbm[i][v], PLUS_INFINITY, ROUND_NOT_NEEDED);
86279            }
86280          }
86281          else {
86282            // Here `a == -denominator'.
86283            // Translate the constraint `0 - v <= dbm_v0'
86284            // into the constraint `0 - v <= dbm_0v - b/denominator'.
86285            N& dbm_0v = dbm_0[v];
86286            add_assign_r(dbm_v[0], dbm_0v, d, ROUND_UP);
86287            // Forget all the other constraints on `v'.
86288            assign_r(dbm_0v, PLUS_INFINITY, ROUND_NOT_NEEDED);
86289            forget_binary_dbm_constraints(v);
86290          }
86291        }
86292        else {
86293          // Here `w != v', so that `expr' is of the form
86294          // +/-denominator * w + b, with `w != v'.
86295          // Remove all constraints on `v'.
86296          forget_all_dbm_constraints(v);
86297          // Shortest-path closure is preserved, but not reduction.
86298          if (marked_shortest_path_reduced()) {
86299            reset_shortest_path_reduced();
86300          }
86301          if (a == denominator) {
86302            // Add the new constraint `v - w >= b/denominator',
86303            // i.e., `w - v <= -b/denominator'.
86304            add_dbm_constraint(v, w, d);
86305          }
86306          else {
86307            // Here a == -denominator, so that we should be adding
86308            // the constraint `v >= -w + b/denominator',
86309            // i.e., `-v <= w - b/denominator'.
86310            // Approximate it by computing an upper bound for `w'.
86311            const N& dbm_0w = dbm_0[w];
86312            if (!is_plus_infinity(dbm_0w)) {
86313              // Add the constraint `-v <= ub_w - b/denominator'.
86314              add_assign_r(dbm_v[0], dbm_0w, d, ROUND_UP);
86315              // Shortest-path closure is not preserved.
86316              reset_shortest_path_closed();
86317            }
86318          }
86319        }
86320        break;
86321
86322      default:
86323        // We already dealt with the other cases.
86324        PPL_UNREACHABLE;
86325        break;
86326      }
86327      PPL_ASSERT(OK());
86328      return;
86329    }
86330  }
86331
86332  // General case.
86333  // Either t == 2, so that
86334  // expr == a_1*x_1 + a_2*x_2 + ... + a_n*x_n + b, where n >= 2,
86335  // or t == 1, expr == a*w + b, but a <> +/- denominator.
86336  // We will remove all the constraints on `v' and add back
86337  // a constraint providing an upper or a lower bound for `v'
86338  // (depending on `relsym').
86339  const bool is_sc = (denominator > 0);
86340  PPL_DIRTY_TEMP_COEFFICIENT(minus_b);
86341  neg_assign(minus_b, b);
86342  const Coefficient& sc_b = is_sc ? b : minus_b;
86343  const Coefficient& minus_sc_b = is_sc ? minus_b : b;
86344  const Coefficient& sc_denom = is_sc ? denominator : minus_denom;
86345  const Coefficient& minus_sc_denom = is_sc ? minus_denom : denominator;
86346  // NOTE: here, for optimization purposes, `minus_expr' is only assigned
86347  // when `denominator' is negative. Do not use it unless you are sure
86348  // it has been correctly assigned.
86349  Linear_Expression minus_expr;
86350  if (!is_sc) {
86351    minus_expr = -expr;
86352  }
86353  const Linear_Expression& sc_expr = is_sc ? expr : minus_expr;
86354
86355  PPL_DIRTY_TEMP(N, sum);
86356  // Index of variable that is unbounded in `this->dbm'.
86357  PPL_UNINITIALIZED(dimension_type, pinf_index);
86358  // Number of unbounded variables found.
86359  dimension_type pinf_count = 0;
86360
86361  // Speculative allocation of temporaries to be used in the following loops.
86362  PPL_DIRTY_TEMP(N, coeff_i);
86363  PPL_DIRTY_TEMP_COEFFICIENT(minus_sc_i);
86364
86365  switch (relsym) {
86366  case LESS_OR_EQUAL:
86367    // Compute an upper approximation for `sc_expr' into `sum'.
86368
86369    // Approximate the inhomogeneous term.
86370    assign_r(sum, sc_b, ROUND_UP);
86371    // Approximate the homogeneous part of `sc_expr'.
86372    // Note: indices above `w' can be disregarded, as they all have
86373    // a zero coefficient in `sc_expr'.
86374    PPL_ASSERT(w != 0);
86375    for (Linear_Expression::const_iterator i = sc_expr.begin(),
86376        i_end = sc_expr.lower_bound(Variable(w)); i != i_end; ++i) {
86377      const Coefficient& sc_i = *i;
86378      const dimension_type i_dim = i.variable().space_dimension();
86379      const int sign_i = sgn(sc_i);
86380      PPL_ASSERT(sign_i != 0);
86381      // Choose carefully: we are approximating `sc_expr'.
86382      const N& approx_i = (sign_i > 0) ? dbm_0[i_dim] : dbm[i_dim][0];
86383      if (is_plus_infinity(approx_i)) {
86384        if (++pinf_count > 1) {
86385          break;
86386        }
86387        pinf_index = i_dim;
86388        continue;
86389      }
86390      if (sign_i > 0) {
86391        assign_r(coeff_i, sc_i, ROUND_UP);
86392      }
86393      else {
86394        neg_assign(minus_sc_i, sc_i);
86395        assign_r(coeff_i, minus_sc_i, ROUND_UP);
86396      }
86397      add_mul_assign_r(sum, coeff_i, approx_i, ROUND_UP);
86398    }
86399
86400    // Remove all constraints on `v'.
86401    forget_all_dbm_constraints(v);
86402    // Shortest-path closure is preserved, but not reduction.
86403    if (marked_shortest_path_reduced()) {
86404      reset_shortest_path_reduced();
86405    }
86406    // Return immediately if no approximation could be computed.
86407    if (pinf_count > 1) {
86408      PPL_ASSERT(OK());
86409      return;
86410    }
86411
86412    // Divide by the (sign corrected) denominator (if needed).
86413    if (sc_denom != 1) {
86414      // Before computing the quotient, the denominator should be approximated
86415      // towards zero. Since `sc_denom' is known to be positive, this amounts to
86416      // rounding downwards, which is achieved as usual by rounding upwards
86417      // `minus_sc_denom' and negating again the result.
86418      PPL_DIRTY_TEMP(N, down_sc_denom);
86419      assign_r(down_sc_denom, minus_sc_denom, ROUND_UP);
86420      neg_assign_r(down_sc_denom, down_sc_denom, ROUND_UP);
86421      div_assign_r(sum, sum, down_sc_denom, ROUND_UP);
86422    }
86423
86424    if (pinf_count == 0) {
86425      // Add the constraint `v <= sum'.
86426      add_dbm_constraint(0, v, sum);
86427      // Deduce constraints of the form `v - u', where `u != v'.
86428      deduce_v_minus_u_bounds(v, w, sc_expr, sc_denom, sum);
86429    }
86430    else if (pinf_count == 1) {
86431      if (pinf_index != v
86432          && expr.get(Variable(pinf_index - 1)) == denominator) {
86433        // Add the constraint `v - pinf_index <= sum'.
86434        add_dbm_constraint(pinf_index, v, sum);
86435      }
86436    }
86437    break;
86438
86439  case GREATER_OR_EQUAL:
86440    // Compute an upper approximation for `-sc_expr' into `sum'.
86441    // Note: approximating `-sc_expr' from above and then negating the
86442    // result is the same as approximating `sc_expr' from below.
86443
86444    // Approximate the inhomogeneous term.
86445    assign_r(sum, minus_sc_b, ROUND_UP);
86446    // Approximate the homogeneous part of `-sc_expr'.
86447    for (Linear_Expression::const_iterator i = sc_expr.begin(),
86448        i_end = sc_expr.lower_bound(Variable(w)); i != i_end; ++i) {
86449      const Coefficient& sc_i = *i;
86450      const int sign_i = sgn(sc_i);
86451      PPL_ASSERT(sign_i != 0);
86452      const dimension_type i_dim = i.variable().space_dimension();
86453      // Choose carefully: we are approximating `-sc_expr'.
86454      const N& approx_i = (sign_i > 0) ? dbm[i_dim][0] : dbm_0[i_dim];
86455      if (is_plus_infinity(approx_i)) {
86456        if (++pinf_count > 1) {
86457          break;
86458        }
86459        pinf_index = i_dim;
86460        continue;
86461      }
86462      if (sign_i > 0) {
86463        assign_r(coeff_i, sc_i, ROUND_UP);
86464      }
86465      else {
86466        neg_assign(minus_sc_i, sc_i);
86467        assign_r(coeff_i, minus_sc_i, ROUND_UP);
86468      }
86469      add_mul_assign_r(sum, coeff_i, approx_i, ROUND_UP);
86470    }
86471
86472    // Remove all constraints on `var'.
86473    forget_all_dbm_constraints(v);
86474    // Shortest-path closure is preserved, but not reduction.
86475    if (marked_shortest_path_reduced()) {
86476      reset_shortest_path_reduced();
86477    }
86478    // Return immediately if no approximation could be computed.
86479    if (pinf_count > 1) {
86480      PPL_ASSERT(OK());
86481      return;
86482    }
86483
86484    // Divide by the (sign corrected) denominator (if needed).
86485    if (sc_denom != 1) {
86486      // Before computing the quotient, the denominator should be approximated
86487      // towards zero. Since `sc_denom' is known to be positive, this amounts to
86488      // rounding downwards, which is achieved as usual by rounding upwards
86489      // `minus_sc_denom' and negating again the result.
86490      PPL_DIRTY_TEMP(N, down_sc_denom);
86491      assign_r(down_sc_denom, minus_sc_denom, ROUND_UP);
86492      neg_assign_r(down_sc_denom, down_sc_denom, ROUND_UP);
86493      div_assign_r(sum, sum, down_sc_denom, ROUND_UP);
86494    }
86495
86496    if (pinf_count == 0) {
86497      // Add the constraint `v >= -sum', i.e., `-v <= sum'.
86498      add_dbm_constraint(v, 0, sum);
86499      // Deduce constraints of the form `u - v', where `u != v'.
86500      deduce_u_minus_v_bounds(v, w, sc_expr, sc_denom, sum);
86501    }
86502    else if (pinf_count == 1) {
86503      if (pinf_index != v
86504          && expr.get(Variable(pinf_index - 1)) == denominator) {
86505        // Add the constraint `v - pinf_index >= -sum',
86506        // i.e., `pinf_index - v <= sum'.
86507        add_dbm_constraint(v, pinf_index, sum);
86508      }
86509    }
86510    break;
86511
86512  default:
86513    // We already dealt with the other cases.
86514    PPL_UNREACHABLE;
86515    break;
86516  }
86517  PPL_ASSERT(OK());
86518}
86519
86520template <typename T>
86521void
86522BD_Shape<T>::generalized_affine_image(const Linear_Expression& lhs,
86523                                      const Relation_Symbol relsym,
86524                                      const Linear_Expression& rhs) {
86525  // Dimension-compatibility checks.
86526  // The dimension of `lhs' should not be greater than the dimension
86527  // of `*this'.
86528  const dimension_type space_dim = space_dimension();
86529  const dimension_type lhs_space_dim = lhs.space_dimension();
86530  if (space_dim < lhs_space_dim) {
86531    throw_dimension_incompatible("generalized_affine_image(e1, r, e2)",
86532                                 "e1", lhs);
86533  }
86534  // The dimension of `rhs' should not be greater than the dimension
86535  // of `*this'.
86536  const dimension_type rhs_space_dim = rhs.space_dimension();
86537  if (space_dim < rhs_space_dim) {
86538    throw_dimension_incompatible("generalized_affine_image(e1, r, e2)",
86539                                 "e2", rhs);
86540  }
86541  // Strict relation symbols are not admitted for BDSs.
86542  if (relsym == LESS_THAN || relsym == GREATER_THAN) {
86543    throw_invalid_argument("generalized_affine_image(e1, r, e2)",
86544                           "r is a strict relation symbol");
86545  }
86546  // The relation symbol cannot be a disequality.
86547  if (relsym == NOT_EQUAL) {
86548    throw_invalid_argument("generalized_affine_image(e1, r, e2)",
86549                           "r is the disequality relation symbol");
86550  }
86551  // The image of an empty BDS is empty.
86552  shortest_path_closure_assign();
86553  if (marked_empty()) {
86554    return;
86555  }
86556  // Number of non-zero coefficients in `lhs': will be set to
86557  // 0, 1, or 2, the latter value meaning any value greater than 1.
86558  dimension_type t_lhs = 0;
86559  // Index of the last non-zero coefficient in `lhs', if any.
86560  dimension_type j_lhs = lhs.last_nonzero();
86561
86562  if (j_lhs != 0) {
86563    ++t_lhs;
86564    if (!lhs.all_zeroes(1, j_lhs)) {
86565      ++t_lhs;
86566    }
86567    --j_lhs;
86568  }
86569
86570  const Coefficient& b_lhs = lhs.inhomogeneous_term();
86571
86572  if (t_lhs == 0) {
86573    // `lhs' is a constant.
86574    // In principle, it is sufficient to add the constraint `lhs relsym rhs'.
86575    // Note that this constraint is a bounded difference if `t_rhs <= 1'
86576    // or `t_rhs > 1' and `rhs == a*v - a*w + b_rhs'. If `rhs' is of a
86577    // more general form, it will be simply ignored.
86578    // TODO: if it is not a bounded difference, should we compute
86579    // approximations for this constraint?
86580    switch (relsym) {
86581    case LESS_OR_EQUAL:
86582      refine_no_check(lhs <= rhs);
86583      break;
86584    case EQUAL:
86585      refine_no_check(lhs == rhs);
86586      break;
86587    case GREATER_OR_EQUAL:
86588      refine_no_check(lhs >= rhs);
86589      break;
86590    default:
86591      // We already dealt with the other cases.
86592      PPL_UNREACHABLE;
86593      break;
86594    }
86595  }
86596  else if (t_lhs == 1) {
86597    // Here `lhs == a_lhs * v + b_lhs'.
86598    // Independently from the form of `rhs', we can exploit the
86599    // method computing generalized affine images for a single variable.
86600    Variable v(j_lhs);
86601    // Compute a sign-corrected relation symbol.
86602    const Coefficient& denom = lhs.coefficient(v);
86603    Relation_Symbol new_relsym = relsym;
86604    if (denom < 0) {
86605      if (relsym == LESS_OR_EQUAL) {
86606        new_relsym = GREATER_OR_EQUAL;
86607      }
86608      else if (relsym == GREATER_OR_EQUAL) {
86609        new_relsym = LESS_OR_EQUAL;
86610      }
86611    }
86612    Linear_Expression expr = rhs - b_lhs;
86613    generalized_affine_image(v, new_relsym, expr, denom);
86614  }
86615  else {
86616    // Here `lhs' is of the general form, having at least two variables.
86617    // Compute the set of variables occurring in `lhs'.
86618    std::vector<Variable> lhs_vars;
86619    for (Linear_Expression::const_iterator i = lhs.begin(), i_end = lhs.end();
86620          i != i_end; ++i) {
86621      lhs_vars.push_back(i.variable());
86622    }
86623    const dimension_type num_common_dims = std::min(lhs_space_dim, rhs_space_dim);
86624    if (!lhs.have_a_common_variable(rhs, Variable(0), Variable(num_common_dims))) {
86625      // `lhs' and `rhs' variables are disjoint.
86626      // Existentially quantify all variables in the lhs.
86627      for (dimension_type i = lhs_vars.size(); i-- > 0; ) {
86628        forget_all_dbm_constraints(lhs_vars[i].id() + 1);
86629      }
86630      // Constrain the left hand side expression so that it is related to
86631      // the right hand side expression as dictated by `relsym'.
86632      // TODO: if the following constraint is NOT a bounded difference,
86633      // it will be simply ignored. Should we compute approximations for it?
86634      switch (relsym) {
86635      case LESS_OR_EQUAL:
86636        refine_no_check(lhs <= rhs);
86637        break;
86638      case EQUAL:
86639        refine_no_check(lhs == rhs);
86640        break;
86641      case GREATER_OR_EQUAL:
86642        refine_no_check(lhs >= rhs);
86643        break;
86644      default:
86645        // We already dealt with the other cases.
86646        PPL_UNREACHABLE;
86647        break;
86648      }
86649    }
86650    else {
86651      // Some variables in `lhs' also occur in `rhs'.
86652
86653#if 1 // Simplified computation (see the TODO note below).
86654
86655      for (dimension_type i = lhs_vars.size(); i-- > 0; ) {
86656        forget_all_dbm_constraints(lhs_vars[i].id() + 1);
86657      }
86658#else // Currently unnecessarily complex computation.
86659
86660      // More accurate computation that is worth doing only if
86661      // the following TODO note is accurately dealt with.
86662
86663      // To ease the computation, we add an additional dimension.
86664      const Variable new_var(space_dim);
86665      add_space_dimensions_and_embed(1);
86666      // Constrain the new dimension to be equal to `rhs'.
86667      // NOTE: calling affine_image() instead of refine_no_check()
86668      // ensures some approximation is tried even when the constraint
86669      // is not a bounded difference.
86670      affine_image(new_var, rhs);
86671      // Existentially quantify all variables in the lhs.
86672      // NOTE: enforce shortest-path closure for precision.
86673      shortest_path_closure_assign();
86674      PPL_ASSERT(!marked_empty());
86675      for (dimension_type i = lhs_vars.size(); i-- > 0; ) {
86676        forget_all_dbm_constraints(lhs_vars[i].id() + 1);
86677      }
86678      // Constrain the new dimension so that it is related to
86679      // the left hand side as dictated by `relsym'.
86680      // TODO: each one of the following constraints is definitely NOT
86681      // a bounded differences (since it has 3 variables at least).
86682      // Thus, the method refine_no_check() will simply ignore it.
86683      // Should we compute approximations for this constraint?
86684      switch (relsym) {
86685      case LESS_OR_EQUAL:
86686        refine_no_check(lhs <= new_var);
86687        break;
86688      case EQUAL:
86689        refine_no_check(lhs == new_var);
86690        break;
86691      case GREATER_OR_EQUAL:
86692        refine_no_check(lhs >= new_var);
86693        break;
86694      default:
86695        // We already dealt with the other cases.
86696        PPL_UNREACHABLE;
86697        break;
86698      }
86699      // Remove the temporarily added dimension.
86700      remove_higher_space_dimensions(space_dim-1);
86701#endif // Currently unnecessarily complex computation.
86702    }
86703  }
86704
86705  PPL_ASSERT(OK());
86706}
86707
86708template <typename T>
86709void
86710BD_Shape<T>::generalized_affine_preimage(const Variable var,
86711                                         const Relation_Symbol relsym,
86712                                         const Linear_Expression& expr,
86713                                         Coefficient_traits::const_reference
86714                                         denominator) {
86715  // The denominator cannot be zero.
86716  if (denominator == 0) {
86717    throw_invalid_argument("generalized_affine_preimage(v, r, e, d)",
86718                           "d == 0");
86719  }
86720  // Dimension-compatibility checks.
86721  // The dimension of `expr' should not be greater than the dimension
86722  // of `*this'.
86723  const dimension_type space_dim = space_dimension();
86724  const dimension_type expr_space_dim = expr.space_dimension();
86725  if (space_dim < expr_space_dim) {
86726    throw_dimension_incompatible("generalized_affine_preimage(v, r, e, d)",
86727                                 "e", expr);
86728  }
86729  // `var' should be one of the dimensions of the BDS.
86730  const dimension_type v = var.id() + 1;
86731  if (v > space_dim) {
86732    throw_dimension_incompatible("generalized_affine_preimage(v, r, e, d)",
86733                                 var.id());
86734  }
86735  // The relation symbol cannot be a strict relation symbol.
86736  if (relsym == LESS_THAN || relsym == GREATER_THAN) {
86737    throw_invalid_argument("generalized_affine_preimage(v, r, e, d)",
86738                           "r is a strict relation symbol");
86739  }
86740  // The relation symbol cannot be a disequality.
86741  if (relsym == NOT_EQUAL)  {
86742    throw_invalid_argument("generalized_affine_preimage(v, r, e, d)",
86743                           "r is the disequality relation symbol");
86744  }
86745  if (relsym == EQUAL) {
86746    // The relation symbol is "=":
86747    // this is just an affine preimage computation.
86748    affine_preimage(var, expr, denominator);
86749    return;
86750  }
86751
86752  // The preimage of an empty BDS is empty too.
86753  shortest_path_closure_assign();
86754  if (marked_empty()) {
86755    return;
86756  }
86757  // Check whether the preimage of this affine relation can be easily
86758  // computed as the image of its inverse relation.
86759  const Coefficient& expr_v = expr.coefficient(var);
86760  if (expr_v != 0) {
86761    const Relation_Symbol reversed_relsym = (relsym == LESS_OR_EQUAL)
86762      ? GREATER_OR_EQUAL : LESS_OR_EQUAL;
86763    const Linear_Expression inverse
86764      = expr - (expr_v + denominator)*var;
86765    PPL_DIRTY_TEMP_COEFFICIENT(inverse_denom);
86766    neg_assign(inverse_denom, expr_v);
86767    const Relation_Symbol inverse_relsym
86768      = (sgn(denominator) == sgn(inverse_denom)) ? relsym : reversed_relsym;
86769    generalized_affine_image(var, inverse_relsym, inverse, inverse_denom);
86770    return;
86771  }
86772
86773  refine(var, relsym, expr, denominator);
86774  // If the shrunk BD_Shape is empty, its preimage is empty too; ...
86775  if (is_empty()) {
86776    return;
86777  }
86778  // ...  otherwise, since the relation was not invertible,
86779  // we just forget all constraints on `v'.
86780  forget_all_dbm_constraints(v);
86781  // Shortest-path closure is preserved, but not reduction.
86782  if (marked_shortest_path_reduced()) {
86783    reset_shortest_path_reduced();
86784  }
86785  PPL_ASSERT(OK());
86786}
86787
86788template <typename T>
86789void
86790BD_Shape<T>::generalized_affine_preimage(const Linear_Expression& lhs,
86791                                         const Relation_Symbol relsym,
86792                                         const Linear_Expression& rhs) {
86793  // Dimension-compatibility checks.
86794  // The dimension of `lhs' should not be greater than the dimension
86795  // of `*this'.
86796  const dimension_type bds_space_dim = space_dimension();
86797  const dimension_type lhs_space_dim = lhs.space_dimension();
86798  if (bds_space_dim < lhs_space_dim) {
86799    throw_dimension_incompatible("generalized_affine_preimage(e1, r, e2)",
86800                                 "e1", lhs);
86801  }
86802  // The dimension of `rhs' should not be greater than the dimension
86803  // of `*this'.
86804  const dimension_type rhs_space_dim = rhs.space_dimension();
86805  if (bds_space_dim < rhs_space_dim) {
86806    throw_dimension_incompatible("generalized_affine_preimage(e1, r, e2)",
86807                                 "e2", rhs);
86808  }
86809  // Strict relation symbols are not admitted for BDSs.
86810  if (relsym == LESS_THAN || relsym == GREATER_THAN) {
86811    throw_invalid_argument("generalized_affine_preimage(e1, r, e2)",
86812                           "r is a strict relation symbol");
86813  }
86814  // The relation symbol cannot be a disequality.
86815  if (relsym == NOT_EQUAL) {
86816    throw_invalid_argument("generalized_affine_preimage(e1, r, e2)",
86817                           "r is the disequality relation symbol");
86818  }
86819  // The preimage of an empty BDS is empty.
86820  shortest_path_closure_assign();
86821  if (marked_empty()) {
86822    return;
86823  }
86824  // Number of non-zero coefficients in `lhs': will be set to
86825  // 0, 1, or 2, the latter value meaning any value greater than 1.
86826  dimension_type t_lhs = 0;
86827  // Index of the last non-zero coefficient in `lhs', if any.
86828  dimension_type j_lhs = lhs.last_nonzero();
86829
86830  if (j_lhs != 0) {
86831    ++t_lhs;
86832    if (!lhs.all_zeroes(1, j_lhs)) {
86833      ++t_lhs;
86834    }
86835    --j_lhs;
86836  }
86837
86838  const Coefficient& b_lhs = lhs.inhomogeneous_term();
86839
86840  if (t_lhs == 0) {
86841    // `lhs' is a constant.
86842    // In this case, preimage and image happen to be the same.
86843    generalized_affine_image(lhs, relsym, rhs);
86844    return;
86845  }
86846  else if (t_lhs == 1) {
86847    // Here `lhs == a_lhs * v + b_lhs'.
86848    // Independently from the form of `rhs', we can exploit the
86849    // method computing generalized affine preimages for a single variable.
86850    Variable v(j_lhs);
86851    // Compute a sign-corrected relation symbol.
86852    const Coefficient& denom = lhs.coefficient(v);
86853    Relation_Symbol new_relsym = relsym;
86854    if (denom < 0) {
86855      if (relsym == LESS_OR_EQUAL) {
86856        new_relsym = GREATER_OR_EQUAL;
86857      }
86858      else if (relsym == GREATER_OR_EQUAL) {
86859        new_relsym = LESS_OR_EQUAL;
86860      }
86861    }
86862    Linear_Expression expr = rhs - b_lhs;
86863    generalized_affine_preimage(v, new_relsym, expr, denom);
86864  }
86865  else {
86866    // Here `lhs' is of the general form, having at least two variables.
86867    // Compute the set of variables occurring in `lhs'.
86868    std::vector<Variable> lhs_vars;
86869    for (Linear_Expression::const_iterator i = lhs.begin(), i_end = lhs.end();
86870          i != i_end; ++i) {
86871      lhs_vars.push_back(i.variable());
86872    }
86873    const dimension_type num_common_dims = std::min(lhs_space_dim, rhs_space_dim);
86874    if (!lhs.have_a_common_variable(rhs, Variable(0), Variable(num_common_dims))) {
86875      // `lhs' and `rhs' variables are disjoint.
86876
86877      // Constrain the left hand side expression so that it is related to
86878      // the right hand side expression as dictated by `relsym'.
86879      // TODO: if the following constraint is NOT a bounded difference,
86880      // it will be simply ignored. Should we compute approximations for it?
86881      switch (relsym) {
86882      case LESS_OR_EQUAL:
86883        refine_no_check(lhs <= rhs);
86884        break;
86885      case EQUAL:
86886        refine_no_check(lhs == rhs);
86887        break;
86888      case GREATER_OR_EQUAL:
86889        refine_no_check(lhs >= rhs);
86890        break;
86891      default:
86892        // We already dealt with the other cases.
86893        PPL_UNREACHABLE;
86894        break;
86895      }
86896
86897      // If the shrunk BD_Shape is empty, its preimage is empty too; ...
86898      if (is_empty()) {
86899        return;
86900      }
86901      // Existentially quantify all variables in the lhs.
86902      for (dimension_type i = lhs_vars.size(); i-- > 0; ) {
86903        forget_all_dbm_constraints(lhs_vars[i].id() + 1);
86904      }
86905    }
86906    else {
86907
86908      // Some variables in `lhs' also occur in `rhs'.
86909      // To ease the computation, we add an additional dimension.
86910      const Variable new_var(bds_space_dim);
86911      add_space_dimensions_and_embed(1);
86912      // Constrain the new dimension to be equal to `lhs'.
86913      // NOTE: calling affine_image() instead of refine_no_check()
86914      // ensures some approximation is tried even when the constraint
86915      // is not a bounded difference.
86916      affine_image(new_var, lhs);
86917      // Existentiallly quantify all variables in the lhs.
86918      // NOTE: enforce shortest-path closure for precision.
86919      shortest_path_closure_assign();
86920      PPL_ASSERT(!marked_empty());
86921      for (dimension_type i = lhs_vars.size(); i-- > 0; ) {
86922        forget_all_dbm_constraints(lhs_vars[i].id() + 1);
86923      }
86924      // Constrain the new dimension so that it is related to
86925      // the left hand side as dictated by `relsym'.
86926      // Note: if `rhs == a_rhs*v + b_rhs' where `a_rhs' is in {0, 1},
86927      // then one of the following constraints will be added,
86928      // since it is a bounded difference. Else the method
86929      // refine_no_check() will ignore it, because the
86930      // constraint is NOT a bounded difference.
86931      switch (relsym) {
86932      case LESS_OR_EQUAL:
86933        refine_no_check(new_var <= rhs);
86934        break;
86935      case EQUAL:
86936        refine_no_check(new_var == rhs);
86937        break;
86938      case GREATER_OR_EQUAL:
86939        refine_no_check(new_var >= rhs);
86940        break;
86941      default:
86942        // We already dealt with the other cases.
86943        PPL_UNREACHABLE;
86944        break;
86945      }
86946      // Remove the temporarily added dimension.
86947      remove_higher_space_dimensions(bds_space_dim);
86948    }
86949  }
86950
86951  PPL_ASSERT(OK());
86952}
86953
86954template <typename T>
86955Constraint_System
86956BD_Shape<T>::constraints() const {
86957  const dimension_type space_dim = space_dimension();
86958  Constraint_System cs;
86959  cs.set_space_dimension(space_dim);
86960
86961  if (space_dim == 0) {
86962    if (marked_empty()) {
86963      cs = Constraint_System::zero_dim_empty();
86964    }
86965    return cs;
86966  }
86967
86968  if (marked_empty()) {
86969    cs.insert(Constraint::zero_dim_false());
86970    return cs;
86971  }
86972
86973  if (marked_shortest_path_reduced()) {
86974    // Disregard redundant constraints.
86975    cs = minimized_constraints();
86976    return cs;
86977  }
86978
86979  PPL_DIRTY_TEMP_COEFFICIENT(a);
86980  PPL_DIRTY_TEMP_COEFFICIENT(b);
86981  // Go through all the unary constraints in `dbm'.
86982  const DB_Row<N>& dbm_0 = dbm[0];
86983  for (dimension_type j = 1; j <= space_dim; ++j) {
86984    const Variable x(j-1);
86985    const N& dbm_0j = dbm_0[j];
86986    const N& dbm_j0 = dbm[j][0];
86987    if (is_additive_inverse(dbm_j0, dbm_0j)) {
86988      // We have a unary equality constraint.
86989      numer_denom(dbm_0j, b, a);
86990      cs.insert(a*x == b);
86991    }
86992    else {
86993      // We have 0, 1 or 2 unary inequality constraints.
86994      if (!is_plus_infinity(dbm_0j)) {
86995        numer_denom(dbm_0j, b, a);
86996        cs.insert(a*x <= b);
86997      }
86998      if (!is_plus_infinity(dbm_j0)) {
86999        numer_denom(dbm_j0, b, a);
87000        cs.insert(-a*x <= b);
87001      }
87002    }
87003  }
87004
87005  // Go through all the binary constraints in `dbm'.
87006  for (dimension_type i = 1; i <= space_dim; ++i) {
87007    const Variable y(i-1);
87008    const DB_Row<N>& dbm_i = dbm[i];
87009    for (dimension_type j = i + 1; j <= space_dim; ++j) {
87010      const Variable x(j-1);
87011      const N& dbm_ij = dbm_i[j];
87012      const N& dbm_ji = dbm[j][i];
87013      if (is_additive_inverse(dbm_ji, dbm_ij)) {
87014        // We have a binary equality constraint.
87015        numer_denom(dbm_ij, b, a);
87016        cs.insert(a*x - a*y == b);
87017      }
87018      else {
87019        // We have 0, 1 or 2 binary inequality constraints.
87020        if (!is_plus_infinity(dbm_ij)) {
87021          numer_denom(dbm_ij, b, a);
87022          cs.insert(a*x - a*y <= b);
87023        }
87024        if (!is_plus_infinity(dbm_ji)) {
87025          numer_denom(dbm_ji, b, a);
87026          cs.insert(a*y - a*x <= b);
87027        }
87028      }
87029    }
87030  }
87031  return cs;
87032}
87033
87034template <typename T>
87035Constraint_System
87036BD_Shape<T>::minimized_constraints() const {
87037  shortest_path_reduction_assign();
87038  const dimension_type space_dim = space_dimension();
87039  Constraint_System cs;
87040  cs.set_space_dimension(space_dim);
87041
87042  if (space_dim == 0) {
87043    if (marked_empty()) {
87044      cs = Constraint_System::zero_dim_empty();
87045    }
87046    return cs;
87047  }
87048
87049  if (marked_empty()) {
87050    cs.insert(Constraint::zero_dim_false());
87051    return cs;
87052  }
87053
87054  PPL_DIRTY_TEMP_COEFFICIENT(numer);
87055  PPL_DIRTY_TEMP_COEFFICIENT(denom);
87056
87057  // Compute leader information.
87058  std::vector<dimension_type> leaders;
87059  compute_leaders(leaders);
87060  std::vector<dimension_type> leader_indices;
87061  compute_leader_indices(leaders, leader_indices);
87062  const dimension_type num_leaders = leader_indices.size();
87063
87064  // Go through the non-leaders to generate equality constraints.
87065  const DB_Row<N>& dbm_0 = dbm[0];
87066  for (dimension_type i = 1; i <= space_dim; ++i) {
87067    const dimension_type leader = leaders[i];
87068    if (i != leader) {
87069      // Generate the constraint relating `i' and its leader.
87070      if (leader == 0) {
87071        // A unary equality has to be generated.
87072        PPL_ASSERT(!is_plus_infinity(dbm_0[i]));
87073        numer_denom(dbm_0[i], numer, denom);
87074        cs.insert(denom*Variable(i-1) == numer);
87075      }
87076      else {
87077        // A binary equality has to be generated.
87078        PPL_ASSERT(!is_plus_infinity(dbm[i][leader]));
87079        numer_denom(dbm[i][leader], numer, denom);
87080        cs.insert(denom*Variable(leader-1) - denom*Variable(i-1) == numer);
87081      }
87082    }
87083  }
87084
87085  // Go through the leaders to generate inequality constraints.
87086  // First generate all the unary inequalities.
87087  const Bit_Row& red_0 = redundancy_dbm[0];
87088  for (dimension_type l_i = 1; l_i < num_leaders; ++l_i) {
87089    const dimension_type i = leader_indices[l_i];
87090    if (!red_0[i]) {
87091      numer_denom(dbm_0[i], numer, denom);
87092      cs.insert(denom*Variable(i-1) <= numer);
87093    }
87094    if (!redundancy_dbm[i][0]) {
87095      numer_denom(dbm[i][0], numer, denom);
87096      cs.insert(-denom*Variable(i-1) <= numer);
87097    }
87098  }
87099  // Then generate all the binary inequalities.
87100  for (dimension_type l_i = 1; l_i < num_leaders; ++l_i) {
87101    const dimension_type i = leader_indices[l_i];
87102    const DB_Row<N>& dbm_i = dbm[i];
87103    const Bit_Row& red_i = redundancy_dbm[i];
87104    for (dimension_type l_j = l_i + 1; l_j < num_leaders; ++l_j) {
87105      const dimension_type j = leader_indices[l_j];
87106      if (!red_i[j]) {
87107        numer_denom(dbm_i[j], numer, denom);
87108        cs.insert(denom*Variable(j-1) - denom*Variable(i-1) <= numer);
87109      }
87110      if (!redundancy_dbm[j][i]) {
87111        numer_denom(dbm[j][i], numer, denom);
87112        cs.insert(denom*Variable(i-1) - denom*Variable(j-1) <= numer);
87113      }
87114    }
87115  }
87116  return cs;
87117}
87118
87119template <typename T>
87120void
87121BD_Shape<T>::expand_space_dimension(Variable var, dimension_type m) {
87122  dimension_type old_dim = space_dimension();
87123  // `var' should be one of the dimensions of the vector space.
87124  if (var.space_dimension() > old_dim) {
87125    throw_dimension_incompatible("expand_space_dimension(v, m)", "v", var);
87126  }
87127
87128  // The space dimension of the resulting BDS should not
87129  // overflow the maximum allowed space dimension.
87130  if (m > max_space_dimension() - space_dimension()) {
87131    throw_invalid_argument("expand_dimension(v, m)",
87132                           "adding m new space dimensions exceeds "
87133                           "the maximum allowed space dimension");
87134  }
87135  // Nothing to do, if no dimensions must be added.
87136  if (m == 0) {
87137    return;
87138  }
87139  // Add the required new dimensions.
87140  add_space_dimensions_and_embed(m);
87141
87142  // For each constraints involving variable `var', we add a
87143  // similar constraint with the new variable substituted for
87144  // variable `var'.
87145  const dimension_type v_id = var.id() + 1;
87146  const DB_Row<N>& dbm_v = dbm[v_id];
87147  for (dimension_type i = old_dim + 1; i-- > 0; ) {
87148    DB_Row<N>& dbm_i = dbm[i];
87149    const N& dbm_i_v = dbm[i][v_id];
87150    const N& dbm_v_i = dbm_v[i];
87151    for (dimension_type j = old_dim+1; j < old_dim+m+1; ++j) {
87152      dbm_i[j] = dbm_i_v;
87153      dbm[j][i] = dbm_v_i;
87154    }
87155  }
87156  // In general, adding a constraint does not preserve the shortest-path
87157  // closure or reduction of the bounded difference shape.
87158  if (marked_shortest_path_closed()) {
87159    reset_shortest_path_closed();
87160  }
87161  PPL_ASSERT(OK());
87162}
87163
87164template <typename T>
87165void
87166BD_Shape<T>::fold_space_dimensions(const Variables_Set& vars,
87167                                   Variable dest) {
87168  const dimension_type space_dim = space_dimension();
87169  // `dest' should be one of the dimensions of the BDS.
87170  if (dest.space_dimension() > space_dim) {
87171    throw_dimension_incompatible("fold_space_dimensions(vs, v)",
87172                                 "v", dest);
87173  }
87174  // The folding of no dimensions is a no-op.
87175  if (vars.empty()) {
87176    return;
87177  }
87178  // All variables in `vars' should be dimensions of the BDS.
87179  if (vars.space_dimension() > space_dim) {
87180    throw_dimension_incompatible("fold_space_dimensions(vs, v)",
87181                                 vars.space_dimension());
87182  }
87183  // Moreover, `dest.id()' should not occur in `vars'.
87184  if (vars.find(dest.id()) != vars.end()) {
87185    throw_invalid_argument("fold_space_dimensions(vs, v)",
87186                           "v should not occur in vs");
87187  }
87188  shortest_path_closure_assign();
87189  if (!marked_empty()) {
87190    // Recompute the elements of the row and the column corresponding
87191    // to variable `dest' by taking the join of their value with the
87192    // value of the corresponding elements in the row and column of the
87193    // variable `vars'.
87194    const dimension_type v_id = dest.id() + 1;
87195    DB_Row<N>& dbm_v = dbm[v_id];
87196    for (Variables_Set::const_iterator i = vars.begin(),
87197           vs_end = vars.end(); i != vs_end; ++i) {
87198      const dimension_type to_be_folded_id = *i + 1;
87199      const DB_Row<N>& dbm_to_be_folded_id = dbm[to_be_folded_id];
87200      for (dimension_type j = space_dim + 1; j-- > 0; ) {
87201        max_assign(dbm[j][v_id], dbm[j][to_be_folded_id]);
87202        max_assign(dbm_v[j], dbm_to_be_folded_id[j]);
87203      }
87204    }
87205  }
87206  remove_space_dimensions(vars);
87207}
87208
87209template <typename T>
87210void
87211BD_Shape<T>::drop_some_non_integer_points(Complexity_Class) {
87212  if (std::numeric_limits<T>::is_integer) {
87213    return;
87214  }
87215  const dimension_type space_dim = space_dimension();
87216  shortest_path_closure_assign();
87217  if (space_dim == 0 || marked_empty()) {
87218    return;
87219  }
87220  for (dimension_type i = space_dim + 1; i-- > 0; ) {
87221    DB_Row<N>& dbm_i = dbm[i];
87222    for (dimension_type j = space_dim + 1; j-- > 0; ) {
87223      if (i != j) {
87224        drop_some_non_integer_points_helper(dbm_i[j]);
87225      }
87226    }
87227  }
87228  PPL_ASSERT(OK());
87229}
87230
87231template <typename T>
87232void
87233BD_Shape<T>::drop_some_non_integer_points(const Variables_Set& vars,
87234                                          Complexity_Class) {
87235  // Dimension-compatibility check.
87236  const dimension_type space_dim = space_dimension();
87237  const dimension_type min_space_dim = vars.space_dimension();
87238  if (space_dim < min_space_dim) {
87239    throw_dimension_incompatible("drop_some_non_integer_points(vs, cmpl)",
87240                                 min_space_dim);
87241  }
87242  if (std::numeric_limits<T>::is_integer || min_space_dim == 0) {
87243    return;
87244  }
87245  shortest_path_closure_assign();
87246  if (marked_empty()) {
87247    return;
87248  }
87249  const Variables_Set::const_iterator v_begin = vars.begin();
87250  const Variables_Set::const_iterator v_end = vars.end();
87251  PPL_ASSERT(v_begin != v_end);
87252  // Unary constraints on a variable occurring in `vars'.
87253  DB_Row<N>& dbm_0 = dbm[0];
87254  for (Variables_Set::const_iterator v_i = v_begin; v_i != v_end; ++v_i) {
87255    const dimension_type i = *v_i + 1;
87256    drop_some_non_integer_points_helper(dbm_0[i]);
87257    drop_some_non_integer_points_helper(dbm[i][0]);
87258  }
87259
87260  // Binary constraints where both variables occur in `vars'.
87261  for (Variables_Set::const_iterator v_i = v_begin; v_i != v_end; ++v_i) {
87262    const dimension_type i = *v_i + 1;
87263    DB_Row<N>& dbm_i = dbm[i];
87264    for (Variables_Set::const_iterator v_j = v_begin; v_j != v_end; ++v_j) {
87265      const dimension_type j = *v_j + 1;
87266      if (i != j) {
87267        drop_some_non_integer_points_helper(dbm_i[j]);
87268      }
87269    }
87270  }
87271  PPL_ASSERT(OK());
87272}
87273
87274/*! \relates Parma_Polyhedra_Library::BD_Shape */
87275template <typename T>
87276std::ostream&
87277IO_Operators::operator<<(std::ostream& s, const BD_Shape<T>& bds) {
87278  typedef typename BD_Shape<T>::coefficient_type N;
87279  if (bds.is_universe()) {
87280    s << "true";
87281  }
87282  else {
87283    // We control empty bounded difference shape.
87284    dimension_type n = bds.space_dimension();
87285    if (bds.marked_empty()) {
87286      s << "false";
87287    }
87288    else {
87289      PPL_DIRTY_TEMP(N, v);
87290      bool first = true;
87291      for (dimension_type i = 0; i <= n; ++i) {
87292        for (dimension_type j = i + 1; j <= n; ++j) {
87293          const N& c_i_j = bds.dbm[i][j];
87294          const N& c_j_i = bds.dbm[j][i];
87295          if (is_additive_inverse(c_j_i, c_i_j)) {
87296            // We will print an equality.
87297            if (first) {
87298              first = false;
87299            }
87300            else {
87301              s << ", ";
87302            }
87303            if (i == 0) {
87304              // We have got a equality constraint with one variable.
87305              s << Variable(j - 1);
87306              s << " = " << c_i_j;
87307            }
87308            else {
87309              // We have got a equality constraint with two variables.
87310              if (sgn(c_i_j) >= 0) {
87311                s << Variable(j - 1);
87312                s << " - ";
87313                s << Variable(i - 1);
87314                s << " = " << c_i_j;
87315              }
87316              else {
87317                s << Variable(i - 1);
87318                s << " - ";
87319                s << Variable(j - 1);
87320                s << " = " << c_j_i;
87321              }
87322            }
87323          }
87324          else {
87325            // We will print a non-strict inequality.
87326            if (!is_plus_infinity(c_j_i)) {
87327              if (first) {
87328                first = false;
87329              }
87330              else {
87331                s << ", ";
87332              }
87333              if (i == 0) {
87334                // We have got a constraint with only one variable.
87335                s << Variable(j - 1);
87336                neg_assign_r(v, c_j_i, ROUND_DOWN);
87337                s << " >= " << v;
87338              }
87339              else {
87340                // We have got a constraint with two variables.
87341                if (sgn(c_j_i) >= 0) {
87342                  s << Variable(i - 1);
87343                  s << " - ";
87344                  s << Variable(j - 1);
87345                  s << " <= " << c_j_i;
87346                }
87347                else {
87348                  s << Variable(j - 1);
87349                  s << " - ";
87350                  s << Variable(i - 1);
87351                  neg_assign_r(v, c_j_i, ROUND_DOWN);
87352                  s << " >= " << v;
87353                }
87354              }
87355            }
87356            if (!is_plus_infinity(c_i_j)) {
87357              if (first) {
87358                first = false;
87359              }
87360              else {
87361                s << ", ";
87362              }
87363              if (i == 0) {
87364                // We have got a constraint with only one variable.
87365                s << Variable(j - 1);
87366                s << " <= " << c_i_j;
87367              }
87368              else {
87369                // We have got a constraint with two variables.
87370                if (sgn(c_i_j) >= 0) {
87371                  s << Variable(j - 1);
87372                  s << " - ";
87373                  s << Variable(i - 1);
87374                  s << " <= " << c_i_j;
87375                }
87376                else {
87377                  s << Variable(i - 1);
87378                  s << " - ";
87379                  s << Variable(j - 1);
87380                  neg_assign_r(v, c_i_j, ROUND_DOWN);
87381                  s << " >= " << v;
87382                }
87383              }
87384            }
87385          }
87386        }
87387      }
87388    }
87389  }
87390  return s;
87391}
87392
87393template <typename T>
87394void
87395BD_Shape<T>::ascii_dump(std::ostream& s) const {
87396  status.ascii_dump(s);
87397  s << "\n";
87398  dbm.ascii_dump(s);
87399  s << "\n";
87400  redundancy_dbm.ascii_dump(s);
87401}
87402
87403PPL_OUTPUT_TEMPLATE_DEFINITIONS(T, BD_Shape<T>)
87404
87405template <typename T>
87406bool
87407BD_Shape<T>::ascii_load(std::istream& s) {
87408  if (!status.ascii_load(s)) {
87409    return false;
87410  }
87411  if (!dbm.ascii_load(s)) {
87412    return false;
87413  }
87414  if (!redundancy_dbm.ascii_load(s)) {
87415    return false;
87416  }
87417  return true;
87418}
87419
87420template <typename T>
87421memory_size_type
87422BD_Shape<T>::external_memory_in_bytes() const {
87423  return dbm.external_memory_in_bytes()
87424    + redundancy_dbm.external_memory_in_bytes();
87425}
87426
87427template <typename T>
87428bool
87429BD_Shape<T>::OK() const {
87430  // Check whether the difference-bound matrix is well-formed.
87431  if (!dbm.OK()) {
87432    return false;
87433  }
87434  // Check whether the status information is legal.
87435  if (!status.OK()) {
87436    return false;
87437  }
87438  // An empty BDS is OK.
87439  if (marked_empty()) {
87440    return true;
87441  }
87442  // MINUS_INFINITY cannot occur at all.
87443  for (dimension_type i = dbm.num_rows(); i-- > 0; ) {
87444    for (dimension_type j = dbm.num_rows(); j-- > 0; ) {
87445      if (is_minus_infinity(dbm[i][j])) {
87446#ifndef NDEBUG
87447        using namespace Parma_Polyhedra_Library::IO_Operators;
87448        std::cerr << "BD_Shape::dbm[" << i << "][" << j << "] = "
87449                  << dbm[i][j] << "!"
87450                  << std::endl;
87451#endif
87452        return false;
87453      }
87454    }
87455  }
87456  // On the main diagonal only PLUS_INFINITY can occur.
87457  for (dimension_type i = dbm.num_rows(); i-- > 0; ) {
87458    if (!is_plus_infinity(dbm[i][i])) {
87459#ifndef NDEBUG
87460      using namespace Parma_Polyhedra_Library::IO_Operators;
87461      std::cerr << "BD_Shape::dbm[" << i << "][" << i << "] = "
87462                << dbm[i][i] << "!  (+inf was expected.)"
87463                << std::endl;
87464#endif
87465      return false;
87466    }
87467  }
87468  // Check whether the shortest-path closure information is legal.
87469  if (marked_shortest_path_closed()) {
87470    BD_Shape x = *this;
87471    x.reset_shortest_path_closed();
87472    x.shortest_path_closure_assign();
87473    if (x.dbm != dbm) {
87474#ifndef NDEBUG
87475      std::cerr << "BD_Shape is marked as closed but it is not!"
87476                << std::endl;
87477#endif
87478      return false;
87479    }
87480  }
87481
87482  // The following tests might result in false alarms when using floating
87483  // point coefficients: they are only meaningful if the coefficient type
87484  // base is exact (since otherwise shortest-path closure is approximated).
87485  if (std::numeric_limits<coefficient_type_base>::is_exact) {
87486
87487    // Check whether the shortest-path reduction information is legal.
87488    if (marked_shortest_path_reduced()) {
87489      // A non-redundant constraint cannot be equal to PLUS_INFINITY.
87490      for (dimension_type i = dbm.num_rows(); i-- > 0; ) {
87491        for (dimension_type j = dbm.num_rows(); j-- > 0; ) {
87492          if (!redundancy_dbm[i][j] && is_plus_infinity(dbm[i][j])) {
87493#ifndef NDEBUG
87494            using namespace Parma_Polyhedra_Library::IO_Operators;
87495            std::cerr << "BD_Shape::dbm[" << i << "][" << j << "] = "
87496                      << dbm[i][j] << " is marked as non-redundant!"
87497                      << std::endl;
87498#endif
87499            return false;
87500          }
87501        }
87502      }
87503      BD_Shape x = *this;
87504      x.reset_shortest_path_reduced();
87505      x.shortest_path_reduction_assign();
87506      if (x.redundancy_dbm != redundancy_dbm) {
87507#ifndef NDEBUG
87508        std::cerr << "BD_Shape is marked as reduced but it is not!"
87509                  << std::endl;
87510#endif
87511        return false;
87512      }
87513    }
87514  }
87515
87516  // All checks passed.
87517  return true;
87518}
87519
87520template <typename T>
87521void
87522BD_Shape<T>::throw_dimension_incompatible(const char* method,
87523                                          const BD_Shape& y) const {
87524  std::ostringstream s;
87525  s << "PPL::BD_Shape::" << method << ":" << std::endl
87526    << "this->space_dimension() == " << space_dimension()
87527    << ", y->space_dimension() == " << y.space_dimension() << ".";
87528  throw std::invalid_argument(s.str());
87529}
87530
87531template <typename T>
87532void
87533BD_Shape<T>::throw_dimension_incompatible(const char* method,
87534                                          dimension_type required_dim) const {
87535  std::ostringstream s;
87536  s << "PPL::BD_Shape::" << method << ":" << std::endl
87537    << "this->space_dimension() == " << space_dimension()
87538    << ", required dimension == " << required_dim << ".";
87539  throw std::invalid_argument(s.str());
87540}
87541
87542template <typename T>
87543void
87544BD_Shape<T>::throw_dimension_incompatible(const char* method,
87545                                          const Constraint& c) const {
87546  std::ostringstream s;
87547  s << "PPL::BD_Shape::" << method << ":" << std::endl
87548    << "this->space_dimension() == " << space_dimension()
87549    << ", c->space_dimension == " << c.space_dimension() << ".";
87550  throw std::invalid_argument(s.str());
87551}
87552
87553template <typename T>
87554void
87555BD_Shape<T>::throw_dimension_incompatible(const char* method,
87556                                          const Congruence& cg) const {
87557  std::ostringstream s;
87558  s << "PPL::BD_Shape::" << method << ":" << std::endl
87559    << "this->space_dimension() == " << space_dimension()
87560    << ", cg->space_dimension == " << cg.space_dimension() << ".";
87561  throw std::invalid_argument(s.str());
87562}
87563
87564template <typename T>
87565void
87566BD_Shape<T>::throw_dimension_incompatible(const char* method,
87567                                          const Generator& g) const {
87568  std::ostringstream s;
87569  s << "PPL::BD_Shape::" << method << ":" << std::endl
87570    << "this->space_dimension() == " << space_dimension()
87571    << ", g->space_dimension == " << g.space_dimension() << ".";
87572  throw std::invalid_argument(s.str());
87573}
87574
87575template <typename T>
87576void
87577BD_Shape<T>::throw_expression_too_complex(const char* method,
87578                                          const Linear_Expression& le) {
87579  using namespace IO_Operators;
87580  std::ostringstream s;
87581  s << "PPL::BD_Shape::" << method << ":" << std::endl
87582    << le << " is too complex.";
87583  throw std::invalid_argument(s.str());
87584}
87585
87586
87587template <typename T>
87588void
87589BD_Shape<T>::throw_dimension_incompatible(const char* method,
87590                                          const char* le_name,
87591                                          const Linear_Expression& le) const {
87592  std::ostringstream s;
87593  s << "PPL::BD_Shape::" << method << ":" << std::endl
87594    << "this->space_dimension() == " << space_dimension()
87595    << ", " << le_name << "->space_dimension() == "
87596    << le.space_dimension() << ".";
87597  throw std::invalid_argument(s.str());
87598}
87599
87600template <typename T>
87601template<typename Interval_Info>
87602void
87603BD_Shape<T>::throw_dimension_incompatible(const char* method,
87604                                          const char* lf_name,
87605                                          const Linear_Form< Interval<T,
87606                                          Interval_Info> >& lf) const {
87607  std::ostringstream s;
87608  s << "PPL::BD_Shape::" << method << ":" << std::endl
87609    << "this->space_dimension() == " << space_dimension()
87610    << ", " << lf_name << "->space_dimension() == "
87611    << lf.space_dimension() << ".";
87612  throw std::invalid_argument(s.str());
87613}
87614
87615template <typename T>
87616void
87617BD_Shape<T>::throw_invalid_argument(const char* method, const char* reason) {
87618  std::ostringstream s;
87619  s << "PPL::BD_Shape::" << method << ":" << std::endl
87620    << reason << ".";
87621  throw std::invalid_argument(s.str());
87622}
87623
87624} // namespace Parma_Polyhedra_Library
87625
87626/* Automatically generated from PPL source file ../src/BD_Shape_defs.hh line 2373. */
87627
87628/* Automatically generated from PPL source file ../src/Rational_Interval.hh line 1. */
87629/* Rational_Interval class declaration and implementation.
87630*/
87631
87632
87633/* Automatically generated from PPL source file ../src/Rational_Interval.hh line 28. */
87634#include <gmpxx.h>
87635
87636namespace Parma_Polyhedra_Library {
87637
87638struct Rational_Interval_Info_Policy {
87639  const_bool_nodef(store_special, true);
87640  const_bool_nodef(store_open, true);
87641  const_bool_nodef(cache_empty, true);
87642  const_bool_nodef(cache_singleton, true);
87643  const_bool_nodef(cache_normalized, false);
87644  const_int_nodef(next_bit, 0);
87645  const_bool_nodef(may_be_empty, true);
87646  const_bool_nodef(may_contain_infinity, false);
87647  const_bool_nodef(check_inexact, false);
87648};
87649
87650typedef Interval_Info_Bitset<unsigned int,
87651                             Rational_Interval_Info_Policy> Rational_Interval_Info;
87652
87653#ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
87654//! An interval with rational, possibly open boundaries.
87655#endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
87656typedef Interval<mpq_class, Rational_Interval_Info> Rational_Interval;
87657
87658} // namespace Parma_Polyhedra_Library
87659
87660/* Automatically generated from PPL source file ../src/Box_templates.hh line 42. */
87661#include <vector>
87662#include <map>
87663#include <iostream>
87664
87665namespace Parma_Polyhedra_Library {
87666
87667template <typename ITV>
87668inline
87669Box<ITV>::Box(dimension_type num_dimensions, Degenerate_Element kind)
87670  : seq(check_space_dimension_overflow(num_dimensions,
87671                                       max_space_dimension(),
87672                                       "PPL::Box::",
87673                                       "Box(n, k)",
87674                                       "n exceeds the maximum "
87675                                       "allowed space dimension")),
87676    status() {
87677  // In a box that is marked empty the intervals are completely
87678  // meaningless: we exploit this by avoiding their initialization.
87679  if (kind == UNIVERSE) {
87680    for (dimension_type i = num_dimensions; i-- > 0; ) {
87681      seq[i].assign(UNIVERSE);
87682    }
87683    set_empty_up_to_date();
87684  }
87685  else {
87686    set_empty();
87687  }
87688  PPL_ASSERT(OK());
87689}
87690
87691template <typename ITV>
87692inline
87693Box<ITV>::Box(const Constraint_System& cs)
87694  : seq(check_space_dimension_overflow(cs.space_dimension(),
87695                                       max_space_dimension(),
87696                                       "PPL::Box::",
87697                                       "Box(cs)",
87698                                       "cs exceeds the maximum "
87699                                       "allowed space dimension")),
87700    status() {
87701  // FIXME: check whether we can avoid the double initialization.
87702  for (dimension_type i = cs.space_dimension(); i-- > 0; ) {
87703    seq[i].assign(UNIVERSE);
87704  }
87705  add_constraints_no_check(cs);
87706}
87707
87708template <typename ITV>
87709inline
87710Box<ITV>::Box(const Congruence_System& cgs)
87711  : seq(check_space_dimension_overflow(cgs.space_dimension(),
87712                                       max_space_dimension(),
87713                                       "PPL::Box::",
87714                                       "Box(cgs)",
87715                                       "cgs exceeds the maximum "
87716                                       "allowed space dimension")),
87717    status() {
87718  // FIXME: check whether we can avoid the double initialization.
87719  for (dimension_type i = cgs.space_dimension(); i-- > 0; ) {
87720    seq[i].assign(UNIVERSE);
87721  }
87722  add_congruences_no_check(cgs);
87723}
87724
87725template <typename ITV>
87726template <typename Other_ITV>
87727inline
87728Box<ITV>::Box(const Box<Other_ITV>& y, Complexity_Class)
87729  : seq(y.space_dimension()),
87730    // FIXME: why the following does not work?
87731    // status(y.status) {
87732    status() {
87733  // FIXME: remove when the above is fixed.
87734  if (y.marked_empty()) {
87735    set_empty();
87736  }
87737
87738  if (!y.marked_empty()) {
87739    for (dimension_type k = y.space_dimension(); k-- > 0; ) {
87740      seq[k].assign(y.seq[k]);
87741    }
87742  }
87743  PPL_ASSERT(OK());
87744}
87745
87746template <typename ITV>
87747Box<ITV>::Box(const Generator_System& gs)
87748  : seq(check_space_dimension_overflow(gs.space_dimension(),
87749                                       max_space_dimension(),
87750                                       "PPL::Box::",
87751                                       "Box(gs)",
87752                                       "gs exceeds the maximum "
87753                                       "allowed space dimension")),
87754    status() {
87755  const Generator_System::const_iterator gs_begin = gs.begin();
87756  const Generator_System::const_iterator gs_end = gs.end();
87757  if (gs_begin == gs_end) {
87758    // An empty generator system defines the empty box.
87759    set_empty();
87760    return;
87761  }
87762
87763  // The empty flag will be meaningful, whatever happens from now on.
87764  set_empty_up_to_date();
87765
87766  const dimension_type space_dim = space_dimension();
87767  PPL_DIRTY_TEMP(mpq_class, q);
87768  bool point_seen = false;
87769  // Going through all the points.
87770  for (Generator_System::const_iterator
87771         gs_i = gs_begin; gs_i != gs_end; ++gs_i) {
87772    const Generator& g = *gs_i;
87773    if (g.is_point()) {
87774      const Coefficient& d = g.divisor();
87775      if (point_seen) {
87776        // This is not the first point: `seq' already contains valid values.
87777        // TODO: If the variables in the expression that have coefficient 0
87778        // have no effect on seq[i], this loop can be optimized using
87779        // Generator::expr_type::const_iterator.
87780        for (dimension_type i = space_dim; i-- > 0; ) {
87781          assign_r(q.get_num(), g.coefficient(Variable(i)), ROUND_NOT_NEEDED);
87782          assign_r(q.get_den(), d, ROUND_NOT_NEEDED);
87783          q.canonicalize();
87784          PPL_DIRTY_TEMP(ITV, iq);
87785          iq.build(i_constraint(EQUAL, q));
87786          seq[i].join_assign(iq);
87787        }
87788      }
87789      else {
87790        // This is the first point seen: initialize `seq'.
87791        point_seen = true;
87792        // TODO: If the variables in the expression that have coefficient 0
87793        // have no effect on seq[i], this loop can be optimized using
87794        // Generator::expr_type::const_iterator.
87795        for (dimension_type i = space_dim; i-- > 0; ) {
87796          assign_r(q.get_num(), g.coefficient(Variable(i)), ROUND_NOT_NEEDED);
87797          assign_r(q.get_den(), d, ROUND_NOT_NEEDED);
87798          q.canonicalize();
87799          seq[i].build(i_constraint(EQUAL, q));
87800        }
87801      }
87802    }
87803  }
87804
87805  if (!point_seen) {
87806    // The generator system is not empty, but contains no points.
87807    throw std::invalid_argument("PPL::Box<ITV>::Box(gs):\n"
87808                                "the non-empty generator system gs "
87809                                "contains no points.");
87810  }
87811
87812  // Going through all the lines, rays and closure points.
87813  for (Generator_System::const_iterator gs_i = gs_begin;
87814       gs_i != gs_end; ++gs_i) {
87815    const Generator& g = *gs_i;
87816    switch (g.type()) {
87817    case Generator::LINE:
87818      for (Generator::expr_type::const_iterator i = g.expression().begin(),
87819              i_end = g.expression().end();
87820              i != i_end; ++i) {
87821          seq[i.variable().id()].assign(UNIVERSE);
87822      }
87823      break;
87824    case Generator::RAY:
87825      for (Generator::expr_type::const_iterator i = g.expression().begin(),
87826              i_end = g.expression().end();
87827              i != i_end; ++i) {
87828        switch (sgn(*i)) {
87829        case 1:
87830          seq[i.variable().id()].upper_extend();
87831          break;
87832        case -1:
87833          seq[i.variable().id()].lower_extend();
87834          break;
87835        default:
87836          PPL_UNREACHABLE;
87837          break;
87838        }
87839      }
87840      break;
87841    case Generator::CLOSURE_POINT:
87842      {
87843        const Coefficient& d = g.divisor();
87844        // TODO: If the variables in the expression that have coefficient 0
87845        // have no effect on seq[i], this loop can be optimized using
87846        // Generator::expr_type::const_iterator.
87847        for (dimension_type i = space_dim; i-- > 0; ) {
87848          assign_r(q.get_num(), g.coefficient(Variable(i)), ROUND_NOT_NEEDED);
87849          assign_r(q.get_den(), d, ROUND_NOT_NEEDED);
87850          q.canonicalize();
87851          ITV& seq_i = seq[i];
87852          seq_i.lower_extend(i_constraint(GREATER_THAN, q));
87853          seq_i.upper_extend(i_constraint(LESS_THAN, q));
87854        }
87855      }
87856      break;
87857    default:
87858      // Points already dealt with.
87859      break;
87860    }
87861  }
87862  PPL_ASSERT(OK());
87863}
87864
87865template <typename ITV>
87866template <typename T>
87867Box<ITV>::Box(const BD_Shape<T>& bds, Complexity_Class)
87868  : seq(check_space_dimension_overflow(bds.space_dimension(),
87869                                       max_space_dimension(),
87870                                       "PPL::Box::",
87871                                       "Box(bds)",
87872                                       "bds exceeds the maximum "
87873                                       "allowed space dimension")),
87874    status() {
87875  // Expose all the interval constraints.
87876  bds.shortest_path_closure_assign();
87877  if (bds.marked_empty()) {
87878    set_empty();
87879    PPL_ASSERT(OK());
87880    return;
87881  }
87882
87883  // The empty flag will be meaningful, whatever happens from now on.
87884  set_empty_up_to_date();
87885
87886  const dimension_type space_dim = space_dimension();
87887  if (space_dim == 0) {
87888    PPL_ASSERT(OK());
87889    return;
87890  }
87891
87892  typedef typename BD_Shape<T>::coefficient_type Coeff;
87893  PPL_DIRTY_TEMP(Coeff, tmp);
87894  const DB_Row<Coeff>& dbm_0 = bds.dbm[0];
87895  for (dimension_type i = space_dim; i-- > 0; ) {
87896    I_Constraint<Coeff> lower;
87897    I_Constraint<Coeff> upper;
87898    ITV& seq_i = seq[i];
87899
87900    // Set the upper bound.
87901    const Coeff& u = dbm_0[i+1];
87902    if (!is_plus_infinity(u)) {
87903      upper.set(LESS_OR_EQUAL, u, true);
87904    }
87905
87906    // Set the lower bound.
87907    const Coeff& negated_l = bds.dbm[i+1][0];
87908    if (!is_plus_infinity(negated_l)) {
87909      neg_assign_r(tmp, negated_l, ROUND_DOWN);
87910      lower.set(GREATER_OR_EQUAL, tmp);
87911    }
87912
87913    seq_i.build(lower, upper);
87914  }
87915  PPL_ASSERT(OK());
87916}
87917
87918template <typename ITV>
87919template <typename T>
87920Box<ITV>::Box(const Octagonal_Shape<T>& oct, Complexity_Class)
87921  : seq(check_space_dimension_overflow(oct.space_dimension(),
87922                                       max_space_dimension(),
87923                                       "PPL::Box::",
87924                                       "Box(oct)",
87925                                       "oct exceeds the maximum "
87926                                       "allowed space dimension")),
87927    status() {
87928  // Expose all the interval constraints.
87929  oct.strong_closure_assign();
87930  if (oct.marked_empty()) {
87931    set_empty();
87932    return;
87933  }
87934
87935  // The empty flag will be meaningful, whatever happens from now on.
87936  set_empty_up_to_date();
87937
87938  const dimension_type space_dim = space_dimension();
87939  if (space_dim == 0) {
87940    return;
87941  }
87942
87943  PPL_DIRTY_TEMP(mpq_class, lower_bound);
87944  PPL_DIRTY_TEMP(mpq_class, upper_bound);
87945  for (dimension_type i = space_dim; i-- > 0; ) {
87946    typedef typename Octagonal_Shape<T>::coefficient_type Coeff;
87947    I_Constraint<mpq_class> lower;
87948    I_Constraint<mpq_class> upper;
87949    ITV& seq_i = seq[i];
87950    const dimension_type ii = 2*i;
87951    const dimension_type cii = ii + 1;
87952
87953    // Set the upper bound.
87954    const Coeff& twice_ub = oct.matrix[cii][ii];
87955    if (!is_plus_infinity(twice_ub)) {
87956      assign_r(upper_bound, twice_ub, ROUND_NOT_NEEDED);
87957      div_2exp_assign_r(upper_bound, upper_bound, 1, ROUND_NOT_NEEDED);
87958      upper.set(LESS_OR_EQUAL, upper_bound);
87959    }
87960
87961    // Set the lower bound.
87962    const Coeff& twice_lb = oct.matrix[ii][cii];
87963    if (!is_plus_infinity(twice_lb)) {
87964      assign_r(lower_bound, twice_lb, ROUND_NOT_NEEDED);
87965      neg_assign_r(lower_bound, lower_bound, ROUND_NOT_NEEDED);
87966      div_2exp_assign_r(lower_bound, lower_bound, 1, ROUND_NOT_NEEDED);
87967      lower.set(GREATER_OR_EQUAL, lower_bound);
87968    }
87969    seq_i.build(lower, upper);
87970  }
87971}
87972
87973template <typename ITV>
87974Box<ITV>::Box(const Polyhedron& ph, Complexity_Class complexity)
87975  : seq(check_space_dimension_overflow(ph.space_dimension(),
87976                                       max_space_dimension(),
87977                                       "PPL::Box::",
87978                                       "Box(ph)",
87979                                       "ph exceeds the maximum "
87980                                       "allowed space dimension")),
87981    status() {
87982  // The empty flag will be meaningful, whatever happens from now on.
87983  set_empty_up_to_date();
87984
87985  // We do not need to bother about `complexity' if:
87986  // a) the polyhedron is already marked empty; or ...
87987  if (ph.marked_empty()) {
87988    set_empty();
87989    return;
87990  }
87991
87992  // b) the polyhedron is zero-dimensional; or ...
87993  const dimension_type space_dim = ph.space_dimension();
87994  if (space_dim == 0) {
87995    return;
87996  }
87997
87998  // c) the polyhedron is already described by a generator system.
87999  if (ph.generators_are_up_to_date() && !ph.has_pending_constraints()) {
88000    Box tmp(ph.generators());
88001    m_swap(tmp);
88002    return;
88003  }
88004
88005  // Here generators are not up-to-date or there are pending constraints.
88006  PPL_ASSERT(ph.constraints_are_up_to_date());
88007
88008  if (complexity == POLYNOMIAL_COMPLEXITY) {
88009    // FIXME: is there a way to avoid this initialization?
88010    for (dimension_type i = space_dim; i-- > 0; ) {
88011      seq[i].assign(UNIVERSE);
88012    }
88013    // Get a simplified version of the constraints.
88014    const Constraint_System cs = ph.simplified_constraints();
88015    // Propagate easy-to-find bounds from the constraints,
88016    // allowing for a limited number of iterations.
88017    // FIXME: 20 is just a wild guess.
88018    const dimension_type max_iterations = 20;
88019    propagate_constraints_no_check(cs, max_iterations);
88020  }
88021  else if (complexity == SIMPLEX_COMPLEXITY) {
88022    MIP_Problem lp(space_dim);
88023    const Constraint_System& ph_cs = ph.constraints();
88024    if (!ph_cs.has_strict_inequalities()) {
88025      lp.add_constraints(ph_cs);
88026    }
88027    else {
88028      // Adding to `lp' a topologically closed version of `ph_cs'.
88029      for (Constraint_System::const_iterator i = ph_cs.begin(),
88030             ph_cs_end = ph_cs.end(); i != ph_cs_end; ++i) {
88031        const Constraint& c = *i;
88032        if (c.is_strict_inequality()) {
88033          const Linear_Expression expr(c.expression());
88034          lp.add_constraint(expr >= 0);
88035        }
88036        else {
88037          lp.add_constraint(c);
88038        }
88039      }
88040    }
88041    // Check for unsatisfiability.
88042    if (!lp.is_satisfiable()) {
88043      set_empty();
88044      return;
88045    }
88046    // Get all the bounds for the space dimensions.
88047    Generator g(point());
88048    PPL_DIRTY_TEMP(mpq_class, lower_bound);
88049    PPL_DIRTY_TEMP(mpq_class, upper_bound);
88050    PPL_DIRTY_TEMP_COEFFICIENT(bound_numer);
88051    PPL_DIRTY_TEMP_COEFFICIENT(bound_denom);
88052    for (dimension_type i = space_dim; i-- > 0; ) {
88053      I_Constraint<mpq_class> lower;
88054      I_Constraint<mpq_class> upper;
88055      ITV& seq_i = seq[i];
88056      lp.set_objective_function(Variable(i));
88057      // Evaluate upper bound.
88058      lp.set_optimization_mode(MAXIMIZATION);
88059      if (lp.solve() == OPTIMIZED_MIP_PROBLEM) {
88060        g = lp.optimizing_point();
88061        lp.evaluate_objective_function(g, bound_numer, bound_denom);
88062        assign_r(upper_bound.get_num(), bound_numer, ROUND_NOT_NEEDED);
88063        assign_r(upper_bound.get_den(), bound_denom, ROUND_NOT_NEEDED);
88064        PPL_ASSERT(is_canonical(upper_bound));
88065        upper.set(LESS_OR_EQUAL, upper_bound);
88066      }
88067      // Evaluate optimal lower bound.
88068      lp.set_optimization_mode(MINIMIZATION);
88069      if (lp.solve() == OPTIMIZED_MIP_PROBLEM) {
88070        g = lp.optimizing_point();
88071        lp.evaluate_objective_function(g, bound_numer, bound_denom);
88072        assign_r(lower_bound.get_num(), bound_numer, ROUND_NOT_NEEDED);
88073        assign_r(lower_bound.get_den(), bound_denom, ROUND_NOT_NEEDED);
88074        PPL_ASSERT(is_canonical(lower_bound));
88075        lower.set(GREATER_OR_EQUAL, lower_bound);
88076      }
88077      seq_i.build(lower, upper);
88078    }
88079  }
88080  else {
88081    PPL_ASSERT(complexity == ANY_COMPLEXITY);
88082    if (ph.is_empty()) {
88083      set_empty();
88084    }
88085    else {
88086      Box tmp(ph.generators());
88087      m_swap(tmp);
88088    }
88089  }
88090}
88091
88092template <typename ITV>
88093Box<ITV>::Box(const Grid& gr, Complexity_Class)
88094  : seq(check_space_dimension_overflow(gr.space_dimension(),
88095                                       max_space_dimension(),
88096                                       "PPL::Box::",
88097                                       "Box(gr)",
88098                                       "gr exceeds the maximum "
88099                                       "allowed space dimension")),
88100    status() {
88101
88102  if (gr.marked_empty()) {
88103    set_empty();
88104    return;
88105  }
88106
88107  // The empty flag will be meaningful, whatever happens from now on.
88108  set_empty_up_to_date();
88109
88110  const dimension_type space_dim = gr.space_dimension();
88111
88112  if (space_dim == 0) {
88113    return;
88114  }
88115
88116  if (!gr.generators_are_up_to_date() && !gr.update_generators()) {
88117    // Updating found the grid empty.
88118    set_empty();
88119    return;
88120  }
88121
88122  PPL_ASSERT(!gr.gen_sys.empty());
88123
88124  // For each dimension that is bounded by the grid, set both bounds
88125  // of the interval to the value of the associated coefficient in a
88126  // generator point.
88127  PPL_DIRTY_TEMP(mpq_class, bound);
88128  PPL_DIRTY_TEMP_COEFFICIENT(bound_numer);
88129  PPL_DIRTY_TEMP_COEFFICIENT(bound_denom);
88130  for (dimension_type i = space_dim; i-- > 0; ) {
88131    ITV& seq_i = seq[i];
88132    Variable var(i);
88133    bool max;
88134    if (gr.maximize(var, bound_numer, bound_denom, max)) {
88135      assign_r(bound.get_num(), bound_numer, ROUND_NOT_NEEDED);
88136      assign_r(bound.get_den(), bound_denom, ROUND_NOT_NEEDED);
88137      bound.canonicalize();
88138      seq_i.build(i_constraint(EQUAL, bound));
88139    }
88140    else {
88141      seq_i.assign(UNIVERSE);
88142    }
88143  }
88144}
88145
88146template <typename ITV>
88147template <typename D1, typename D2, typename R>
88148Box<ITV>::Box(const Partially_Reduced_Product<D1, D2, R>& dp,
88149              Complexity_Class complexity)
88150  : seq(), status() {
88151  check_space_dimension_overflow(dp.space_dimension(),
88152                                 max_space_dimension(),
88153                                 "PPL::Box::",
88154                                 "Box(dp)",
88155                                 "dp exceeds the maximum "
88156                                 "allowed space dimension");
88157  Box tmp1(dp.domain1(), complexity);
88158  Box tmp2(dp.domain2(), complexity);
88159  tmp1.intersection_assign(tmp2);
88160  m_swap(tmp1);
88161}
88162
88163template <typename ITV>
88164inline void
88165Box<ITV>::add_space_dimensions_and_embed(const dimension_type m) {
88166  // Adding no dimensions is a no-op.
88167  if (m == 0) {
88168    return;
88169  }
88170  check_space_dimension_overflow(m, max_space_dimension() - space_dimension(),
88171                                 "PPL::Box::",
88172                                 "add_space_dimensions_and_embed(m)",
88173                                 "adding m new space dimensions exceeds "
88174                                 "the maximum allowed space dimension");
88175  // To embed an n-dimension space box in a (n+m)-dimension space,
88176  // we just add `m' new universe elements to the sequence.
88177  seq.insert(seq.end(), m, ITV(UNIVERSE));
88178  PPL_ASSERT(OK());
88179}
88180
88181template <typename ITV>
88182inline void
88183Box<ITV>::add_space_dimensions_and_project(const dimension_type m) {
88184  // Adding no dimensions is a no-op.
88185  if (m == 0) {
88186    return;
88187  }
88188  check_space_dimension_overflow(m, max_space_dimension() - space_dimension(),
88189                                 "PPL::Box::",
88190                                 "add_space_dimensions_and_project(m)",
88191                                 "adding m new space dimensions exceeds "
88192                                 "the maximum allowed space dimension");
88193  // Add `m' new zero elements to the sequence.
88194  seq.insert(seq.end(), m, ITV(0));
88195  PPL_ASSERT(OK());
88196}
88197
88198template <typename ITV>
88199bool
88200operator==(const Box<ITV>& x, const Box<ITV>& y) {
88201  const dimension_type x_space_dim = x.space_dimension();
88202  if (x_space_dim != y.space_dimension()) {
88203    return false;
88204  }
88205
88206  if (x.is_empty()) {
88207    return y.is_empty();
88208  }
88209
88210  if (y.is_empty()) {
88211    return x.is_empty();
88212  }
88213
88214  for (dimension_type k = x_space_dim; k-- > 0; ) {
88215    if (x.seq[k] != y.seq[k]) {
88216      return false;
88217    }
88218  }
88219  return true;
88220}
88221
88222template <typename ITV>
88223bool
88224Box<ITV>::bounds(const Linear_Expression& expr, const bool from_above) const {
88225  // `expr' should be dimension-compatible with `*this'.
88226  const dimension_type expr_space_dim = expr.space_dimension();
88227  const dimension_type space_dim = space_dimension();
88228  if (space_dim < expr_space_dim) {
88229    throw_dimension_incompatible((from_above
88230                                  ? "bounds_from_above(e)"
88231                                  : "bounds_from_below(e)"), "e", expr);
88232  }
88233  // A zero-dimensional or empty Box bounds everything.
88234  if (space_dim == 0 || is_empty()) {
88235    return true;
88236  }
88237  const int from_above_sign = from_above ? 1 : -1;
88238  // TODO: This loop can be optimized more, if needed, exploiting the
88239  // (possible) sparseness of expr.
88240  for (Linear_Expression::const_iterator i = expr.begin(),
88241          i_end = expr.end(); i != i_end; ++i) {
88242    const Variable v = i.variable();
88243    switch (sgn(*i) * from_above_sign) {
88244    case 1:
88245      if (seq[v.id()].upper_is_boundary_infinity()) {
88246        return false;
88247      }
88248      break;
88249    case 0:
88250      PPL_UNREACHABLE;
88251      break;
88252    case -1:
88253      if (seq[v.id()].lower_is_boundary_infinity()) {
88254        return false;
88255      }
88256      break;
88257    }
88258  }
88259  return true;
88260}
88261
88262template <typename ITV>
88263Poly_Con_Relation
88264interval_relation(const ITV& i,
88265                  const Constraint::Type constraint_type,
88266                  Coefficient_traits::const_reference numer,
88267                  Coefficient_traits::const_reference denom) {
88268
88269  if (i.is_universe()) {
88270    return Poly_Con_Relation::strictly_intersects();
88271  }
88272
88273  PPL_DIRTY_TEMP(mpq_class, bound);
88274  assign_r(bound.get_num(), numer, ROUND_NOT_NEEDED);
88275  assign_r(bound.get_den(), denom, ROUND_NOT_NEEDED);
88276  bound.canonicalize();
88277  neg_assign_r(bound, bound, ROUND_NOT_NEEDED);
88278  const bool is_lower_bound = (denom > 0);
88279
88280  PPL_DIRTY_TEMP(mpq_class, bound_diff);
88281  if (constraint_type == Constraint::EQUALITY) {
88282    if (i.lower_is_boundary_infinity()) {
88283      PPL_ASSERT(!i.upper_is_boundary_infinity());
88284      assign_r(bound_diff, i.upper(), ROUND_NOT_NEEDED);
88285      sub_assign_r(bound_diff, bound_diff, bound, ROUND_NOT_NEEDED);
88286      switch (sgn(bound_diff)) {
88287      case 1:
88288        return Poly_Con_Relation::strictly_intersects();
88289      case 0:
88290        return i.upper_is_open()
88291          ? Poly_Con_Relation::is_disjoint()
88292          : Poly_Con_Relation::strictly_intersects();
88293      case -1:
88294        return Poly_Con_Relation::is_disjoint();
88295      }
88296    }
88297    else {
88298      assign_r(bound_diff, i.lower(), ROUND_NOT_NEEDED);
88299      sub_assign_r(bound_diff, bound_diff, bound, ROUND_NOT_NEEDED);
88300      switch (sgn(bound_diff)) {
88301      case 1:
88302        return Poly_Con_Relation::is_disjoint();
88303      case 0:
88304        if (i.lower_is_open()) {
88305          return Poly_Con_Relation::is_disjoint();
88306        }
88307        if (i.is_singleton()) {
88308          return Poly_Con_Relation::is_included()
88309            && Poly_Con_Relation::saturates();
88310        }
88311        return Poly_Con_Relation::strictly_intersects();
88312      case -1:
88313        if (i.upper_is_boundary_infinity()) {
88314          return Poly_Con_Relation::strictly_intersects();
88315        }
88316        else {
88317          assign_r(bound_diff, i.upper(), ROUND_NOT_NEEDED);
88318          sub_assign_r(bound_diff, bound_diff, bound, ROUND_NOT_NEEDED);
88319          switch (sgn(bound_diff)) {
88320          case 1:
88321            return Poly_Con_Relation::strictly_intersects();
88322          case 0:
88323            if (i.upper_is_open()) {
88324              return Poly_Con_Relation::is_disjoint();
88325            }
88326            else {
88327              return Poly_Con_Relation::strictly_intersects();
88328            }
88329          case -1:
88330            return Poly_Con_Relation::is_disjoint();
88331          }
88332        }
88333      }
88334    }
88335  }
88336
88337  PPL_ASSERT(constraint_type != Constraint::EQUALITY);
88338  if (is_lower_bound) {
88339    if (i.lower_is_boundary_infinity()) {
88340      PPL_ASSERT(!i.upper_is_boundary_infinity());
88341      assign_r(bound_diff, i.upper(), ROUND_NOT_NEEDED);
88342      sub_assign_r(bound_diff, bound_diff, bound, ROUND_NOT_NEEDED);
88343      switch (sgn(bound_diff)) {
88344      case 1:
88345        return Poly_Con_Relation::strictly_intersects();
88346      case 0:
88347        if (constraint_type == Constraint::STRICT_INEQUALITY
88348            || i.upper_is_open()) {
88349          return Poly_Con_Relation::is_disjoint();
88350        }
88351        else {
88352          return Poly_Con_Relation::strictly_intersects();
88353        }
88354      case -1:
88355        return Poly_Con_Relation::is_disjoint();
88356      }
88357    }
88358    else {
88359      assign_r(bound_diff, i.lower(), ROUND_NOT_NEEDED);
88360      sub_assign_r(bound_diff, bound_diff, bound, ROUND_NOT_NEEDED);
88361      switch (sgn(bound_diff)) {
88362      case 1:
88363        return Poly_Con_Relation::is_included();
88364      case 0:
88365        if (constraint_type == Constraint::NONSTRICT_INEQUALITY
88366            || i.lower_is_open()) {
88367          Poly_Con_Relation result = Poly_Con_Relation::is_included();
88368          if (i.is_singleton()) {
88369            result = result && Poly_Con_Relation::saturates();
88370          }
88371          return result;
88372        }
88373        else {
88374          PPL_ASSERT(constraint_type == Constraint::STRICT_INEQUALITY
88375                 && !i.lower_is_open());
88376          if (i.is_singleton()) {
88377            return Poly_Con_Relation::is_disjoint()
88378              && Poly_Con_Relation::saturates();
88379          }
88380          else {
88381            return Poly_Con_Relation::strictly_intersects();
88382          }
88383        }
88384      case -1:
88385        if (i.upper_is_boundary_infinity()) {
88386          return Poly_Con_Relation::strictly_intersects();
88387        }
88388        else {
88389          assign_r(bound_diff, i.upper(), ROUND_NOT_NEEDED);
88390          sub_assign_r(bound_diff, bound_diff, bound, ROUND_NOT_NEEDED);
88391          switch (sgn(bound_diff)) {
88392          case 1:
88393            return Poly_Con_Relation::strictly_intersects();
88394          case 0:
88395            if (constraint_type == Constraint::STRICT_INEQUALITY
88396                || i.upper_is_open()) {
88397              return Poly_Con_Relation::is_disjoint();
88398            }
88399            else {
88400              return Poly_Con_Relation::strictly_intersects();
88401            }
88402          case -1:
88403            return Poly_Con_Relation::is_disjoint();
88404          }
88405        }
88406      }
88407    }
88408  }
88409  else {
88410    // `c' is an upper bound.
88411    if (i.upper_is_boundary_infinity()) {
88412      return Poly_Con_Relation::strictly_intersects();
88413    }
88414    else {
88415      assign_r(bound_diff, i.upper(), ROUND_NOT_NEEDED);
88416      sub_assign_r(bound_diff, bound_diff, bound, ROUND_NOT_NEEDED);
88417      switch (sgn(bound_diff)) {
88418      case -1:
88419        return Poly_Con_Relation::is_included();
88420      case 0:
88421        if (constraint_type == Constraint::NONSTRICT_INEQUALITY
88422            || i.upper_is_open()) {
88423          Poly_Con_Relation result = Poly_Con_Relation::is_included();
88424          if (i.is_singleton()) {
88425            result = result && Poly_Con_Relation::saturates();
88426          }
88427          return result;
88428        }
88429        else {
88430          PPL_ASSERT(constraint_type == Constraint::STRICT_INEQUALITY
88431                 && !i.upper_is_open());
88432          if (i.is_singleton()) {
88433            return Poly_Con_Relation::is_disjoint()
88434              && Poly_Con_Relation::saturates();
88435          }
88436          else {
88437            return Poly_Con_Relation::strictly_intersects();
88438          }
88439        }
88440      case 1:
88441        if (i.lower_is_boundary_infinity()) {
88442          return Poly_Con_Relation::strictly_intersects();
88443        }
88444        else {
88445          assign_r(bound_diff, i.lower(), ROUND_NOT_NEEDED);
88446          sub_assign_r(bound_diff, bound_diff, bound, ROUND_NOT_NEEDED);
88447          switch (sgn(bound_diff)) {
88448          case -1:
88449            return Poly_Con_Relation::strictly_intersects();
88450          case 0:
88451            if (constraint_type == Constraint::STRICT_INEQUALITY
88452                || i.lower_is_open()) {
88453              return Poly_Con_Relation::is_disjoint();
88454            }
88455            else {
88456              return Poly_Con_Relation::strictly_intersects();
88457            }
88458          case 1:
88459            return Poly_Con_Relation::is_disjoint();
88460          }
88461        }
88462      }
88463    }
88464  }
88465
88466  // Quiet a compiler warning: this program point is unreachable.
88467  PPL_UNREACHABLE;
88468  return Poly_Con_Relation::nothing();
88469}
88470
88471template <typename ITV>
88472Poly_Con_Relation
88473Box<ITV>::relation_with(const Congruence& cg) const {
88474  const dimension_type cg_space_dim = cg.space_dimension();
88475  const dimension_type space_dim = space_dimension();
88476
88477  // Dimension-compatibility check.
88478  if (cg_space_dim > space_dim) {
88479    throw_dimension_incompatible("relation_with(cg)", cg);
88480  }
88481  if (is_empty()) {
88482    return Poly_Con_Relation::saturates()
88483      && Poly_Con_Relation::is_included()
88484      && Poly_Con_Relation::is_disjoint();
88485  }
88486
88487  if (space_dim == 0) {
88488    if (cg.is_inconsistent()) {
88489      return Poly_Con_Relation::is_disjoint();
88490    }
88491    else {
88492      return Poly_Con_Relation::saturates()
88493        && Poly_Con_Relation::is_included();
88494    }
88495  }
88496
88497  if (cg.is_equality()) {
88498    const Constraint c(cg);
88499    return relation_with(c);
88500  }
88501
88502  PPL_DIRTY_TEMP(Rational_Interval, r);
88503  PPL_DIRTY_TEMP(Rational_Interval, t);
88504  PPL_DIRTY_TEMP(mpq_class, m);
88505  r = 0;
88506  for (Congruence::expr_type::const_iterator i = cg.expression().begin(),
88507      i_end = cg.expression().end(); i != i_end; ++i) {
88508    const Coefficient& cg_i = *i;
88509    const Variable v = i.variable();
88510    assign_r(m, cg_i, ROUND_NOT_NEEDED);
88511    // FIXME: an add_mul_assign() method would come handy here.
88512    t.build(seq[v.id()].lower_constraint(), seq[v.id()].upper_constraint());
88513    t *= m;
88514    r += t;
88515  }
88516
88517  if (r.lower_is_boundary_infinity() || r.upper_is_boundary_infinity()) {
88518    return Poly_Con_Relation::strictly_intersects();
88519  }
88520
88521  // Find the value that satisfies the congruence and is
88522  // nearest to the lower bound such that the point lies on or above it.
88523
88524  PPL_DIRTY_TEMP_COEFFICIENT(lower);
88525  PPL_DIRTY_TEMP_COEFFICIENT(mod);
88526  PPL_DIRTY_TEMP_COEFFICIENT(v);
88527  mod = cg.modulus();
88528  v = cg.inhomogeneous_term() % mod;
88529  assign_r(lower, r.lower(), ROUND_DOWN);
88530  v -= ((lower / mod) * mod);
88531  if (v + lower > 0) {
88532    v -= mod;
88533  }
88534  return interval_relation(r, Constraint::EQUALITY, v);
88535}
88536
88537template <typename ITV>
88538Poly_Con_Relation
88539Box<ITV>::relation_with(const Constraint& c) const {
88540  const dimension_type c_space_dim = c.space_dimension();
88541  const dimension_type space_dim = space_dimension();
88542
88543  // Dimension-compatibility check.
88544  if (c_space_dim > space_dim) {
88545    throw_dimension_incompatible("relation_with(c)", c);
88546  }
88547
88548  if (is_empty()) {
88549    return Poly_Con_Relation::saturates()
88550      && Poly_Con_Relation::is_included()
88551      && Poly_Con_Relation::is_disjoint();
88552  }
88553
88554  if (space_dim == 0) {
88555    if ((c.is_equality() && c.inhomogeneous_term() != 0)
88556        || (c.is_inequality() && c.inhomogeneous_term() < 0)) {
88557      return Poly_Con_Relation::is_disjoint();
88558    }
88559    else if (c.is_strict_inequality() && c.inhomogeneous_term() == 0) {
88560      // The constraint 0 > 0 implicitly defines the hyperplane 0 = 0;
88561      // thus, the zero-dimensional point also saturates it.
88562      return Poly_Con_Relation::saturates()
88563        && Poly_Con_Relation::is_disjoint();
88564    }
88565    else if (c.is_equality() || c.inhomogeneous_term() == 0) {
88566      return Poly_Con_Relation::saturates()
88567        && Poly_Con_Relation::is_included();
88568    }
88569    else {
88570      // The zero-dimensional point saturates
88571      // neither the positivity constraint 1 >= 0,
88572      // nor the strict positivity constraint 1 > 0.
88573      return Poly_Con_Relation::is_included();
88574    }
88575  }
88576
88577  dimension_type c_num_vars = 0;
88578  dimension_type c_only_var = 0;
88579
88580  if (Box_Helpers::extract_interval_constraint(c, c_num_vars, c_only_var)) {
88581    if (c_num_vars == 0) {
88582      // c is a trivial constraint.
88583      switch (sgn(c.inhomogeneous_term())) {
88584      case -1:
88585        return Poly_Con_Relation::is_disjoint();
88586      case 0:
88587        if (c.is_strict_inequality()) {
88588          return Poly_Con_Relation::saturates()
88589            && Poly_Con_Relation::is_disjoint();
88590        }
88591        else {
88592          return Poly_Con_Relation::saturates()
88593            && Poly_Con_Relation::is_included();
88594        }
88595      case 1:
88596        return Poly_Con_Relation::is_included();
88597      }
88598    }
88599    else {
88600      // c is an interval constraint.
88601      return interval_relation(seq[c_only_var],
88602                               c.type(),
88603                               c.inhomogeneous_term(),
88604                               c.coefficient(Variable(c_only_var)));
88605    }
88606  }
88607  else {
88608    // Deal with a non-trivial and non-interval constraint.
88609    PPL_DIRTY_TEMP(Rational_Interval, r);
88610    PPL_DIRTY_TEMP(Rational_Interval, t);
88611    PPL_DIRTY_TEMP(mpq_class, m);
88612    r = 0;
88613    const Constraint::expr_type& e = c.expression();
88614    for (Constraint::expr_type::const_iterator i = e.begin(), i_end = e.end();
88615          i != i_end; ++i) {
88616      assign_r(m, *i, ROUND_NOT_NEEDED);
88617      const Variable v = i.variable();
88618      // FIXME: an add_mul_assign() method would come handy here.
88619      t.build(seq[v.id()].lower_constraint(), seq[v.id()].upper_constraint());
88620      t *= m;
88621      r += t;
88622    }
88623    return interval_relation(r,
88624                             c.type(),
88625                             c.inhomogeneous_term());
88626  }
88627
88628  // Quiet a compiler warning: this program point is unreachable.
88629  PPL_UNREACHABLE;
88630  return Poly_Con_Relation::nothing();
88631}
88632
88633template <typename ITV>
88634Poly_Gen_Relation
88635Box<ITV>::relation_with(const Generator& g) const {
88636  const dimension_type space_dim = space_dimension();
88637  const dimension_type g_space_dim = g.space_dimension();
88638
88639  // Dimension-compatibility check.
88640  if (space_dim < g_space_dim) {
88641    throw_dimension_incompatible("relation_with(g)", g);
88642  }
88643
88644  // The empty box cannot subsume a generator.
88645  if (is_empty()) {
88646    return Poly_Gen_Relation::nothing();
88647  }
88648
88649  // A universe box in a zero-dimensional space subsumes
88650  // all the generators of a zero-dimensional space.
88651  if (space_dim == 0) {
88652    return Poly_Gen_Relation::subsumes();
88653  }
88654
88655  if (g.is_line_or_ray()) {
88656    if (g.is_line()) {
88657      const Generator::expr_type& e = g.expression();
88658      for (Generator::expr_type::const_iterator i = e.begin(), i_end = e.end();
88659           i != i_end; ++i) {
88660        if (!seq[i.variable().id()].is_universe()) {
88661          return Poly_Gen_Relation::nothing();
88662        }
88663      }
88664      return Poly_Gen_Relation::subsumes();
88665    }
88666    else {
88667      PPL_ASSERT(g.is_ray());
88668      const Generator::expr_type& e = g.expression();
88669      for (Generator::expr_type::const_iterator i = e.begin(), i_end = e.end();
88670           i != i_end; ++i) {
88671        const Variable v = i.variable();
88672        switch (sgn(*i)) {
88673        case 1:
88674          if (!seq[v.id()].upper_is_boundary_infinity()) {
88675            return Poly_Gen_Relation::nothing();
88676          }
88677          break;
88678        case 0:
88679          PPL_UNREACHABLE;
88680          break;
88681        case -1:
88682          if (!seq[v.id()].lower_is_boundary_infinity()) {
88683            return Poly_Gen_Relation::nothing();
88684          }
88685          break;
88686        }
88687      }
88688      return Poly_Gen_Relation::subsumes();
88689    }
88690  }
88691
88692  // Here `g' is a point or closure point.
88693  const Coefficient& g_divisor = g.divisor();
88694  PPL_DIRTY_TEMP(mpq_class, g_coord);
88695  PPL_DIRTY_TEMP(mpq_class, bound);
88696  // TODO: If the variables in the expression that have coefficient 0
88697  // have no effect on seq[i], this loop can be optimized using
88698  // Generator::expr_type::const_iterator.
88699  for (dimension_type i = g_space_dim; i-- > 0; ) {
88700    const ITV& seq_i = seq[i];
88701    if (seq_i.is_universe()) {
88702      continue;
88703    }
88704    assign_r(g_coord.get_num(), g.coefficient(Variable(i)), ROUND_NOT_NEEDED);
88705    assign_r(g_coord.get_den(), g_divisor, ROUND_NOT_NEEDED);
88706    g_coord.canonicalize();
88707    // Check lower bound.
88708    if (!seq_i.lower_is_boundary_infinity()) {
88709      assign_r(bound, seq_i.lower(), ROUND_NOT_NEEDED);
88710      if (g_coord <= bound) {
88711        if (seq_i.lower_is_open()) {
88712          if (g.is_point() || g_coord != bound) {
88713            return Poly_Gen_Relation::nothing();
88714          }
88715        }
88716        else if (g_coord != bound) {
88717          return Poly_Gen_Relation::nothing();
88718        }
88719      }
88720    }
88721    // Check upper bound.
88722    if (!seq_i.upper_is_boundary_infinity()) {
88723      assign_r(bound, seq_i.upper(), ROUND_NOT_NEEDED);
88724      if (g_coord >= bound) {
88725        if (seq_i.upper_is_open()) {
88726          if (g.is_point() || g_coord != bound) {
88727            return Poly_Gen_Relation::nothing();
88728          }
88729        }
88730        else if (g_coord != bound) {
88731          return Poly_Gen_Relation::nothing();
88732        }
88733      }
88734    }
88735  }
88736  return Poly_Gen_Relation::subsumes();
88737}
88738
88739
88740template <typename ITV>
88741bool
88742Box<ITV>::max_min(const Linear_Expression& expr,
88743                  const bool maximize,
88744                  Coefficient& ext_n, Coefficient& ext_d,
88745                  bool& included) const {
88746  // `expr' should be dimension-compatible with `*this'.
88747  const dimension_type space_dim = space_dimension();
88748  const dimension_type expr_space_dim = expr.space_dimension();
88749  if (space_dim < expr_space_dim) {
88750    throw_dimension_incompatible((maximize
88751                                  ? "maximize(e, ...)"
88752                                  : "minimize(e, ...)"), "e", expr);
88753  }
88754
88755  // Deal with zero-dim Box first.
88756  if (space_dim == 0) {
88757    if (marked_empty()) {
88758      return false;
88759    }
88760    else {
88761      ext_n = expr.inhomogeneous_term();
88762      ext_d = 1;
88763      included = true;
88764      return true;
88765    }
88766  }
88767
88768  // For an empty Box we simply return false.
88769  if (is_empty()) {
88770    return false;
88771  }
88772
88773  PPL_DIRTY_TEMP(mpq_class, result);
88774  assign_r(result, expr.inhomogeneous_term(), ROUND_NOT_NEEDED);
88775  bool is_included = true;
88776  const int maximize_sign = maximize ? 1 : -1;
88777  PPL_DIRTY_TEMP(mpq_class, bound_i);
88778  PPL_DIRTY_TEMP(mpq_class, expr_i);
88779  for (Linear_Expression::const_iterator i = expr.begin(),
88780          i_end = expr.end(); i != i_end; ++i) {
88781    const ITV& seq_i = seq[i.variable().id()];
88782    assign_r(expr_i, *i, ROUND_NOT_NEEDED);
88783    switch (sgn(expr_i) * maximize_sign) {
88784    case 1:
88785      if (seq_i.upper_is_boundary_infinity()) {
88786        return false;
88787      }
88788      assign_r(bound_i, seq_i.upper(), ROUND_NOT_NEEDED);
88789      add_mul_assign_r(result, bound_i, expr_i, ROUND_NOT_NEEDED);
88790      if (seq_i.upper_is_open()) {
88791        is_included = false;
88792      }
88793      break;
88794    case 0:
88795      PPL_UNREACHABLE;
88796      break;
88797    case -1:
88798      if (seq_i.lower_is_boundary_infinity()) {
88799        return false;
88800      }
88801      assign_r(bound_i, seq_i.lower(), ROUND_NOT_NEEDED);
88802      add_mul_assign_r(result, bound_i, expr_i, ROUND_NOT_NEEDED);
88803      if (seq_i.lower_is_open()) {
88804        is_included = false;
88805      }
88806      break;
88807    }
88808  }
88809  // Extract output info.
88810  PPL_ASSERT(is_canonical(result));
88811  ext_n = result.get_num();
88812  ext_d = result.get_den();
88813  included = is_included;
88814  return true;
88815}
88816
88817template <typename ITV>
88818bool
88819Box<ITV>::max_min(const Linear_Expression& expr,
88820                  const bool maximize,
88821                  Coefficient& ext_n, Coefficient& ext_d,
88822                  bool& included,
88823                  Generator& g) const {
88824  if (!max_min(expr, maximize, ext_n, ext_d, included)) {
88825    return false;
88826  }
88827  // Compute generator `g'.
88828  Linear_Expression g_expr;
88829  PPL_DIRTY_TEMP_COEFFICIENT(g_divisor);
88830  g_divisor = 1;
88831  const int maximize_sign = maximize ? 1 : -1;
88832  PPL_DIRTY_TEMP(mpq_class, g_coord);
88833  PPL_DIRTY_TEMP_COEFFICIENT(numer);
88834  PPL_DIRTY_TEMP_COEFFICIENT(denom);
88835  PPL_DIRTY_TEMP_COEFFICIENT(lcm);
88836  PPL_DIRTY_TEMP_COEFFICIENT(factor);
88837  // TODO: Check if the following loop can be optimized to exploit the
88838  // (possible) sparseness of expr.
88839  for (dimension_type i = space_dimension(); i-- > 0; ) {
88840    const ITV& seq_i = seq[i];
88841    switch (sgn(expr.coefficient(Variable(i))) * maximize_sign) {
88842    case 1:
88843      assign_r(g_coord, seq_i.upper(), ROUND_NOT_NEEDED);
88844      break;
88845    case 0:
88846      // If 0 belongs to the interval, choose it
88847      // (and directly proceed to the next iteration).
88848      // FIXME: name qualification issue.
88849      if (seq_i.contains(0)) {
88850        continue;
88851      }
88852      if (!seq_i.lower_is_boundary_infinity()) {
88853        if (seq_i.lower_is_open()) {
88854          if (!seq_i.upper_is_boundary_infinity()) {
88855            if (seq_i.upper_is_open()) {
88856              // Bounded and open interval: compute middle point.
88857              assign_r(g_coord, seq_i.lower(), ROUND_NOT_NEEDED);
88858              PPL_DIRTY_TEMP(mpq_class, q_seq_i_upper);
88859              assign_r(q_seq_i_upper, seq_i.upper(), ROUND_NOT_NEEDED);
88860              g_coord += q_seq_i_upper;
88861              g_coord /= 2;
88862            }
88863            else {
88864              // The upper bound is in the interval.
88865              assign_r(g_coord, seq_i.upper(), ROUND_NOT_NEEDED);
88866            }
88867          }
88868          else {
88869            // Lower is open, upper is unbounded.
88870            assign_r(g_coord, seq_i.lower(), ROUND_NOT_NEEDED);
88871            ++g_coord;
88872          }
88873        }
88874        else {
88875          // The lower bound is in the interval.
88876          assign_r(g_coord, seq_i.lower(), ROUND_NOT_NEEDED);
88877        }
88878      }
88879      else {
88880        // Lower is unbounded, hence upper is bounded
88881        // (since we know that 0 does not belong to the interval).
88882        PPL_ASSERT(!seq_i.upper_is_boundary_infinity());
88883        assign_r(g_coord, seq_i.upper(), ROUND_NOT_NEEDED);
88884        if (seq_i.upper_is_open()) {
88885          --g_coord;
88886        }
88887      }
88888      break;
88889    case -1:
88890      assign_r(g_coord, seq_i.lower(), ROUND_NOT_NEEDED);
88891      break;
88892    }
88893    // Add g_coord * Variable(i) to the generator.
88894    assign_r(denom, g_coord.get_den(), ROUND_NOT_NEEDED);
88895    lcm_assign(lcm, g_divisor, denom);
88896    exact_div_assign(factor, lcm, g_divisor);
88897    g_expr *= factor;
88898    exact_div_assign(factor, lcm, denom);
88899    assign_r(numer, g_coord.get_num(), ROUND_NOT_NEEDED);
88900    numer *= factor;
88901    g_expr += numer * Variable(i);
88902    g_divisor = lcm;
88903  }
88904  g = Generator::point(g_expr, g_divisor);
88905  return true;
88906}
88907
88908template <typename ITV>
88909bool
88910Box<ITV>::contains(const Box& y) const {
88911  const Box& x = *this;
88912  // Dimension-compatibility check.
88913  if (x.space_dimension() != y.space_dimension()) {
88914    x.throw_dimension_incompatible("contains(y)", y);
88915  }
88916
88917  // If `y' is empty, then `x' contains `y'.
88918  if (y.is_empty()) {
88919    return true;
88920  }
88921
88922  // If `x' is empty, then `x' cannot contain `y'.
88923  if (x.is_empty()) {
88924    return false;
88925  }
88926
88927  for (dimension_type k = x.seq.size(); k-- > 0; ) {
88928    // FIXME: fix this name qualification issue.
88929    if (!x.seq[k].contains(y.seq[k])) {
88930      return false;
88931    }
88932  }
88933  return true;
88934}
88935
88936template <typename ITV>
88937bool
88938Box<ITV>::is_disjoint_from(const Box& y) const {
88939  const Box& x = *this;
88940  // Dimension-compatibility check.
88941  if (x.space_dimension() != y.space_dimension()) {
88942    x.throw_dimension_incompatible("is_disjoint_from(y)", y);
88943  }
88944
88945  // If any of `x' or `y' is marked empty, then they are disjoint.
88946  // Note: no need to use `is_empty', as the following loop is anyway correct.
88947  if (x.marked_empty() || y.marked_empty()) {
88948    return true;
88949  }
88950
88951  for (dimension_type k = x.seq.size(); k-- > 0; ) {
88952    // FIXME: fix this name qualification issue.
88953    if (x.seq[k].is_disjoint_from(y.seq[k])) {
88954      return true;
88955    }
88956  }
88957  return false;
88958}
88959
88960template <typename ITV>
88961inline bool
88962Box<ITV>::upper_bound_assign_if_exact(const Box& y) {
88963  Box& x = *this;
88964
88965  // Dimension-compatibility check.
88966  if (x.space_dimension() != y.space_dimension()) {
88967    x.throw_dimension_incompatible("upper_bound_assign_if_exact(y)", y);
88968  }
88969
88970  // The lub of a box with an empty box is equal to the first box.
88971  if (y.is_empty()) {
88972    return true;
88973  }
88974  if (x.is_empty()) {
88975    x = y;
88976    return true;
88977  }
88978
88979  bool x_j_does_not_contain_y_j = false;
88980  bool y_j_does_not_contain_x_j = false;
88981
88982  for (dimension_type i = x.seq.size(); i-- > 0; ) {
88983    const ITV& x_seq_i = x.seq[i];
88984    const ITV& y_seq_i = y.seq[i];
88985
88986    if (!x_seq_i.can_be_exactly_joined_to(y_seq_i)) {
88987      return false;
88988    }
88989
88990    // Note: the use of `y_i_does_not_contain_x_i' is needed
88991    // because we want to temporarily preserve the old value
88992    // of `y_j_does_not_contain_x_j'.
88993    bool y_i_does_not_contain_x_i = !y_seq_i.contains(x_seq_i);
88994    if (y_i_does_not_contain_x_i && x_j_does_not_contain_y_j) {
88995      return false;
88996    }
88997    if (!x_seq_i.contains(y_seq_i)) {
88998      if (y_j_does_not_contain_x_j) {
88999        return false;
89000      }
89001      else {
89002        x_j_does_not_contain_y_j = true;
89003      }
89004    }
89005    if (y_i_does_not_contain_x_i) {
89006      y_j_does_not_contain_x_j = true;
89007    }
89008  }
89009
89010  // The upper bound is exact: compute it into *this.
89011  for (dimension_type k = x.seq.size(); k-- > 0; ) {
89012    x.seq[k].join_assign(y.seq[k]);
89013  }
89014  return true;
89015}
89016
89017template <typename ITV>
89018bool
89019Box<ITV>::OK() const {
89020  if (status.test_empty_up_to_date() && !status.test_empty()) {
89021    Box tmp = *this;
89022    tmp.reset_empty_up_to_date();
89023    if (tmp.check_empty()) {
89024#ifndef NDEBUG
89025      std::cerr << "The box is empty, but it is marked as non-empty."
89026                << std::endl;
89027#endif // NDEBUG
89028      return false;
89029    }
89030  }
89031
89032  // A box that is not marked empty must have meaningful intervals.
89033  if (!marked_empty()) {
89034    for (dimension_type k = seq.size(); k-- > 0; ) {
89035      if (!seq[k].OK()) {
89036        return false;
89037      }
89038    }
89039  }
89040
89041  return true;
89042}
89043
89044template <typename ITV>
89045dimension_type
89046Box<ITV>::affine_dimension() const {
89047  dimension_type d = space_dimension();
89048  // A zero-space-dim box always has affine dimension zero.
89049  if (d == 0) {
89050    return 0;
89051  }
89052
89053  // An empty box has affine dimension zero.
89054  if (is_empty()) {
89055    return 0;
89056  }
89057
89058  for (dimension_type k = d; k-- > 0; ) {
89059    if (seq[k].is_singleton()) {
89060      --d;
89061    }
89062  }
89063
89064  return d;
89065}
89066
89067template <typename ITV>
89068bool
89069Box<ITV>::check_empty() const {
89070  PPL_ASSERT(!marked_empty());
89071  Box<ITV>& x = const_cast<Box<ITV>&>(*this);
89072  for (dimension_type k = seq.size(); k-- > 0; ) {
89073    if (seq[k].is_empty()) {
89074      x.set_empty();
89075      return true;
89076    }
89077  }
89078  x.set_nonempty();
89079  return false;
89080}
89081
89082template <typename ITV>
89083bool
89084Box<ITV>::is_universe() const {
89085  if (marked_empty()) {
89086    return false;
89087  }
89088  for (dimension_type k = seq.size(); k-- > 0; ) {
89089    if (!seq[k].is_universe()) {
89090      return false;
89091    }
89092  }
89093  return true;
89094}
89095
89096template <typename ITV>
89097bool
89098Box<ITV>::is_topologically_closed() const {
89099  if (ITV::is_always_topologically_closed() || is_empty()) {
89100    return true;
89101  }
89102
89103  for (dimension_type k = seq.size(); k-- > 0; ) {
89104    if (!seq[k].is_topologically_closed()) {
89105      return false;
89106    }
89107  }
89108  return true;
89109}
89110
89111template <typename ITV>
89112bool
89113Box<ITV>::is_discrete() const {
89114  if (is_empty()) {
89115    return true;
89116  }
89117  for (dimension_type k = seq.size(); k-- > 0; ) {
89118    if (!seq[k].is_singleton()) {
89119      return false;
89120    }
89121  }
89122  return true;
89123}
89124
89125template <typename ITV>
89126bool
89127Box<ITV>::is_bounded() const {
89128  if (is_empty()) {
89129    return true;
89130  }
89131  for (dimension_type k = seq.size(); k-- > 0; ) {
89132    if (!seq[k].is_bounded()) {
89133      return false;
89134    }
89135  }
89136  return true;
89137}
89138
89139template <typename ITV>
89140bool
89141Box<ITV>::contains_integer_point() const {
89142  if (marked_empty()) {
89143    return false;
89144  }
89145  for (dimension_type k = seq.size(); k-- > 0; ) {
89146    if (!seq[k].contains_integer_point()) {
89147      return false;
89148    }
89149  }
89150  return true;
89151}
89152
89153template <typename ITV>
89154bool
89155Box<ITV>::frequency(const Linear_Expression& expr,
89156                  Coefficient& freq_n, Coefficient& freq_d,
89157                  Coefficient& val_n, Coefficient& val_d) const {
89158  dimension_type space_dim = space_dimension();
89159  // The dimension of `expr' must be at most the dimension of *this.
89160  if (space_dim < expr.space_dimension()) {
89161    throw_dimension_incompatible("frequency(e, ...)", "e", expr);
89162  }
89163
89164  // Check if `expr' has a constant value.
89165  // If it is constant, set the frequency `freq_n' to 0
89166  // and return true. Otherwise the values for \p expr
89167  // are not discrete so return false.
89168
89169  // Space dimension is 0: if empty, then return false;
89170  // otherwise the frequency is 0 and the value is the inhomogeneous term.
89171  if (space_dim == 0) {
89172    if (is_empty()) {
89173      return false;
89174    }
89175    freq_n = 0;
89176    freq_d = 1;
89177    val_n = expr.inhomogeneous_term();
89178    val_d = 1;
89179    return true;
89180  }
89181
89182  // For an empty Box, we simply return false.
89183  if (is_empty()) {
89184    return false;
89185  }
89186
89187  // The Box has at least 1 dimension and is not empty.
89188  PPL_DIRTY_TEMP_COEFFICIENT(numer);
89189  PPL_DIRTY_TEMP_COEFFICIENT(denom);
89190  PPL_DIRTY_TEMP(mpq_class, tmp);
89191  Coefficient c = expr.inhomogeneous_term();
89192
89193  PPL_DIRTY_TEMP_COEFFICIENT(val_denom);
89194  val_denom = 1;
89195
89196  for (Linear_Expression::const_iterator i = expr.begin(), i_end = expr.end();
89197       i != i_end; ++i) {
89198    const ITV& seq_i = seq[i.variable().id()];
89199    // Check if `v' is constant in the BD shape.
89200    if (seq_i.is_singleton()) {
89201      // If `v' is constant, replace it in `le' by the value.
89202      assign_r(tmp, seq_i.lower(), ROUND_NOT_NEEDED);
89203      numer = tmp.get_num();
89204      denom = tmp.get_den();
89205      c *= denom;
89206      c += numer * val_denom * (*i);
89207      val_denom *= denom;
89208      continue;
89209    }
89210    // The expression `expr' is not constant.
89211    return false;
89212  }
89213
89214  // The expression `expr' is constant.
89215  freq_n = 0;
89216  freq_d = 1;
89217
89218  // Reduce `val_n' and `val_d'.
89219  normalize2(c, val_denom, val_n, val_d);
89220  return true;
89221}
89222
89223template <typename ITV>
89224bool
89225Box<ITV>::constrains(Variable var) const {
89226  // `var' should be one of the dimensions of the polyhedron.
89227  const dimension_type var_space_dim = var.space_dimension();
89228  if (space_dimension() < var_space_dim) {
89229    throw_dimension_incompatible("constrains(v)", "v", var);
89230  }
89231
89232  if (marked_empty() || !seq[var_space_dim-1].is_universe()) {
89233    return true;
89234  }
89235  // Now force an emptiness check.
89236  return is_empty();
89237}
89238
89239template <typename ITV>
89240void
89241Box<ITV>::unconstrain(const Variables_Set& vars) {
89242  // The cylindrification with respect to no dimensions is a no-op.
89243  // This case also captures the only legal cylindrification
89244  // of a box in a 0-dim space.
89245  if (vars.empty()) {
89246    return;
89247  }
89248
89249  // Dimension-compatibility check.
89250  const dimension_type min_space_dim = vars.space_dimension();
89251  if (space_dimension() < min_space_dim) {
89252    throw_dimension_incompatible("unconstrain(vs)", min_space_dim);
89253  }
89254  // If the box is already empty, there is nothing left to do.
89255  if (marked_empty()) {
89256    return;
89257  }
89258
89259  // Here the box might still be empty (but we haven't detected it yet):
89260  // check emptiness of the interval for each of the variables in
89261  // `vars' before cylindrification.
89262  for (Variables_Set::const_iterator vsi = vars.begin(),
89263         vsi_end = vars.end(); vsi != vsi_end; ++vsi) {
89264    ITV& seq_vsi = seq[*vsi];
89265    if (!seq_vsi.is_empty()) {
89266      seq_vsi.assign(UNIVERSE);
89267    }
89268    else {
89269      set_empty();
89270      break;
89271    }
89272  }
89273  PPL_ASSERT(OK());
89274}
89275
89276template <typename ITV>
89277void
89278Box<ITV>::topological_closure_assign() {
89279  if (ITV::is_always_topologically_closed() || is_empty()) {
89280    return;
89281  }
89282
89283  for (dimension_type k = seq.size(); k-- > 0; ) {
89284    seq[k].topological_closure_assign();
89285  }
89286}
89287
89288template <typename ITV>
89289void
89290Box<ITV>::wrap_assign(const Variables_Set& vars,
89291                      Bounded_Integer_Type_Width w,
89292                      Bounded_Integer_Type_Representation r,
89293                      Bounded_Integer_Type_Overflow o,
89294                      const Constraint_System* cs_p,
89295                      unsigned complexity_threshold,
89296                      bool wrap_individually) {
89297#if 0 // Generic implementation commented out.
89298  Implementation::wrap_assign(*this,
89299                              vars, w, r, o, cs_p,
89300                              complexity_threshold, wrap_individually,
89301                              "Box");
89302#else // Specialized implementation.
89303  PPL_USED(wrap_individually);
89304  PPL_USED(complexity_threshold);
89305  Box& x = *this;
89306
89307  // Dimension-compatibility check for `*cs_p', if any.
89308  const dimension_type vars_space_dim = vars.space_dimension();
89309  if (cs_p != 0 && cs_p->space_dimension() > vars_space_dim) {
89310    std::ostringstream s;
89311    s << "PPL::Box<ITV>::wrap_assign(vars, w, r, o, cs_p, ...):"
89312      << std::endl
89313      << "vars.space_dimension() == " << vars_space_dim
89314      << ", cs_p->space_dimension() == " << cs_p->space_dimension() << ".";
89315    throw std::invalid_argument(s.str());
89316  }
89317
89318  // Wrapping no variable only requires refining with *cs_p, if any.
89319  if (vars.empty()) {
89320    if (cs_p != 0) {
89321      refine_with_constraints(*cs_p);
89322    }
89323    return;
89324  }
89325
89326  // Dimension-compatibility check for `vars'.
89327  const dimension_type space_dim = x.space_dimension();
89328  if (space_dim < vars_space_dim) {
89329    std::ostringstream s;
89330    s << "PPL::Box<ITV>::wrap_assign(vars, ...):"
89331      << std::endl
89332      << "this->space_dimension() == " << space_dim
89333      << ", required space dimension == " << vars_space_dim << ".";
89334    throw std::invalid_argument(s.str());
89335  }
89336
89337  // Wrapping an empty polyhedron is a no-op.
89338  if (x.is_empty()) {
89339    return;
89340  }
89341
89342  // FIXME: temporarily (ab-) using Coefficient.
89343  // Set `min_value' and `max_value' to the minimum and maximum values
89344  // a variable of width `w' and signedness `s' can take.
89345  PPL_DIRTY_TEMP_COEFFICIENT(min_value);
89346  PPL_DIRTY_TEMP_COEFFICIENT(max_value);
89347  if (r == UNSIGNED) {
89348    min_value = 0;
89349    mul_2exp_assign(max_value, Coefficient_one(), w);
89350    --max_value;
89351  }
89352  else {
89353    PPL_ASSERT(r == SIGNED_2_COMPLEMENT);
89354    mul_2exp_assign(max_value, Coefficient_one(), w-1);
89355    neg_assign(min_value, max_value);
89356    --max_value;
89357  }
89358
89359  // FIXME: Build the (integer) quadrant interval.
89360  PPL_DIRTY_TEMP(ITV, integer_quadrant_itv);
89361  PPL_DIRTY_TEMP(ITV, rational_quadrant_itv);
89362  {
89363    I_Constraint<Coefficient> lower = i_constraint(GREATER_OR_EQUAL, min_value);
89364    I_Constraint<Coefficient> upper = i_constraint(LESS_OR_EQUAL, max_value);
89365    integer_quadrant_itv.build(lower, upper);
89366    // The rational quadrant is only needed if overflow is undefined.
89367    if (o == OVERFLOW_UNDEFINED) {
89368      ++max_value;
89369      upper = i_constraint(LESS_THAN, max_value);
89370      rational_quadrant_itv.build(lower, upper);
89371    }
89372  }
89373
89374  const Variables_Set::const_iterator vs_end = vars.end();
89375
89376  if (cs_p == 0) {
89377    // No constraint refinement is needed here.
89378    switch (o) {
89379    case OVERFLOW_WRAPS:
89380      for (Variables_Set::const_iterator i = vars.begin(); i != vs_end; ++i) {
89381        x.seq[*i].wrap_assign(w, r, integer_quadrant_itv);
89382      }
89383      reset_empty_up_to_date();
89384      break;
89385    case OVERFLOW_UNDEFINED:
89386      for (Variables_Set::const_iterator i = vars.begin(); i != vs_end; ++i) {
89387        ITV& x_seq_v = x.seq[*i];
89388        if (!rational_quadrant_itv.contains(x_seq_v)) {
89389          x_seq_v.assign(integer_quadrant_itv);
89390        }
89391      }
89392      break;
89393    case OVERFLOW_IMPOSSIBLE:
89394      for (Variables_Set::const_iterator i = vars.begin(); i != vs_end; ++i) {
89395        x.seq[*i].intersect_assign(integer_quadrant_itv);
89396      }
89397      reset_empty_up_to_date();
89398      break;
89399    }
89400    PPL_ASSERT(x.OK());
89401    return;
89402  }
89403
89404  PPL_ASSERT(cs_p != 0);
89405  const Constraint_System& cs = *cs_p;
89406  // A map associating interval constraints to variable indexes.
89407  typedef std::map<dimension_type, std::vector<const Constraint*> > map_type;
89408  map_type var_cs_map;
89409  for (Constraint_System::const_iterator i = cs.begin(),
89410         i_end = cs.end(); i != i_end; ++i) {
89411    const Constraint& c = *i;
89412    dimension_type c_num_vars = 0;
89413    dimension_type c_only_var = 0;
89414    if (Box_Helpers::extract_interval_constraint(c, c_num_vars, c_only_var)) {
89415      if (c_num_vars == 1) {
89416        // An interval constraint on variable index `c_only_var'.
89417        PPL_ASSERT(c_only_var < space_dim);
89418        // We do care about c if c_only_var is going to be wrapped.
89419        if (vars.find(c_only_var) != vs_end) {
89420          var_cs_map[c_only_var].push_back(&c);
89421        }
89422      }
89423      else {
89424        PPL_ASSERT(c_num_vars == 0);
89425        // Note: tautologies have been filtered out by iterators.
89426        PPL_ASSERT(c.is_inconsistent());
89427        x.set_empty();
89428        return;
89429      }
89430    }
89431  }
89432
89433  PPL_DIRTY_TEMP(ITV, refinement_itv);
89434  const map_type::const_iterator var_cs_map_end = var_cs_map.end();
89435  // Loop through the variable indexes in `vars'.
89436  for (Variables_Set::const_iterator i = vars.begin(); i != vs_end; ++i) {
89437    const dimension_type v = *i;
89438    refinement_itv = integer_quadrant_itv;
89439    // Look for the refinement constraints for space dimension index `v'.
89440    map_type::const_iterator var_cs_map_iter = var_cs_map.find(v);
89441    if (var_cs_map_iter != var_cs_map_end) {
89442      // Refine interval for variable `v'.
89443      const map_type::mapped_type& var_cs = var_cs_map_iter->second;
89444      for (dimension_type j = var_cs.size(); j-- > 0; ) {
89445        const Constraint& c = *var_cs[j];
89446        refine_interval_no_check(refinement_itv,
89447                                 c.type(),
89448                                 c.inhomogeneous_term(),
89449                                 c.coefficient(Variable(v)));
89450      }
89451    }
89452    // Wrap space dimension index `v'.
89453    ITV& x_seq_v = x.seq[v];
89454    switch (o) {
89455    case OVERFLOW_WRAPS:
89456      x_seq_v.wrap_assign(w, r, refinement_itv);
89457      break;
89458    case OVERFLOW_UNDEFINED:
89459      if (!rational_quadrant_itv.contains(x_seq_v)) {
89460        x_seq_v.assign(UNIVERSE);
89461      }
89462      break;
89463    case OVERFLOW_IMPOSSIBLE:
89464      x_seq_v.intersect_assign(refinement_itv);
89465      break;
89466    }
89467  }
89468  PPL_ASSERT(x.OK());
89469#endif
89470}
89471
89472template <typename ITV>
89473void
89474Box<ITV>::drop_some_non_integer_points(Complexity_Class) {
89475  if (std::numeric_limits<typename ITV::boundary_type>::is_integer
89476      && !ITV::info_type::store_open) {
89477    return;
89478  }
89479
89480  if (marked_empty()) {
89481    return;
89482  }
89483
89484  for (dimension_type k = seq.size(); k-- > 0; ) {
89485    seq[k].drop_some_non_integer_points();
89486  }
89487
89488  PPL_ASSERT(OK());
89489}
89490
89491template <typename ITV>
89492void
89493Box<ITV>::drop_some_non_integer_points(const Variables_Set& vars,
89494                                       Complexity_Class) {
89495  // Dimension-compatibility check.
89496  const dimension_type min_space_dim = vars.space_dimension();
89497  if (space_dimension() < min_space_dim) {
89498    throw_dimension_incompatible("drop_some_non_integer_points(vs, cmpl)",
89499                                 min_space_dim);
89500  }
89501  if (std::numeric_limits<typename ITV::boundary_type>::is_integer
89502      && !ITV::info_type::store_open) {
89503    return;
89504  }
89505
89506  if (marked_empty()) {
89507    return;
89508  }
89509
89510  for (Variables_Set::const_iterator v_i = vars.begin(),
89511         v_end = vars.end(); v_i != v_end; ++v_i) {
89512    seq[*v_i].drop_some_non_integer_points();
89513  }
89514
89515  PPL_ASSERT(OK());
89516}
89517
89518template <typename ITV>
89519void
89520Box<ITV>::intersection_assign(const Box& y) {
89521  Box& x = *this;
89522  const dimension_type space_dim = space_dimension();
89523
89524  // Dimension-compatibility check.
89525  if (space_dim != y.space_dimension()) {
89526    x.throw_dimension_incompatible("intersection_assign(y)", y);
89527  }
89528
89529  // If one of the two boxes is empty, the intersection is empty.
89530  if (x.marked_empty()) {
89531    return;
89532  }
89533  if (y.marked_empty()) {
89534    x.set_empty();
89535    return;
89536  }
89537
89538  // If both boxes are zero-dimensional, then at this point they are
89539  // necessarily non-empty, so that their intersection is non-empty too.
89540  if (space_dim == 0) {
89541    return;
89542  }
89543
89544  // FIXME: here we may conditionally exploit a capability of the
89545  // underlying interval to eagerly detect empty results.
89546  reset_empty_up_to_date();
89547
89548  for (dimension_type k = space_dim; k-- > 0; ) {
89549    x.seq[k].intersect_assign(y.seq[k]);
89550  }
89551
89552  PPL_ASSERT(x.OK());
89553}
89554
89555template <typename ITV>
89556void
89557Box<ITV>::upper_bound_assign(const Box& y) {
89558  Box& x = *this;
89559
89560  // Dimension-compatibility check.
89561  if (x.space_dimension() != y.space_dimension()) {
89562    x.throw_dimension_incompatible("upper_bound_assign(y)", y);
89563  }
89564
89565  // The lub of a box with an empty box is equal to the first box.
89566  if (y.is_empty()) {
89567    return;
89568  }
89569  if (x.is_empty()) {
89570    x = y;
89571    return;
89572  }
89573
89574  for (dimension_type k = x.seq.size(); k-- > 0; ) {
89575    x.seq[k].join_assign(y.seq[k]);
89576  }
89577
89578  PPL_ASSERT(x.OK());
89579}
89580
89581template <typename ITV>
89582void
89583Box<ITV>::concatenate_assign(const Box& y) {
89584  Box& x = *this;
89585  const dimension_type x_space_dim = x.space_dimension();
89586  const dimension_type y_space_dim = y.space_dimension();
89587
89588  // If `y' is marked empty, the result will be empty too.
89589  if (y.marked_empty()) {
89590    x.set_empty();
89591  }
89592
89593  // If `y' is a 0-dim space box, there is nothing left to do.
89594  if (y_space_dim == 0) {
89595    return;
89596  }
89597  // The resulting space dimension must be at most the maximum.
89598  check_space_dimension_overflow(y.space_dimension(),
89599                                 max_space_dimension() - space_dimension(),
89600                                 "PPL::Box::",
89601                                 "concatenate_assign(y)",
89602                                 "concatenation exceeds the maximum "
89603                                 "allowed space dimension");
89604  // Here `y_space_dim > 0', so that a non-trivial concatenation will occur:
89605  // make sure that reallocation will occur once at most.
89606  x.seq.reserve(x_space_dim + y_space_dim);
89607
89608  // If `x' is marked empty, then it is sufficient to adjust
89609  // the dimension of the vector space.
89610  if (x.marked_empty()) {
89611    x.seq.insert(x.seq.end(), y_space_dim, ITV(EMPTY));
89612    PPL_ASSERT(x.OK());
89613    return;
89614  }
89615
89616  // Here neither `x' nor `y' are marked empty: concatenate them.
89617  std::copy(y.seq.begin(), y.seq.end(),
89618            std::back_insert_iterator<Sequence>(x.seq));
89619  // Update the `empty_up_to_date' flag.
89620  if (!y.status.test_empty_up_to_date()) {
89621    reset_empty_up_to_date();
89622  }
89623
89624  PPL_ASSERT(x.OK());
89625}
89626
89627template <typename ITV>
89628void
89629Box<ITV>::difference_assign(const Box& y) {
89630  const dimension_type space_dim = space_dimension();
89631
89632  // Dimension-compatibility check.
89633  if (space_dim != y.space_dimension()) {
89634    throw_dimension_incompatible("difference_assign(y)", y);
89635  }
89636
89637  Box& x = *this;
89638  if (x.is_empty() || y.is_empty()) {
89639    return;
89640  }
89641  switch (space_dim) {
89642  case 0:
89643    // If `x' is zero-dimensional, then at this point both `x' and `y'
89644    // are the universe box, so that their difference is empty.
89645    x.set_empty();
89646    break;
89647
89648  case 1:
89649    x.seq[0].difference_assign(y.seq[0]);
89650    if (x.seq[0].is_empty()) {
89651      x.set_empty();
89652    }
89653    break;
89654
89655  default:
89656    {
89657      dimension_type index_non_contained = space_dim;
89658      dimension_type number_non_contained = 0;
89659      for (dimension_type i = space_dim; i-- > 0; ) {
89660        if (!y.seq[i].contains(x.seq[i])) {
89661          if (++number_non_contained == 1) {
89662            index_non_contained = i;
89663          }
89664          else {
89665            break;
89666          }
89667        }
89668      }
89669
89670      switch (number_non_contained) {
89671      case 0:
89672        // `y' covers `x': the difference is empty.
89673        x.set_empty();
89674        break;
89675      case 1:
89676        x.seq[index_non_contained]
89677          .difference_assign(y.seq[index_non_contained]);
89678        if (x.seq[index_non_contained].is_empty()) {
89679          x.set_empty();
89680        }
89681        break;
89682      default:
89683        // Nothing to do: the difference is `x'.
89684        break;
89685      }
89686    }
89687    break;
89688  }
89689  PPL_ASSERT(OK());
89690}
89691
89692template <typename ITV>
89693bool
89694Box<ITV>::simplify_using_context_assign(const Box& y) {
89695  Box& x = *this;
89696  const dimension_type num_dims = x.space_dimension();
89697  // Dimension-compatibility check.
89698  if (num_dims != y.space_dimension()) {
89699    x.throw_dimension_incompatible("simplify_using_context_assign(y)", y);
89700  }
89701
89702  // Filter away the zero-dimensional case.
89703  if (num_dims == 0) {
89704    if (y.marked_empty()) {
89705      x.set_nonempty();
89706      return false;
89707    }
89708    else {
89709      return !x.marked_empty();
89710    }
89711  }
89712
89713  // Filter away the case when `y' is empty.
89714  if (y.is_empty()) {
89715    for (dimension_type i = num_dims; i-- > 0; ) {
89716      x.seq[i].assign(UNIVERSE);
89717    }
89718    x.set_nonempty();
89719    return false;
89720  }
89721
89722  if (x.is_empty()) {
89723    // Find in `y' a non-universe interval, if any.
89724    for (dimension_type i = 0; i < num_dims; ++i) {
89725      if (y.seq[i].is_universe()) {
89726        x.seq[i].assign(UNIVERSE);
89727      }
89728      else {
89729        // Set x.seq[i] so as to contradict y.seq[i], if possible.
89730        ITV& seq_i = x.seq[i];
89731        seq_i.empty_intersection_assign(y.seq[i]);
89732        if (seq_i.is_empty()) {
89733          // We were not able to assign to `seq_i' a non-empty interval:
89734          // reset `seq_i' to the universe interval and keep searching.
89735          seq_i.assign(UNIVERSE);
89736          continue;
89737        }
89738        // We assigned to `seq_i' a non-empty interval:
89739        // set the other intervals to universe and return.
89740        for (++i; i < num_dims; ++i) {
89741          x.seq[i].assign(UNIVERSE);
89742        }
89743        x.set_nonempty();
89744        PPL_ASSERT(x.OK());
89745        return false;
89746      }
89747    }
89748    // All intervals in `y' are universe or could not be contradicted:
89749    // simplification can leave the empty box `x' as is.
89750    PPL_ASSERT(x.OK() && x.is_empty());
89751    return false;
89752  }
89753
89754  // Loop index `i' is intentionally going upwards.
89755  for (dimension_type i = 0; i < num_dims; ++i) {
89756    if (!x.seq[i].simplify_using_context_assign(y.seq[i])) {
89757      PPL_ASSERT(!x.seq[i].is_empty());
89758      // The intersection of `x' and `y' is empty due to the i-th interval:
89759      // reset other intervals to UNIVERSE.
89760      for (dimension_type j = num_dims; j-- > i; ) {
89761        x.seq[j].assign(UNIVERSE);
89762      }
89763      for (dimension_type j = i; j-- > 0; ) {
89764        x.seq[j].assign(UNIVERSE);
89765      }
89766      PPL_ASSERT(x.OK());
89767      return false;
89768    }
89769  }
89770  PPL_ASSERT(x.OK());
89771  return true;
89772}
89773
89774template <typename ITV>
89775void
89776Box<ITV>::time_elapse_assign(const Box& y) {
89777  Box& x = *this;
89778  const dimension_type x_space_dim = x.space_dimension();
89779
89780  // Dimension-compatibility check.
89781  if (x_space_dim != y.space_dimension()) {
89782    x.throw_dimension_incompatible("time_elapse_assign(y)", y);
89783  }
89784
89785  // Dealing with the zero-dimensional case.
89786  if (x_space_dim == 0) {
89787    if (y.marked_empty()) {
89788      x.set_empty();
89789    }
89790    return;
89791  }
89792
89793  // If either one of `x' or `y' is empty, the result is empty too.
89794  // Note: if possible, avoid cost of checking for emptiness.
89795  if (x.marked_empty() || y.marked_empty()
89796      || x.is_empty() || y.is_empty()) {
89797    x.set_empty();
89798    return;
89799  }
89800
89801  for (dimension_type i = x_space_dim; i-- > 0; ) {
89802    ITV& x_seq_i = x.seq[i];
89803    const ITV& y_seq_i = y.seq[i];
89804    if (!x_seq_i.lower_is_boundary_infinity()) {
89805      if (y_seq_i.lower_is_boundary_infinity() || y_seq_i.lower() < 0) {
89806        x_seq_i.lower_extend();
89807      }
89808    }
89809    if (!x_seq_i.upper_is_boundary_infinity()) {
89810      if (y_seq_i.upper_is_boundary_infinity() || y_seq_i.upper() > 0) {
89811        x_seq_i.upper_extend();
89812      }
89813    }
89814  }
89815  PPL_ASSERT(x.OK());
89816}
89817
89818template <typename ITV>
89819inline void
89820Box<ITV>::remove_space_dimensions(const Variables_Set& vars) {
89821  // The removal of no dimensions from any box is a no-op.
89822  // Note that this case also captures the only legal removal of
89823  // space dimensions from a box in a zero-dimensional space.
89824  if (vars.empty()) {
89825    PPL_ASSERT(OK());
89826    return;
89827  }
89828
89829  const dimension_type old_space_dim = space_dimension();
89830
89831  // Dimension-compatibility check.
89832  const dimension_type vsi_space_dim = vars.space_dimension();
89833  if (old_space_dim < vsi_space_dim) {
89834    throw_dimension_incompatible("remove_space_dimensions(vs)",
89835                                 vsi_space_dim);
89836  }
89837
89838  const dimension_type new_space_dim = old_space_dim - vars.size();
89839
89840  // If the box is empty (this must be detected), then resizing is all
89841  // what is needed.  If it is not empty and we are removing _all_ the
89842  // dimensions then, again, resizing suffices.
89843  if (is_empty() || new_space_dim == 0) {
89844    seq.resize(new_space_dim);
89845    PPL_ASSERT(OK());
89846    return;
89847  }
89848
89849  // For each variable to be removed, we fill the corresponding interval
89850  // by shifting left those intervals that will not be removed.
89851  Variables_Set::const_iterator vsi = vars.begin();
89852  Variables_Set::const_iterator vsi_end = vars.end();
89853  dimension_type dst = *vsi;
89854  dimension_type src = dst + 1;
89855  for (++vsi; vsi != vsi_end; ++vsi) {
89856    const dimension_type vsi_next = *vsi;
89857    // All intervals in between are moved to the left.
89858    while (src < vsi_next) {
89859      swap(seq[dst++], seq[src++]);
89860    }
89861    ++src;
89862  }
89863
89864  // Moving the remaining intervals.
89865  while (src < old_space_dim) {
89866    swap(seq[dst++], seq[src++]);
89867  }
89868
89869  PPL_ASSERT(dst == new_space_dim);
89870  seq.resize(new_space_dim);
89871
89872  PPL_ASSERT(OK());
89873}
89874
89875template <typename ITV>
89876void
89877Box<ITV>::remove_higher_space_dimensions(const dimension_type new_dimension) {
89878  // Dimension-compatibility check: the variable having
89879  // maximum index is the one occurring last in the set.
89880  const dimension_type space_dim = space_dimension();
89881  if (new_dimension > space_dim) {
89882    throw_dimension_incompatible("remove_higher_space_dimensions(nd)",
89883                                 new_dimension);
89884  }
89885
89886  // The removal of no dimensions from any box is a no-op.
89887  // Note that this case also captures the only legal removal of
89888  // dimensions from a zero-dim space box.
89889  if (new_dimension == space_dim) {
89890    PPL_ASSERT(OK());
89891    return;
89892  }
89893
89894  seq.resize(new_dimension);
89895  PPL_ASSERT(OK());
89896}
89897
89898template <typename ITV>
89899template <typename Partial_Function>
89900void
89901Box<ITV>::map_space_dimensions(const Partial_Function& pfunc) {
89902  const dimension_type space_dim = space_dimension();
89903  if (space_dim == 0) {
89904    return;
89905  }
89906
89907  if (pfunc.has_empty_codomain()) {
89908    // All dimensions vanish: the box becomes zero_dimensional.
89909    remove_higher_space_dimensions(0);
89910    return;
89911  }
89912
89913  const dimension_type new_space_dim = pfunc.max_in_codomain() + 1;
89914  // If the box is empty, then simply adjust the space dimension.
89915  if (is_empty()) {
89916    remove_higher_space_dimensions(new_space_dim);
89917    return;
89918  }
89919
89920  // We create a new Box with the new space dimension.
89921  Box<ITV> tmp(new_space_dim);
89922  // Map the intervals, exchanging the indexes.
89923  for (dimension_type i = 0; i < space_dim; ++i) {
89924    dimension_type new_i;
89925    if (pfunc.maps(i, new_i)) {
89926      swap(seq[i], tmp.seq[new_i]);
89927    }
89928  }
89929  m_swap(tmp);
89930  PPL_ASSERT(OK());
89931}
89932
89933template <typename ITV>
89934void
89935Box<ITV>::fold_space_dimensions(const Variables_Set& vars,
89936                                const Variable dest) {
89937  const dimension_type space_dim = space_dimension();
89938  // `dest' should be one of the dimensions of the box.
89939  if (dest.space_dimension() > space_dim) {
89940    throw_dimension_incompatible("fold_space_dimensions(vs, v)", "v", dest);
89941  }
89942
89943  // The folding of no dimensions is a no-op.
89944  if (vars.empty()) {
89945    return;
89946  }
89947
89948  // All variables in `vars' should be dimensions of the box.
89949  if (vars.space_dimension() > space_dim) {
89950    throw_dimension_incompatible("fold_space_dimensions(vs, v)",
89951                                 vars.space_dimension());
89952  }
89953  // Moreover, `dest.id()' should not occur in `vars'.
89954  if (vars.find(dest.id()) != vars.end()) {
89955    throw_invalid_argument("fold_space_dimensions(vs, v)",
89956                           "v should not occur in vs");
89957  }
89958
89959  // Note: the check for emptiness is needed for correctness.
89960  if (!is_empty()) {
89961    // Join the interval corresponding to variable `dest' with the intervals
89962    // corresponding to the variables in `vars'.
89963    ITV& seq_v = seq[dest.id()];
89964    for (Variables_Set::const_iterator i = vars.begin(),
89965           vs_end = vars.end(); i != vs_end; ++i) {
89966      seq_v.join_assign(seq[*i]);
89967    }
89968  }
89969  remove_space_dimensions(vars);
89970}
89971
89972template <typename ITV>
89973void
89974Box<ITV>::add_constraint_no_check(const Constraint& c) {
89975  PPL_ASSERT(c.space_dimension() <= space_dimension());
89976
89977  dimension_type c_num_vars = 0;
89978  dimension_type c_only_var = 0;
89979  // Throw an exception if c is not an interval constraints.
89980  if (!Box_Helpers::extract_interval_constraint(c, c_num_vars, c_only_var)) {
89981    throw_invalid_argument("add_constraint(c)",
89982                           "c is not an interval constraint");
89983  }
89984
89985  // Throw an exception if c is a nontrivial strict constraint
89986  // and ITV does not support open boundaries.
89987  if (c.is_strict_inequality() && c_num_vars != 0
89988      && ITV::is_always_topologically_closed()) {
89989    throw_invalid_argument("add_constraint(c)",
89990                           "c is a nontrivial strict constraint");
89991  }
89992
89993  // Avoid doing useless work if the box is known to be empty.
89994  if (marked_empty()) {
89995    return;
89996  }
89997
89998  const Coefficient& n = c.inhomogeneous_term();
89999  if (c_num_vars == 0) {
90000    // Dealing with a trivial constraint.
90001    if (n < 0
90002        || (c.is_equality() && n != 0)
90003        || (c.is_strict_inequality() && n == 0)) {
90004      set_empty();
90005    }
90006    return;
90007  }
90008
90009  PPL_ASSERT(c_num_vars == 1);
90010  const Coefficient& d = c.coefficient(Variable(c_only_var));
90011  add_interval_constraint_no_check(c_only_var, c.type(), n, d);
90012}
90013
90014template <typename ITV>
90015void
90016Box<ITV>::add_constraints_no_check(const Constraint_System& cs) {
90017  PPL_ASSERT(cs.space_dimension() <= space_dimension());
90018  // Note: even when the box is known to be empty, we need to go
90019  // through all the constraints to fulfill the method's contract
90020  // for what concerns exception throwing.
90021  for (Constraint_System::const_iterator i = cs.begin(),
90022         cs_end = cs.end(); i != cs_end; ++i) {
90023    add_constraint_no_check(*i);
90024  }
90025  PPL_ASSERT(OK());
90026}
90027
90028template <typename ITV>
90029void
90030Box<ITV>::add_congruence_no_check(const Congruence& cg) {
90031  PPL_ASSERT(cg.space_dimension() <= space_dimension());
90032
90033  // Set aside the case of proper congruences.
90034  if (cg.is_proper_congruence()) {
90035    if (cg.is_inconsistent()) {
90036      set_empty();
90037      return;
90038    }
90039    else if (cg.is_tautological()) {
90040      return;
90041    }
90042    else {
90043      throw_invalid_argument("add_congruence(cg)",
90044                             "cg is a nontrivial proper congruence");
90045    }
90046  }
90047
90048  PPL_ASSERT(cg.is_equality());
90049  dimension_type cg_num_vars = 0;
90050  dimension_type cg_only_var = 0;
90051  // Throw an exception if c is not an interval congruence.
90052  if (!Box_Helpers::extract_interval_congruence(cg, cg_num_vars, cg_only_var)) {
90053    throw_invalid_argument("add_congruence(cg)",
90054                           "cg is not an interval congruence");
90055  }
90056
90057  // Avoid doing useless work if the box is known to be empty.
90058  if (marked_empty()) {
90059    return;
90060  }
90061
90062  const Coefficient& n = cg.inhomogeneous_term();
90063  if (cg_num_vars == 0) {
90064    // Dealing with a trivial equality congruence.
90065    if (n != 0) {
90066      set_empty();
90067    }
90068    return;
90069  }
90070
90071  PPL_ASSERT(cg_num_vars == 1);
90072  const Coefficient& d = cg.coefficient(Variable(cg_only_var));
90073  add_interval_constraint_no_check(cg_only_var, Constraint::EQUALITY, n, d);
90074}
90075
90076template <typename ITV>
90077void
90078Box<ITV>::add_congruences_no_check(const Congruence_System& cgs) {
90079  PPL_ASSERT(cgs.space_dimension() <= space_dimension());
90080  // Note: even when the box is known to be empty, we need to go
90081  // through all the congruences to fulfill the method's contract
90082  // for what concerns exception throwing.
90083  for (Congruence_System::const_iterator i = cgs.begin(),
90084         cgs_end = cgs.end(); i != cgs_end; ++i) {
90085    add_congruence_no_check(*i);
90086  }
90087  PPL_ASSERT(OK());
90088}
90089
90090template <typename ITV>
90091void
90092Box<ITV>::refine_no_check(const Constraint& c) {
90093  PPL_ASSERT(c.space_dimension() <= space_dimension());
90094  PPL_ASSERT(!marked_empty());
90095
90096  dimension_type c_num_vars = 0;
90097  dimension_type c_only_var = 0;
90098  // Non-interval constraints are approximated.
90099  if (!Box_Helpers::extract_interval_constraint(c, c_num_vars, c_only_var)) {
90100    propagate_constraint_no_check(c);
90101    return;
90102  }
90103
90104  const Coefficient& n = c.inhomogeneous_term();
90105  if (c_num_vars == 0) {
90106    // Dealing with a trivial constraint.
90107    if (n < 0
90108        || (c.is_equality() && n != 0)
90109        || (c.is_strict_inequality() && n == 0)) {
90110      set_empty();
90111    }
90112    return;
90113  }
90114
90115  PPL_ASSERT(c_num_vars == 1);
90116  const Coefficient& d = c.coefficient(Variable(c_only_var));
90117  add_interval_constraint_no_check(c_only_var, c.type(), n, d);
90118}
90119
90120template <typename ITV>
90121void
90122Box<ITV>::refine_no_check(const Constraint_System& cs) {
90123  PPL_ASSERT(cs.space_dimension() <= space_dimension());
90124  for (Constraint_System::const_iterator i = cs.begin(),
90125         cs_end = cs.end(); !marked_empty() && i != cs_end; ++i) {
90126    refine_no_check(*i);
90127  }
90128  PPL_ASSERT(OK());
90129}
90130
90131template <typename ITV>
90132void
90133Box<ITV>::refine_no_check(const Congruence& cg) {
90134  PPL_ASSERT(!marked_empty());
90135
90136  PPL_ASSERT(cg.space_dimension() <= space_dimension());
90137
90138  if (cg.is_proper_congruence()) {
90139    // A proper congruences is also an interval constraint
90140    // if and only if it is trivial.
90141    if (cg.is_inconsistent()) {
90142      set_empty();
90143    }
90144    return;
90145  }
90146
90147  PPL_ASSERT(cg.is_equality());
90148  Constraint c(cg);
90149  refine_no_check(c);
90150}
90151
90152template <typename ITV>
90153void
90154Box<ITV>::refine_no_check(const Congruence_System& cgs) {
90155  PPL_ASSERT(cgs.space_dimension() <= space_dimension());
90156  for (Congruence_System::const_iterator i = cgs.begin(),
90157         cgs_end = cgs.end(); !marked_empty() && i != cgs_end; ++i) {
90158    refine_no_check(*i);
90159  }
90160  PPL_ASSERT(OK());
90161}
90162
90163#if 1 // Alternative implementations for propagate_constraint_no_check.
90164namespace Implementation {
90165
90166namespace Boxes {
90167
90168inline bool
90169propagate_constraint_check_result(Result r, Ternary& open) {
90170  r = result_relation_class(r);
90171  switch (r) {
90172  case V_GT_MINUS_INFINITY:
90173  case V_LT_PLUS_INFINITY:
90174    return true;
90175  case V_LT:
90176  case V_GT:
90177    open = T_YES;
90178    return false;
90179  case V_LE:
90180  case V_GE:
90181    if (open == T_NO) {
90182      open = T_MAYBE;
90183    }
90184    return false;
90185  case V_EQ:
90186    return false;
90187  default:
90188    PPL_UNREACHABLE;
90189    return true;
90190  }
90191}
90192
90193} // namespace Boxes
90194
90195} // namespace Implementation
90196
90197
90198template <typename ITV>
90199void
90200Box<ITV>::propagate_constraint_no_check(const Constraint& c) {
90201  using namespace Implementation::Boxes;
90202
90203  PPL_ASSERT(c.space_dimension() <= space_dimension());
90204
90205  typedef
90206    typename Select_Temp_Boundary_Type<typename ITV::boundary_type>::type
90207    Temp_Boundary_Type;
90208
90209  const dimension_type c_space_dim = c.space_dimension();
90210  const Constraint::Type c_type = c.type();
90211  const Coefficient& c_inhomogeneous_term = c.inhomogeneous_term();
90212
90213  // Find a space dimension having a non-zero coefficient (if any).
90214  const dimension_type last_k
90215    = c.expression().last_nonzero(1, c_space_dim + 1);
90216  if (last_k == c_space_dim + 1) {
90217    // Constraint c is trivial: check if it is inconsistent.
90218    if (c_inhomogeneous_term < 0
90219        || (c_inhomogeneous_term == 0
90220            && c_type != Constraint::NONSTRICT_INEQUALITY)) {
90221      set_empty();
90222    }
90223    return;
90224  }
90225
90226  // Here constraint c is non-trivial.
90227  PPL_ASSERT(last_k <= c_space_dim);
90228  Temp_Boundary_Type t_bound;
90229  Temp_Boundary_Type t_a;
90230  Temp_Boundary_Type t_x;
90231  Ternary open;
90232  const Constraint::expr_type c_e = c.expression();
90233  for (Constraint::expr_type::const_iterator k = c_e.begin(),
90234         k_end = c_e.lower_bound(Variable(last_k)); k != k_end; ++k) {
90235    const Coefficient& a_k = *k;
90236    const Variable k_var = k.variable();
90237    const int sgn_a_k = sgn(a_k);
90238    if (sgn_a_k == 0) {
90239      continue;
90240    }
90241    Result r;
90242    if (sgn_a_k > 0) {
90243      open = (c_type == Constraint::STRICT_INEQUALITY) ? T_YES : T_NO;
90244      if (open == T_NO) {
90245        maybe_reset_fpu_inexact<Temp_Boundary_Type>();
90246      }
90247      r = assign_r(t_bound, c_inhomogeneous_term, ROUND_UP);
90248      if (propagate_constraint_check_result(r, open)) {
90249        goto maybe_refine_upper_1;
90250      }
90251      r = neg_assign_r(t_bound, t_bound, ROUND_DOWN);
90252      if (propagate_constraint_check_result(r, open)) {
90253        goto maybe_refine_upper_1;
90254      }
90255      for (Constraint::expr_type::const_iterator i = c_e.begin(),
90256            i_end = c_e.lower_bound(Variable(last_k)); i != i_end; ++i) {
90257        const Variable i_var = i.variable();
90258        if (i_var.id() == k_var.id()) {
90259          continue;
90260        }
90261        const Coefficient& a_i = *i;
90262        const int sgn_a_i = sgn(a_i);
90263        ITV& x_i = seq[i_var.id()];
90264        if (sgn_a_i < 0) {
90265          if (x_i.lower_is_boundary_infinity()) {
90266            goto maybe_refine_upper_1;
90267          }
90268          r = assign_r(t_a, a_i, ROUND_DOWN);
90269          if (propagate_constraint_check_result(r, open)) {
90270            goto maybe_refine_upper_1;
90271          }
90272          r = assign_r(t_x, x_i.lower(), ROUND_DOWN);
90273          if (propagate_constraint_check_result(r, open)) {
90274            goto maybe_refine_upper_1;
90275          }
90276          if (x_i.lower_is_open()) {
90277            open = T_YES;
90278          }
90279          r = sub_mul_assign_r(t_bound, t_a, t_x, ROUND_DOWN);
90280          if (propagate_constraint_check_result(r, open)) {
90281            goto maybe_refine_upper_1;
90282          }
90283        }
90284        else {
90285          PPL_ASSERT(sgn_a_i > 0);
90286          if (x_i.upper_is_boundary_infinity()) {
90287            goto maybe_refine_upper_1;
90288          }
90289          r = assign_r(t_a, a_i, ROUND_UP);
90290          if (propagate_constraint_check_result(r, open)) {
90291            goto maybe_refine_upper_1;
90292          }
90293          r = assign_r(t_x, x_i.upper(), ROUND_UP);
90294          if (propagate_constraint_check_result(r, open)) {
90295            goto maybe_refine_upper_1;
90296          }
90297          if (x_i.upper_is_open()) {
90298            open = T_YES;
90299          }
90300          r = sub_mul_assign_r(t_bound, t_a, t_x, ROUND_DOWN);
90301          if (propagate_constraint_check_result(r, open)) {
90302            goto maybe_refine_upper_1;
90303          }
90304        }
90305      }
90306      r = assign_r(t_a, a_k, ROUND_UP);
90307      if (propagate_constraint_check_result(r, open)) {
90308        goto maybe_refine_upper_1;
90309      }
90310      r = div_assign_r(t_bound, t_bound, t_a, ROUND_DOWN);
90311      if (propagate_constraint_check_result(r, open)) {
90312        goto maybe_refine_upper_1;
90313      }
90314
90315      // Refine the lower bound of `seq[k]' with `t_bound'.
90316      if (open == T_MAYBE
90317          && maybe_check_fpu_inexact<Temp_Boundary_Type>() == 1) {
90318        open = T_YES;
90319      }
90320      {
90321        const Relation_Symbol rel
90322          = (open == T_YES) ? GREATER_THAN : GREATER_OR_EQUAL;
90323        seq[k_var.id()].add_constraint(i_constraint(rel, t_bound));
90324      }
90325      reset_empty_up_to_date();
90326    maybe_refine_upper_1:
90327      if (c_type != Constraint::EQUALITY) {
90328        continue;
90329      }
90330      open = T_NO;
90331      maybe_reset_fpu_inexact<Temp_Boundary_Type>();
90332      r = assign_r(t_bound, c_inhomogeneous_term, ROUND_DOWN);
90333      if (propagate_constraint_check_result(r, open)) {
90334        goto next_k;
90335      }
90336      r = neg_assign_r(t_bound, t_bound, ROUND_UP);
90337      if (propagate_constraint_check_result(r, open)) {
90338        goto next_k;
90339      }
90340      for (Constraint::expr_type::const_iterator i = c_e.begin(),
90341            i_end = c_e.lower_bound(Variable(c_space_dim)); i != i_end; ++i) {
90342        const Variable i_var = i.variable();
90343        if (i_var.id() == k_var.id()) {
90344          continue;
90345        }
90346        const Coefficient& a_i = *i;
90347        const int sgn_a_i = sgn(a_i);
90348        ITV& x_i = seq[i_var.id()];
90349        if (sgn_a_i < 0) {
90350          if (x_i.upper_is_boundary_infinity()) {
90351            goto next_k;
90352          }
90353          r = assign_r(t_a, a_i, ROUND_UP);
90354          if (propagate_constraint_check_result(r, open)) {
90355            goto next_k;
90356          }
90357          r = assign_r(t_x, x_i.upper(), ROUND_UP);
90358          if (propagate_constraint_check_result(r, open)) {
90359            goto next_k;
90360          }
90361          if (x_i.upper_is_open()) {
90362            open = T_YES;
90363          }
90364          r = sub_mul_assign_r(t_bound, t_a, t_x, ROUND_UP);
90365          if (propagate_constraint_check_result(r, open)) {
90366            goto next_k;
90367          }
90368        }
90369        else {
90370          PPL_ASSERT(sgn_a_i > 0);
90371          if (x_i.lower_is_boundary_infinity()) {
90372            goto next_k;
90373          }
90374          r = assign_r(t_a, a_i, ROUND_DOWN);
90375          if (propagate_constraint_check_result(r, open)) {
90376            goto next_k;
90377          }
90378          r = assign_r(t_x, x_i.lower(), ROUND_DOWN);
90379          if (propagate_constraint_check_result(r, open)) {
90380            goto next_k;
90381          }
90382          if (x_i.lower_is_open()) {
90383            open = T_YES;
90384          }
90385          r = sub_mul_assign_r(t_bound, t_a, t_x, ROUND_UP);
90386          if (propagate_constraint_check_result(r, open)) {
90387            goto next_k;
90388          }
90389        }
90390      }
90391      r = assign_r(t_a, a_k, ROUND_DOWN);
90392      if (propagate_constraint_check_result(r, open)) {
90393        goto next_k;
90394      }
90395      r = div_assign_r(t_bound, t_bound, t_a, ROUND_UP);
90396      if (propagate_constraint_check_result(r, open)) {
90397        goto next_k;
90398      }
90399
90400      // Refine the upper bound of seq[k] with t_bound.
90401      if (open == T_MAYBE
90402          && maybe_check_fpu_inexact<Temp_Boundary_Type>() == 1) {
90403        open = T_YES;
90404      }
90405      const Relation_Symbol rel
90406        = (open == T_YES) ? LESS_THAN : LESS_OR_EQUAL;
90407      seq[k_var.id()].add_constraint(i_constraint(rel, t_bound));
90408      reset_empty_up_to_date();
90409    }
90410    else {
90411      PPL_ASSERT(sgn_a_k < 0);
90412      open = (c_type == Constraint::STRICT_INEQUALITY) ? T_YES : T_NO;
90413      if (open == T_NO) {
90414        maybe_reset_fpu_inexact<Temp_Boundary_Type>();
90415      }
90416      r = assign_r(t_bound, c_inhomogeneous_term, ROUND_UP);
90417      if (propagate_constraint_check_result(r, open)) {
90418        goto maybe_refine_upper_2;
90419      }
90420      r = neg_assign_r(t_bound, t_bound, ROUND_DOWN);
90421      if (propagate_constraint_check_result(r, open)) {
90422        goto maybe_refine_upper_2;
90423      }
90424      for (Constraint::expr_type::const_iterator i = c_e.begin(),
90425            i_end = c_e.lower_bound(Variable(c_space_dim)); i != i_end; ++i) {
90426        const Variable i_var = i.variable();
90427        if (i_var.id() == k_var.id()) {
90428          continue;
90429        }
90430        const Coefficient& a_i = *i;
90431        const int sgn_a_i = sgn(a_i);
90432        ITV& x_i = seq[i_var.id()];
90433        if (sgn_a_i < 0) {
90434          if (x_i.lower_is_boundary_infinity()) {
90435            goto maybe_refine_upper_2;
90436          }
90437          r = assign_r(t_a, a_i, ROUND_DOWN);
90438          if (propagate_constraint_check_result(r, open)) {
90439            goto maybe_refine_upper_2;
90440          }
90441          r = assign_r(t_x, x_i.lower(), ROUND_DOWN);
90442          if (propagate_constraint_check_result(r, open)) {
90443            goto maybe_refine_upper_2;
90444          }
90445          if (x_i.lower_is_open()) {
90446            open = T_YES;
90447          }
90448          r = sub_mul_assign_r(t_bound, t_a, t_x, ROUND_UP);
90449          if (propagate_constraint_check_result(r, open)) {
90450            goto maybe_refine_upper_2;
90451          }
90452        }
90453        else {
90454          PPL_ASSERT(sgn_a_i > 0);
90455          if (x_i.upper_is_boundary_infinity()) {
90456            goto maybe_refine_upper_2;
90457          }
90458          r = assign_r(t_a, a_i, ROUND_UP);
90459          if (propagate_constraint_check_result(r, open)) {
90460            goto maybe_refine_upper_2;
90461          }
90462          r = assign_r(t_x, x_i.upper(), ROUND_UP);
90463          if (propagate_constraint_check_result(r, open)) {
90464            goto maybe_refine_upper_2;
90465          }
90466          if (x_i.upper_is_open()) {
90467            open = T_YES;
90468          }
90469          r = sub_mul_assign_r(t_bound, t_a, t_x, ROUND_DOWN);
90470          if (propagate_constraint_check_result(r, open)) {
90471            goto maybe_refine_upper_2;
90472          }
90473        }
90474      }
90475      r = assign_r(t_a, a_k, ROUND_UP);
90476      if (propagate_constraint_check_result(r, open)) {
90477        goto maybe_refine_upper_2;
90478      }
90479      r = div_assign_r(t_bound, t_bound, t_a, ROUND_UP);
90480      if (propagate_constraint_check_result(r, open)) {
90481        goto maybe_refine_upper_2;
90482      }
90483      // Refine the upper bound of seq[k] with t_bound.
90484      if (open == T_MAYBE
90485          && maybe_check_fpu_inexact<Temp_Boundary_Type>() == 1) {
90486        open = T_YES;
90487      }
90488      {
90489        const Relation_Symbol rel
90490          = (open == T_YES) ? LESS_THAN : LESS_OR_EQUAL;
90491        seq[k_var.id()].add_constraint(i_constraint(rel, t_bound));
90492      }
90493      reset_empty_up_to_date();
90494    maybe_refine_upper_2:
90495      if (c_type != Constraint::EQUALITY) {
90496        continue;
90497      }
90498      open = T_NO;
90499      maybe_reset_fpu_inexact<Temp_Boundary_Type>();
90500      r = assign_r(t_bound, c_inhomogeneous_term, ROUND_DOWN);
90501      if (propagate_constraint_check_result(r, open)) {
90502        goto next_k;
90503      }
90504      r = neg_assign_r(t_bound, t_bound, ROUND_UP);
90505      if (propagate_constraint_check_result(r, open)) {
90506        goto next_k;
90507      }
90508      for (Constraint::expr_type::const_iterator i = c_e.begin(),
90509            i_end = c_e.lower_bound(Variable(c_space_dim)); i != i_end; ++i) {
90510        const Variable i_var = i.variable();
90511        if (i_var.id() == k_var.id()) {
90512          continue;
90513        }
90514        const Coefficient& a_i = *i;
90515        const int sgn_a_i = sgn(a_i);
90516        ITV& x_i = seq[i_var.id()];
90517        if (sgn_a_i < 0) {
90518          if (x_i.upper_is_boundary_infinity()) {
90519            goto next_k;
90520          }
90521          r = assign_r(t_a, a_i, ROUND_UP);
90522          if (propagate_constraint_check_result(r, open)) {
90523            goto next_k;
90524          }
90525          r = assign_r(t_x, x_i.upper(), ROUND_UP);
90526          if (propagate_constraint_check_result(r, open)) {
90527            goto next_k;
90528          }
90529          if (x_i.upper_is_open()) {
90530            open = T_YES;
90531          }
90532          r = sub_mul_assign_r(t_bound, t_a, t_x, ROUND_UP);
90533          if (propagate_constraint_check_result(r, open)) {
90534            goto next_k;
90535          }
90536        }
90537        else {
90538          PPL_ASSERT(sgn_a_i > 0);
90539          if (x_i.lower_is_boundary_infinity()) {
90540            goto next_k;
90541          }
90542          r = assign_r(t_a, a_i, ROUND_DOWN);
90543          if (propagate_constraint_check_result(r, open)) {
90544            goto next_k;
90545          }
90546          r = assign_r(t_x, x_i.lower(), ROUND_DOWN);
90547          if (propagate_constraint_check_result(r, open)) {
90548            goto next_k;
90549          }
90550          if (x_i.lower_is_open()) {
90551            open = T_YES;
90552          }
90553          r = sub_mul_assign_r(t_bound, t_a, t_x, ROUND_UP);
90554          if (propagate_constraint_check_result(r, open)) {
90555            goto next_k;
90556          }
90557        }
90558      }
90559      r = assign_r(t_a, a_k, ROUND_DOWN);
90560      if (propagate_constraint_check_result(r, open)) {
90561        goto next_k;
90562      }
90563      r = div_assign_r(t_bound, t_bound, t_a, ROUND_DOWN);
90564      if (propagate_constraint_check_result(r, open)) {
90565        goto next_k;
90566      }
90567
90568      // Refine the lower bound of seq[k] with t_bound.
90569      if (open == T_MAYBE
90570          && maybe_check_fpu_inexact<Temp_Boundary_Type>() == 1) {
90571        open = T_YES;
90572      }
90573      const Relation_Symbol rel
90574        = (open == T_YES) ? GREATER_THAN : GREATER_OR_EQUAL;
90575      seq[k_var.id()].add_constraint(i_constraint(rel, t_bound));
90576      reset_empty_up_to_date();
90577    }
90578  next_k:
90579    ;
90580  }
90581}
90582
90583#else // Alternative implementations for propagate_constraint_no_check.
90584
90585template <typename ITV>
90586void
90587Box<ITV>::propagate_constraint_no_check(const Constraint& c) {
90588  PPL_ASSERT(c.space_dimension() <= space_dimension());
90589
90590  dimension_type c_space_dim = c.space_dimension();
90591  ITV k[c_space_dim];
90592  ITV p[c_space_dim];
90593  for (Constraint::expr_type::const_iterator i = c_e.begin(),
90594        i_end = c_e.lower_bound(Variable(c_space_dim)); i != i_end; ++i) {
90595    const Variable i_var = i.variable();
90596    k[i_var.id()] = *i;
90597    ITV& p_i = p[i_var.id()];
90598    p_i = seq[i_var.id()];
90599    p_i.mul_assign(p_i, k[i_var.id()]);
90600  }
90601  const Coefficient& inhomogeneous_term = c.inhomogeneous_term();
90602  for (Constraint::expr_type::const_iterator i = c_e.begin(),
90603        i_end = c_e.lower_bound(Variable(c_space_dim)); i != i_end; ++i) {
90604    const Variable i_var = i.variable();
90605    int sgn_coefficient_i = sgn(*i);
90606    ITV q(inhomogeneous_term);
90607    for (Constraint::expr_type::const_iterator j = c_e.begin(),
90608          j_end = c_e.lower_bound(Variable(c_space_dim)); j != j_end; ++j) {
90609      const Variable j_var = j.variable();
90610      if (i_var == j_var) {
90611        continue;
90612      }
90613      q.add_assign(q, p[j_var.id()]);
90614    }
90615    q.div_assign(q, k[i_var.id()]);
90616    q.neg_assign(q);
90617    Relation_Symbol rel;
90618    switch (c.type()) {
90619    case Constraint::EQUALITY:
90620      rel = EQUAL;
90621      break;
90622    case Constraint::NONSTRICT_INEQUALITY:
90623      rel = (sgn_coefficient_i > 0) ? GREATER_OR_EQUAL : LESS_OR_EQUAL;
90624      break;
90625    case Constraint::STRICT_INEQUALITY:
90626      rel = (sgn_coefficient_i > 0) ? GREATER_THAN : LESS_THAN;
90627      break;
90628    }
90629    seq[i_var.id()].add_constraint(i_constraint(rel, q));
90630    // FIXME: could/should we exploit the return value of add_constraint
90631    //        in case it is available?
90632    // FIXME: should we instead be lazy and do not even bother about
90633    //        the possibility the interval becomes empty apart from setting
90634    //        empty_up_to_date = false?
90635    if (seq[i_var.id()].is_empty()) {
90636      set_empty();
90637      break;
90638    }
90639  }
90640
90641  PPL_ASSERT(OK());
90642}
90643
90644#endif // Alternative implementations for propagate_constraint_no_check.
90645
90646template <typename ITV>
90647void
90648Box<ITV>
90649::propagate_constraints_no_check(const Constraint_System& cs,
90650                                 const dimension_type max_iterations) {
90651  const dimension_type space_dim = space_dimension();
90652  PPL_ASSERT(cs.space_dimension() <= space_dim);
90653
90654  const Constraint_System::const_iterator cs_begin = cs.begin();
90655  const Constraint_System::const_iterator cs_end = cs.end();
90656  const dimension_type propagation_weight
90657    = Implementation::num_constraints(cs) * space_dim;
90658
90659  Sequence copy;
90660  bool changed;
90661  dimension_type num_iterations = 0;
90662  do {
90663    WEIGHT_BEGIN();
90664    ++num_iterations;
90665    copy = seq;
90666    for (Constraint_System::const_iterator i = cs_begin; i != cs_end; ++i) {
90667      propagate_constraint_no_check(*i);
90668    }
90669
90670    WEIGHT_ADD_MUL(40, propagation_weight);
90671    // Check if the client has requested abandoning all expensive
90672    // computations.  If so, the exception specified by the client
90673    // is thrown now.
90674    maybe_abandon();
90675
90676    // NOTE: if max_iterations == 0 (i.e., no iteration limit is set)
90677    // the following test will anyway trigger on wrap around.
90678    if (num_iterations == max_iterations) {
90679      break;
90680    }
90681
90682    changed = (copy != seq);
90683  } while (changed);
90684}
90685
90686template <typename ITV>
90687void
90688Box<ITV>::affine_image(const Variable var,
90689                       const Linear_Expression& expr,
90690                       Coefficient_traits::const_reference denominator) {
90691  // The denominator cannot be zero.
90692  if (denominator == 0) {
90693    throw_invalid_argument("affine_image(v, e, d)", "d == 0");
90694  }
90695
90696  // Dimension-compatibility checks.
90697  const dimension_type space_dim = space_dimension();
90698  const dimension_type expr_space_dim = expr.space_dimension();
90699  if (space_dim < expr_space_dim) {
90700    throw_dimension_incompatible("affine_image(v, e, d)", "e", expr);
90701  }
90702  // `var' should be one of the dimensions of the polyhedron.
90703  const dimension_type var_space_dim = var.space_dimension();
90704  if (space_dim < var_space_dim) {
90705    throw_dimension_incompatible("affine_image(v, e, d)", "v", var);
90706  }
90707
90708  if (is_empty()) {
90709    return;
90710  }
90711
90712  Tmp_Interval_Type expr_value;
90713  Tmp_Interval_Type temp0;
90714  Tmp_Interval_Type temp1;
90715  expr_value.assign(expr.inhomogeneous_term());
90716  for (Linear_Expression::const_iterator i = expr.begin(),
90717          i_end = expr.end(); i != i_end; ++i) {
90718    temp0.assign(*i);
90719    temp1.assign(seq[i.variable().id()]);
90720    temp0.mul_assign(temp0, temp1);
90721    expr_value.add_assign(expr_value, temp0);
90722  }
90723  if (denominator != 1) {
90724    temp0.assign(denominator);
90725    expr_value.div_assign(expr_value, temp0);
90726  }
90727  seq[var.id()].assign(expr_value);
90728
90729  PPL_ASSERT(OK());
90730}
90731
90732template <typename ITV>
90733void
90734Box<ITV>::affine_form_image(const Variable var,
90735                            const Linear_Form<ITV>& lf) {
90736
90737  // Check that ITV has a floating point boundary type.
90738  PPL_COMPILE_TIME_CHECK(!std::numeric_limits<typename ITV::boundary_type>
90739            ::is_exact, "Box<ITV>::affine_form_image(Variable, Linear_Form):"
90740                        "ITV has not a floating point boundary type.");
90741
90742  // Dimension-compatibility checks.
90743  const dimension_type space_dim = space_dimension();
90744  const dimension_type lf_space_dim = lf.space_dimension();
90745  if (space_dim < lf_space_dim) {
90746    throw_dimension_incompatible("affine_form_image(var, lf)", "lf", lf);
90747  }
90748
90749  // `var' should be one of the dimensions of the polyhedron.
90750  const dimension_type var_space_dim = var.space_dimension();
90751  if (space_dim < var_space_dim) {
90752    throw_dimension_incompatible("affine_form_image(var, lf)", "var", var);
90753  }
90754
90755  if (is_empty()) {
90756    return;
90757  }
90758
90759  // Intervalization of 'lf'.
90760  ITV result = lf.inhomogeneous_term();
90761  for (dimension_type i = 0; i < lf_space_dim; ++i) {
90762    ITV current_addend = lf.coefficient(Variable(i));
90763    const ITV& curr_int = seq[i];
90764    current_addend *= curr_int;
90765    result += current_addend;
90766  }
90767
90768  seq[var.id()].assign(result);
90769  PPL_ASSERT(OK());
90770}
90771
90772template <typename ITV>
90773void
90774Box<ITV>::affine_preimage(const Variable var,
90775                          const Linear_Expression& expr,
90776                          Coefficient_traits::const_reference
90777                          denominator) {
90778  // The denominator cannot be zero.
90779  if (denominator == 0) {
90780    throw_invalid_argument("affine_preimage(v, e, d)", "d == 0");
90781  }
90782
90783  // Dimension-compatibility checks.
90784  const dimension_type x_space_dim = space_dimension();
90785  const dimension_type expr_space_dim = expr.space_dimension();
90786  if (x_space_dim < expr_space_dim) {
90787    throw_dimension_incompatible("affine_preimage(v, e, d)", "e", expr);
90788  }
90789  // `var' should be one of the dimensions of the polyhedron.
90790  const dimension_type var_space_dim = var.space_dimension();
90791  if (x_space_dim < var_space_dim) {
90792    throw_dimension_incompatible("affine_preimage(v, e, d)", "v", var);
90793  }
90794
90795  if (is_empty()) {
90796    return;
90797  }
90798
90799  const Coefficient& expr_v = expr.coefficient(var);
90800  const bool invertible = (expr_v != 0);
90801  if (!invertible) {
90802    Tmp_Interval_Type expr_value;
90803    Tmp_Interval_Type temp0;
90804    Tmp_Interval_Type temp1;
90805    expr_value.assign(expr.inhomogeneous_term());
90806    for (Linear_Expression::const_iterator i = expr.begin(),
90807            i_end = expr.end(); i != i_end; ++i) {
90808      temp0.assign(*i);
90809      temp1.assign(seq[i.variable().id()]);
90810      temp0.mul_assign(temp0, temp1);
90811      expr_value.add_assign(expr_value, temp0);
90812    }
90813    if (denominator != 1) {
90814      temp0.assign(denominator);
90815      expr_value.div_assign(expr_value, temp0);
90816    }
90817    ITV& x_seq_v = seq[var.id()];
90818    expr_value.intersect_assign(x_seq_v);
90819    if (expr_value.is_empty()) {
90820      set_empty();
90821    }
90822    else {
90823      x_seq_v.assign(UNIVERSE);
90824    }
90825  }
90826  else {
90827    // The affine transformation is invertible.
90828    // CHECKME: for efficiency, would it be meaningful to avoid
90829    // the computation of inverse by partially evaluating the call
90830    // to affine_image?
90831    Linear_Expression inverse;
90832    inverse -= expr;
90833    inverse += (expr_v + denominator) * var;
90834    affine_image(var, inverse, expr_v);
90835  }
90836  PPL_ASSERT(OK());
90837}
90838
90839template <typename ITV>
90840void
90841Box<ITV>
90842::bounded_affine_image(const Variable var,
90843                       const Linear_Expression& lb_expr,
90844                       const Linear_Expression& ub_expr,
90845                       Coefficient_traits::const_reference denominator) {
90846  // The denominator cannot be zero.
90847  if (denominator == 0) {
90848    throw_invalid_argument("bounded_affine_image(v, lb, ub, d)", "d == 0");
90849  }
90850
90851  // Dimension-compatibility checks.
90852  const dimension_type space_dim = space_dimension();
90853  // The dimension of `lb_expr' and `ub_expr' should not be
90854  // greater than the dimension of `*this'.
90855  const dimension_type lb_space_dim = lb_expr.space_dimension();
90856  if (space_dim < lb_space_dim) {
90857    throw_dimension_incompatible("bounded_affine_image(v, lb, ub, d)",
90858                                 "lb", lb_expr);
90859  }
90860  const dimension_type ub_space_dim = ub_expr.space_dimension();
90861  if (space_dim < ub_space_dim) {
90862    throw_dimension_incompatible("bounded_affine_image(v, lb, ub, d)",
90863                                 "ub", ub_expr);
90864  }
90865    // `var' should be one of the dimensions of the box.
90866  const dimension_type var_space_dim = var.space_dimension();
90867  if (space_dim < var_space_dim) {
90868    throw_dimension_incompatible("affine_image(v, e, d)", "v", var);
90869  }
90870  // Any image of an empty box is empty.
90871  if (is_empty()) {
90872    return;
90873  }
90874  // Add the constraint implied by the `lb_expr' and `ub_expr'.
90875  if (denominator > 0) {
90876    refine_with_constraint(lb_expr <= ub_expr);
90877  }
90878  else {
90879    refine_with_constraint(lb_expr >= ub_expr);
90880  }
90881
90882  // Check whether `var' occurs in `lb_expr' and/or `ub_expr'.
90883  if (lb_expr.coefficient(var) == 0) {
90884    // Here `var' can only occur in `ub_expr'.
90885    generalized_affine_image(var,
90886                             LESS_OR_EQUAL,
90887                             ub_expr,
90888                             denominator);
90889    if (denominator > 0) {
90890      refine_with_constraint(lb_expr <= denominator*var);
90891    }
90892    else {
90893      refine_with_constraint(denominator*var <= lb_expr);
90894    }
90895  }
90896  else if (ub_expr.coefficient(var) == 0) {
90897    // Here `var' can only occur in `lb_expr'.
90898    generalized_affine_image(var,
90899                             GREATER_OR_EQUAL,
90900                             lb_expr,
90901                             denominator);
90902    if (denominator > 0) {
90903      refine_with_constraint(denominator*var <= ub_expr);
90904    }
90905    else {
90906      refine_with_constraint(ub_expr <= denominator*var);
90907    }
90908  }
90909  else {
90910    // Here `var' occurs in both `lb_expr' and `ub_expr'.  As boxes
90911    // can only use the non-relational constraints, we find the
90912    // maximum/minimum values `ub_expr' and `lb_expr' obtain with the
90913    // box and use these instead of the `ub-expr' and `lb-expr'.
90914    PPL_DIRTY_TEMP_COEFFICIENT(max_numer);
90915    PPL_DIRTY_TEMP_COEFFICIENT(max_denom);
90916    bool max_included;
90917    PPL_DIRTY_TEMP_COEFFICIENT(min_numer);
90918    PPL_DIRTY_TEMP_COEFFICIENT(min_denom);
90919    bool min_included;
90920    ITV& seq_v = seq[var.id()];
90921    if (maximize(ub_expr, max_numer, max_denom, max_included)) {
90922      if (minimize(lb_expr, min_numer, min_denom, min_included)) {
90923        // The `ub_expr' has a maximum value and the `lb_expr'
90924        // has a minimum value for the box.
90925        // Set the bounds for `var' using the minimum for `lb_expr'.
90926        min_denom *= denominator;
90927        PPL_DIRTY_TEMP(mpq_class, q1);
90928        PPL_DIRTY_TEMP(mpq_class, q2);
90929        assign_r(q1.get_num(), min_numer, ROUND_NOT_NEEDED);
90930        assign_r(q1.get_den(), min_denom, ROUND_NOT_NEEDED);
90931        q1.canonicalize();
90932        // Now make the maximum of lb_expr the upper bound.  If the
90933        // maximum is not at a box point, then inequality is strict.
90934        max_denom *= denominator;
90935        assign_r(q2.get_num(), max_numer, ROUND_NOT_NEEDED);
90936        assign_r(q2.get_den(), max_denom, ROUND_NOT_NEEDED);
90937        q2.canonicalize();
90938
90939        if (denominator > 0) {
90940          Relation_Symbol gr = min_included ? GREATER_OR_EQUAL : GREATER_THAN;
90941          Relation_Symbol lr = max_included ? LESS_OR_EQUAL : LESS_THAN;
90942          seq_v.build(i_constraint(gr, q1), i_constraint(lr, q2));
90943        }
90944        else {
90945          Relation_Symbol gr = max_included ? GREATER_OR_EQUAL : GREATER_THAN;
90946          Relation_Symbol lr = min_included ? LESS_OR_EQUAL : LESS_THAN;
90947          seq_v.build(i_constraint(gr, q2), i_constraint(lr, q1));
90948        }
90949      }
90950      else {
90951        // The `ub_expr' has a maximum value but the `lb_expr'
90952        // has no minimum value for the box.
90953        // Set the bounds for `var' using the maximum for `lb_expr'.
90954        PPL_DIRTY_TEMP(mpq_class, q);
90955        max_denom *= denominator;
90956        assign_r(q.get_num(), max_numer, ROUND_NOT_NEEDED);
90957        assign_r(q.get_den(), max_denom, ROUND_NOT_NEEDED);
90958        q.canonicalize();
90959        Relation_Symbol rel = (denominator > 0)
90960          ? (max_included ? LESS_OR_EQUAL : LESS_THAN)
90961          : (max_included ? GREATER_OR_EQUAL : GREATER_THAN);
90962        seq_v.build(i_constraint(rel, q));
90963      }
90964    }
90965    else if (minimize(lb_expr, min_numer, min_denom, min_included)) {
90966        // The `ub_expr' has no maximum value but the `lb_expr'
90967        // has a minimum value for the box.
90968        // Set the bounds for `var' using the minimum for `lb_expr'.
90969        min_denom *= denominator;
90970        PPL_DIRTY_TEMP(mpq_class, q);
90971        assign_r(q.get_num(), min_numer, ROUND_NOT_NEEDED);
90972        assign_r(q.get_den(), min_denom, ROUND_NOT_NEEDED);
90973        q.canonicalize();
90974
90975        Relation_Symbol rel = (denominator > 0)
90976          ? (min_included ? GREATER_OR_EQUAL : GREATER_THAN)
90977          : (min_included ? LESS_OR_EQUAL : LESS_THAN);
90978        seq_v.build(i_constraint(rel, q));
90979    }
90980    else {
90981      // The `ub_expr' has no maximum value and the `lb_expr'
90982      // has no minimum value for the box.
90983      // So we set the bounds to be unbounded.
90984      seq_v.assign(UNIVERSE);
90985    }
90986  }
90987  PPL_ASSERT(OK());
90988}
90989
90990template <typename ITV>
90991void
90992Box<ITV>
90993::bounded_affine_preimage(const Variable var,
90994                          const Linear_Expression& lb_expr,
90995                          const Linear_Expression& ub_expr,
90996                          Coefficient_traits::const_reference denominator) {
90997  // The denominator cannot be zero.
90998  const dimension_type space_dim = space_dimension();
90999  if (denominator == 0) {
91000    throw_invalid_argument("bounded_affine_preimage(v, lb, ub, d)", "d == 0");
91001  }
91002
91003  // Dimension-compatibility checks.
91004  // `var' should be one of the dimensions of the polyhedron.
91005  const dimension_type var_space_dim = var.space_dimension();
91006  if (space_dim < var_space_dim) {
91007    throw_dimension_incompatible("bounded_affine_preimage(v, lb, ub, d)",
91008                                 "v", var);
91009  }
91010  // The dimension of `lb_expr' and `ub_expr' should not be
91011  // greater than the dimension of `*this'.
91012  const dimension_type lb_space_dim = lb_expr.space_dimension();
91013  if (space_dim < lb_space_dim) {
91014    throw_dimension_incompatible("bounded_affine_preimage(v, lb, ub, d)",
91015                                 "lb", lb_expr);
91016  }
91017  const dimension_type ub_space_dim = ub_expr.space_dimension();
91018  if (space_dim < ub_space_dim) {
91019    throw_dimension_incompatible("bounded_affine_preimage(v, lb, ub, d)",
91020                                 "ub", ub_expr);
91021  }
91022
91023  // Any preimage of an empty polyhedron is empty.
91024  if (marked_empty()) {
91025    return;
91026  }
91027
91028  const bool negative_denom = (denominator < 0);
91029  const Coefficient& lb_var_coeff = lb_expr.coefficient(var);
91030  const Coefficient& ub_var_coeff = ub_expr.coefficient(var);
91031
91032  // If the implied constraint between `ub_expr and `lb_expr' is
91033  // independent of `var', then impose it now.
91034  if (lb_var_coeff == ub_var_coeff) {
91035    if (negative_denom) {
91036      refine_with_constraint(lb_expr >= ub_expr);
91037    }
91038    else {
91039      refine_with_constraint(lb_expr <= ub_expr);
91040    }
91041  }
91042
91043  ITV& seq_var = seq[var.id()];
91044  if (!seq_var.is_universe()) {
91045    // We want to work with a positive denominator,
91046    // so the sign and its (unsigned) value are separated.
91047    PPL_DIRTY_TEMP_COEFFICIENT(pos_denominator);
91048    pos_denominator = denominator;
91049    if (negative_denom) {
91050      neg_assign(pos_denominator, pos_denominator);
91051    }
91052    // Store all the information about the upper and lower bounds
91053    // for `var' before making this interval unbounded.
91054    bool open_lower = seq_var.lower_is_open();
91055    bool unbounded_lower = seq_var.lower_is_boundary_infinity();
91056    PPL_DIRTY_TEMP(mpq_class, q_seq_var_lower);
91057    PPL_DIRTY_TEMP_COEFFICIENT(numer_lower);
91058    PPL_DIRTY_TEMP_COEFFICIENT(denom_lower);
91059    if (!unbounded_lower) {
91060      assign_r(q_seq_var_lower, seq_var.lower(), ROUND_NOT_NEEDED);
91061      assign_r(numer_lower, q_seq_var_lower.get_num(), ROUND_NOT_NEEDED);
91062      assign_r(denom_lower, q_seq_var_lower.get_den(), ROUND_NOT_NEEDED);
91063      if (negative_denom) {
91064        neg_assign(denom_lower, denom_lower);
91065      }
91066      numer_lower *= pos_denominator;
91067      seq_var.lower_extend();
91068    }
91069    bool open_upper = seq_var.upper_is_open();
91070    bool unbounded_upper = seq_var.upper_is_boundary_infinity();
91071    PPL_DIRTY_TEMP(mpq_class, q_seq_var_upper);
91072    PPL_DIRTY_TEMP_COEFFICIENT(numer_upper);
91073    PPL_DIRTY_TEMP_COEFFICIENT(denom_upper);
91074    if (!unbounded_upper) {
91075      assign_r(q_seq_var_upper, seq_var.upper(), ROUND_NOT_NEEDED);
91076      assign_r(numer_upper, q_seq_var_upper.get_num(), ROUND_NOT_NEEDED);
91077      assign_r(denom_upper, q_seq_var_upper.get_den(), ROUND_NOT_NEEDED);
91078      if (negative_denom) {
91079        neg_assign(denom_upper, denom_upper);
91080      }
91081      numer_upper *= pos_denominator;
91082      seq_var.upper_extend();
91083    }
91084
91085    if (!unbounded_lower) {
91086      // `lb_expr' is revised by removing the `var' component,
91087      // multiplying by `-' denominator of the lower bound for `var',
91088      // and adding the lower bound for `var' to the inhomogeneous term.
91089      Linear_Expression revised_lb_expr(ub_expr);
91090      revised_lb_expr -= ub_var_coeff * var;
91091      PPL_DIRTY_TEMP_COEFFICIENT(d);
91092      neg_assign(d, denom_lower);
91093      revised_lb_expr *= d;
91094      revised_lb_expr += numer_lower;
91095
91096      // Find the minimum value for the revised lower bound expression
91097      // and use this to refine the appropriate bound.
91098      bool included;
91099      PPL_DIRTY_TEMP_COEFFICIENT(denom);
91100      if (minimize(revised_lb_expr, numer_lower, denom, included)) {
91101        denom_lower *= (denom * ub_var_coeff);
91102        PPL_DIRTY_TEMP(mpq_class, q);
91103        assign_r(q.get_num(), numer_lower, ROUND_NOT_NEEDED);
91104        assign_r(q.get_den(), denom_lower, ROUND_NOT_NEEDED);
91105        q.canonicalize();
91106        if (!included) {
91107          open_lower = true;
91108        }
91109        Relation_Symbol rel;
91110        if ((ub_var_coeff >= 0) ? !negative_denom : negative_denom) {
91111          rel = open_lower ? GREATER_THAN : GREATER_OR_EQUAL;
91112        }
91113        else {
91114          rel = open_lower ? LESS_THAN : LESS_OR_EQUAL;
91115        }
91116        seq_var.add_constraint(i_constraint(rel, q));
91117        if (seq_var.is_empty()) {
91118          set_empty();
91119          return;
91120        }
91121      }
91122    }
91123
91124    if (!unbounded_upper) {
91125      // `ub_expr' is revised by removing the `var' component,
91126      // multiplying by `-' denominator of the upper bound for `var',
91127      // and adding the upper bound for `var' to the inhomogeneous term.
91128      Linear_Expression revised_ub_expr(lb_expr);
91129      revised_ub_expr -= lb_var_coeff * var;
91130      PPL_DIRTY_TEMP_COEFFICIENT(d);
91131      neg_assign(d, denom_upper);
91132      revised_ub_expr *= d;
91133      revised_ub_expr += numer_upper;
91134
91135      // Find the maximum value for the revised upper bound expression
91136      // and use this to refine the appropriate bound.
91137      bool included;
91138      PPL_DIRTY_TEMP_COEFFICIENT(denom);
91139      if (maximize(revised_ub_expr, numer_upper, denom, included)) {
91140        denom_upper *= (denom * lb_var_coeff);
91141        PPL_DIRTY_TEMP(mpq_class, q);
91142        assign_r(q.get_num(), numer_upper, ROUND_NOT_NEEDED);
91143        assign_r(q.get_den(), denom_upper, ROUND_NOT_NEEDED);
91144        q.canonicalize();
91145        if (!included) {
91146          open_upper = true;
91147        }
91148        Relation_Symbol rel;
91149        if ((lb_var_coeff >= 0) ? !negative_denom : negative_denom) {
91150          rel = open_upper ? LESS_THAN : LESS_OR_EQUAL;
91151        }
91152        else {
91153          rel = open_upper ? GREATER_THAN : GREATER_OR_EQUAL;
91154        }
91155        seq_var.add_constraint(i_constraint(rel, q));
91156        if (seq_var.is_empty()) {
91157          set_empty();
91158          return;
91159        }
91160      }
91161    }
91162  }
91163
91164  // If the implied constraint between `ub_expr and `lb_expr' is
91165  // dependent on `var', then impose on the new box.
91166  if (lb_var_coeff != ub_var_coeff) {
91167    if (denominator > 0) {
91168      refine_with_constraint(lb_expr <= ub_expr);
91169    }
91170    else {
91171      refine_with_constraint(lb_expr >= ub_expr);
91172    }
91173  }
91174
91175  PPL_ASSERT(OK());
91176}
91177
91178template <typename ITV>
91179void
91180Box<ITV>
91181::generalized_affine_image(const Variable var,
91182                           const Relation_Symbol relsym,
91183                           const Linear_Expression& expr,
91184                           Coefficient_traits::const_reference denominator) {
91185  // The denominator cannot be zero.
91186  if (denominator == 0) {
91187    throw_invalid_argument("generalized_affine_image(v, r, e, d)", "d == 0");
91188  }
91189
91190  // Dimension-compatibility checks.
91191  const dimension_type space_dim = space_dimension();
91192  // The dimension of `expr' should not be greater than the dimension
91193  // of `*this'.
91194  if (space_dim < expr.space_dimension()) {
91195    throw_dimension_incompatible("generalized_affine_image(v, r, e, d)",
91196                                 "e", expr);
91197  }
91198  // `var' should be one of the dimensions of the box.
91199  const dimension_type var_space_dim = var.space_dimension();
91200  if (space_dim < var_space_dim) {
91201    throw_dimension_incompatible("generalized_affine_image(v, r, e, d)",
91202                                 "v", var);
91203  }
91204
91205  // The relation symbol cannot be a disequality.
91206  if (relsym == NOT_EQUAL) {
91207    throw_invalid_argument("generalized_affine_image(v, r, e, d)",
91208                           "r is the disequality relation symbol");
91209  }
91210
91211  // First compute the affine image.
91212  affine_image(var, expr, denominator);
91213
91214  if (relsym == EQUAL) {
91215    // The affine relation is indeed an affine function.
91216    return;
91217  }
91218  // Any image of an empty box is empty.
91219  if (is_empty()) {
91220    return;
91221  }
91222
91223  ITV& seq_var = seq[var.id()];
91224  switch (relsym) {
91225  case LESS_OR_EQUAL:
91226    seq_var.lower_extend();
91227    break;
91228  case LESS_THAN:
91229    seq_var.lower_extend();
91230    if (!seq_var.upper_is_boundary_infinity()) {
91231      seq_var.remove_sup();
91232    }
91233    break;
91234  case GREATER_OR_EQUAL:
91235    seq_var.upper_extend();
91236    break;
91237  case GREATER_THAN:
91238    seq_var.upper_extend();
91239    if (!seq_var.lower_is_boundary_infinity()) {
91240      seq_var.remove_inf();
91241    }
91242    break;
91243  default:
91244    // The EQUAL and NOT_EQUAL cases have been already dealt with.
91245    PPL_UNREACHABLE;
91246    break;
91247  }
91248  PPL_ASSERT(OK());
91249}
91250
91251template <typename ITV>
91252void
91253Box<ITV>
91254::generalized_affine_preimage(const Variable var,
91255                              const Relation_Symbol relsym,
91256                              const Linear_Expression& expr,
91257                              Coefficient_traits::const_reference denominator)
91258{
91259  // The denominator cannot be zero.
91260  if (denominator == 0) {
91261    throw_invalid_argument("generalized_affine_preimage(v, r, e, d)",
91262                           "d == 0");
91263  }
91264  // Dimension-compatibility checks.
91265  const dimension_type space_dim = space_dimension();
91266  // The dimension of `expr' should not be greater than the dimension
91267  // of `*this'.
91268  if (space_dim < expr.space_dimension()) {
91269    throw_dimension_incompatible("generalized_affine_preimage(v, r, e, d)",
91270                                 "e", expr);
91271  }
91272  // `var' should be one of the dimensions of the box.
91273  const dimension_type var_space_dim = var.space_dimension();
91274  if (space_dim < var_space_dim) {
91275    throw_dimension_incompatible("generalized_affine_preimage(v, r, e, d)",
91276                                 "v", var);
91277  }
91278  // The relation symbol cannot be a disequality.
91279  if (relsym == NOT_EQUAL) {
91280    throw_invalid_argument("generalized_affine_preimage(v, r, e, d)",
91281                           "r is the disequality relation symbol");
91282  }
91283
91284  // Check whether the affine relation is indeed an affine function.
91285  if (relsym == EQUAL) {
91286    affine_preimage(var, expr, denominator);
91287    return;
91288  }
91289
91290  // Compute the reversed relation symbol to simplify later coding.
91291  Relation_Symbol reversed_relsym;
91292  switch (relsym) {
91293  case LESS_THAN:
91294    reversed_relsym = GREATER_THAN;
91295    break;
91296  case LESS_OR_EQUAL:
91297    reversed_relsym = GREATER_OR_EQUAL;
91298    break;
91299  case GREATER_OR_EQUAL:
91300    reversed_relsym = LESS_OR_EQUAL;
91301    break;
91302  case GREATER_THAN:
91303    reversed_relsym = LESS_THAN;
91304    break;
91305  default:
91306    // The EQUAL and NOT_EQUAL cases have been already dealt with.
91307    PPL_UNREACHABLE;
91308    break;
91309  }
91310
91311  // Check whether the preimage of this affine relation can be easily
91312  // computed as the image of its inverse relation.
91313  const Coefficient& var_coefficient = expr.coefficient(var);
91314  if (var_coefficient != 0) {
91315    Linear_Expression inverse_expr
91316      = expr - (denominator + var_coefficient) * var;
91317    PPL_DIRTY_TEMP_COEFFICIENT(inverse_denominator);
91318    neg_assign(inverse_denominator, var_coefficient);
91319    Relation_Symbol inverse_relsym
91320      = (sgn(denominator) == sgn(inverse_denominator))
91321      ? relsym
91322      : reversed_relsym;
91323    generalized_affine_image(var, inverse_relsym, inverse_expr,
91324                             inverse_denominator);
91325    return;
91326  }
91327
91328  // Here `var_coefficient == 0', so that the preimage cannot
91329  // be easily computed by inverting the affine relation.
91330  // Shrink the box by adding the constraint induced
91331  // by the affine relation.
91332  // First, compute the maximum and minimum value reached by
91333  // `denominator*var' on the box as we need to use non-relational
91334  // expressions.
91335  PPL_DIRTY_TEMP_COEFFICIENT(max_numer);
91336  PPL_DIRTY_TEMP_COEFFICIENT(max_denom);
91337  bool max_included;
91338  bool bound_above = maximize(denominator*var, max_numer, max_denom, max_included);
91339  PPL_DIRTY_TEMP_COEFFICIENT(min_numer);
91340  PPL_DIRTY_TEMP_COEFFICIENT(min_denom);
91341  bool min_included;
91342  bool bound_below = minimize(denominator*var, min_numer, min_denom, min_included);
91343  // Use the correct relation symbol
91344  const Relation_Symbol corrected_relsym
91345    = (denominator > 0) ? relsym : reversed_relsym;
91346  // Revise the expression to take into account the denominator of the
91347  // maximum/minimum value for `var'.
91348  Linear_Expression revised_expr;
91349  PPL_DIRTY_TEMP_COEFFICIENT(d);
91350  if (corrected_relsym == LESS_THAN || corrected_relsym == LESS_OR_EQUAL) {
91351    if (bound_below) {
91352      revised_expr = expr;
91353      revised_expr.set_inhomogeneous_term(Coefficient_zero());
91354      revised_expr *= d;
91355    }
91356  }
91357  else {
91358    if (bound_above) {
91359      revised_expr = expr;
91360      revised_expr.set_inhomogeneous_term(Coefficient_zero());
91361      revised_expr *= max_denom;
91362    }
91363  }
91364
91365  switch (corrected_relsym) {
91366  case LESS_THAN:
91367    if (bound_below) {
91368      refine_with_constraint(min_numer < revised_expr);
91369    }
91370    break;
91371  case LESS_OR_EQUAL:
91372    if (bound_below) {
91373      (min_included)
91374        ? refine_with_constraint(min_numer <= revised_expr)
91375        : refine_with_constraint(min_numer < revised_expr);
91376    }
91377    break;
91378  case GREATER_OR_EQUAL:
91379    if (bound_above) {
91380      (max_included)
91381        ? refine_with_constraint(max_numer >= revised_expr)
91382        : refine_with_constraint(max_numer > revised_expr);
91383    }
91384    break;
91385  case GREATER_THAN:
91386    if (bound_above) {
91387      refine_with_constraint(max_numer > revised_expr);
91388    }
91389    break;
91390  default:
91391    // The EQUAL and NOT_EQUAL cases have been already dealt with.
91392    PPL_UNREACHABLE;
91393    break;
91394  }
91395  // If the shrunk box is empty, its preimage is empty too.
91396  if (is_empty()) {
91397    return;
91398  }
91399  ITV& seq_v = seq[var.id()];
91400  seq_v.assign(UNIVERSE);
91401  PPL_ASSERT(OK());
91402}
91403
91404template <typename ITV>
91405void
91406Box<ITV>
91407::generalized_affine_image(const Linear_Expression& lhs,
91408                           const Relation_Symbol relsym,
91409                           const Linear_Expression& rhs) {
91410  // Dimension-compatibility checks.
91411  // The dimension of `lhs' should not be greater than the dimension
91412  // of `*this'.
91413  dimension_type lhs_space_dim = lhs.space_dimension();
91414  const dimension_type space_dim = space_dimension();
91415  if (space_dim < lhs_space_dim) {
91416    throw_dimension_incompatible("generalized_affine_image(e1, r, e2)",
91417                                 "e1", lhs);
91418  }
91419  // The dimension of `rhs' should not be greater than the dimension
91420  // of `*this'.
91421  const dimension_type rhs_space_dim = rhs.space_dimension();
91422  if (space_dim < rhs_space_dim) {
91423    throw_dimension_incompatible("generalized_affine_image(e1, r, e2)",
91424                                 "e2", rhs);
91425  }
91426
91427  // The relation symbol cannot be a disequality.
91428  if (relsym == NOT_EQUAL) {
91429    throw_invalid_argument("generalized_affine_image(e1, r, e2)",
91430                           "r is the disequality relation symbol");
91431  }
91432
91433  // Any image of an empty box is empty.
91434  if (marked_empty()) {
91435    return;
91436  }
91437
91438  // Compute the maximum and minimum value reached by the rhs on the box.
91439  PPL_DIRTY_TEMP_COEFFICIENT(max_numer);
91440  PPL_DIRTY_TEMP_COEFFICIENT(max_denom);
91441  bool max_included;
91442  bool max_rhs = maximize(rhs, max_numer, max_denom, max_included);
91443  PPL_DIRTY_TEMP_COEFFICIENT(min_numer);
91444  PPL_DIRTY_TEMP_COEFFICIENT(min_denom);
91445  bool min_included;
91446  bool min_rhs = minimize(rhs, min_numer, min_denom, min_included);
91447
91448  // Check whether there is 0, 1 or more than one variable in the lhs
91449  // and record the variable with the highest dimension; set the box
91450  // intervals to be unbounded for all other dimensions with non-zero
91451  // coefficients in the lhs.
91452  bool has_var = false;
91453  dimension_type has_var_id = lhs.last_nonzero();
91454
91455  if (has_var_id != 0) {
91456    has_var = true;
91457    --has_var_id;
91458    dimension_type other_var = lhs.first_nonzero(1, has_var_id + 1);
91459    --other_var;
91460    if (other_var != has_var_id) {
91461      // There is more than one dimension with non-zero coefficient, so
91462      // we cannot have any information about the dimensions in the lhs.
91463      ITV& seq_var = seq[has_var_id];
91464      seq_var.assign(UNIVERSE);
91465      // Since all but the highest dimension with non-zero coefficient
91466      // in the lhs have been set unbounded, it remains to set the
91467      // highest dimension in the lhs unbounded.
91468      ITV& seq_i = seq[other_var];
91469      seq_i.assign(UNIVERSE);
91470      PPL_ASSERT(OK());
91471      return;
91472    }
91473  }
91474
91475  if (has_var) {
91476    // There is exactly one dimension with non-zero coefficient.
91477    ITV& seq_var = seq[has_var_id];
91478
91479    // Compute the new bounds for this dimension defined by the rhs
91480    // expression.
91481    const Coefficient& inhomo = lhs.inhomogeneous_term();
91482    const Coefficient& coeff = lhs.coefficient(Variable(has_var_id));
91483    PPL_DIRTY_TEMP(mpq_class, q_max);
91484    PPL_DIRTY_TEMP(mpq_class, q_min);
91485    if (max_rhs) {
91486      max_numer -= inhomo * max_denom;
91487      max_denom *= coeff;
91488      assign_r(q_max.get_num(), max_numer, ROUND_NOT_NEEDED);
91489      assign_r(q_max.get_den(), max_denom, ROUND_NOT_NEEDED);
91490      q_max.canonicalize();
91491    }
91492    if (min_rhs) {
91493      min_numer -= inhomo * min_denom;
91494      min_denom *= coeff;
91495      assign_r(q_min.get_num(), min_numer, ROUND_NOT_NEEDED);
91496      assign_r(q_min.get_den(), min_denom, ROUND_NOT_NEEDED);
91497      q_min.canonicalize();
91498    }
91499
91500    // The choice as to which bounds should be set depends on the sign
91501    // of the coefficient of the dimension `has_var_id' in the lhs.
91502    if (coeff > 0) {
91503      // The coefficient of the dimension in the lhs is positive.
91504      switch (relsym) {
91505      case LESS_OR_EQUAL:
91506        if (max_rhs) {
91507          Relation_Symbol rel = max_included ? LESS_OR_EQUAL : LESS_THAN;
91508          seq_var.build(i_constraint(rel, q_max));
91509        }
91510        else {
91511          seq_var.assign(UNIVERSE);
91512        }
91513        break;
91514      case LESS_THAN:
91515        if (max_rhs) {
91516          seq_var.build(i_constraint(LESS_THAN, q_max));
91517        }
91518        else {
91519          seq_var.assign(UNIVERSE);
91520        }
91521        break;
91522      case EQUAL:
91523        {
91524          I_Constraint<mpq_class> l;
91525          I_Constraint<mpq_class> u;
91526          if (max_rhs) {
91527            u.set(max_included ? LESS_OR_EQUAL : LESS_THAN, q_max);
91528          }
91529          if (min_rhs) {
91530            l.set(min_included ? GREATER_OR_EQUAL : GREATER_THAN, q_min);
91531          }
91532          seq_var.build(l, u);
91533          break;
91534        }
91535      case GREATER_OR_EQUAL:
91536        if (min_rhs) {
91537          Relation_Symbol rel = min_included ? GREATER_OR_EQUAL : GREATER_THAN;
91538          seq_var.build(i_constraint(rel, q_min));
91539        }
91540        else {
91541          seq_var.assign(UNIVERSE);
91542        }
91543        break;
91544      case GREATER_THAN:
91545        if (min_rhs) {
91546          seq_var.build(i_constraint(GREATER_THAN, q_min));
91547        }
91548        else {
91549          seq_var.assign(UNIVERSE);
91550        }
91551        break;
91552      default:
91553        // The NOT_EQUAL case has been already dealt with.
91554        PPL_UNREACHABLE;
91555        break;
91556      }
91557    }
91558    else {
91559      // The coefficient of the dimension in the lhs is negative.
91560      switch (relsym) {
91561      case GREATER_OR_EQUAL:
91562        if (min_rhs) {
91563          Relation_Symbol rel = min_included ? LESS_OR_EQUAL : LESS_THAN;
91564          seq_var.build(i_constraint(rel, q_min));
91565        }
91566        else {
91567          seq_var.assign(UNIVERSE);
91568        }
91569        break;
91570      case GREATER_THAN:
91571        if (min_rhs) {
91572          seq_var.build(i_constraint(LESS_THAN, q_min));
91573        }
91574        else {
91575          seq_var.assign(UNIVERSE);
91576        }
91577        break;
91578      case EQUAL:
91579        {
91580          I_Constraint<mpq_class> l;
91581          I_Constraint<mpq_class> u;
91582          if (max_rhs) {
91583            l.set(max_included ? GREATER_OR_EQUAL : GREATER_THAN, q_max);
91584          }
91585          if (min_rhs) {
91586            u.set(min_included ? LESS_OR_EQUAL : LESS_THAN, q_min);
91587          }
91588          seq_var.build(l, u);
91589          break;
91590        }
91591      case LESS_OR_EQUAL:
91592        if (max_rhs) {
91593          Relation_Symbol rel = max_included ? GREATER_OR_EQUAL : GREATER_THAN;
91594          seq_var.build(i_constraint(rel, q_max));
91595        }
91596        else {
91597          seq_var.assign(UNIVERSE);
91598        }
91599        break;
91600      case LESS_THAN:
91601        if (max_rhs) {
91602          seq_var.build(i_constraint(GREATER_THAN, q_max));
91603        }
91604        else {
91605          seq_var.assign(UNIVERSE);
91606        }
91607        break;
91608      default:
91609        // The NOT_EQUAL case has been already dealt with.
91610        PPL_UNREACHABLE;
91611        break;
91612      }
91613    }
91614  }
91615
91616  else {
91617    // The lhs is a constant value, so we just need to add the
91618    // appropriate constraint.
91619    const Coefficient& inhomo = lhs.inhomogeneous_term();
91620    switch (relsym) {
91621    case LESS_THAN:
91622      refine_with_constraint(inhomo < rhs);
91623      break;
91624    case LESS_OR_EQUAL:
91625      refine_with_constraint(inhomo <= rhs);
91626      break;
91627    case EQUAL:
91628      refine_with_constraint(inhomo == rhs);
91629      break;
91630    case GREATER_OR_EQUAL:
91631      refine_with_constraint(inhomo >= rhs);
91632      break;
91633    case GREATER_THAN:
91634      refine_with_constraint(inhomo > rhs);
91635      break;
91636    default:
91637      // The NOT_EQUAL case has been already dealt with.
91638      PPL_UNREACHABLE;
91639      break;
91640    }
91641  }
91642  PPL_ASSERT(OK());
91643}
91644
91645template <typename ITV>
91646void
91647Box<ITV>::generalized_affine_preimage(const Linear_Expression& lhs,
91648                                      const Relation_Symbol relsym,
91649                                      const Linear_Expression& rhs) {
91650  // Dimension-compatibility checks.
91651  // The dimension of `lhs' should not be greater than the dimension
91652  // of `*this'.
91653  dimension_type lhs_space_dim = lhs.space_dimension();
91654  const dimension_type space_dim = space_dimension();
91655  if (space_dim < lhs_space_dim) {
91656    throw_dimension_incompatible("generalized_affine_image(e1, r, e2)",
91657                                 "e1", lhs);
91658  }
91659  // The dimension of `rhs' should not be greater than the dimension
91660  // of `*this'.
91661  const dimension_type rhs_space_dim = rhs.space_dimension();
91662  if (space_dim < rhs_space_dim) {
91663    throw_dimension_incompatible("generalized_affine_image(e1, r, e2)",
91664                                 "e2", rhs);
91665  }
91666
91667  // The relation symbol cannot be a disequality.
91668  if (relsym == NOT_EQUAL) {
91669    throw_invalid_argument("generalized_affine_image(e1, r, e2)",
91670                           "r is the disequality relation symbol");
91671  }
91672  // Any image of an empty box is empty.
91673  if (marked_empty()) {
91674    return;
91675  }
91676  // For any dimension occurring in the lhs, swap and change the sign
91677  // of this component for the rhs and lhs.  Then use these in a call
91678  // to generalized_affine_image/3.
91679  Linear_Expression revised_lhs = lhs;
91680  Linear_Expression revised_rhs = rhs;
91681  for (Linear_Expression::const_iterator i = lhs.begin(),
91682         i_end = lhs.end(); i != i_end; ++i) {
91683    const Variable var = i.variable();
91684    PPL_DIRTY_TEMP_COEFFICIENT(tmp);
91685    tmp = *i;
91686    tmp += rhs.coefficient(var);
91687    sub_mul_assign(revised_rhs, tmp, var);
91688    sub_mul_assign(revised_lhs, tmp, var);
91689  }
91690  generalized_affine_image(revised_lhs, relsym, revised_rhs);
91691  PPL_ASSERT(OK());
91692}
91693
91694template <typename ITV>
91695template <typename T, typename Iterator>
91696typename Enable_If<Is_Same<T, Box<ITV> >::value
91697                   && Is_Same_Or_Derived<Interval_Base, ITV>::value,
91698                   void>::type
91699Box<ITV>::CC76_widening_assign(const T& y, Iterator first, Iterator last) {
91700  if (y.is_empty()) {
91701    return;
91702  }
91703  for (dimension_type i = seq.size(); i-- > 0; ) {
91704    seq[i].CC76_widening_assign(y.seq[i], first, last);
91705  }
91706
91707  PPL_ASSERT(OK());
91708}
91709
91710template <typename ITV>
91711template <typename T>
91712typename Enable_If<Is_Same<T, Box<ITV> >::value
91713                   && Is_Same_Or_Derived<Interval_Base, ITV>::value,
91714                   void>::type
91715Box<ITV>::CC76_widening_assign(const T& y, unsigned* tp) {
91716  static typename ITV::boundary_type stop_points[] = {
91717    typename ITV::boundary_type(-2),
91718    typename ITV::boundary_type(-1),
91719    typename ITV::boundary_type(0),
91720    typename ITV::boundary_type(1),
91721    typename ITV::boundary_type(2)
91722  };
91723
91724  Box& x = *this;
91725  // If there are tokens available, work on a temporary copy.
91726  if (tp != 0 && *tp > 0) {
91727    Box<ITV> x_tmp(x);
91728    x_tmp.CC76_widening_assign(y, 0);
91729    // If the widening was not precise, use one of the available tokens.
91730    if (!x.contains(x_tmp)) {
91731      --(*tp);
91732    }
91733    return;
91734  }
91735  x.CC76_widening_assign(y,
91736                         stop_points,
91737                         stop_points
91738                         + sizeof(stop_points)/sizeof(stop_points[0]));
91739}
91740
91741template <typename ITV>
91742void
91743Box<ITV>::get_limiting_box(const Constraint_System& cs,
91744                           Box& limiting_box) const {
91745  // Private method: the caller has to ensure the following.
91746  PPL_ASSERT(cs.space_dimension() <= space_dimension());
91747
91748  for (Constraint_System::const_iterator cs_i = cs.begin(),
91749         cs_end = cs.end(); cs_i != cs_end; ++cs_i) {
91750    const Constraint& c = *cs_i;
91751    dimension_type c_num_vars = 0;
91752    dimension_type c_only_var = 0;
91753    // Constraints that are not interval constraints are ignored.
91754    if (!Box_Helpers::extract_interval_constraint(c, c_num_vars, c_only_var)) {
91755      continue;
91756    }
91757    // Trivial constraints are ignored.
91758    if (c_num_vars != 0) {
91759      // c is a non-trivial interval constraint.
91760      // add interval constraint to limiting box
91761      const Coefficient& n = c.inhomogeneous_term();
91762      const Coefficient& d = c.coefficient(Variable(c_only_var));
91763      if (interval_relation(seq[c_only_var], c.type(), n, d)
91764          == Poly_Con_Relation::is_included()) {
91765        limiting_box.add_interval_constraint_no_check(c_only_var, c.type(),
91766                                                      n, d);
91767      }
91768    }
91769  }
91770}
91771
91772template <typename ITV>
91773void
91774Box<ITV>::limited_CC76_extrapolation_assign(const Box& y,
91775                                            const Constraint_System& cs,
91776                                            unsigned* tp) {
91777  Box& x = *this;
91778  const dimension_type space_dim = x.space_dimension();
91779
91780  // Dimension-compatibility check.
91781  if (space_dim != y.space_dimension()) {
91782    throw_dimension_incompatible("limited_CC76_extrapolation_assign(y, cs)",
91783                                  y);
91784  }
91785  // `cs' must be dimension-compatible with the two boxes.
91786  const dimension_type cs_space_dim = cs.space_dimension();
91787  if (space_dim < cs_space_dim) {
91788    throw_constraint_incompatible("limited_CC76_extrapolation_assign(y, cs)");
91789  }
91790  // The limited CC76-extrapolation between two boxes in a
91791  // zero-dimensional space is also a zero-dimensional box
91792  if (space_dim == 0) {
91793    return;
91794  }
91795  // Assume `y' is contained in or equal to `*this'.
91796  PPL_EXPECT_HEAVY(copy_contains(*this, y));
91797
91798  // If `*this' is empty, since `*this' contains `y', `y' is empty too.
91799  if (marked_empty()) {
91800    return;
91801  }
91802  // If `y' is empty, we return.
91803  if (y.marked_empty()) {
91804    return;
91805  }
91806  // Build a limiting box using all the constraints in cs
91807  // that are satisfied by *this.
91808  Box limiting_box(space_dim, UNIVERSE);
91809  get_limiting_box(cs, limiting_box);
91810
91811  x.CC76_widening_assign(y, tp);
91812
91813  // Intersect the widened box with the limiting box.
91814  intersection_assign(limiting_box);
91815}
91816
91817template <typename ITV>
91818template <typename T>
91819typename Enable_If<Is_Same<T, Box<ITV> >::value
91820                   && Is_Same_Or_Derived<Interval_Base, ITV>::value,
91821                   void>::type
91822Box<ITV>::CC76_narrowing_assign(const T& y) {
91823  const dimension_type space_dim = space_dimension();
91824
91825  // Dimension-compatibility check.
91826  if (space_dim != y.space_dimension()) {
91827    throw_dimension_incompatible("CC76_narrowing_assign(y)", y);
91828  }
91829
91830  // Assume `*this' is contained in or equal to `y'.
91831  PPL_EXPECT_HEAVY(copy_contains(y, *this));
91832
91833  // If both boxes are zero-dimensional,
91834  // since `y' contains `*this', we simply return `*this'.
91835  if (space_dim == 0) {
91836    return;
91837  }
91838  // If `y' is empty, since `y' contains `this', `*this' is empty too.
91839  if (y.is_empty()) {
91840    return;
91841  }
91842  // If `*this' is empty, we return.
91843  if (is_empty()) {
91844    return;
91845  }
91846  // Replace each constraint in `*this' by the corresponding constraint
91847  // in `y' if the corresponding inhomogeneous terms are both finite.
91848  for (dimension_type i = space_dim; i-- > 0; ) {
91849    ITV& x_i = seq[i];
91850    const ITV& y_i = y.seq[i];
91851    if (!x_i.lower_is_boundary_infinity()
91852        && !y_i.lower_is_boundary_infinity()
91853        && x_i.lower() != y_i.lower()) {
91854      x_i.lower() = y_i.lower();
91855    }
91856    if (!x_i.upper_is_boundary_infinity()
91857        && !y_i.upper_is_boundary_infinity()
91858        && x_i.upper() != y_i.upper()) {
91859      x_i.upper() = y_i.upper();
91860    }
91861  }
91862  PPL_ASSERT(OK());
91863}
91864
91865template <typename ITV>
91866Constraint_System
91867Box<ITV>::constraints() const {
91868  const dimension_type space_dim = space_dimension();
91869  Constraint_System cs;
91870  cs.set_space_dimension(space_dim);
91871
91872  if (space_dim == 0) {
91873    if (marked_empty()) {
91874      cs = Constraint_System::zero_dim_empty();
91875    }
91876    return cs;
91877  }
91878
91879  if (marked_empty()) {
91880    cs.insert(Constraint::zero_dim_false());
91881    return cs;
91882  }
91883
91884  for (dimension_type k = 0; k < space_dim; ++k) {
91885    const Variable v_k = Variable(k);
91886    PPL_DIRTY_TEMP_COEFFICIENT(n);
91887    PPL_DIRTY_TEMP_COEFFICIENT(d);
91888    bool closed = false;
91889    if (has_lower_bound(v_k, n, d, closed)) {
91890      if (closed) {
91891        cs.insert(d * v_k >= n);
91892      }
91893      else {
91894        cs.insert(d * v_k > n);
91895      }
91896    }
91897    if (has_upper_bound(v_k, n, d, closed)) {
91898      if (closed) {
91899        cs.insert(d * v_k <= n);
91900      }
91901      else {
91902        cs.insert(d * v_k < n);
91903      }
91904    }
91905  }
91906  return cs;
91907}
91908
91909template <typename ITV>
91910Constraint_System
91911Box<ITV>::minimized_constraints() const {
91912  const dimension_type space_dim = space_dimension();
91913  Constraint_System cs;
91914  cs.set_space_dimension(space_dim);
91915
91916  if (space_dim == 0) {
91917    if (marked_empty()) {
91918      cs = Constraint_System::zero_dim_empty();
91919    }
91920    return cs;
91921  }
91922
91923  // Make sure emptiness is detected.
91924  if (is_empty()) {
91925    cs.insert(Constraint::zero_dim_false());
91926    return cs;
91927  }
91928
91929  for (dimension_type k = 0; k < space_dim; ++k) {
91930    const Variable v_k = Variable(k);
91931    PPL_DIRTY_TEMP_COEFFICIENT(n);
91932    PPL_DIRTY_TEMP_COEFFICIENT(d);
91933    bool closed = false;
91934    if (has_lower_bound(v_k, n, d, closed)) {
91935      if (closed) {
91936        // Make sure equality constraints are detected.
91937        if (seq[k].is_singleton()) {
91938          cs.insert(d * v_k == n);
91939          continue;
91940        }
91941        else {
91942          cs.insert(d * v_k >= n);
91943        }
91944      }
91945      else {
91946        cs.insert(d * v_k > n);
91947      }
91948    }
91949    if (has_upper_bound(v_k, n, d, closed)) {
91950      if (closed) {
91951        cs.insert(d * v_k <= n);
91952      }
91953      else {
91954        cs.insert(d * v_k < n);
91955      }
91956    }
91957  }
91958  return cs;
91959}
91960
91961template <typename ITV>
91962Congruence_System
91963Box<ITV>::congruences() const {
91964  const dimension_type space_dim = space_dimension();
91965  Congruence_System cgs(space_dim);
91966
91967  if (space_dim == 0) {
91968    if (marked_empty()) {
91969      cgs = Congruence_System::zero_dim_empty();
91970    }
91971    return cgs;
91972  }
91973
91974  // Make sure emptiness is detected.
91975  if (is_empty()) {
91976    cgs.insert(Congruence::zero_dim_false());
91977    return cgs;
91978  }
91979
91980  for (dimension_type k = 0; k < space_dim; ++k) {
91981    const Variable v_k = Variable(k);
91982    PPL_DIRTY_TEMP_COEFFICIENT(n);
91983    PPL_DIRTY_TEMP_COEFFICIENT(d);
91984    bool closed = false;
91985    if (has_lower_bound(v_k, n, d, closed) && closed) {
91986      // Make sure equality congruences are detected.
91987      if (seq[k].is_singleton()) {
91988        cgs.insert((d * v_k %= n) / 0);
91989      }
91990    }
91991  }
91992  return cgs;
91993}
91994
91995template <typename ITV>
91996memory_size_type
91997Box<ITV>::external_memory_in_bytes() const {
91998  memory_size_type n = seq.capacity() * sizeof(ITV);
91999  for (dimension_type k = seq.size(); k-- > 0; ) {
92000    n += seq[k].external_memory_in_bytes();
92001  }
92002  return n;
92003}
92004
92005/*! \relates Parma_Polyhedra_Library::Box */
92006template <typename ITV>
92007std::ostream&
92008IO_Operators::operator<<(std::ostream& s, const Box<ITV>& box) {
92009  if (box.is_empty()) {
92010    s << "false";
92011  }
92012  else if (box.is_universe()) {
92013    s << "true";
92014  }
92015  else {
92016    for (dimension_type k = 0,
92017           space_dim = box.space_dimension(); k < space_dim; ) {
92018      s << Variable(k) << " in " << box[k];
92019      ++k;
92020      if (k < space_dim) {
92021        s << ", ";
92022      }
92023      else {
92024        break;
92025      }
92026    }
92027  }
92028  return s;
92029}
92030
92031template <typename ITV>
92032void
92033Box<ITV>::ascii_dump(std::ostream& s) const {
92034  const char separator = ' ';
92035  status.ascii_dump(s);
92036  const dimension_type space_dim = space_dimension();
92037  s << "space_dim" << separator << space_dim;
92038  s << "\n";
92039  for (dimension_type i = 0; i < space_dim;  ++i) {
92040    seq[i].ascii_dump(s);
92041  }
92042}
92043
92044PPL_OUTPUT_TEMPLATE_DEFINITIONS(ITV, Box<ITV>)
92045
92046template <typename ITV>
92047bool
92048Box<ITV>::ascii_load(std::istream& s) {
92049  if (!status.ascii_load(s)) {
92050    return false;
92051  }
92052  std::string str;
92053  dimension_type space_dim;
92054  if (!(s >> str) || str != "space_dim") {
92055    return false;
92056  }
92057  if (!(s >> space_dim)) {
92058    return false;
92059  }
92060  seq.clear();
92061  ITV seq_i;
92062  for (dimension_type i = 0; i < space_dim;  ++i) {
92063    if (seq_i.ascii_load(s)) {
92064      seq.push_back(seq_i);
92065    }
92066    else {
92067      return false;
92068    }
92069  }
92070
92071  // Check invariants.
92072  PPL_ASSERT(OK());
92073  return true;
92074}
92075
92076template <typename ITV>
92077void
92078Box<ITV>::throw_dimension_incompatible(const char* method,
92079                                       const Box& y) const {
92080  std::ostringstream s;
92081  s << "PPL::Box::" << method << ":" << std::endl
92082    << "this->space_dimension() == " << this->space_dimension()
92083    << ", y->space_dimension() == " << y.space_dimension() << ".";
92084  throw std::invalid_argument(s.str());
92085}
92086
92087template <typename ITV>
92088void
92089Box<ITV>
92090::throw_dimension_incompatible(const char* method,
92091                               dimension_type required_dim) const {
92092  std::ostringstream s;
92093  s << "PPL::Box::" << method << ":" << std::endl
92094    << "this->space_dimension() == " << space_dimension()
92095    << ", required dimension == " << required_dim << ".";
92096  throw std::invalid_argument(s.str());
92097}
92098
92099template <typename ITV>
92100void
92101Box<ITV>::throw_dimension_incompatible(const char* method,
92102                                       const Constraint& c) const {
92103  std::ostringstream s;
92104  s << "PPL::Box::" << method << ":" << std::endl
92105    << "this->space_dimension() == " << space_dimension()
92106    << ", c->space_dimension == " << c.space_dimension() << ".";
92107  throw std::invalid_argument(s.str());
92108}
92109
92110template <typename ITV>
92111void
92112Box<ITV>::throw_dimension_incompatible(const char* method,
92113                                       const Congruence& cg) const {
92114  std::ostringstream s;
92115  s << "PPL::Box::" << method << ":" << std::endl
92116    << "this->space_dimension() == " << space_dimension()
92117    << ", cg->space_dimension == " << cg.space_dimension() << ".";
92118  throw std::invalid_argument(s.str());
92119}
92120
92121template <typename ITV>
92122void
92123Box<ITV>::throw_dimension_incompatible(const char* method,
92124                                       const Constraint_System& cs) const {
92125  std::ostringstream s;
92126  s << "PPL::Box::" << method << ":" << std::endl
92127    << "this->space_dimension() == " << space_dimension()
92128    << ", cs->space_dimension == " << cs.space_dimension() << ".";
92129  throw std::invalid_argument(s.str());
92130}
92131
92132template <typename ITV>
92133void
92134Box<ITV>::throw_dimension_incompatible(const char* method,
92135                                       const Congruence_System& cgs) const {
92136  std::ostringstream s;
92137  s << "PPL::Box::" << method << ":" << std::endl
92138    << "this->space_dimension() == " << space_dimension()
92139    << ", cgs->space_dimension == " << cgs.space_dimension() << ".";
92140  throw std::invalid_argument(s.str());
92141}
92142
92143template <typename ITV>
92144void
92145Box<ITV>::throw_dimension_incompatible(const char* method,
92146                                       const Generator& g) const {
92147  std::ostringstream s;
92148  s << "PPL::Box::" << method << ":" << std::endl
92149    << "this->space_dimension() == " << space_dimension()
92150    << ", g->space_dimension == " << g.space_dimension() << ".";
92151  throw std::invalid_argument(s.str());
92152}
92153
92154template <typename ITV>
92155void
92156Box<ITV>::throw_constraint_incompatible(const char* method) {
92157  std::ostringstream s;
92158  s << "PPL::Box::" << method << ":" << std::endl
92159    << "the constraint is incompatible.";
92160  throw std::invalid_argument(s.str());
92161}
92162
92163template <typename ITV>
92164void
92165Box<ITV>::throw_expression_too_complex(const char* method,
92166                                       const Linear_Expression& le) {
92167  using namespace IO_Operators;
92168  std::ostringstream s;
92169  s << "PPL::Box::" << method << ":" << std::endl
92170    << le << " is too complex.";
92171  throw std::invalid_argument(s.str());
92172}
92173
92174template <typename ITV>
92175void
92176Box<ITV>::throw_dimension_incompatible(const char* method,
92177                                       const char* le_name,
92178                                       const Linear_Expression& le) const {
92179  std::ostringstream s;
92180  s << "PPL::Box::" << method << ":" << std::endl
92181    << "this->space_dimension() == " << space_dimension()
92182    << ", " << le_name << "->space_dimension() == "
92183    << le.space_dimension() << ".";
92184  throw std::invalid_argument(s.str());
92185}
92186
92187template <typename ITV>
92188template <typename C>
92189void
92190Box<ITV>::throw_dimension_incompatible(const char* method,
92191                                       const char* lf_name,
92192                                       const Linear_Form<C>& lf) const {
92193  std::ostringstream s;
92194  s << "PPL::Box::" << method << ":\n"
92195    << "this->space_dimension() == " << space_dimension()
92196    << ", " << lf_name << "->space_dimension() == "
92197    << lf.space_dimension() << ".";
92198  throw std::invalid_argument(s.str());
92199}
92200
92201template <typename ITV>
92202void
92203Box<ITV>::throw_invalid_argument(const char* method, const char* reason) {
92204  std::ostringstream s;
92205  s << "PPL::Box::" << method << ":" << std::endl
92206    << reason;
92207  throw std::invalid_argument(s.str());
92208}
92209
92210#ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
92211/*! \relates Box */
92212#endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
92213template <typename Specialization,
92214          typename Temp, typename To, typename ITV>
92215bool
92216l_m_distance_assign(Checked_Number<To, Extended_Number_Policy>& r,
92217                    const Box<ITV>& x, const Box<ITV>& y,
92218                    const Rounding_Dir dir,
92219                    Temp& tmp0, Temp& tmp1, Temp& tmp2) {
92220  const dimension_type x_space_dim = x.space_dimension();
92221  // Dimension-compatibility check.
92222  if (x_space_dim != y.space_dimension()) {
92223    return false;
92224  }
92225  // Zero-dim boxes are equal if and only if they are both empty or universe.
92226  if (x_space_dim == 0) {
92227    if (x.marked_empty() == y.marked_empty()) {
92228      assign_r(r, 0, ROUND_NOT_NEEDED);
92229    }
92230    else {
92231      assign_r(r, PLUS_INFINITY, ROUND_NOT_NEEDED);
92232    }
92233    return true;
92234  }
92235
92236  // The distance computation requires a check for emptiness.
92237  (void) x.is_empty();
92238  (void) y.is_empty();
92239  // If one of two boxes is empty, then they are equal if and only if
92240  // the other box is empty too.
92241  if (x.marked_empty() || y.marked_empty()) {
92242    if (x.marked_empty() == y.marked_empty()) {
92243      assign_r(r, 0, ROUND_NOT_NEEDED);
92244      return true;
92245    }
92246    else {
92247      goto pinf;
92248    }
92249  }
92250
92251  assign_r(tmp0, 0, ROUND_NOT_NEEDED);
92252  for (dimension_type i = x_space_dim; i-- > 0; ) {
92253    const ITV& x_i = x.seq[i];
92254    const ITV& y_i = y.seq[i];
92255    // Dealing with the lower bounds.
92256    if (x_i.lower_is_boundary_infinity()) {
92257      if (!y_i.lower_is_boundary_infinity()) {
92258        goto pinf;
92259      }
92260    }
92261    else if (y_i.lower_is_boundary_infinity()) {
92262      goto pinf;
92263    }
92264    else {
92265      const Temp* tmp1p;
92266      const Temp* tmp2p;
92267      if (x_i.lower() > y_i.lower()) {
92268        maybe_assign(tmp1p, tmp1, x_i.lower(), dir);
92269        maybe_assign(tmp2p, tmp2, y_i.lower(), inverse(dir));
92270      }
92271      else {
92272        maybe_assign(tmp1p, tmp1, y_i.lower(), dir);
92273        maybe_assign(tmp2p, tmp2, x_i.lower(), inverse(dir));
92274      }
92275      sub_assign_r(tmp1, *tmp1p, *tmp2p, dir);
92276      PPL_ASSERT(sgn(tmp1) >= 0);
92277      Specialization::combine(tmp0, tmp1, dir);
92278    }
92279    // Dealing with the lower bounds.
92280    if (x_i.upper_is_boundary_infinity()) {
92281      if (y_i.upper_is_boundary_infinity()) {
92282        continue;
92283      }
92284      else {
92285        goto pinf;
92286      }
92287    }
92288    else if (y_i.upper_is_boundary_infinity()) {
92289      goto pinf;
92290    }
92291    else {
92292      const Temp* tmp1p;
92293      const Temp* tmp2p;
92294      if (x_i.upper() > y_i.upper()) {
92295        maybe_assign(tmp1p, tmp1, x_i.upper(), dir);
92296        maybe_assign(tmp2p, tmp2, y_i.upper(), inverse(dir));
92297      }
92298      else {
92299        maybe_assign(tmp1p, tmp1, y_i.upper(), dir);
92300        maybe_assign(tmp2p, tmp2, x_i.upper(), inverse(dir));
92301      }
92302      sub_assign_r(tmp1, *tmp1p, *tmp2p, dir);
92303      PPL_ASSERT(sgn(tmp1) >= 0);
92304      Specialization::combine(tmp0, tmp1, dir);
92305    }
92306  }
92307  Specialization::finalize(tmp0, dir);
92308  assign_r(r, tmp0, dir);
92309  return true;
92310
92311 pinf:
92312  assign_r(r, PLUS_INFINITY, ROUND_NOT_NEEDED);
92313  return true;
92314}
92315
92316} // namespace Parma_Polyhedra_Library
92317
92318/* Automatically generated from PPL source file ../src/Box_defs.hh line 2287. */
92319
92320/* Automatically generated from PPL source file ../src/Linear_Form_templates.hh line 30. */
92321#include <stdexcept>
92322#include <iostream>
92323#include <cmath>
92324
92325namespace Parma_Polyhedra_Library {
92326
92327template <typename C>
92328Linear_Form<C>::Linear_Form(const Variable v)
92329  : vec() {
92330  const dimension_type space_dim = v.space_dimension();
92331  if (space_dim > max_space_dimension()) {
92332    throw std::length_error("Linear_Form<C>::"
92333                            "Linear_Form(v):\n"
92334                            "v exceeds the maximum allowed "
92335                            "space dimension.");
92336  }
92337  vec.reserve(compute_capacity(space_dim+1, vec_type().max_size()));
92338  vec.resize(space_dim+1, zero);
92339  vec[v.space_dimension()] = C(typename C::boundary_type(1));
92340}
92341
92342template <typename C>
92343Linear_Form<C>::Linear_Form(const Variable v, const Variable w)
92344  : vec() {
92345  const dimension_type v_space_dim = v.space_dimension();
92346  const dimension_type w_space_dim = w.space_dimension();
92347  const dimension_type space_dim = std::max(v_space_dim, w_space_dim);
92348  if (space_dim > max_space_dimension()) {
92349    throw std::length_error("Linear_Form<C>::"
92350                            "Linear_Form(v, w):\n"
92351                            "v or w exceed the maximum allowed "
92352                            "space dimension.");
92353  }
92354  vec.reserve(compute_capacity(space_dim+1, vec_type().max_size()));
92355  vec.resize(space_dim+1, zero);
92356  if (v_space_dim != w_space_dim) {
92357    vec[v_space_dim] = C(typename C::boundary_type(1));
92358    vec[w_space_dim] = C(typename C::boundary_type(-1));
92359  }
92360}
92361
92362template <typename C>
92363Linear_Form<C>::Linear_Form(const Linear_Expression& e)
92364  : vec() {
92365  const dimension_type space_dim = e.space_dimension();
92366  if (space_dim > max_space_dimension()) {
92367    throw std::length_error("Linear_Form<C>::"
92368                            "Linear_Form(e):\n"
92369                            "e exceeds the maximum allowed "
92370                            "space dimension.");
92371  }
92372  vec.reserve(compute_capacity(space_dim+1, vec_type().max_size()));
92373  vec.resize(space_dim+1);
92374  for (dimension_type i = space_dim; i-- > 0; )
92375    vec[i+1] = e.coefficient(Variable(i));
92376  vec[0] = e.inhomogeneous_term();
92377}
92378
92379/*! \relates Linear_Form */
92380template <typename C>
92381Linear_Form<C>
92382operator+(const Linear_Form<C>& f1, const Linear_Form<C>& f2) {
92383  dimension_type f1_size = f1.size();
92384  dimension_type f2_size = f2.size();
92385  dimension_type min_size;
92386  dimension_type max_size;
92387  const Linear_Form<C>* p_e_max;
92388  if (f1_size > f2_size) {
92389    min_size = f2_size;
92390    max_size = f1_size;
92391    p_e_max = &f1;
92392  }
92393  else {
92394    min_size = f1_size;
92395    max_size = f2_size;
92396    p_e_max = &f2;
92397  }
92398
92399  Linear_Form<C> r(max_size, false);
92400  dimension_type i = max_size;
92401  while (i > min_size) {
92402    --i;
92403    r[i] = p_e_max->vec[i];
92404  }
92405  while (i > 0) {
92406    --i;
92407    r[i] = f1[i];
92408    r[i] += f2[i];
92409  }
92410  return r;
92411}
92412
92413/*! \relates Linear_Form */
92414template <typename C>
92415Linear_Form<C>
92416operator+(const Variable v, const Linear_Form<C>& f) {
92417  const dimension_type v_space_dim = v.space_dimension();
92418  if (v_space_dim > Linear_Form<C>::max_space_dimension()) {
92419    throw std::length_error("Linear_Form "
92420                            "operator+(v, f):\n"
92421                            "v exceeds the maximum allowed "
92422                            "space dimension.");
92423  }
92424  Linear_Form<C> r(f);
92425  if (v_space_dim > f.space_dimension()) {
92426    r.extend(v_space_dim+1);
92427  }
92428  r[v_space_dim] += C(typename C::boundary_type(1));
92429  return r;
92430}
92431
92432/*! \relates Linear_Form */
92433template <typename C>
92434Linear_Form<C>
92435operator+(const C& n, const Linear_Form<C>& f) {
92436  Linear_Form<C> r(f);
92437  r[0] += n;
92438  return r;
92439}
92440
92441/*! \relates Linear_Form */
92442template <typename C>
92443Linear_Form<C>
92444operator-(const Linear_Form<C>& f) {
92445  Linear_Form<C> r(f);
92446  for (dimension_type i = f.size(); i-- > 0; ) {
92447    r[i].neg_assign(r[i]);
92448  }
92449  return r;
92450}
92451
92452/*! \relates Linear_Form */
92453template <typename C>
92454Linear_Form<C>
92455operator-(const Linear_Form<C>& f1, const Linear_Form<C>& f2) {
92456  dimension_type f1_size = f1.size();
92457  dimension_type f2_size = f2.size();
92458  if (f1_size > f2_size) {
92459    Linear_Form<C> r(f1_size, false);
92460    dimension_type i = f1_size;
92461    while (i > f2_size) {
92462      --i;
92463      r[i] = f1[i];
92464    }
92465    while (i > 0) {
92466      --i;
92467      r[i] = f1[i];
92468      r[i] -= f2[i];
92469    }
92470    return r;
92471  }
92472  else {
92473    Linear_Form<C> r(f2_size, false);
92474    dimension_type i = f2_size;
92475    while (i > f1_size) {
92476      --i;
92477      r[i].neg_assign(f2[i]);
92478    }
92479    while (i > 0) {
92480      --i;
92481      r[i] = f1[i];
92482      r[i] -= f2[i];
92483    }
92484    return r;
92485  }
92486}
92487
92488/*! \relates Linear_Form */
92489template <typename C>
92490Linear_Form<C>
92491operator-(const Variable v, const Linear_Form<C>& f) {
92492  const dimension_type v_space_dim = v.space_dimension();
92493  if (v_space_dim > Linear_Form<C>::max_space_dimension()) {
92494    throw std::length_error("Linear_Form "
92495                            "operator-(v, e):\n"
92496                            "v exceeds the maximum allowed "
92497                            "space dimension.");
92498  }
92499  Linear_Form<C> r(f);
92500  if (v_space_dim > f.space_dimension()) {
92501    r.extend(v_space_dim+1);
92502  }
92503  for (dimension_type i = f.size(); i-- > 0; ) {
92504    r[i].neg_assign(r[i]);
92505  }
92506  r[v_space_dim] += C(typename C::boundary_type(1));
92507  return r;
92508}
92509
92510/*! \relates Linear_Form */
92511template <typename C>
92512Linear_Form<C>
92513operator-(const Linear_Form<C>& f, const Variable v) {
92514  const dimension_type v_space_dim = v.space_dimension();
92515  if (v_space_dim > Linear_Form<C>::max_space_dimension()) {
92516    throw std::length_error("Linear_Form "
92517                            "operator-(e, v):\n"
92518                            "v exceeds the maximum allowed "
92519                            "space dimension.");
92520  }
92521  Linear_Form<C> r(f);
92522  if (v_space_dim > f.space_dimension()) {
92523    r.extend(v_space_dim+1);
92524  }
92525  r[v_space_dim] -= C(typename C::boundary_type(1));
92526  return r;
92527}
92528
92529/*! \relates Linear_Form */
92530template <typename C>
92531Linear_Form<C>
92532operator-(const C& n, const Linear_Form<C>& f) {
92533  Linear_Form<C> r(f);
92534  for (dimension_type i = f.size(); i-- > 0; ) {
92535    r[i].neg_assign(r[i]);
92536  }
92537  r[0] += n;
92538  return r;
92539}
92540
92541/*! \relates Linear_Form */
92542template <typename C>
92543Linear_Form<C>
92544operator*(const C& n, const Linear_Form<C>& f) {
92545  Linear_Form<C> r(f);
92546  for (dimension_type i = f.size(); i-- > 0; ) {
92547    r[i] *= n;
92548  }
92549  return r;
92550}
92551
92552/*! \relates Linear_Form */
92553template <typename C>
92554Linear_Form<C>&
92555operator+=(Linear_Form<C>& f1, const Linear_Form<C>& f2) {
92556  dimension_type f1_size = f1.size();
92557  dimension_type f2_size = f2.size();
92558  if (f1_size < f2_size) {
92559    f1.extend(f2_size);
92560  }
92561  for (dimension_type i = f2_size; i-- > 0; ) {
92562    f1[i] += f2[i];
92563  }
92564  return f1;
92565}
92566
92567/*! \relates Linear_Form */
92568template <typename C>
92569Linear_Form<C>&
92570operator+=(Linear_Form<C>& f, const Variable v) {
92571  const dimension_type v_space_dim = v.space_dimension();
92572  if (v_space_dim > Linear_Form<C>::max_space_dimension()) {
92573    throw std::length_error("Linear_Form<C>& "
92574                            "operator+=(e, v):\n"
92575                            "v exceeds the maximum allowed space dimension.");
92576  }
92577  if (v_space_dim > f.space_dimension()) {
92578    f.extend(v_space_dim+1);
92579  }
92580  f[v_space_dim] += C(typename C::boundary_type(1));
92581  return f;
92582}
92583
92584/*! \relates Linear_Form */
92585template <typename C>
92586Linear_Form<C>&
92587operator-=(Linear_Form<C>& f1, const Linear_Form<C>& f2) {
92588  dimension_type f1_size = f1.size();
92589  dimension_type f2_size = f2.size();
92590  if (f1_size < f2_size) {
92591    f1.extend(f2_size);
92592  }
92593  for (dimension_type i = f2_size; i-- > 0; ) {
92594    f1[i] -= f2[i];
92595  }
92596  return f1;
92597}
92598
92599/*! \relates Linear_Form */
92600template <typename C>
92601Linear_Form<C>&
92602operator-=(Linear_Form<C>& f, const Variable v) {
92603  const dimension_type v_space_dim = v.space_dimension();
92604  if (v_space_dim > Linear_Form<C>::max_space_dimension()) {
92605    throw std::length_error("Linear_Form<C>& "
92606                            "operator-=(e, v):\n"
92607                            "v exceeds the maximum allowed space dimension.");
92608  }
92609  if (v_space_dim > f.space_dimension()) {
92610    f.extend(v_space_dim+1);
92611  }
92612  f[v_space_dim] -= C(typename C::boundary_type(1));
92613  return f;
92614}
92615
92616/*! \relates Linear_Form */
92617template <typename C>
92618Linear_Form<C>&
92619operator*=(Linear_Form<C>& f, const C& n) {
92620  dimension_type f_size = f.size();
92621  for (dimension_type i = f_size; i-- > 0; ) {
92622    f[i] *= n;
92623  }
92624  return f;
92625}
92626
92627/*! \relates Linear_Form */
92628template <typename C>
92629Linear_Form<C>&
92630operator/=(Linear_Form<C>& f, const C& n) {
92631  dimension_type f_size = f.size();
92632  for (dimension_type i = f_size; i-- > 0; ) {
92633    f[i] /= n;
92634  }
92635  return f;
92636}
92637
92638/*! \relates Linear_Form */
92639template <typename C>
92640inline bool
92641operator==(const Linear_Form<C>& x, const Linear_Form<C>& y) {
92642  const dimension_type x_size = x.size();
92643  const dimension_type y_size = y.size();
92644  if (x_size >= y_size) {
92645    for (dimension_type i = y_size; i-- > 0; ) {
92646      if (x[i] != y[i]) {
92647        return false;
92648      }
92649    }
92650    for (dimension_type i = x_size; --i >= y_size; ) {
92651      if (x[i] != x.zero) {
92652        return false;
92653      }
92654    }
92655  }
92656  else {
92657    for (dimension_type i = x_size; i-- > 0; ) {
92658      if (x[i] != y[i]) {
92659        return false;
92660      }
92661    }
92662    for (dimension_type i = y_size; --i >= x_size; ) {
92663      if (y[i] != x.zero) {
92664        return false;
92665      }
92666    }
92667
92668  }
92669
92670  return true;
92671}
92672
92673template <typename C>
92674void
92675Linear_Form<C>::negate() {
92676  for (dimension_type i = vec.size(); i-- > 0; ) {
92677    vec[i].neg_assign(vec[i]);
92678  }
92679  return;
92680}
92681
92682template <typename C>
92683inline memory_size_type
92684Linear_Form<C>::external_memory_in_bytes() const {
92685  memory_size_type n = 0;
92686  for (dimension_type i = size(); i-- > 0; ) {
92687    n += vec[i].external_memory_in_bytes();
92688  }
92689  n += vec.capacity()*sizeof(C);
92690  return n;
92691}
92692
92693template <typename C>
92694bool
92695Linear_Form<C>::OK() const {
92696  for (dimension_type i = size(); i-- > 0; ) {
92697    if (!vec[i].OK()) {
92698      return false;
92699    }
92700  }
92701  return true;
92702}
92703
92704// Floating point analysis related methods.
92705template <typename C>
92706void
92707Linear_Form<C>::relative_error(
92708                const Floating_Point_Format analyzed_format,
92709                Linear_Form& result) const {
92710  typedef typename C::boundary_type analyzer_format;
92711
92712  // Get the necessary information on the analyzed's format.
92713  unsigned int f_base;
92714  unsigned int f_mantissa_bits;
92715  switch (analyzed_format) {
92716    case IEEE754_HALF:
92717      f_base = float_ieee754_half::BASE;
92718      f_mantissa_bits = float_ieee754_half::MANTISSA_BITS;
92719      break;
92720    case IEEE754_SINGLE:
92721      f_base = float_ieee754_single::BASE;
92722      f_mantissa_bits = float_ieee754_single::MANTISSA_BITS;
92723      break;
92724    case IEEE754_DOUBLE:
92725      f_base = float_ieee754_double::BASE;
92726      f_mantissa_bits = float_ieee754_double::MANTISSA_BITS;
92727      break;
92728    case IBM_SINGLE:
92729      f_base = float_ibm_single::BASE;
92730      f_mantissa_bits = float_ibm_single::MANTISSA_BITS;
92731      break;
92732    case IEEE754_QUAD:
92733      f_base = float_ieee754_quad::BASE;
92734      f_mantissa_bits = float_ieee754_quad::MANTISSA_BITS;
92735      break;
92736    case INTEL_DOUBLE_EXTENDED:
92737      f_base = float_intel_double_extended::BASE;
92738      f_mantissa_bits = float_intel_double_extended::MANTISSA_BITS;
92739      break;
92740    default:
92741      PPL_UNREACHABLE;
92742      break;
92743  }
92744
92745  C error_propagator;
92746  // We assume that f_base is a power of 2.
92747  unsigned int u_power = msb_position(f_base) * f_mantissa_bits;
92748  int neg_power = -static_cast<int>(u_power);
92749  analyzer_format lb = static_cast<analyzer_format>(ldexp(1.0, neg_power));
92750
92751  error_propagator.build(i_constraint(GREATER_OR_EQUAL, -lb),
92752                         i_constraint(LESS_OR_EQUAL, lb));
92753
92754  // Handle the inhomogeneous term.
92755  const C* current_term = &inhomogeneous_term();
92756  assert(current_term->is_bounded());
92757
92758  C current_multiplier(std::max(std::abs(current_term->lower()),
92759                                std::abs(current_term->upper())));
92760  Linear_Form current_result_term(current_multiplier);
92761  current_result_term *= error_propagator;
92762  result = Linear_Form(current_result_term);
92763
92764  // Handle the other terms.
92765  dimension_type dimension = space_dimension();
92766  for (dimension_type i = 0; i < dimension; ++i) {
92767    current_term = &coefficient(Variable(i));
92768    assert(current_term->is_bounded());
92769    current_multiplier = C(std::max(std::abs(current_term->lower()),
92770                                    std::abs(current_term->upper())));
92771    current_result_term = Linear_Form(Variable(i));
92772    current_result_term *= current_multiplier;
92773    current_result_term *= error_propagator;
92774    result += current_result_term;
92775  }
92776
92777  return;
92778}
92779
92780template <typename C>
92781template <typename Target>
92782bool
92783Linear_Form<C>::intervalize(const FP_Oracle<Target,C>& oracle,
92784                            C& result) const {
92785  result = C(inhomogeneous_term());
92786  dimension_type dimension = space_dimension();
92787  for (dimension_type i = 0; i < dimension; ++i) {
92788    C current_addend = coefficient(Variable(i));
92789    C curr_int;
92790    if (!oracle.get_interval(i, curr_int)) {
92791      return false;
92792    }
92793    current_addend *= curr_int;
92794    result += current_addend;
92795  }
92796
92797  return true;
92798}
92799
92800/*! \relates Parma_Polyhedra_Library::Linear_Form */
92801template <typename C>
92802std::ostream&
92803IO_Operators::operator<<(std::ostream& s, const Linear_Form<C>& f) {
92804  const dimension_type num_variables = f.space_dimension();
92805  bool first = true;
92806  for (dimension_type v = 0; v < num_variables; ++v) {
92807    const C& fv = f[v+1];
92808    if (fv != typename C::boundary_type(0)) {
92809      if (first) {
92810        if (fv == typename C::boundary_type(-1)) {
92811          s << "-";
92812        }
92813        else if (fv != typename C::boundary_type(1)) {
92814          s << fv << "*";
92815        }
92816        first = false;
92817      }
92818      else {
92819        if (fv == typename C::boundary_type(-1)) {
92820          s << " - ";
92821        }
92822        else {
92823          s << " + ";
92824          if (fv != typename C::boundary_type(1)) {
92825            s << fv << "*";
92826          }
92827        }
92828      }
92829      s << Variable(v);
92830    }
92831  }
92832  // Inhomogeneous term.
92833  const C& it = f[0];
92834  if (it != 0) {
92835    if (!first) {
92836        s << " + ";
92837    }
92838    else {
92839      first = false;
92840    }
92841    s << it;
92842  }
92843
92844  if (first) {
92845    // The null linear form.
92846    s << Linear_Form<C>::zero;
92847  }
92848  return s;
92849}
92850
92851PPL_OUTPUT_TEMPLATE_DEFINITIONS(C, Linear_Form<C>)
92852
92853template <typename C>
92854C Linear_Form<C>::zero(typename C::boundary_type(0));
92855
92856} // namespace Parma_Polyhedra_Library
92857
92858/* Automatically generated from PPL source file ../src/linearize.hh line 1. */
92859/* Linearization function implementation.
92860*/
92861
92862
92863/* Automatically generated from PPL source file ../src/Concrete_Expression_defs.hh line 1. */
92864/* Concrete_Expression class declaration.
92865*/
92866
92867
92868/* Automatically generated from PPL source file ../src/Concrete_Expression_defs.hh line 30. */
92869
92870namespace Parma_Polyhedra_Library {
92871
92872//! The type of a concrete expression.
92873class Concrete_Expression_Type {
92874public:
92875  /*! \brief
92876    Returns the bounded integer type corresponding to \p width,
92877    \p representation and \p overflow.
92878  */
92879  static Concrete_Expression_Type
92880  bounded_integer(Bounded_Integer_Type_Width width,
92881                  Bounded_Integer_Type_Representation representation,
92882                  Bounded_Integer_Type_Overflow overflow);
92883
92884  /*! \brief
92885    Returns the floating point type corresponding to \p format.
92886  */
92887  static Concrete_Expression_Type
92888  floating_point(Floating_Point_Format format);
92889
92890  /*! \brief
92891    Returns <CODE>true</CODE> if and only if \p *this is a bounded
92892    integer type.
92893  */
92894  bool is_bounded_integer() const;
92895
92896  /*! \brief
92897    Returns <CODE>true</CODE> if and only if \p *this is a floating
92898    point type.
92899  */
92900  bool is_floating_point() const;
92901
92902  /*! \brief
92903    Returns the width in bits of the bounded integer type encoded by
92904    \p *this.
92905
92906    The behavior is undefined if \p *this does not encode a bounded
92907    integer type.
92908  */
92909  Bounded_Integer_Type_Width bounded_integer_type_width() const;
92910
92911  /*! \brief
92912    Returns the representation of the bounded integer type encoded by
92913    \p *this.
92914
92915    The behavior is undefined if \p *this does not encode a bounded
92916    integer type.
92917  */
92918  Bounded_Integer_Type_Representation
92919  bounded_integer_type_representation() const;
92920
92921  /*! \brief
92922    Returns the overflow behavior of the bounded integer type encoded by
92923    \p *this.
92924
92925    The behavior is undefined if \p *this does not encode a bounded
92926    integer type.
92927  */
92928  Bounded_Integer_Type_Overflow
92929  bounded_integer_type_overflow() const;
92930
92931  /*! \brief
92932    Returns the format of the floating point type encoded by \p *this.
92933
92934    The behavior is undefined if \p *this does not encode a floating
92935    point type.
92936  */
92937  Floating_Point_Format floating_point_format() const;
92938
92939  //! Checks if all the invariants are satisfied.
92940  bool OK() const;
92941
92942private:
92943  //! A 32-bit word encoding the type.
92944  struct Implementation {
92945    bool bounded_integer:1;
92946    unsigned int bounded_integer_type_width:23;
92947    unsigned int bounded_integer_type_representation:2;
92948    unsigned int bounded_integer_type_overflow:2;
92949    unsigned int floating_point_format:4;
92950  };
92951
92952  //! Constructor from \p implementation.
92953  Concrete_Expression_Type(Implementation implementation);
92954
92955  //! The encoding of \p *this.
92956  Implementation impl;
92957};
92958
92959//! Base class for all concrete expressions.
92960template <typename Target>
92961class Concrete_Expression_Common {
92962public:
92963  //! Returns the type of \* this.
92964  Concrete_Expression_Type type() const;
92965
92966  //! Returns the kind of \* this.
92967  Concrete_Expression_Kind kind() const;
92968
92969  //! Tests if \p *this has the same kind as <CODE>Derived\<Target\></CODE>.
92970  template <template <typename T> class Derived>
92971  bool is() const;
92972
92973  /*! \brief
92974    Returns a pointer to \p *this converted to type
92975    <CODE>Derived\<Target\>*</CODE>.
92976  */
92977  template <template <typename T> class Derived>
92978  Derived<Target>* as();
92979
92980  /*! \brief
92981    Returns a pointer to \p *this converted to type
92982    <CODE>const Derived\<Target\>*</CODE>.
92983  */
92984  template <template <typename T> class Derived>
92985  const Derived<Target>* as() const;
92986
92987};
92988
92989//! Base class for binary operator applied to two concrete expressions.
92990template <typename Target>
92991class Binary_Operator_Common {
92992public:
92993  //! Returns a constant identifying the operator of \p *this.
92994  Concrete_Expression_BOP binary_operator() const;
92995
92996  //! Returns the left-hand side of \p *this.
92997  const Concrete_Expression<Target>* left_hand_side() const;
92998
92999  //! Returns the right-hand side of \p *this.
93000  const Concrete_Expression<Target>* right_hand_side() const;
93001};
93002
93003//! Base class for unary operator applied to one concrete expression.
93004template <typename Target>
93005class Unary_Operator_Common {
93006public:
93007  //! Returns a constant identifying the operator of \p *this.
93008  Concrete_Expression_UOP unary_operator() const;
93009
93010  //! Returns the argument \p *this.
93011  const Concrete_Expression<Target>* argument() const;
93012};
93013
93014//! Base class for cast operator concrete expressions.
93015template <typename Target>
93016class Cast_Operator_Common {
93017  //! Returns the casted expression.
93018  const Concrete_Expression<Target>* argument() const;
93019};
93020
93021//! Base class for integer constant concrete expressions.
93022template <typename Target>
93023class Integer_Constant_Common {
93024};
93025
93026//! Base class for floating-point constant concrete expression.
93027template <typename Target>
93028class Floating_Point_Constant_Common {
93029};
93030
93031//! Base class for references to some approximable.
93032template <typename Target>
93033class Approximable_Reference_Common {
93034};
93035
93036} // namespace Parma_Polyhedra_Library
93037
93038/* Automatically generated from PPL source file ../src/Concrete_Expression_inlines.hh line 1. */
93039/* Concrete_Expression class implementation: inline functions.
93040*/
93041
93042
93043namespace Parma_Polyhedra_Library {
93044
93045inline
93046Concrete_Expression_Type
93047::Concrete_Expression_Type(Implementation implementation)
93048  : impl(implementation) {
93049}
93050
93051inline Concrete_Expression_Type
93052Concrete_Expression_Type
93053::bounded_integer(const Bounded_Integer_Type_Width width,
93054                  const Bounded_Integer_Type_Representation representation,
93055                  const Bounded_Integer_Type_Overflow overflow) {
93056  Implementation impl;
93057  impl.bounded_integer = true;
93058  impl.bounded_integer_type_width = width;
93059  impl.bounded_integer_type_representation = representation;
93060  impl.bounded_integer_type_overflow = overflow;
93061  // Arbitrary choice to ensure determinism.
93062  impl.floating_point_format = IEEE754_HALF;
93063  return Concrete_Expression_Type(impl);
93064}
93065
93066inline Concrete_Expression_Type
93067Concrete_Expression_Type
93068::floating_point(const Floating_Point_Format format) {
93069  Implementation impl;
93070  impl.bounded_integer = false;
93071  impl.floating_point_format = format;
93072  // Arbitrary choices to ensure determinism.
93073  impl.bounded_integer_type_width = BITS_128;
93074  impl.bounded_integer_type_representation =  SIGNED_2_COMPLEMENT;
93075  impl.bounded_integer_type_overflow = OVERFLOW_IMPOSSIBLE;
93076  return Concrete_Expression_Type(impl);
93077}
93078
93079inline bool
93080Concrete_Expression_Type::is_bounded_integer() const {
93081  return impl.bounded_integer;
93082}
93083
93084inline bool
93085Concrete_Expression_Type::is_floating_point() const {
93086  return !impl.bounded_integer;
93087}
93088
93089inline Bounded_Integer_Type_Width
93090Concrete_Expression_Type::bounded_integer_type_width() const {
93091  const unsigned int u = impl.bounded_integer_type_width;
93092  return static_cast<Bounded_Integer_Type_Width>(u);
93093}
93094
93095inline Bounded_Integer_Type_Representation
93096Concrete_Expression_Type::bounded_integer_type_representation() const {
93097  const unsigned int u = impl.bounded_integer_type_representation;
93098  return static_cast<Bounded_Integer_Type_Representation>(u);
93099}
93100
93101inline Bounded_Integer_Type_Overflow
93102Concrete_Expression_Type::bounded_integer_type_overflow() const {
93103  const unsigned int u = impl.bounded_integer_type_overflow;
93104  return static_cast<Bounded_Integer_Type_Overflow>(u);
93105}
93106
93107inline Floating_Point_Format
93108Concrete_Expression_Type::floating_point_format() const {
93109  const unsigned int u = impl.floating_point_format;
93110  return static_cast<Floating_Point_Format>(u);
93111}
93112
93113template <typename Target>
93114template <template <typename T> class Derived>
93115inline bool
93116Concrete_Expression_Common<Target>::is() const {
93117  return static_cast<const Concrete_Expression<Target>*>(this)->kind() ==
93118         Derived<Target>::KIND;
93119}
93120
93121template <typename Target>
93122template <template <typename T> class Derived>
93123inline Derived<Target>*
93124Concrete_Expression_Common<Target>::as() {
93125  PPL_ASSERT(is<Derived>());
93126  return static_cast<Derived<Target>*>(this);
93127}
93128
93129template <typename Target>
93130template <template <typename T> class Derived>
93131inline const Derived<Target>*
93132Concrete_Expression_Common<Target>::as() const {
93133  PPL_ASSERT(is<Derived>());
93134  return static_cast<const Derived<Target>*>(this);
93135}
93136
93137} // namespace Parma_Polyhedra_Library
93138
93139/* Automatically generated from PPL source file ../src/Concrete_Expression_defs.hh line 200. */
93140
93141/* Automatically generated from PPL source file ../src/linearize.hh line 31. */
93142#include <map>
93143
93144namespace Parma_Polyhedra_Library {
93145
93146/*! \brief \relates Parma_Polyhedra_Library::Concrete_Expression
93147  Helper function used by <CODE>linearize</CODE> to linearize a
93148  sum of floating point expressions.
93149
93150  Makes \p result become the linearization of \p *this in the given
93151  composite abstract store.
93152
93153  \tparam Target
93154  A type template parameter specifying the instantiation of
93155  Concrete_Expression to be used.
93156
93157  \tparam FP_Interval_Type
93158  A type template parameter for the intervals used in the abstract domain.
93159  The interval bounds should have a floating point type.
93160
93161  \return
93162  <CODE>true</CODE> if the linearization succeeded,
93163  <CODE>false</CODE> otherwise.
93164
93165  \param bop_expr
93166  The binary operator concrete expression to linearize.
93167  Its binary operator type must be <CODE>ADD</CODE>.
93168
93169  \param oracle
93170  The FP_Oracle to be queried.
93171
93172  \param lf_store
93173  The linear form abstract store.
93174
93175  \param result
93176  The modified linear form.
93177
93178  \par Linearization of sum floating-point expressions
93179
93180  Let \f$i + \sum_{v \in \cV}i_{v}v \f$ and
93181  \f$i' + \sum_{v \in \cV}i'_{v}v \f$
93182  be two linear forms and \f$\aslf\f$ a sound abstract operator on linear
93183  forms such that:
93184
93185  \f[
93186  \left(i + \sum_{v \in \cV}i_{v}v \right)
93187  \aslf
93188  \left(i' + \sum_{v \in \cV}i'_{v}v \right)
93189  =
93190  \left(i \asifp i'\right)
93191  + \sum_{v \in \cV}\left(i_{v} \asifp i'_{v} \right)v.
93192  \f]
93193
93194  Given an expression \f$e_{1} \oplus e_{2}\f$ and a composite
93195  abstract store \f$\left \llbracket \rho^{\#}, \rho^{\#}_l \right
93196  \rrbracket\f$, we construct the interval linear form
93197  \f$\linexprenv{e_{1} \oplus e_{2}}{\rho^{\#}}{\rho^{\#}_l}\f$
93198  as follows:
93199  \f[
93200  \linexprenv{e_{1} \oplus e_{2}}{\rho^{\#}}{\rho^{\#}_l}
93201  =
93202  \linexprenv{e_{1}}{\rho^{\#}}{\rho^{\#}_l}
93203  \aslf
93204  \linexprenv{e_{2}}{\rho^{\#}}{\rho^{\#}_l}
93205  \aslf
93206  \varepsilon_{\mathbf{f}}\left(\linexprenv{e_{1}}{\rho^{\#}}{\rho^{\#}_l}
93207  \right)
93208  \aslf
93209  \varepsilon_{\mathbf{f}}\left(\linexprenv{e_{2}}{\rho^{\#}}{\rho^{\#}_l}
93210  \right)
93211  \aslf
93212  mf_{\mathbf{f}}[-1, 1]
93213  \f]
93214  where \f$\varepsilon_{\mathbf{f}}(l)\f$ is the relative error
93215  associated to \f$l\f$ (see method <CODE>relative_error</CODE> of
93216  class Linear_Form) and \f$mf_{\mathbf{f}}\f$ is a rounding
93217  error computed by function <CODE>compute_absolute_error</CODE>.
93218*/
93219template <typename Target, typename FP_Interval_Type>
93220static bool
93221add_linearize(const Binary_Operator<Target>& bop_expr,
93222              const FP_Oracle<Target,FP_Interval_Type>& oracle,
93223              const std::map<dimension_type, Linear_Form<FP_Interval_Type> >&
93224              lf_store,
93225              Linear_Form<FP_Interval_Type>& result) {
93226  PPL_ASSERT(bop_expr.binary_operator() == Binary_Operator<Target>::ADD);
93227
93228  typedef Linear_Form<FP_Interval_Type> FP_Linear_Form;
93229
93230  if (!linearize(*(bop_expr.left_hand_side()), oracle, lf_store, result)) {
93231    return false;
93232  }
93233
93234  Floating_Point_Format analyzed_format =
93235    bop_expr.type().floating_point_format();
93236  FP_Linear_Form rel_error;
93237  result.relative_error(analyzed_format, rel_error);
93238  result += rel_error;
93239  FP_Linear_Form linearized_second_operand;
93240  if (!linearize(*(bop_expr.right_hand_side()), oracle, lf_store,
93241                 linearized_second_operand)) {
93242    return false;
93243  }
93244
93245  result += linearized_second_operand;
93246  linearized_second_operand.relative_error(analyzed_format, rel_error);
93247  result += rel_error;
93248  FP_Interval_Type absolute_error =
93249                   compute_absolute_error<FP_Interval_Type>(analyzed_format);
93250  result += absolute_error;
93251  return !result.overflows();
93252}
93253
93254/*! \brief \relates Parma_Polyhedra_Library::Concrete_Expression
93255  Helper function used by <CODE>linearize</CODE> to linearize a
93256  difference of floating point expressions.
93257
93258  Makes \p result become the linearization of \p *this in the given
93259  composite abstract store.
93260
93261  \tparam Target
93262  A type template parameter specifying the instantiation of
93263  Concrete_Expression to be used.
93264
93265  \tparam FP_Interval_Type
93266  A type template parameter for the intervals used in the abstract domain.
93267  The interval bounds should have a floating point type.
93268
93269  \return
93270  <CODE>true</CODE> if the linearization succeeded,
93271  <CODE>false</CODE> otherwise.
93272
93273  \param bop_expr
93274  The binary operator concrete expression to linearize.
93275  Its binary operator type must be <CODE>SUB</CODE>.
93276
93277  \param oracle
93278  The FP_Oracle to be queried.
93279
93280  \param lf_store
93281  The linear form abstract store.
93282
93283  \param result
93284  The modified linear form.
93285
93286  \par Linearization of difference floating-point expressions
93287
93288  Let \f$i + \sum_{v \in \cV}i_{v}v \f$ and
93289  \f$i' + \sum_{v \in \cV}i'_{v}v \f$
93290  be two linear forms, \f$\aslf\f$ and \f$\adlf\f$ two sound abstract
93291  operators on linear form such that:
93292  \f[
93293  \left(i + \sum_{v \in \cV}i_{v}v\right)
93294  \aslf
93295  \left(i' + \sum_{v \in \cV}i'_{v}v\right)
93296  =
93297  \left(i \asifp i'\right)
93298  + \sum_{v \in \cV}\left(i_{v} \asifp i'_{v}\right)v,
93299  \f]
93300  \f[
93301  \left(i + \sum_{v \in \cV}i_{v}v\right)
93302  \adlf
93303  \left(i' + \sum_{v \in \cV}i'_{v}v\right)
93304  =
93305  \left(i \adifp i'\right)
93306  + \sum_{v \in \cV}\left(i_{v} \adifp i'_{v}\right)v.
93307  \f]
93308  Given an expression \f$e_{1} \ominus e_{2}\f$ and a composite
93309  abstract store \f$\left \llbracket \rho^{\#}, \rho^{\#}_l \right
93310  \rrbracket\f$,  we construct the interval linear form
93311  \f$\linexprenv{e_{1} \ominus e_{2}}{\rho^{\#}}{\rho^{\#}_l}\f$
93312  on \f$\cV\f$ as follows:
93313  \f[
93314  \linexprenv{e_{1} \ominus e_{2}}{\rho^{\#}}{\rho^{\#}_l}
93315  =
93316  \linexprenv{e_{1}}{\rho^{\#}}{\rho^{\#}_l}
93317  \adlf
93318  \linexprenv{e_{2}}{\rho^{\#}}{\rho^{\#}_l}
93319  \aslf
93320  \varepsilon_{\mathbf{f}}\left(\linexprenv{e_{1}}{\rho^{\#}}{\rho^{\#}_l}
93321  \right)
93322  \aslf
93323  \varepsilon_{\mathbf{f}}\left(\linexprenv{e_{2}}{\rho^{\#}}{\rho^{\#}_l}
93324  \right)
93325  \aslf
93326  mf_{\mathbf{f}}[-1, 1]
93327  \f]
93328  where \f$\varepsilon_{\mathbf{f}}(l)\f$ is the relative error
93329  associated to \f$l\f$ (see method <CODE>relative_error</CODE> of
93330  class Linear_Form) and \f$mf_{\mathbf{f}}\f$ is a rounding
93331  error computed by function <CODE>compute_absolute_error</CODE>.
93332*/
93333template <typename Target, typename FP_Interval_Type>
93334static bool
93335sub_linearize(const Binary_Operator<Target>& bop_expr,
93336              const FP_Oracle<Target,FP_Interval_Type>& oracle,
93337              const std::map<dimension_type, Linear_Form<FP_Interval_Type> >& lf_store,
93338              Linear_Form<FP_Interval_Type>& result) {
93339  PPL_ASSERT(bop_expr.binary_operator() == Binary_Operator<Target>::SUB);
93340
93341  typedef Linear_Form<FP_Interval_Type> FP_Linear_Form;
93342
93343  if (!linearize(*(bop_expr.left_hand_side()), oracle, lf_store, result)) {
93344    return false;
93345  }
93346
93347  Floating_Point_Format analyzed_format =
93348    bop_expr.type().floating_point_format();
93349  FP_Linear_Form rel_error;
93350  result.relative_error(analyzed_format, rel_error);
93351  result += rel_error;
93352  FP_Linear_Form linearized_second_operand;
93353  if (!linearize(*(bop_expr.right_hand_side()), oracle, lf_store,
93354                 linearized_second_operand)) {
93355    return false;
93356  }
93357
93358  result -= linearized_second_operand;
93359  linearized_second_operand.relative_error(analyzed_format, rel_error);
93360  result += rel_error;
93361  FP_Interval_Type absolute_error =
93362                   compute_absolute_error<FP_Interval_Type>(analyzed_format);
93363  result += absolute_error;
93364  return !result.overflows();
93365}
93366
93367/*! \brief \relates Parma_Polyhedra_Library::Concrete_Expression
93368  Helper function used by <CODE>linearize</CODE> to linearize a
93369  product of floating point expressions.
93370
93371  Makes \p result become the linearization of \p *this in the given
93372  composite abstract store.
93373
93374  \tparam Target
93375  A type template parameter specifying the instantiation of
93376  Concrete_Expression to be used.
93377
93378  \tparam FP_Interval_Type
93379  A type template parameter for the intervals used in the abstract domain.
93380  The interval bounds should have a floating point type.
93381
93382  \return
93383  <CODE>true</CODE> if the linearization succeeded,
93384  <CODE>false</CODE> otherwise.
93385
93386  \param bop_expr
93387  The binary operator concrete expression to linearize.
93388  Its binary operator type must be <CODE>MUL</CODE>.
93389
93390  \param oracle
93391  The FP_Oracle to be queried.
93392
93393  \param lf_store
93394  The linear form abstract store.
93395
93396  \param result
93397  The modified linear form.
93398
93399  \par Linearization of multiplication floating-point expressions
93400
93401  Let \f$i + \sum_{v \in \cV}i_{v}v \f$ and
93402  \f$i' + \sum_{v \in \cV}i'_{v}v \f$
93403  be two linear forms, \f$\aslf\f$ and \f$\amlf\f$ two sound abstract
93404  operators on linear forms such that:
93405  \f[
93406  \left(i + \sum_{v \in \cV}i_{v}v\right)
93407  \aslf
93408  \left(i' + \sum_{v \in \cV}i'_{v}v\right)
93409  =
93410  \left(i \asifp i'\right)
93411  + \sum_{v \in \cV}\left(i_{v} \asifp i'_{v}\right)v,
93412  \f]
93413  \f[
93414  i
93415  \amlf
93416  \left(i' + \sum_{v \in \cV}i'_{v}v\right)
93417  =
93418  \left(i \amifp i'\right)
93419  + \sum_{v \in \cV}\left(i \amifp i'_{v}\right)v.
93420  \f]
93421  Given an expression \f$[a, b] \otimes e_{2}\f$ and a composite
93422  abstract store \f$\left \llbracket \rho^{\#}, \rho^{\#}_l \right
93423  \rrbracket\f$, we construct the interval linear form
93424  \f$\linexprenv{[a, b] \otimes e_{2}}{\rho^{\#}}{\rho^{\#}_l}\f$
93425  as follows:
93426  \f[
93427  \linexprenv{[a, b] \otimes e_{2}}{\rho^{\#}}{\rho^{\#}_l}
93428  =
93429  \left([a, b]
93430  \amlf
93431  \linexprenv{e_{2}}{\rho^{\#}}{\rho^{\#}_l}\right)
93432  \aslf
93433  \left([a, b]
93434  \amlf
93435  \varepsilon_{\mathbf{f}}\left(\linexprenv{e_{2}}{\rho^{\#}}{\rho^{\#}_l}
93436  \right)\right)
93437  \aslf
93438  mf_{\mathbf{f}}[-1, 1].
93439  \f].
93440
93441  Given an expression \f$e_{1} \otimes [a, b]\f$ and a composite
93442  abstract store \f$\left \llbracket \rho^{\#}, \rho^{\#}_l \right
93443  \rrbracket\f$, we construct the interval linear form
93444  \f$\linexprenv{e_{1} \otimes [a, b]}{\rho^{\#}}{\rho^{\#}_l}\f$
93445  as follows:
93446  \f[
93447  \linexprenv{e_{1} \otimes [a, b]}{\rho^{\#}}{\rho^{\#}_l}
93448  =
93449  \linexprenv{[a, b] \otimes e_{1}}{\rho^{\#}}{\rho^{\#}_l}.
93450  \f]
93451
93452  Given an expression \f$e_{1} \otimes e_{2}\f$ and a composite
93453  abstract store \f$\left \llbracket \rho^{\#}, \rho^{\#}_l \right
93454  \rrbracket\f$, we construct the interval linear form
93455  \f$\linexprenv{e_{1} \otimes e_{2}}{\rho^{\#}}{\rho^{\#}_l}\f$
93456  as follows:
93457  \f[
93458  \linexprenv{e_{1} \otimes e_{2}}{\rho^{\#}}{\rho^{\#}_l}
93459  =
93460  \linexprenv{\iota\left(\linexprenv{e_{1}}{\rho^{\#}}{\rho^{\#}_l}
93461  \right)\rho^{\#}
93462  \otimes e_{2}}{\rho^{\#}}{\rho^{\#}_l},
93463  \f]
93464  where \f$\varepsilon_{\mathbf{f}}(l)\f$ is the relative error
93465  associated to \f$l\f$ (see method <CODE>relative_error</CODE> of
93466  class Linear_Form), \f$\iota(l)\rho^{\#}\f$ is the intervalization
93467  of \f$l\f$ (see method <CODE>intervalize</CODE> of class Linear_Form),
93468  and \f$mf_{\mathbf{f}}\f$ is a rounding error computed by function
93469  <CODE>compute_absolute_error</CODE>.
93470
93471  Even though we intervalize the first operand in the above example, the
93472  actual implementation utilizes an heuristics for choosing which of the two
93473  operands must be intervalized in order to obtain the most precise result.
93474*/
93475template <typename Target, typename FP_Interval_Type>
93476static bool
93477mul_linearize(const Binary_Operator<Target>& bop_expr,
93478              const FP_Oracle<Target,FP_Interval_Type>& oracle,
93479              const std::map<dimension_type, Linear_Form<FP_Interval_Type> >& lf_store,
93480              Linear_Form<FP_Interval_Type>& result) {
93481  PPL_ASSERT(bop_expr.binary_operator() == Binary_Operator<Target>::MUL);
93482
93483  typedef typename FP_Interval_Type::boundary_type analyzer_format;
93484  typedef Linear_Form<FP_Interval_Type> FP_Linear_Form;
93485
93486  /*
93487    FIXME: We currently adopt the "Interval-Size Local" strategy in order to
93488    decide which of the two linear forms must be intervalized, as described
93489    in Section 6.2.4 ("Multiplication Strategies") of Antoine Mine's Ph.D.
93490    thesis "Weakly Relational Numerical Abstract Domains".
93491    In this Section are also described other multiplication strategies, such
93492    as All-Cases, Relative-Size Local, Simplification-Driven Global and
93493    Homogeneity Global.
93494  */
93495
93496  // Here we choose which of the two linear forms must be intervalized.
93497
93498  // true if we intervalize the first form, false if we intervalize the second.
93499  bool intervalize_first;
93500  FP_Linear_Form linearized_first_operand;
93501  if (!linearize(*(bop_expr.left_hand_side()), oracle, lf_store,
93502                 linearized_first_operand)) {
93503    return false;
93504  }
93505  FP_Interval_Type intervalized_first_operand;
93506  if (!linearized_first_operand.intervalize(oracle,
93507                                            intervalized_first_operand)) {
93508    return false;
93509  }
93510  FP_Linear_Form linearized_second_operand;
93511  if (!linearize(*(bop_expr.right_hand_side()), oracle, lf_store,
93512                 linearized_second_operand)) {
93513    return false;
93514  }
93515  FP_Interval_Type intervalized_second_operand;
93516  if (!linearized_second_operand.intervalize(oracle,
93517                                             intervalized_second_operand)) {
93518    return false;
93519  }
93520
93521  // FIXME: we are not sure that what we do here is policy-proof.
93522  if (intervalized_first_operand.is_bounded()) {
93523    if (intervalized_second_operand.is_bounded()) {
93524      analyzer_format first_interval_size
93525        = intervalized_first_operand.upper()
93526        - intervalized_first_operand.lower();
93527      analyzer_format second_interval_size
93528        = intervalized_second_operand.upper()
93529        - intervalized_second_operand.lower();
93530      if (first_interval_size <= second_interval_size) {
93531        intervalize_first = true;
93532      }
93533      else {
93534        intervalize_first = false;
93535      }
93536    }
93537    else {
93538      intervalize_first = true;
93539    }
93540  }
93541  else {
93542    if (intervalized_second_operand.is_bounded()) {
93543      intervalize_first = false;
93544    }
93545    else {
93546      return false;
93547    }
93548  }
93549
93550  // Here we do the actual computation.
93551  // For optimizing, we store the relative error directly into result.
93552  Floating_Point_Format analyzed_format =
93553    bop_expr.type().floating_point_format();
93554  if (intervalize_first) {
93555    linearized_second_operand.relative_error(analyzed_format, result);
93556    linearized_second_operand *= intervalized_first_operand;
93557    result *= intervalized_first_operand;
93558    result += linearized_second_operand;
93559  }
93560  else {
93561    linearized_first_operand.relative_error(analyzed_format, result);
93562    linearized_first_operand *= intervalized_second_operand;
93563    result *= intervalized_second_operand;
93564    result += linearized_first_operand;
93565  }
93566
93567  FP_Interval_Type absolute_error =
93568                   compute_absolute_error<FP_Interval_Type>(analyzed_format);
93569  result += absolute_error;
93570  return !result.overflows();
93571}
93572
93573/*! \brief \relates Parma_Polyhedra_Library::Concrete_Expression
93574  Helper function used by <CODE>linearize</CODE> to linearize a
93575  division of floating point expressions.
93576
93577  Makes \p result become the linearization of \p *this in the given
93578  composite abstract store.
93579
93580  \tparam Target
93581  A type template parameter specifying the instantiation of
93582  Concrete_Expression to be used.
93583
93584  \tparam FP_Interval_Type
93585  A type template parameter for the intervals used in the abstract domain.
93586  The interval bounds should have a floating point type.
93587
93588  \return
93589  <CODE>true</CODE> if the linearization succeeded,
93590  <CODE>false</CODE> otherwise.
93591
93592  \param bop_expr
93593  The binary operator concrete expression to linearize.
93594  Its binary operator type must be <CODE>DIV</CODE>.
93595
93596  \param oracle
93597  The FP_Oracle to be queried.
93598
93599  \param lf_store
93600  The linear form abstract store.
93601
93602  \param result
93603  The modified linear form.
93604
93605  \par Linearization of division floating-point expressions
93606
93607  Let \f$i + \sum_{v \in \cV}i_{v}v \f$ and
93608  \f$i' + \sum_{v \in \cV}i'_{v}v \f$
93609  be two linear forms, \f$\aslf\f$ and \f$\adivlf\f$ two sound abstract
93610  operator on linear forms such that:
93611  \f[
93612  \left(i + \sum_{v \in \cV}i_{v}v\right)
93613  \aslf
93614  \left(i' + \sum_{v \in \cV}i'_{v}v\right)
93615  =
93616  \left(i \asifp i'\right)
93617  + \sum_{v \in \cV}\left(i_{v} \asifp i'_{v}\right)v,
93618  \f]
93619  \f[
93620  \left(i + \sum_{v \in \cV}i_{v}v\right)
93621  \adivlf
93622  i'
93623  =
93624  \left(i \adivifp i'\right)
93625  + \sum_{v \in \cV}\left(i_{v} \adivifp i'\right)v.
93626  \f]
93627  Given an expression \f$e_{1} \oslash [a, b]\f$ and a composite
93628  abstract store \f$\left \llbracket \rho^{\#}, \rho^{\#}_l \right
93629  \rrbracket\f$,
93630  we construct the interval linear form
93631  \f$
93632  \linexprenv{e_{1} \oslash [a, b]}{\rho^{\#}}{\rho^{\#}_l}
93633  \f$
93634  as follows:
93635  \f[
93636  \linexprenv{e_{1} \oslash [a, b]}{\rho^{\#}}{\rho^{\#}_l}
93637  =
93638  \left(\linexprenv{e_{1}}{\rho^{\#}}{\rho^{\#}_l}
93639  \adivlf
93640  [a, b]\right)
93641  \aslf
93642  \left(\varepsilon_{\mathbf{f}}\left(
93643  \linexprenv{e_{1}}{\rho^{\#}}{\rho^{\#}_l}
93644  \right)
93645  \adivlf
93646  [a, b]\right)
93647  \aslf
93648  mf_{\mathbf{f}}[-1, 1],
93649  \f]
93650  given an expression \f$e_{1} \oslash e_{2}\f$ and a composite
93651  abstract store \f$\left \llbracket \rho^{\#}, \rho^{\#}_l \right
93652  \rrbracket\f$, we construct the interval linear form
93653  \f$\linexprenv{e_{1} \oslash e_{2}}{\rho^{\#}}{\rho^{\#}_l}\f$
93654  as follows:
93655  \f[
93656  \linexprenv{e_{1} \oslash e_{2}}{\rho^{\#}}{\rho^{\#}_l}
93657  =
93658  \linexprenv{e_{1} \oslash \iota\left(
93659  \linexprenv{e_{2}}{\rho^{\#}}{\rho^{\#}_l}
93660  \right)\rho^{\#}}{\rho^{\#}}{\rho^{\#}_l},
93661  \f]
93662  where \f$\varepsilon_{\mathbf{f}}(l)\f$ is the relative error
93663  associated to \f$l\f$ (see method <CODE>relative_error</CODE> of
93664  class Linear_Form), \f$\iota(l)\rho^{\#}\f$ is the intervalization
93665  of \f$l\f$ (see method <CODE>intervalize</CODE> of class Linear_Form),
93666  and \f$mf_{\mathbf{f}}\f$ is a rounding error computed by function
93667  <CODE>compute_absolute_error</CODE>.
93668*/
93669template <typename Target, typename FP_Interval_Type>
93670static bool
93671div_linearize(const Binary_Operator<Target>& bop_expr,
93672              const FP_Oracle<Target,FP_Interval_Type>& oracle,
93673              const std::map<dimension_type, Linear_Form<FP_Interval_Type> >& lf_store,
93674              Linear_Form<FP_Interval_Type>& result) {
93675  PPL_ASSERT(bop_expr.binary_operator() == Binary_Operator<Target>::DIV);
93676
93677  typedef Linear_Form<FP_Interval_Type> FP_Linear_Form;
93678
93679  FP_Linear_Form linearized_second_operand;
93680  if (!linearize(*(bop_expr.right_hand_side()), oracle, lf_store,
93681                 linearized_second_operand)) {
93682    return false;
93683  }
93684  FP_Interval_Type intervalized_second_operand;
93685  if (!linearized_second_operand.intervalize(oracle,
93686                                             intervalized_second_operand)) {
93687    return false;
93688  }
93689  // Check if we may divide by zero.
93690  if ((intervalized_second_operand.lower_is_boundary_infinity()
93691       || intervalized_second_operand.lower() <= 0) &&
93692      (intervalized_second_operand.upper_is_boundary_infinity()
93693       || intervalized_second_operand.upper() >= 0)) {
93694    return false;
93695  }
93696  if (!linearize(*(bop_expr.left_hand_side()), oracle, lf_store, result)) {
93697    return false;
93698  }
93699
93700  Floating_Point_Format analyzed_format =
93701    bop_expr.type().floating_point_format();
93702  FP_Linear_Form rel_error;
93703  result.relative_error(analyzed_format, rel_error);
93704  result /= intervalized_second_operand;
93705  rel_error /= intervalized_second_operand;
93706  result += rel_error;
93707  FP_Interval_Type absolute_error =
93708                   compute_absolute_error<FP_Interval_Type>(analyzed_format);
93709  result += absolute_error;
93710  return !result.overflows();
93711}
93712
93713/*! \brief \relates Parma_Polyhedra_Library::Concrete_Expression
93714  Helper function used by <CODE>linearize</CODE> to linearize a cast
93715  floating point expression.
93716
93717  Makes \p result become the linearization of \p *this in the given
93718  composite abstract store.
93719
93720  \tparam Target
93721  A type template parameter specifying the instantiation of
93722  Concrete_Expression to be used.
93723
93724  \tparam FP_Interval_Type
93725  A type template parameter for the intervals used in the abstract domain.
93726  The interval bounds should have a floating point type.
93727
93728  \return
93729  <CODE>true</CODE> if the linearization succeeded,
93730  <CODE>false</CODE> otherwise.
93731
93732  \param cast_expr
93733  The cast operator concrete expression to linearize.
93734
93735  \param oracle
93736  The FP_Oracle to be queried.
93737
93738  \param lf_store
93739  The linear form abstract store.
93740
93741  \param result
93742  The modified linear form.
93743*/
93744template <typename Target, typename FP_Interval_Type>
93745static bool
93746cast_linearize(const Cast_Operator<Target>& cast_expr,
93747               const FP_Oracle<Target,FP_Interval_Type>& oracle,
93748               const std::map<dimension_type, Linear_Form<FP_Interval_Type> >& lf_store,
93749               Linear_Form<FP_Interval_Type>& result) {
93750  typedef typename FP_Interval_Type::boundary_type analyzer_format;
93751  typedef Linear_Form<FP_Interval_Type> FP_Linear_Form;
93752
93753  Floating_Point_Format analyzed_format =
93754    cast_expr.type().floating_point_format();
93755  const Concrete_Expression<Target>* cast_arg = cast_expr.argument();
93756  if (cast_arg->type().is_floating_point()) {
93757    if (!linearize(*cast_arg, oracle, lf_store, result)) {
93758      return false;
93759    }
93760    if (!is_less_precise_than(analyzed_format,
93761                              cast_arg->type().floating_point_format())
93762        || result == FP_Linear_Form(FP_Interval_Type(0))
93763        || result == FP_Linear_Form(FP_Interval_Type(1))) {
93764      /*
93765        FIXME: find a general way to check if the casted constant
93766        is exactly representable in the less precise format.
93767      */
93768      /*
93769        We are casting to a more precise format or casting
93770        a definitely safe value: do not add errors.
93771      */
93772      return true;
93773    }
93774  }
93775  else {
93776    FP_Interval_Type expr_value;
93777    if (!oracle.get_integer_expr_value(*cast_arg, expr_value))
93778      return false;
93779    result = FP_Linear_Form(expr_value);
93780    if (is_less_precise_than(Float<analyzer_format>::Binary::floating_point_format, analyzed_format)
93781        || result == FP_Linear_Form(FP_Interval_Type(0))
93782        || result == FP_Linear_Form(FP_Interval_Type(1))) {
93783      /*
93784        FIXME: find a general way to check if the casted constant
93785        is exactly representable in the less precise format.
93786      */
93787      /*
93788        We are casting to a more precise format or casting
93789        a definitely safe value: do not add errors.
93790      */
93791      return true;
93792    }
93793  }
93794
93795  FP_Linear_Form rel_error;
93796  result.relative_error(analyzed_format, rel_error);
93797  result += rel_error;
93798  FP_Interval_Type absolute_error =
93799                   compute_absolute_error<FP_Interval_Type>(analyzed_format);
93800  result += absolute_error;
93801  return !result.overflows();
93802}
93803
93804//! Linearizes a floating point expression.
93805/*! \relates Parma_Polyhedra_Library::Concrete_Expression
93806  Makes \p result become a linear form that correctly approximates the
93807  value of \p expr in the given composite abstract store.
93808
93809  \tparam Target
93810  A type template parameter specifying the instantiation of
93811  Concrete_Expression to be used.
93812
93813  \tparam FP_Interval_Type
93814  A type template parameter for the intervals used in the abstract domain.
93815  The interval bounds should have a floating point type.
93816
93817  \return
93818  <CODE>true</CODE> if the linearization succeeded,
93819  <CODE>false</CODE> otherwise.
93820
93821  \param expr
93822  The concrete expression to linearize.
93823
93824  \param oracle
93825  The FP_Oracle to be queried.
93826
93827  \param lf_store
93828  The linear form abstract store.
93829
93830  \param result
93831  Becomes the linearized expression.
93832
93833  Formally, if \p expr represents the expression \f$e\f$ and
93834  \p lf_store represents the linear form abstract store \f$\rho^{\#}_l\f$,
93835  then \p result will become \f$\linexprenv{e}{\rho^{\#}}{\rho^{\#}_l}\f$
93836  if the linearization succeeds.
93837*/
93838template <typename Target, typename FP_Interval_Type>
93839bool
93840linearize(const Concrete_Expression<Target>& expr,
93841          const FP_Oracle<Target,FP_Interval_Type>& oracle,
93842          const std::map<dimension_type, Linear_Form<FP_Interval_Type> >& lf_store,
93843          Linear_Form<FP_Interval_Type>& result) {
93844  typedef typename FP_Interval_Type::boundary_type analyzer_format;
93845  typedef Linear_Form<FP_Interval_Type> FP_Linear_Form;
93846  typedef std::map<dimension_type, FP_Linear_Form>
93847    FP_Linear_Form_Abstract_Store;
93848
93849  PPL_ASSERT(expr.type().is_floating_point());
93850  // Check that analyzer_format is a floating point type.
93851  PPL_COMPILE_TIME_CHECK(!std::numeric_limits<analyzer_format>::is_exact,
93852      "linearize<Target, FP_Interval_Type>:"
93853      " FP_Interval_Type is not the type of an interval with floating point boundaries.");
93854
93855  switch(expr.kind()) {
93856  case Integer_Constant<Target>::KIND:
93857    PPL_UNREACHABLE;
93858    break;
93859  case Floating_Point_Constant<Target>::KIND:
93860  {
93861    const Floating_Point_Constant<Target>* fpc_expr =
93862      expr.template as<Floating_Point_Constant>();
93863    FP_Interval_Type constant_value;
93864    if (!oracle.get_fp_constant_value(*fpc_expr, constant_value)) {
93865      return false;
93866    }
93867    result = FP_Linear_Form(constant_value);
93868    return true;
93869  }
93870  case Unary_Operator<Target>::KIND:
93871  {
93872    const Unary_Operator<Target>* uop_expr =
93873      expr.template as<Unary_Operator>();
93874    switch (uop_expr->unary_operator()) {
93875    case Unary_Operator<Target>::UPLUS:
93876      return linearize(*(uop_expr->argument()), oracle, lf_store, result);
93877    case Unary_Operator<Target>::UMINUS:
93878      if (!linearize(*(uop_expr->argument()), oracle, lf_store, result)) {
93879        return false;
93880      }
93881
93882      result.negate();
93883      return true;
93884    case Unary_Operator<Target>::BNOT:
93885      throw std::runtime_error("PPL internal error: unimplemented");
93886      break;
93887    default:
93888      PPL_UNREACHABLE;
93889      break;
93890    }
93891    break;
93892  }
93893  case Binary_Operator<Target>::KIND:
93894  {
93895    const Binary_Operator<Target>* bop_expr =
93896      expr.template as<Binary_Operator>();
93897    switch (bop_expr->binary_operator()) {
93898    case Binary_Operator<Target>::ADD:
93899      return add_linearize(*bop_expr, oracle, lf_store, result);
93900    case Binary_Operator<Target>::SUB:
93901      return sub_linearize(*bop_expr, oracle, lf_store, result);
93902    case Binary_Operator<Target>::MUL:
93903      return mul_linearize(*bop_expr, oracle, lf_store, result);
93904    case Binary_Operator<Target>::DIV:
93905      return div_linearize(*bop_expr, oracle, lf_store, result);
93906    case Binary_Operator<Target>::REM:
93907    case Binary_Operator<Target>::BAND:
93908    case Binary_Operator<Target>::BOR:
93909    case Binary_Operator<Target>::BXOR:
93910    case Binary_Operator<Target>::LSHIFT:
93911    case Binary_Operator<Target>::RSHIFT:
93912      // FIXME: can we do better?
93913      return false;
93914    default:
93915      PPL_UNREACHABLE;
93916      return false;
93917    }
93918    break;
93919  }
93920  case Approximable_Reference<Target>::KIND:
93921  {
93922    const Approximable_Reference<Target>* ref_expr =
93923      expr.template as<Approximable_Reference>();
93924    std::set<dimension_type> associated_dimensions;
93925    if (!oracle.get_associated_dimensions(*ref_expr, associated_dimensions)
93926        || associated_dimensions.empty()) {
93927      /*
93928        We were unable to find any associated space dimension:
93929        linearization fails.
93930      */
93931      return false;
93932    }
93933
93934    if (associated_dimensions.size() == 1) {
93935      /* If a linear form associated to the only referenced
93936         space dimension exists in lf_store, return that form.
93937         Otherwise, return the simplest linear form. */
93938      dimension_type variable_index = *associated_dimensions.begin();
93939      PPL_ASSERT(variable_index != not_a_dimension());
93940
93941      typename FP_Linear_Form_Abstract_Store::const_iterator
93942        variable_value = lf_store.find(variable_index);
93943      if (variable_value == lf_store.end()) {
93944        result = FP_Linear_Form(Variable(variable_index));
93945        return true;
93946      }
93947
93948      result = FP_Linear_Form(variable_value->second);
93949      /* FIXME: do we really need to contemplate the possibility
93950         that an unbounded linear form was saved into lf_store? */
93951      return !result.overflows();
93952    }
93953
93954    /*
93955      Here associated_dimensions.size() > 1. Try to return the LUB
93956      of all intervals associated to each space dimension.
93957    */
93958    PPL_ASSERT(associated_dimensions.size() > 1);
93959    std::set<dimension_type>::const_iterator i
93960      = associated_dimensions.begin();
93961    std::set<dimension_type>::const_iterator i_end
93962      = associated_dimensions.end();
93963    FP_Interval_Type lub(EMPTY);
93964    for (; i != i_end; ++i) {
93965      FP_Interval_Type curr_int;
93966      PPL_ASSERT(*i != not_a_dimension());
93967      if (!oracle.get_interval(*i, curr_int)) {
93968        return false;
93969      }
93970
93971      lub.join_assign(curr_int);
93972    }
93973
93974    result = FP_Linear_Form(lub);
93975    return !result.overflows();
93976  }
93977  case Cast_Operator<Target>::KIND:
93978  {
93979    const Cast_Operator<Target>* cast_expr =
93980      expr.template as<Cast_Operator>();
93981    return cast_linearize(*cast_expr, oracle, lf_store, result);
93982  }
93983  default:
93984    PPL_UNREACHABLE;
93985    break;
93986  }
93987
93988  PPL_UNREACHABLE;
93989  return false;
93990}
93991
93992} // namespace Parma_Polyhedra_Library
93993
93994/* Automatically generated from PPL source file ../src/PIP_Tree_defs.hh line 1. */
93995/* PIP_Tree_Node class declaration.
93996*/
93997
93998
93999/* Automatically generated from PPL source file ../src/PIP_Tree_types.hh line 1. */
94000
94001
94002namespace Parma_Polyhedra_Library {
94003
94004class PIP_Tree_Node;
94005class PIP_Solution_Node;
94006class PIP_Decision_Node;
94007
94008typedef const PIP_Tree_Node* PIP_Tree;
94009
94010} // namespace Parma_Polyhedra_Library
94011
94012/* Automatically generated from PPL source file ../src/PIP_Problem_defs.hh line 1. */
94013/* PIP_Problem class declaration.
94014*/
94015
94016
94017/* Automatically generated from PPL source file ../src/PIP_Problem_defs.hh line 36. */
94018#include <vector>
94019#include <deque>
94020#include <iosfwd>
94021
94022namespace Parma_Polyhedra_Library {
94023
94024namespace IO_Operators {
94025
94026//! Output operator.
94027/*! \relates Parma_Polyhedra_Library::PIP_Problem */
94028std::ostream&
94029operator<<(std::ostream& s, const PIP_Problem& pip);
94030
94031} // namespace IO_Operators
94032
94033//! Swaps \p x with \p y.
94034/*! \relates PIP_Problem */
94035void swap(PIP_Problem& x, PIP_Problem& y);
94036
94037} // namespace Parma_Polyhedra_Library
94038
94039//! A Parametric Integer (linear) Programming problem.
94040/*! \ingroup PPL_CXX_interface
94041  An object of this class encodes a parametric integer (linear)
94042  programming problem. The PIP problem is specified by providing:
94043   - the dimension of the vector space;
94044   - the subset of those dimensions of the vector space that are
94045     interpreted as integer parameters (the other space dimensions
94046     are interpreted as non-parameter integer variables);
94047   - a finite set of linear equality and (strict or non-strict)
94048     inequality constraints involving variables and/or parameters;
94049     these constraints are used to define:
94050       - the <EM>feasible region</EM>, if they involve one or more
94051         problem variable (and maybe some parameters);
94052       - the <EM>initial context</EM>, if they only involve the
94053         parameters;
94054   - optionally, the so-called <EM>big parameter</EM>,
94055     i.e., a problem parameter to be considered arbitrarily big.
94056
94057  Note that all problem variables and problem parameters are assumed
94058  to take non-negative integer values, so that there is no need
94059  to specify non-negativity constraints.
94060
94061  The class provides support for the (incremental) solution of the
94062  PIP problem based on variations of the revised simplex method and
94063  on Gomory cut generation techniques.
94064
94065  The solution for a PIP problem is the lexicographic minimum of the
94066  integer points of the feasible region, expressed in terms of the
94067  parameters. As the problem to be solved only involves non-negative
94068  variables and parameters, the problem will always be either unfeasible
94069  or optimizable.
94070
94071  As the feasibility and the solution value of a PIP problem depend on the
94072  values of the parameters, the solution is a binary decision tree,
94073  dividing the context parameter set into subsets.
94074  The tree nodes are of two kinds:
94075   - \e Decision nodes.
94076     These are internal tree nodes encoding one or more linear tests
94077     on the parameters; if all the tests are satisfied, then the solution
94078     is the node's \e true child; otherwise, the solution is the node's
94079     \e false child;
94080   - \e Solution nodes.
94081     These are leaf nodes in the tree, encoding the solution of the problem
94082     in the current context subset, where each variable is defined in terms
94083     of a linear expression of the parameters.
94084     Solution nodes also optionally embed a set of parameter constraints:
94085     if all these constraints are satisfied, the solution is described by
94086     the node, otherwise the problem has no solution.
94087
94088  It may happen that a decision node has no \e false child. This means
94089  that there is no solution if at least one of the corresponding
94090  constraints is not satisfied. Decision nodes having two or more linear
94091  tests on the parameters cannot have a \e false child. Decision nodes
94092  always have a \e true child.
94093
94094  Both kinds of tree nodes may also contain the definition of extra
94095  parameters which are artificially introduced by the solver to enforce
94096  an integral solution. Such artificial parameters are defined by
94097  the integer division of a linear expression on the parameters
94098  by an integer coefficient.
94099
94100  By exploiting the incremental nature of the solver, it is possible
94101  to reuse part of the computational work already done when solving
94102  variants of a given PIP_Problem: currently, incremental resolution
94103  supports the addition of space dimensions, the addition of parameters
94104  and the addition of constraints.
94105
94106  \par Example problem
94107  An example PIP problem can be defined the following:
94108  \code
94109  3*j >= -2*i+8
94110  j <= 4*i - 4
94111  i <= n
94112  j <= m
94113  \endcode
94114  where \c i and \c j are the problem variables
94115  and \c n and \c m are the problem parameters.
94116  This problem can be optimized; the resulting solution tree may be
94117  represented as follows:
94118  \verbatim
94119  if 7*n >= 10 then
94120    if 7*m >= 12 then
94121      {i = 2 ; j = 2}
94122    else
94123      Parameter P = (m) div 2
94124      if 2*n + 3*m >= 8 then
94125        {i = -m - P + 4 ; j = m}
94126      else
94127        _|_
94128  else
94129    _|_
94130  \endverbatim
94131  The solution tree starts with a decision node depending on the
94132  context constraint <code>7*n >= 10</code>.
94133  If this constraint is satisfied by the values assigned to the
94134  problem parameters, then the (textually first) \c then branch is taken,
94135  reaching the \e true child of the root node (which in this case
94136  is another decision node); otherwise, the (textually last) \c else
94137  branch is taken, for which there is no corresponding \e false child.
94138  \par
94139  The \f$\perp\f$ notation, also called \e bottom, denotes the
94140  lexicographic minimum of an empty set of solutions,
94141  here meaning the corresponding subproblem is unfeasible.
94142  \par
94143  Notice that a tree node may introduce new (non-problem) parameters,
94144  as is the case for parameter \c P in the (textually first) \c else
94145  branch above. These \e artificial parameters are only meaningful
94146  inside the subtree where they are defined and are used to define
94147  the parametric values of the problem variables in solution nodes
94148  (e.g., the <CODE>{i,j}</CODE> vector in the textually third \c then branch).
94149
94150  \par Context restriction
94151  The above solution is correct in an unrestricted initial context,
94152  meaning all possible values are allowed for the parameters. If we
94153  restrict the context with the following parameter inequalities:
94154  \code
94155  m >= n
94156  n >= 5
94157  \endcode
94158  then the resulting optimizing tree will be a simple solution node:
94159  \verbatim
94160  {i = 2 ; j = 2}
94161  \endverbatim
94162
94163  \par Creating the PIP_Problem object
94164  The PIP_Problem object corresponding to the above example can be
94165  created as follows:
94166  \code
94167  Variable i(0);
94168  Variable j(1);
94169  Variable n(2);
94170  Variable m(3);
94171  Variables_Set params(n, m);
94172  Constraint_System cs;
94173  cs.insert(3*j >= -2*i+8);
94174  cs.insert(j <= 4*i - 4);
94175  cs.insert(j <= m);
94176  cs.insert(i <= n);
94177  PIP_Problem pip(cs.space_dimension(), cs.begin(), cs.end(), params);
94178  \endcode
94179  If you want to restrict the initial context, simply add the parameter
94180  constraints the same way as for normal constraints.
94181  \code
94182  cs.insert(m >= n);
94183  cs.insert(n >= 5);
94184  \endcode
94185
94186  \par Solving the problem
94187  Once the PIP_Problem object has been created, you can start the
94188  resolution of the problem by calling the solve() method:
94189  \code
94190  PIP_Problem_Status status = pip.solve();
94191  \endcode
94192  where the returned \c status indicates if the problem has been optimized
94193  or if it is unfeasible for any possible configuration of the parameter
94194  values. The resolution process is also started if an attempt is made
94195  to get its solution, as follows:
94196  \code
94197  const PIP_Tree_Node* node = pip.solution();
94198  \endcode
94199  In this case, an unfeasible problem will result in an empty solution
94200  tree, i.e., assigning a null pointer to \c node.
94201
94202  \par Printing the solution tree
94203  A previously computed solution tree may be printed as follows:
94204  \code
94205  pip.print_solution(std::cout);
94206  \endcode
94207  This will produce the following output (note: variables and parameters
94208  are printed according to the default output function; see
94209  <code>Variable::set_output_function</code>):
94210  \verbatim
94211  if 7*C >= 10 then
94212    if 7*D >= 12 then
94213      {2 ; 2}
94214    else
94215      Parameter E = (D) div 2
94216      if 2*C + 3*D >= 8 then
94217        {-D - E + 4 ; D}
94218      else
94219        _|_
94220  else
94221    _|_
94222  \endverbatim
94223
94224  \par Spanning the solution tree
94225  A parameter assignment for a PIP problem binds each of the problem
94226  parameters to a non-negative integer value. After fixing a parameter
94227  assignment, the ``spanning'' of the PIP problem solution tree refers
94228  to the process whereby the solution tree is navigated, starting from
94229  the root node: the value of artificial parameters is computed according
94230  to the parameter assignment and the node's constraints are evaluated,
94231  thereby descending in either the true or the false subtree of decision
94232  nodes and eventually reaching a solution node or a bottom node.
94233  If a solution node is found, each of the problem variables is provided
94234  with a parametric expression, which can be evaluated to a fixed value
94235  using the given parameter assignment and the computed values for
94236  artificial parameters.
94237  \par
94238  The coding of the spanning process can be done as follows.
94239  First, the root of the PIP solution tree is retrieved:
94240  \code
94241  const PIP_Tree_Node* node = pip.solution();
94242  \endcode
94243  If \c node represents an unfeasible solution (i.e., \f$\perp\f$),
94244  its value will be \c 0. For a non-null tree node, the virtual methods
94245  \c PIP_Tree_Node::as_decision() and \c PIP_Tree_Node::as_solution()
94246  can be used to check whether the node is a decision or a solution node:
94247  \code
94248  const PIP_Solution_Node* sol = node->as_solution();
94249  if (sol != 0) {
94250    // The node is a solution node
94251    ...
94252  }
94253  else {
94254    // The node is a decision node
94255    const PIP_Decision_Node* dec = node->as_decision();
94256    ...
94257  }
94258  \endcode
94259  \par
94260  The true (resp., false) child node of a Decision Node may be accessed by
94261  using method \c PIP_Decision_Node::child_node(bool), passing \c true
94262  (resp., \c false) as the input argument.
94263
94264  \par Artificial parameters
94265  A PIP_Tree_Node::Artificial_Parameter object represents the result
94266  of the integer division of a Linear_Expression (on the other
94267  parameters, including the previously-defined artificials)
94268  by an integer denominator (a Coefficient object).
94269  The dimensions of the artificial parameters (if any) in a tree node
94270  have consecutive indices starting from <code>dim+1</code>, where the value
94271  of \c dim is computed as follows:
94272   - for the tree root node, \c dim is the space dimension of the PIP_Problem;
94273   - for any other node of the tree, it is recursively obtained by adding
94274     the value of \c dim computed for the parent node to the number of
94275     artificial parameters defined in the parent node.
94276  \par
94277  Since the numbering of dimensions for artificial parameters follows
94278  the rule above, the addition of new problem variables and/or new problem
94279  parameters to an already solved PIP_Problem object (as done when
94280  incrementally solving a problem) will result in the systematic
94281  renumbering of all the existing artificial parameters.
94282
94283  \par Node constraints
94284  All kind of tree nodes can contain context constraints.
94285  Decision nodes always contain at least one of them.
94286  The node's local constraint system can be obtained using method
94287  PIP_Tree_Node::constraints.
94288  These constraints only involve parameters, including both the problem
94289  parameters and the artificial parameters that have been defined
94290  in nodes occurring on the path from the root node to the current node.
94291  The meaning of these constraints is as follows:
94292   - On a decision node, if all tests in the constraints are true, then the
94293     solution is the \e true child; otherwise it is the \e false child.
94294   - On a solution node, if the (possibly empty) system of constraints
94295     evaluates to true for a given parameter assignment, then the solution
94296     is described by the node; otherwise the solution is \f$\perp\f$
94297     (i.e., the problem is unfeasible for that parameter assignment).
94298
94299  \par Getting the optimal values for the variables
94300  After spanning the solution tree using the given parameter assignment,
94301  if a solution node has been reached, then it is possible to retrieve
94302  the parametric expression for each of the problem variables using
94303  method PIP_Solution_Node::parametric_values. The retrieved expression
94304  will be defined in terms of all the parameters (problem parameters
94305  and artificial parameters defined along the path).
94306
94307  \par Solving maximization problems
94308  You can solve a lexicographic maximization problem by reformulating its
94309  constraints using variable substitution. Proceed the following steps:
94310   - Create a big parameter (see PIP_Problem::set_big_parameter_dimension),
94311     which we will call \f$M\f$.
94312   - Reformulate each of the maximization problem constraints by
94313     substituting each \f$x_i\f$ variable with an expression of the form
94314     \f$M-x'_i\f$, where the \f$x'_i\f$ variables are positive variables to
94315     be minimized.
94316   - Solve the lexicographic minimum for the \f$x'\f$ variable vector.
94317   - In the solution expressions, the values of the \f$x'\f$ variables will
94318     be expressed in the form: \f$x'_i = M-x_i\f$. To get back the value of
94319     the expression of each \f$x_i\f$ variable, just apply the
94320     formula: \f$x_i = M-x'_i\f$.
94321  \par
94322  Note that if the resulting expression of one of the \f$x'_i\f$ variables
94323  is not in the \f$x'_i = M-x_i\f$ form, this means that the
94324  sign-unrestricted problem is unbounded.
94325  \par
94326  You can choose to maximize only a subset of the variables while minimizing
94327  the other variables. In that case, just apply the variable substitution
94328  method on the variables you want to be maximized. The variable
94329  optimization priority will still be in lexicographic order.
94330
94331  \par
94332  \b Example: consider you want to find the lexicographic maximum of the
94333  \f$(x,y)\f$ vector, under the constraints:
94334    \f[\left\{\begin{array}{l}
94335      y \geq 2x - 4\\
94336      y \leq -x + p
94337    \end{array}\right.\f]
94338  \par
94339  where \f$p\f$ is a parameter.
94340  \par
94341  After variable substitution, the constraints become:
94342    \f[\left\{\begin{array}{l}
94343      M - y \geq 2M - 2x - 4\\
94344      M - y \leq -M + x + p
94345    \end{array}\right.\f]
94346  \par
94347  The code for creating the corresponding problem object is the following:
94348  \code
94349  Variable x(0);
94350  Variable y(1);
94351  Variable p(2);
94352  Variable M(3);
94353  Variables_Set params(p, M);
94354  Constraint_System cs;
94355  cs.insert(M - y >= 2*M - 2*x - 4);
94356  cs.insert(M - y <= -M + x + p);
94357  PIP_Problem pip(cs.space_dimension(), cs.begin(), cs.end(), params);
94358  pip.set_big_parameter_dimension(3);     // M is the big parameter
94359  \endcode
94360  Solving the problem provides the following solution:
94361  \verbatim
94362  Parameter E = (C + 1) div 3
94363  {D - E - 1 ; -C + D + E + 1}
94364  \endverbatim
94365  Under the notations above, the solution is:
94366  \f[ \left\{\begin{array}{l}
94367    x' = M - \left\lfloor\frac{p+1}{3}\right\rfloor - 1 \\
94368    y' = M - p + \left\lfloor\frac{p+1}{3}\right\rfloor + 1
94369  \end{array}\right.
94370  \f]
94371  \par
94372  Performing substitution again provides us with the values of the original
94373  variables:
94374  \f[ \left\{\begin{array}{l}
94375    x = \left\lfloor\frac{p+1}{3}\right\rfloor + 1 \\
94376    y = p - \left\lfloor\frac{p+1}{3}\right\rfloor - 1
94377  \end{array}\right.
94378  \f]
94379
94380  \par Allowing variables to be arbitrarily signed
94381  You can deal with arbitrarily signed variables by reformulating the
94382  constraints using variable substitution. Proceed the following steps:
94383   - Create a big parameter (see PIP_Problem::set_big_parameter_dimension),
94384     which we will call \f$M\f$.
94385   - Reformulate each of the maximization problem constraints by
94386     substituting each \f$x_i\f$ variable with an expression of the form
94387     \f$x'_i-M\f$, where the \f$x'_i\f$ variables are positive.
94388   - Solve the lexicographic minimum for the \f$x'\f$ variable vector.
94389   - The solution expression can be read in the form:
94390   - In the solution expressions, the values of the \f$x'\f$ variables will
94391     be expressed in the form: \f$x'_i = x_i+M\f$. To get back the value of
94392     the expression of each signed \f$x_i\f$ variable, just apply the
94393     formula: \f$x_i = x'_i-M\f$.
94394  \par
94395  Note that if the resulting expression of one of the \f$x'_i\f$ variables
94396  is not in the \f$x'_i = x_i+M\f$ form, this means that the
94397  sign-unrestricted problem is unbounded.
94398  \par
94399  You can choose to define only a subset of the variables to be
94400  sign-unrestricted. In that case, just apply the variable substitution
94401  method on the variables you want to be sign-unrestricted.
94402
94403  \par
94404  \b Example: consider you want to find the lexicographic minimum of the
94405  \f$(x,y)\f$ vector, where the \f$x\f$ and \f$y\f$ variables are
94406  sign-unrestricted, under the constraints:
94407    \f[\left\{\begin{array}{l}
94408      y \geq -2x - 4\\
94409      2y \leq x + 2p
94410    \end{array}\right.\f]
94411  \par
94412  where \f$p\f$ is a parameter.
94413  \par
94414  After variable substitution, the constraints become:
94415    \f[\left\{\begin{array}{l}
94416      y' - M \geq -2x' + 2M - 4\\
94417      2y' - 2M \leq x' - M + 2p
94418    \end{array}\right.\f]
94419  \par
94420  The code for creating the corresponding problem object is the following:
94421  \code
94422  Variable x(0);
94423  Variable y(1);
94424  Variable p(2);
94425  Variable M(3);
94426  Variables_Set params(p, M);
94427  Constraint_System cs;
94428  cs.insert(y - M >= -2*x + 2*M - 4);
94429  cs.insert(2*y - 2*M <= x - M + 2*p);
94430  PIP_Problem pip(cs.space_dimension(), cs.begin(), cs.end(), params);
94431  pip.set_big_parameter_dimension(3);     // M is the big parameter
94432  \endcode
94433  \par
94434  Solving the problem provides the following solution:
94435  \verbatim
94436  Parameter E = (2*C + 3) div 5
94437  {D - E - 1 ; D + 2*E - 2}
94438  \endverbatim
94439  Under the notations above, the solution is:
94440  \f[ \left\{\begin{array}{l}
94441    x' = M - \left\lfloor\frac{2p+3}{5}\right\rfloor - 1 \\
94442    y' = M + 2\left\lfloor\frac{2p+3}{5}\right\rfloor - 2
94443  \end{array}\right.
94444  \f]
94445  \par
94446  Performing substitution again provides us with the values of the original
94447  variables:
94448  \f[ \left\{\begin{array}{l}
94449    x = -\left\lfloor\frac{2p+3}{5}\right\rfloor - 1 \\
94450    y = 2\left\lfloor\frac{2p+3}{5}\right\rfloor - 2
94451  \end{array}\right.
94452  \f]
94453
94454  \par Allowing parameters to be arbitrarily signed
94455  You can consider a parameter \f$p\f$ arbitrarily signed by replacing
94456  \f$p\f$ with \f$p^+-p^-\f$, where both \f$p^+\f$ and \f$p^-\f$ are
94457  positive parameters. To represent a set of arbitrarily signed parameters,
94458  replace each parameter \f$p_i\f$ with \f$p^+_i-p^-\f$, where \f$-p^-\f$ is
94459  the minimum negative value of all parameters.
94460
94461  \par Minimizing a linear cost function
94462  Lexicographic solving can be used to find the parametric minimum of a
94463  linear cost function.
94464  \par
94465  Suppose the variables are named \f$x_1, x_2, \dots, x_n\f$, and the
94466  parameters \f$p_1, p_2, \dots, p_m\f$. You can minimize a linear cost
94467  function \f$f(x_2, \dots, x_n, p_1, \dots, p_m)\f$ by simply adding the
94468  constraint \f$x_1 \geq f(x_2, \dots, x_n, p_1, \dots, p_m)\f$ to the
94469  constraint system. As lexicographic minimization ensures \f$x_1\f$ is
94470  minimized in priority, and because \f$x_1\f$ is forced by a constraint to
94471  be superior or equal to the cost function, optimal solutions of the
94472  problem necessarily ensure that the solution value of \f$x_1\f$ is the
94473  optimal value of the cost function.
94474*/
94475class Parma_Polyhedra_Library::PIP_Problem {
94476public:
94477  //! Builds a trivial PIP problem.
94478  /*!
94479    A trivial PIP problem requires to compute the lexicographic minimum
94480    on a vector space under no constraints and with no parameters:
94481    due to the implicit non-negativity constraints, the origin of the
94482    vector space is an optimal solution.
94483
94484    \param dim
94485    The dimension of the vector space enclosing \p *this
94486    (optional argument with default value \f$0\f$).
94487
94488    \exception std::length_error
94489    Thrown if \p dim exceeds <CODE>max_space_dimension()</CODE>.
94490  */
94491  explicit PIP_Problem(dimension_type dim = 0);
94492
94493  /*! \brief
94494    Builds a PIP problem having space dimension \p dim
94495    from the sequence of constraints in the range
94496    \f$[\mathrm{first}, \mathrm{last})\f$;
94497    those dimensions whose indices occur in \p p_vars are
94498    interpreted as parameters.
94499
94500    \param dim
94501    The dimension of the vector space (variables and parameters) enclosing
94502    \p *this.
94503
94504    \param first
94505    An input iterator to the start of the sequence of constraints.
94506
94507    \param last
94508    A past-the-end input iterator to the sequence of constraints.
94509
94510    \param p_vars
94511    The set of variables' indexes that are interpreted as parameters.
94512
94513    \exception std::length_error
94514    Thrown if \p dim exceeds <CODE>max_space_dimension()</CODE>.
94515
94516    \exception std::invalid_argument
94517    Thrown if the space dimension of a constraint in the sequence
94518    (resp., the parameter variables) is strictly greater than \p dim.
94519  */
94520  template <typename In>
94521  PIP_Problem(dimension_type dim, In first, In last,
94522              const Variables_Set& p_vars);
94523
94524  //! Ordinary copy-constructor.
94525  PIP_Problem(const PIP_Problem& y);
94526
94527  //! Destructor.
94528  ~PIP_Problem();
94529
94530  //! Assignment operator.
94531  PIP_Problem& operator=(const PIP_Problem& y);
94532
94533  //! Returns the maximum space dimension a PIP_Problem can handle.
94534  static dimension_type max_space_dimension();
94535
94536  //! Returns the space dimension of the PIP problem.
94537  dimension_type space_dimension() const;
94538
94539  /*! \brief
94540    Returns a set containing all the variables' indexes representing
94541    the parameters of the PIP problem.
94542  */
94543  const Variables_Set& parameter_space_dimensions() const;
94544
94545private:
94546  //! A type alias for a sequence of constraints.
94547  typedef std::vector<Constraint> Constraint_Sequence;
94548
94549public:
94550  /*! \brief
94551    A type alias for the read-only iterator on the constraints
94552    defining the feasible region.
94553  */
94554  typedef Constraint_Sequence::const_iterator const_iterator;
94555
94556  /*! \brief
94557    Returns a read-only iterator to the first constraint defining
94558    the feasible region.
94559  */
94560  const_iterator constraints_begin() const;
94561
94562  /*! \brief
94563    Returns a past-the-end read-only iterator to the sequence of
94564    constraints defining the feasible region.
94565  */
94566  const_iterator constraints_end() const;
94567
94568  //! Resets \p *this to be equal to the trivial PIP problem.
94569  /*!
94570    The space dimension is reset to \f$0\f$.
94571  */
94572  void clear();
94573
94574  /*! \brief
94575    Adds <CODE>m_vars + m_params</CODE> new space dimensions
94576    and embeds the old PIP problem in the new vector space.
94577
94578    \param m_vars
94579    The number of space dimensions to add that are interpreted as
94580    PIP problem variables (i.e., non parameters). These are added
94581    \e before adding the \p m_params parameters.
94582
94583    \param m_params
94584    The number of space dimensions to add that are interpreted as
94585    PIP problem parameters. These are added \e after having added the
94586    \p m_vars problem variables.
94587
94588    \exception std::length_error
94589    Thrown if adding <CODE>m_vars + m_params</CODE> new space
94590    dimensions would cause the vector space to exceed dimension
94591    <CODE>max_space_dimension()</CODE>.
94592
94593    The new space dimensions will be those having the highest indexes
94594    in the new PIP problem; they are initially unconstrained.
94595  */
94596  void add_space_dimensions_and_embed(dimension_type m_vars,
94597                                      dimension_type m_params);
94598
94599  /*! \brief
94600    Sets the space dimensions whose indexes which are in set \p p_vars
94601    to be parameter space dimensions.
94602
94603    \exception std::invalid_argument
94604    Thrown if some index in \p p_vars does not correspond to
94605    a space dimension in \p *this.
94606  */
94607  void add_to_parameter_space_dimensions(const Variables_Set& p_vars);
94608
94609  /*! \brief
94610    Adds a copy of constraint \p c to the PIP problem.
94611
94612    \exception std::invalid_argument
94613    Thrown if the space dimension of \p c is strictly greater than
94614    the space dimension of \p *this.
94615  */
94616  void add_constraint(const Constraint& c);
94617
94618  /*! \brief
94619    Adds a copy of the constraints in \p cs to the PIP problem.
94620
94621    \exception std::invalid_argument
94622    Thrown if the space dimension of constraint system \p cs is strictly
94623    greater than the space dimension of \p *this.
94624  */
94625  void add_constraints(const Constraint_System& cs);
94626
94627  //! Checks satisfiability of \p *this.
94628  /*!
94629    \return
94630    \c true if and only if the PIP problem is satisfiable.
94631  */
94632  bool is_satisfiable() const;
94633
94634  //! Optimizes the PIP problem.
94635  /*!
94636    \return
94637    A PIP_Problem_Status flag indicating the outcome of the optimization
94638    attempt (unfeasible or optimized problem).
94639  */
94640  PIP_Problem_Status solve() const;
94641
94642  //! Returns a feasible solution for \p *this, if it exists.
94643  /*!
94644    A null pointer is returned for an unfeasible PIP problem.
94645  */
94646  PIP_Tree solution() const;
94647
94648  //! Returns an optimizing solution for \p *this, if it exists.
94649  /*!
94650    A null pointer is returned for an unfeasible PIP problem.
94651  */
94652  PIP_Tree optimizing_solution() const;
94653
94654  //! Checks if all the invariants are satisfied.
94655  bool OK() const;
94656
94657  //! Prints on \p s the solution computed for \p *this.
94658  /*!
94659    \param s
94660    The output stream.
94661
94662    \param indent
94663    An indentation parameter (default value 0).
94664
94665    \exception std::logic_error
94666    Thrown if trying to print the solution when the PIP problem
94667    still has to be solved.
94668  */
94669  void print_solution(std::ostream& s, int indent = 0) const;
94670
94671  PPL_OUTPUT_DECLARATIONS
94672
94673  /*! \brief
94674    Loads from \p s an ASCII representation (as produced by
94675    ascii_dump(std::ostream&) const) and sets \p *this accordingly.
94676    Returns <CODE>true</CODE> if successful, <CODE>false</CODE> otherwise.
94677  */
94678  bool ascii_load(std::istream& s);
94679
94680  //! Returns the total size in bytes of the memory occupied by \p *this.
94681  memory_size_type total_memory_in_bytes() const;
94682
94683  //! Returns the size in bytes of the memory managed by \p *this.
94684  memory_size_type external_memory_in_bytes() const;
94685
94686  //! Swaps \p *this with \p y.
94687  void m_swap(PIP_Problem& y);
94688
94689  //! Possible names for PIP_Problem control parameters.
94690  enum Control_Parameter_Name {
94691    //! Cutting strategy
94692    CUTTING_STRATEGY,
94693    //! Pivot row strategy
94694    PIVOT_ROW_STRATEGY,
94695#ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
94696    //! Number of different enumeration values.
94697#endif // PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
94698    CONTROL_PARAMETER_NAME_SIZE
94699  };
94700
94701  //! Possible values for PIP_Problem control parameters.
94702  enum Control_Parameter_Value {
94703    //! Choose the first non-integer row.
94704    CUTTING_STRATEGY_FIRST,
94705    //! Choose row which generates the deepest cut.
94706    CUTTING_STRATEGY_DEEPEST,
94707    //! Always generate all possible cuts.
94708    CUTTING_STRATEGY_ALL,
94709
94710    //! Choose the first row with negative parameter sign.
94711    PIVOT_ROW_STRATEGY_FIRST,
94712    //! Choose a row that generates a lexicographically maximal pivot column.
94713    PIVOT_ROW_STRATEGY_MAX_COLUMN,
94714
94715#ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
94716    //! Number of different enumeration values.
94717#endif // PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
94718    CONTROL_PARAMETER_VALUE_SIZE
94719  };
94720
94721  //! Returns the value of control parameter \p name.
94722  Control_Parameter_Value
94723  get_control_parameter(Control_Parameter_Name name) const;
94724
94725  //! Sets control parameter \p value.
94726  void set_control_parameter(Control_Parameter_Value value);
94727
94728  //! Sets the dimension for the big parameter to \p big_dim.
94729  void set_big_parameter_dimension(dimension_type big_dim);
94730
94731  /*! \brief
94732    Returns the space dimension for the big parameter.
94733
94734    If a big parameter was not set, returns \c not_a_dimension().
94735  */
94736  dimension_type get_big_parameter_dimension() const;
94737
94738private:
94739  //! Initializes the control parameters with default values.
94740  void control_parameters_init();
94741
94742  //! Copies the control parameters from problem object \p y.
94743  void control_parameters_copy(const PIP_Problem& y);
94744
94745  //! The dimension of the vector space.
94746  dimension_type external_space_dim;
94747
94748  /*! \brief
94749    The space dimension of the current (partial) solution of the
94750    PIP problem; it may be smaller than \p external_space_dim.
94751  */
94752  dimension_type internal_space_dim;
94753
94754  //! An enumerated type describing the internal status of the PIP problem.
94755  enum Status {
94756    //! The PIP problem is unsatisfiable.
94757    UNSATISFIABLE,
94758    //! The PIP problem is optimized; the solution tree has been computed.
94759    OPTIMIZED,
94760    /*! \brief
94761      The feasible region of the PIP problem has been changed by adding
94762      new variables, parameters or constraints; a feasible solution for
94763      the old feasible region is still available.
94764    */
94765    PARTIALLY_SATISFIABLE
94766  };
94767
94768  //! The internal state of the MIP problem.
94769  Status status;
94770
94771  //! The current solution decision tree
94772  PIP_Tree_Node* current_solution;
94773
94774  //! The sequence of constraints describing the feasible region.
94775  Constraint_Sequence input_cs;
94776
94777  //! The first index of `input_cs' containing a pending constraint.
94778  dimension_type first_pending_constraint;
94779
94780  /*! \brief
94781    A set containing all the indices of space dimensions that are
94782    interpreted as problem parameters.
94783  */
94784  Variables_Set parameters;
94785
94786#if PPL_USE_SPARSE_MATRIX
94787  typedef Sparse_Row Row;
94788#else
94789  typedef Dense_Row Row;
94790#endif
94791
94792  /*! \brief
94793    The initial context
94794
94795    Contains problem constraints on parameters only
94796  */
94797  Matrix<Row> initial_context;
94798
94799  //! The control parameters for the problem object.
94800  Control_Parameter_Value
94801  control_parameters[CONTROL_PARAMETER_NAME_SIZE];
94802
94803  /*! \brief
94804    The dimension for the big parameter, or \c not_a_dimension()
94805    if not set.
94806  */
94807  dimension_type big_parameter_dimension;
94808
94809  friend class PIP_Solution_Node;
94810};
94811
94812/* Automatically generated from PPL source file ../src/PIP_Problem_inlines.hh line 1. */
94813/* PIP_Problem class implementation: inline functions.
94814*/
94815
94816
94817namespace Parma_Polyhedra_Library {
94818
94819inline dimension_type
94820PIP_Problem::space_dimension() const {
94821  return external_space_dim;
94822}
94823
94824inline dimension_type
94825PIP_Problem::max_space_dimension() {
94826  return Constraint::max_space_dimension();
94827}
94828
94829inline PIP_Problem::const_iterator
94830PIP_Problem::constraints_begin() const {
94831  return input_cs.begin();
94832}
94833
94834inline PIP_Problem::const_iterator
94835PIP_Problem::constraints_end() const {
94836  return input_cs.end();
94837}
94838
94839inline const Variables_Set&
94840PIP_Problem::parameter_space_dimensions() const {
94841  return parameters;
94842}
94843
94844inline void
94845PIP_Problem::m_swap(PIP_Problem& y) {
94846  using std::swap;
94847  swap(external_space_dim, y.external_space_dim);
94848  swap(internal_space_dim, y.internal_space_dim);
94849  swap(status, y.status);
94850  swap(current_solution, y.current_solution);
94851  swap(input_cs, y.input_cs);
94852  swap(first_pending_constraint, y.first_pending_constraint);
94853  swap(parameters, y.parameters);
94854  swap(initial_context, y.initial_context);
94855  for (dimension_type i = CONTROL_PARAMETER_NAME_SIZE; i-- > 0; ) {
94856    swap(control_parameters[i], y.control_parameters[i]);
94857  }
94858  swap(big_parameter_dimension, y.big_parameter_dimension);
94859}
94860
94861inline PIP_Problem&
94862PIP_Problem::operator=(const PIP_Problem& y) {
94863  PIP_Problem tmp(y);
94864  m_swap(tmp);
94865  return *this;
94866}
94867
94868inline PIP_Problem::Control_Parameter_Value
94869PIP_Problem::get_control_parameter(Control_Parameter_Name name) const {
94870  PPL_ASSERT(name >= 0 && name < CONTROL_PARAMETER_NAME_SIZE);
94871  return control_parameters[name];
94872}
94873
94874inline dimension_type
94875PIP_Problem::get_big_parameter_dimension() const {
94876  return big_parameter_dimension;
94877}
94878
94879/*! \relates PIP_Problem */
94880inline void
94881swap(PIP_Problem& x, PIP_Problem& y) {
94882  x.m_swap(y);
94883}
94884
94885} // namespace Parma_Polyhedra_Library
94886
94887/* Automatically generated from PPL source file ../src/PIP_Problem_templates.hh line 1. */
94888/* PIP_Problem class implementation: non-inline template functions.
94889*/
94890
94891
94892/* Automatically generated from PPL source file ../src/PIP_Problem_templates.hh line 28. */
94893
94894namespace Parma_Polyhedra_Library {
94895
94896template <typename In>
94897PIP_Problem::PIP_Problem(dimension_type dim,
94898                         In first, In last,
94899                         const Variables_Set& p_vars)
94900  : external_space_dim(dim),
94901    internal_space_dim(0),
94902    status(PARTIALLY_SATISFIABLE),
94903    current_solution(0),
94904    input_cs(),
94905    first_pending_constraint(0),
94906    parameters(p_vars),
94907    initial_context(),
94908    big_parameter_dimension(not_a_dimension()) {
94909  // Check that integer Variables_Set does not exceed the space dimension
94910  // of the problem.
94911  if (p_vars.space_dimension() > external_space_dim) {
94912    std::ostringstream s;
94913    s << "PPL::PIP_Problem::PIP_Problem(dim, first, last, p_vars):\n"
94914      << "dim == " << external_space_dim
94915      << " and p_vars.space_dimension() == "
94916      << p_vars.space_dimension()
94917      << " are dimension incompatible.";
94918    throw std::invalid_argument(s.str());
94919  }
94920
94921  // Check for space dimension overflow.
94922  if (dim > max_space_dimension()) {
94923    throw std::length_error("PPL::PIP_Problem::"
94924                            "PIP_Problem(dim, first, last, p_vars):\n"
94925                            "dim exceeds the maximum allowed "
94926                            "space dimension.");
94927  }
94928  // Check the constraints.
94929  for (In i = first; i != last; ++i) {
94930    if (i->space_dimension() > dim) {
94931      std::ostringstream s;
94932      s << "PPL::PIP_Problem::"
94933        << "PIP_Problem(dim, first, last, p_vars):\n"
94934        << "range [first, last) contains a constraint having space "
94935        << "dimension == " << i->space_dimension()
94936        << " that exceeds this->space_dimension == " << dim << ".";
94937      throw std::invalid_argument(s.str());
94938    }
94939    input_cs.push_back(*i);
94940  }
94941  control_parameters_init();
94942  PPL_ASSERT(OK());
94943}
94944
94945} // namespace Parma_Polyhedra_Library
94946
94947/* Automatically generated from PPL source file ../src/PIP_Problem_defs.hh line 832. */
94948
94949/* Automatically generated from PPL source file ../src/PIP_Tree_defs.hh line 36. */
94950
94951/* Automatically generated from PPL source file ../src/PIP_Tree_defs.hh line 40. */
94952
94953namespace Parma_Polyhedra_Library {
94954
94955//! A node of the PIP solution tree.
94956/*!
94957  This is the base class for the nodes of the binary trees representing
94958  the solutions of PIP problems. From this one, two classes are derived:
94959    - PIP_Decision_Node, for the internal nodes of the tree;
94960    - PIP_Solution_Node, for the leaves of the tree.
94961*/
94962class PIP_Tree_Node {
94963protected:
94964  //! Constructor: builds a node owned by \p *owner.
94965  explicit PIP_Tree_Node(const PIP_Problem* owner);
94966
94967  //! Copy constructor.
94968  PIP_Tree_Node(const PIP_Tree_Node& y);
94969
94970  //! Returns a pointer to the PIP_Problem owning object.
94971  const PIP_Problem* get_owner() const;
94972
94973  //! Sets the pointer to the PIP_Problem owning object.
94974  virtual void set_owner(const PIP_Problem* owner) = 0;
94975
94976  /*! \brief
94977    Returns \c true if and only if all the nodes in the subtree
94978    rooted in \p *this are owned by \p *owner.
94979  */
94980  virtual bool check_ownership(const PIP_Problem* owner) const = 0;
94981
94982public:
94983#if PPL_USE_SPARSE_MATRIX
94984  typedef Sparse_Row Row;
94985#else
94986  typedef Dense_Row Row;
94987#endif
94988
94989  //! Returns a pointer to a dynamically-allocated copy of \p *this.
94990  virtual PIP_Tree_Node* clone() const = 0;
94991
94992  //! Destructor.
94993  virtual ~PIP_Tree_Node();
94994
94995  //! Returns \c true if and only if \p *this is well formed.
94996  virtual bool OK() const = 0;
94997
94998  //! Returns \p this if \p *this is a solution node, 0 otherwise.
94999  virtual const PIP_Solution_Node* as_solution() const = 0;
95000
95001  //! Returns \p this if \p *this is a decision node, 0 otherwise.
95002  virtual const PIP_Decision_Node* as_decision() const = 0;
95003
95004  /*! \brief
95005    Returns the system of parameter constraints controlling \p *this.
95006
95007    The indices in the constraints are the same as the original variables and
95008    parameters. Coefficients in indices corresponding to variables always are
95009    zero.
95010  */
95011  const Constraint_System& constraints() const;
95012
95013  class Artificial_Parameter;
95014
95015  //! A type alias for a sequence of Artificial_Parameter's.
95016  typedef std::vector<Artificial_Parameter> Artificial_Parameter_Sequence;
95017
95018  //! Returns a const_iterator to the beginning of local artificial parameters.
95019  Artificial_Parameter_Sequence::const_iterator art_parameter_begin() const;
95020
95021  //! Returns a const_iterator to the end of local artificial parameters.
95022  Artificial_Parameter_Sequence::const_iterator art_parameter_end() const;
95023
95024  //! Returns the number of local artificial parameters.
95025  dimension_type art_parameter_count() const;
95026
95027  //! Prints on \p s the tree rooted in \p *this.
95028  /*!
95029    \param s
95030    The output stream.
95031
95032    \param indent
95033    The amount of indentation.
95034  */
95035  void print(std::ostream& s, int indent = 0) const;
95036
95037  //! Dumps to \p s an ASCII representation of \p *this.
95038  void ascii_dump(std::ostream& s) const;
95039
95040  /*! \brief
95041    Loads from \p s an ASCII representation (as produced by
95042    ascii_dump(std::ostream&) const) and sets \p *this accordingly.
95043    Returns <CODE>true</CODE> if successful, <CODE>false</CODE> otherwise.
95044  */
95045  bool ascii_load(std::istream& s);
95046
95047  //! Returns the total size in bytes of the memory occupied by \p *this.
95048  virtual memory_size_type total_memory_in_bytes() const = 0;
95049  //! Returns the size in bytes of the memory managed by \p *this.
95050  virtual memory_size_type external_memory_in_bytes() const = 0;
95051
95052protected:
95053  //! A type alias for a sequence of constraints.
95054  typedef std::vector<Constraint> Constraint_Sequence;
95055
95056  // Only PIP_Problem and PIP_Decision_Node are allowed to use the
95057  // constructor and methods.
95058  friend class PIP_Problem;
95059  friend class PIP_Decision_Node;
95060  friend class PIP_Solution_Node;
95061
95062  //! A pointer to the PIP_Problem object owning this node.
95063  const PIP_Problem* owner_;
95064
95065  //! A pointer to the parent of \p *this, null if \p *this is the root.
95066  const PIP_Decision_Node* parent_;
95067
95068  //! The local system of parameter constraints.
95069  Constraint_System constraints_;
95070
95071  //! The local sequence of expressions for local artificial parameters.
95072  Artificial_Parameter_Sequence artificial_parameters;
95073
95074  //! Returns a pointer to this node's parent.
95075  const PIP_Decision_Node* parent() const;
95076
95077  //! Set this node's parent to \p *p.
95078  void set_parent(const PIP_Decision_Node* p);
95079
95080  /*! \brief
95081    Populates the parametric simplex tableau using external data.
95082
95083    \param pip
95084    The PIP_Problem object containing this node.
95085
95086    \param external_space_dim
95087    The number of all problem variables and problem parameters
95088    (excluding artificial parameters).
95089
95090    \param first_pending_constraint
95091    The first element in \p input_cs to be added to the tableau,
95092    which already contains the previous elements.
95093
95094    \param input_cs
95095    All the constraints of the PIP problem.
95096
95097    \param parameters
95098    The set of indices of the problem parameters.
95099  */
95100  virtual void update_tableau(const PIP_Problem& pip,
95101                              dimension_type external_space_dim,
95102                              dimension_type first_pending_constraint,
95103                              const Constraint_Sequence& input_cs,
95104                              const Variables_Set& parameters) = 0;
95105
95106  /*! \brief
95107    Executes a parametric simplex on the tableau, under specified context.
95108
95109    \return
95110    The root of the PIP tree solution, or 0 if unfeasible.
95111
95112    \param pip
95113    The PIP_Problem object containing this node.
95114
95115    \param check_feasible_context
95116    Whether the resolution process should (re-)check feasibility of
95117    context (since the initial context may have been modified).
95118
95119    \param context
95120    The context, being a set of constraints on the parameters.
95121
95122    \param params
95123    The local parameter set, including parent's artificial parameters.
95124
95125    \param space_dim
95126    The space dimension of parent, including artificial parameters.
95127
95128    \param indent_level
95129    The indentation level (for debugging output only).
95130  */
95131  virtual PIP_Tree_Node* solve(const PIP_Problem& pip,
95132                               bool check_feasible_context,
95133                               const Matrix<Row>& context,
95134                               const Variables_Set& params,
95135                               dimension_type space_dim,
95136                               int indent_level) = 0;
95137
95138  //! Inserts a new parametric constraint in internal row format.
95139  void add_constraint(const Row& row, const Variables_Set& parameters);
95140
95141  //! Merges parent's artificial parameters into \p *this.
95142  void parent_merge();
95143
95144  //! Prints on \p s the tree rooted in \p *this.
95145  /*!
95146    \param s
95147    The output stream.
95148
95149    \param indent
95150    The amount of indentation.
95151
95152    \param pip_dim_is_param
95153    A vector of Boolean flags telling which PIP problem dimensions are
95154    problem parameters. The size of the vector is equal to the PIP
95155    problem internal space dimension (i.e., no artificial parameters).
95156
95157    \param first_art_dim
95158    The first space dimension corresponding to an artificial parameter
95159    that was created in this node (if any).
95160  */
95161  virtual void print_tree(std::ostream& s,
95162                          int indent,
95163                          const std::vector<bool>& pip_dim_is_param,
95164                          dimension_type first_art_dim) const = 0;
95165
95166  //! A helper function used when printing PIP trees.
95167  static void
95168  indent_and_print(std::ostream& s, int indent, const char* str);
95169
95170  /*! \brief
95171    Checks whether a context matrix is satisfiable.
95172
95173    The satisfiability check is implemented by the revised dual simplex
95174    algorithm on the context matrix. The algorithm ensures the feasible
95175    solution is integer by applying a cut generation method when
95176    intermediate non-integer solutions are found.
95177  */
95178  static bool compatibility_check(Matrix<Row>& s);
95179
95180  /*! \brief
95181    Helper method: checks for satisfiability of the restricted context
95182    obtained by adding \p row to \p context.
95183  */
95184  static bool compatibility_check(const Matrix<Row>& context, const Row& row);
95185
95186}; // class PIP_Tree_Node
95187
95188
95189/*! \brief
95190  Artificial parameters in PIP solution trees.
95191
95192  These parameters are built from a linear expression combining other
95193  parameters (constant term included) divided by a positive integer
95194  denominator. Coefficients at variables indices corresponding to
95195  PIP problem variables are always zero.
95196*/
95197class PIP_Tree_Node::Artificial_Parameter
95198  : public Linear_Expression {
95199public:
95200  //! Default constructor: builds a zero artificial parameter.
95201  Artificial_Parameter();
95202
95203  //! Constructor.
95204  /*!
95205    Builds artificial parameter \f$\frac{\mathtt{expr}}{\mathtt{d}}\f$.
95206
95207    \param expr
95208    The expression that, after normalization, will form the numerator of
95209    the artificial parameter.
95210
95211    \param d
95212    The integer constant that, after normalization, will form the
95213    denominator of the artificial parameter.
95214
95215    \exception std::invalid_argument
95216    Thrown if \p d is zero.
95217
95218    Normalization will ensure that the denominator is positive.
95219  */
95220  Artificial_Parameter(const Linear_Expression& expr,
95221                       Coefficient_traits::const_reference d);
95222
95223  //! Copy constructor.
95224  Artificial_Parameter(const Artificial_Parameter& y);
95225
95226  //! Returns the normalized (i.e., positive) denominator.
95227  Coefficient_traits::const_reference denominator() const;
95228
95229  //! Swaps \p *this with \p y.
95230  void m_swap(Artificial_Parameter& y);
95231
95232  //! Returns \c true if and only if \p *this and \p y are equal.
95233  /*!
95234    Note that two artificial parameters having different space dimensions
95235    are considered to be different.
95236  */
95237  bool operator==(const Artificial_Parameter& y) const;
95238  //! Returns \c true if and only if \p *this and \p y are different.
95239  bool operator!=(const Artificial_Parameter& y) const;
95240
95241  PPL_OUTPUT_DECLARATIONS
95242
95243  /*! \brief
95244    Loads from \p s an ASCII representation (as produced by
95245    ascii_dump(std::ostream&) const) and sets \p *this accordingly.
95246    Returns <CODE>true</CODE> if successful, <CODE>false</CODE> otherwise.
95247  */
95248  bool ascii_load(std::istream& s);
95249
95250  //! Returns the total size in bytes of the memory occupied by \p *this.
95251  memory_size_type total_memory_in_bytes() const;
95252  //! Returns the size in bytes of the memory managed by \p *this.
95253  memory_size_type external_memory_in_bytes() const;
95254
95255  //! Returns \c true if and only if the parameter is well-formed.
95256  bool OK() const;
95257
95258private:
95259  //! The normalized (i.e., positive) denominator.
95260  Coefficient denom;
95261}; // class PIP_Tree_Node::Artificial_Parameter
95262
95263
95264//! Swaps \p x with \p y.
95265/*! \relates PIP_Tree_Node::Artificial_Parameter */
95266void
95267swap(PIP_Tree_Node::Artificial_Parameter& x,
95268     PIP_Tree_Node::Artificial_Parameter& y);
95269
95270
95271//! A tree node representing part of the space of solutions.
95272class PIP_Solution_Node : public PIP_Tree_Node {
95273public:
95274
95275  //! Constructor: builds a solution node owned by \p *owner.
95276  explicit PIP_Solution_Node(const PIP_Problem* owner);
95277
95278  //! Returns a pointer to a dynamically-allocated copy of \p *this.
95279  virtual PIP_Tree_Node* clone() const;
95280
95281  //! Destructor.
95282  virtual ~PIP_Solution_Node();
95283
95284  //! Returns \c true if and only if \p *this is well formed.
95285  virtual bool OK() const;
95286
95287  //! Returns \p this.
95288  virtual const PIP_Solution_Node* as_solution() const;
95289
95290  //! Returns 0, since \p this is not a decision node.
95291  virtual const PIP_Decision_Node* as_decision() const;
95292
95293  /*! \brief
95294    Returns a parametric expression for the values of problem variable \p var.
95295
95296    The returned linear expression may involve problem parameters
95297    as well as artificial parameters.
95298
95299    \param var
95300    The problem variable which is queried about.
95301
95302    \exception std::invalid_argument
95303    Thrown if \p var is dimension-incompatible with the PIP_Problem
95304    owning this solution node, or if \p var is a problem parameter.
95305  */
95306  const Linear_Expression& parametric_values(Variable var) const;
95307
95308  //! Dumps to \p os an ASCII representation of \p *this.
95309  void ascii_dump(std::ostream& os) const;
95310
95311  /*! \brief
95312    Loads from \p is an ASCII representation (as produced by
95313    ascii_dump(std::ostream&) const) and sets \p *this accordingly.
95314    Returns <CODE>true</CODE> if successful, <CODE>false</CODE> otherwise.
95315  */
95316  bool ascii_load(std::istream& is);
95317
95318  //! Returns the total size in bytes of the memory occupied by \p *this.
95319  virtual memory_size_type total_memory_in_bytes() const;
95320  //! Returns the size in bytes of the memory managed by \p *this.
95321  virtual memory_size_type external_memory_in_bytes() const;
95322
95323private:
95324  //! The type for parametric simplex tableau.
95325  struct Tableau {
95326    //! The matrix of simplex coefficients.
95327    Matrix<Row> s;
95328    //! The matrix of parameter coefficients.
95329    Matrix<Row> t;
95330    //! A common denominator for all matrix elements
95331    Coefficient denom;
95332
95333    //! Default constructor.
95334    Tableau();
95335    //! Copy constructor.
95336    Tableau(const Tableau& y);
95337    //! Destructor.
95338    ~Tableau();
95339
95340    //! Tests whether the matrix is integer, i.e., the denominator is 1.
95341    bool is_integer() const;
95342
95343    //! Multiplies all coefficients and denominator with ratio.
95344    void scale(Coefficient_traits::const_reference ratio);
95345
95346    //! Normalizes the modulo of coefficients so that they are mutually prime.
95347    /*!
95348      Computes the Greatest Common Divisor (GCD) among the elements of
95349      the matrices and normalizes them and the denominator by the GCD itself.
95350    */
95351    void normalize();
95352
95353    /*! \brief
95354      Compares two pivot row and column pairs before pivoting.
95355
95356      The algorithm searches the first (ie, leftmost) column \f$k\f$ in
95357      parameter matrix for which the \f$c=s_{*j}\frac{t_{ik}}{s_{ij}}\f$
95358      and \f$c'=s_{*j'}\frac{t_{i'k}}{s_{i'j'}}\f$ columns are different,
95359      where \f$s_{*j}\f$ denotes the \f$j\f$<sup>th</sup> column from the
95360      \f$s\f$ matrix and \f$s_{*j'}\f$ is the \f$j'\f$<sup>th</sup> column
95361      of \f$s\f$.
95362
95363      \f$c\f$ is the computed column that would be subtracted to column
95364      \f$k\f$ in parameter matrix if pivoting is done using the \f$(i,j)\f$
95365      row and column pair.
95366      \f$c'\f$ is the computed column that would be subtracted to column
95367      \f$k\f$ in parameter matrix if pivoting is done using the
95368      \f$(i',j')\f$ row and column pair.
95369
95370      The test is true if the computed \f$-c\f$ column is lexicographically
95371      bigger than the \f$-c'\f$ column. Due to the column ordering in the
95372      parameter matrix of the tableau, leftmost search will enforce solution
95373      increase with respect to the following priority order:
95374       - the constant term
95375       - the coefficients for the original parameters
95376       - the coefficients for the oldest artificial parameters.
95377
95378      \return
95379      \c true if pivot row and column pair \f$(i,j)\f$ is more
95380      suitable for pivoting than the \f$(i',j')\f$ pair
95381
95382      \param mapping
95383      The PIP_Solution_Node::mapping vector for the tableau.
95384
95385      \param basis
95386      The PIP_Solution_Node::basis vector for the tableau.
95387
95388      \param row_0
95389      The row number for the first pivot row and column pair to be compared.
95390
95391      \param col_0
95392      The column number for the first pivot row and column pair to be
95393      compared.
95394
95395      \param row_1
95396      The row number for the second pivot row and column pair to be compared.
95397
95398      \param col_1
95399      The column number for the second pivot row and column pair to be
95400      compared.
95401    */
95402    bool is_better_pivot(const std::vector<dimension_type>& mapping,
95403                         const std::vector<bool>& basis,
95404                         const dimension_type row_0,
95405                         const dimension_type col_0,
95406                         const dimension_type row_1,
95407                         const dimension_type col_1) const;
95408
95409    //! Returns the value of the denominator.
95410    Coefficient_traits::const_reference denominator() const;
95411
95412    //! Dumps to \p os an ASCII representation of \p *this.
95413    void ascii_dump(std::ostream& os) const;
95414
95415    /*! \brief
95416      Loads from \p is an ASCII representation (as produced by
95417      ascii_dump(std::ostream&) const) and sets \p *this accordingly.
95418      Returns \c true if successful, \c false otherwise.
95419    */
95420    bool ascii_load(std::istream& is);
95421
95422    //! Returns the size in bytes of the memory managed by \p *this.
95423    /*!
95424      \note
95425      No need for a \c total_memory_in_bytes() method, since
95426      class Tableau is a private inner class of PIP_Solution_Node.
95427    */
95428    memory_size_type external_memory_in_bytes() const;
95429
95430    //! Returns \c true if and only if \p *this is well formed.
95431    bool OK() const;
95432  }; // struct Tableau
95433
95434  //! The parametric simplex tableau.
95435  Tableau tableau;
95436
95437  /*! \brief
95438    A boolean vector for identifying the basic variables.
95439
95440    Variable identifiers are numbered from 0 to <CODE>n+m-1</CODE>, where \p n
95441    is the number of columns in the simplex tableau corresponding to variables,
95442    and \p m is the number of rows.
95443
95444    Indices from 0 to <CODE>n-1</CODE> correspond to the original variables.
95445
95446    Indices from \p n to <CODE>n+m-1</CODE> correspond to the slack variables
95447    associated to the internal constraints, which do not strictly correspond
95448    to original constraints, since these may have been transformed to fit the
95449    standard form of the dual simplex.
95450
95451    The value for <CODE>basis[i]</CODE> is:
95452     - \b true if variable \p i is basic,
95453     - \b false if variable \p i is nonbasic.
95454  */
95455  std::vector<bool> basis;
95456
95457  /*! \brief
95458    A mapping between the tableau rows/columns and the original variables.
95459
95460    The value of <CODE>mapping[i]</CODE> depends of the value of <CODE>basis[i]</CODE>.
95461
95462     - If <CODE>basis[i]</CODE> is \b true, <CODE>mapping[i]</CODE> encodes the column
95463       index of variable \p i in the \p s matrix of the tableau.
95464     - If <CODE>basis[i]</CODE> is \b false, <CODE>mapping[i]</CODE> encodes the row
95465       index of variable \p i in the tableau.
95466  */
95467  std::vector<dimension_type> mapping;
95468
95469  /*! \brief
95470    The variable identifiers associated to the rows of the simplex tableau.
95471  */
95472  std::vector<dimension_type> var_row;
95473
95474  /*! \brief
95475    The variable identifiers associated to the columns of the simplex tableau.
95476  */
95477  std::vector<dimension_type> var_column;
95478
95479  /*! \brief
95480    The variable number of the special inequality used for modeling
95481    equality constraints.
95482
95483    The subset of equality constraints in a specific problem can be expressed
95484    as: \f$f_i(x,p) = 0 ; 1 \leq i \leq n\f$. As the dual simplex standard form
95485    requires constraints to be inequalities, the following constraints can be
95486    modeled as follows:
95487
95488     - \f$f_i(x,p) \geq 0 ; 1 \leq i \leq n\f$
95489
95490     - \f$\sum\limits_{i=1}^n f_i(x,p) \leq 0\f$
95491
95492    The \p special_equality_row value stores the variable number of the
95493    specific constraint which is used to model the latter sum of
95494    constraints. If no such constraint exists, the value is set to \p 0.
95495  */
95496  dimension_type special_equality_row;
95497
95498  /*! \brief
95499    The column index in the parametric part of the simplex tableau
95500    corresponding to the big parameter; \c not_a_dimension() if not set.
95501  */
95502  dimension_type big_dimension;
95503
95504  //! The possible values for the sign of a parametric linear expression.
95505  enum Row_Sign {
95506    //! Not computed yet (default).
95507    UNKNOWN,
95508    //! All row coefficients are zero.
95509    ZERO,
95510    //! All nonzero row coefficients are positive.
95511    POSITIVE,
95512    //! All nonzero row coefficients are negative.
95513    NEGATIVE,
95514    //! The row contains both positive and negative coefficients.
95515    MIXED
95516  };
95517
95518  //! A cache for computed sign values of constraint parametric RHS.
95519  std::vector<Row_Sign> sign;
95520
95521  //! Parametric values for the solution.
95522  std::vector<Linear_Expression> solution;
95523
95524  //! An indicator for solution validity.
95525  bool solution_valid;
95526
95527  //! Returns the sign of row \p x.
95528  static Row_Sign row_sign(const Row& x,
95529                           dimension_type big_dimension);
95530
95531protected:
95532  //! Copy constructor.
95533  PIP_Solution_Node(const PIP_Solution_Node& y);
95534
95535  //! A tag type to select the alternative copy constructor.
95536  struct No_Constraints {};
95537
95538  //! Alternative copy constructor.
95539  /*!
95540    This constructor differs from the default copy constructor in that
95541    it will not copy the constraint system, nor the artificial parameters.
95542  */
95543  PIP_Solution_Node(const PIP_Solution_Node& y, No_Constraints);
95544
95545  // PIP_Problem::ascii load() method needs access set_owner().
95546  friend bool PIP_Problem::ascii_load(std::istream& s);
95547
95548  //! Sets the pointer to the PIP_Problem owning object.
95549  virtual void set_owner(const PIP_Problem* owner);
95550
95551  /*! \brief
95552    Returns \c true if and only if all the nodes in the subtree
95553    rooted in \p *this is owned by \p *pip.
95554  */
95555  virtual bool check_ownership(const PIP_Problem* owner) const;
95556
95557  //! Implements pure virtual method PIP_Tree_Node::update_tableau.
95558  virtual void update_tableau(const PIP_Problem& pip,
95559                              dimension_type external_space_dim,
95560                              dimension_type first_pending_constraint,
95561                              const Constraint_Sequence& input_cs,
95562                              const Variables_Set& parameters);
95563
95564  /*! \brief
95565    Update the solution values.
95566
95567    \param pip_dim_is_param
95568    A vector of Boolean flags telling which PIP problem dimensions are
95569    problem parameters. The size of the vector is equal to the PIP
95570    problem internal space dimension (i.e., no artificial parameters).
95571  */
95572  void update_solution(const std::vector<bool>& pip_dim_is_param) const;
95573
95574  //! Helper method.
95575  void update_solution() const;
95576
95577  //! Implements pure virtual method PIP_Tree_Node::solve.
95578  virtual PIP_Tree_Node* solve(const PIP_Problem& pip,
95579                               bool check_feasible_context,
95580                               const Matrix<Row>& context,
95581                               const Variables_Set& params,
95582                               dimension_type space_dim,
95583                               int indent_level);
95584
95585  /*! \brief
95586    Generate a Gomory cut using non-integer tableau row \p index.
95587
95588    \param index
95589    Row index in simplex tableau from which the cut is generated.
95590
95591    \param parameters
95592    A std::set of the current parameter dimensions (including artificials);
95593    to be updated if a new artificial parameter is to be created.
95594
95595    \param context
95596    A set of linear inequalities on the parameters, in matrix form; to be
95597    updated if a new artificial parameter is to be created.
95598
95599    \param space_dimension
95600    The current space dimension, including variables and all parameters; to
95601    be updated if an extra parameter is to be created.
95602
95603    \param indent_level
95604    The indentation level (for debugging output only).
95605  */
95606  void generate_cut(dimension_type index, Variables_Set& parameters,
95607                    Matrix<Row>& context, dimension_type& space_dimension,
95608                    int indent_level);
95609
95610  //! Prints on \p s the tree rooted in \p *this.
95611  virtual void print_tree(std::ostream& s, int indent,
95612                          const std::vector<bool>& pip_dim_is_param,
95613                          dimension_type first_art_dim) const;
95614
95615}; // class PIP_Solution_Node
95616
95617
95618//! A tree node representing a decision in the space of solutions.
95619class PIP_Decision_Node : public PIP_Tree_Node {
95620public:
95621  //! Returns a pointer to a dynamically-allocated copy of \p *this.
95622  virtual PIP_Tree_Node* clone() const;
95623
95624  //! Destructor.
95625  virtual ~PIP_Decision_Node();
95626
95627  //! Returns \c true if and only if \p *this is well formed.
95628  virtual bool OK() const;
95629
95630  //! Returns \p this.
95631  virtual const PIP_Decision_Node* as_decision() const;
95632
95633  //! Returns 0, since \p this is not a solution node.
95634  virtual const PIP_Solution_Node* as_solution() const;
95635
95636  //! Returns a const pointer to the \p b (true or false) branch of \p *this.
95637  const PIP_Tree_Node* child_node(bool b) const;
95638
95639  //! Returns a pointer to the \p b (true or false) branch of \p *this.
95640  PIP_Tree_Node* child_node(bool b);
95641
95642  //! Dumps to \p s an ASCII representation of \p *this.
95643  void ascii_dump(std::ostream& s) const;
95644
95645  /*! \brief
95646    Loads from \p s an ASCII representation (as produced by
95647    ascii_dump(std::ostream&) const) and sets \p *this accordingly.
95648    Returns <CODE>true</CODE> if successful, <CODE>false</CODE> otherwise.
95649  */
95650  bool ascii_load(std::istream& s);
95651
95652  //! Returns the total size in bytes of the memory occupied by \p *this.
95653  virtual memory_size_type total_memory_in_bytes() const;
95654  //! Returns the size in bytes of the memory managed by \p *this.
95655  virtual memory_size_type external_memory_in_bytes() const;
95656
95657private:
95658  // PIP_Solution_Node is allowed to use the constructor and methods.
95659  friend class PIP_Solution_Node;
95660
95661  // PIP_Problem ascii load method needs access to private constructors.
95662  friend bool PIP_Problem::ascii_load(std::istream& s);
95663
95664  //! Pointer to the "false" child of \p *this.
95665  PIP_Tree_Node* false_child;
95666
95667  //! Pointer to the "true" child of \p *this.
95668  PIP_Tree_Node* true_child;
95669
95670  /*! \brief
95671    Builds a decision node having \p fcp and \p tcp as child.
95672
95673    The decision node will encode the structure
95674    "if \c cs then \p tcp else \p fcp",
95675    where the system of constraints \c cs is initially empty.
95676
95677    \param owner
95678    Pointer to the owning PIP_Problem object; it may be null if and
95679    only if both children are null.
95680
95681    \param fcp
95682    Pointer to "false" child; it may be null.
95683
95684    \param tcp
95685    Pointer to "true" child; it may be null.
95686
95687    \note
95688    If any of \p fcp or \p tcp is not null, then \p owner is required
95689    to be not null and equal to the owner of its non-null children;
95690    otherwise the behavior is undefined.
95691  */
95692  explicit PIP_Decision_Node(const PIP_Problem* owner,
95693                             PIP_Tree_Node* fcp,
95694                             PIP_Tree_Node* tcp);
95695
95696  //! Sets the pointer to the PIP_Problem owning object.
95697  virtual void set_owner(const PIP_Problem* owner);
95698
95699  /*! \brief
95700    Returns \c true if and only if all the nodes in the subtree
95701    rooted in \p *this is owned by \p *pip.
95702  */
95703  virtual bool check_ownership(const PIP_Problem* owner) const;
95704
95705protected:
95706  //! Copy constructor.
95707  PIP_Decision_Node(const PIP_Decision_Node& y);
95708
95709  //! Implements pure virtual method PIP_Tree_Node::update_tableau.
95710  virtual void update_tableau(const PIP_Problem& pip,
95711                              dimension_type external_space_dim,
95712                              dimension_type first_pending_constraint,
95713                              const Constraint_Sequence& input_cs,
95714                              const Variables_Set& parameters);
95715
95716  //! Implements pure virtual method PIP_Tree_Node::solve.
95717  virtual PIP_Tree_Node* solve(const PIP_Problem& pip,
95718                               bool check_feasible_context,
95719                               const Matrix<Row>& context,
95720                               const Variables_Set& params,
95721                               dimension_type space_dim,
95722                               int indent_level);
95723
95724  //! Prints on \p s the tree rooted in \p *this.
95725  virtual void print_tree(std::ostream& s, int indent,
95726                          const std::vector<bool>& pip_dim_is_param,
95727                          dimension_type first_art_dim) const;
95728
95729}; // class PIP_Decision_Node
95730
95731namespace IO_Operators {
95732
95733//! Output operator: prints the solution tree rooted in \p x.
95734/*! \relates Parma_Polyhedra_Library::PIP_Tree_Node */
95735std::ostream& operator<<(std::ostream& os, const PIP_Tree_Node& x);
95736
95737//! Output operator.
95738/*! \relates Parma_Polyhedra_Library::PIP_Tree_Node::Artificial_Parameter */
95739std::ostream& operator<<(std::ostream& os,
95740                         const PIP_Tree_Node::Artificial_Parameter& x);
95741
95742} // namespace IO_Operators
95743
95744} // namespace Parma_Polyhedra_Library
95745
95746/* Automatically generated from PPL source file ../src/PIP_Tree_inlines.hh line 1. */
95747/* PIP_Tree related class implementation: inline functions.
95748*/
95749
95750
95751namespace Parma_Polyhedra_Library {
95752
95753inline
95754PIP_Solution_Node::Tableau::Tableau()
95755  : s(), t(), denom(1) {
95756  PPL_ASSERT(OK());
95757}
95758
95759inline
95760PIP_Solution_Node::Tableau::Tableau(const Tableau& y)
95761  : s(y.s), t(y.t), denom(y.denom) {
95762  PPL_ASSERT(OK());
95763}
95764
95765inline
95766PIP_Solution_Node::Tableau::~Tableau() {
95767}
95768
95769inline bool
95770PIP_Solution_Node::Tableau::is_integer() const {
95771  return denom == 1;
95772}
95773
95774inline Coefficient_traits::const_reference
95775PIP_Solution_Node::Tableau::denominator() const {
95776  return denom;
95777}
95778
95779inline void
95780PIP_Tree_Node::set_parent(const PIP_Decision_Node* p) {
95781  parent_ = p;
95782}
95783
95784inline const PIP_Decision_Node*
95785PIP_Tree_Node::parent() const {
95786  return parent_;
95787}
95788
95789inline const PIP_Problem*
95790PIP_Tree_Node::get_owner() const {
95791  return owner_;
95792}
95793
95794inline const Constraint_System&
95795PIP_Tree_Node::constraints() const {
95796  return constraints_;
95797}
95798
95799inline PIP_Tree_Node::Artificial_Parameter_Sequence::const_iterator
95800PIP_Tree_Node::art_parameter_begin() const {
95801  return artificial_parameters.begin();
95802}
95803
95804inline PIP_Tree_Node::Artificial_Parameter_Sequence::const_iterator
95805PIP_Tree_Node::art_parameter_end() const {
95806  return artificial_parameters.end();
95807}
95808
95809inline dimension_type
95810PIP_Tree_Node::art_parameter_count() const {
95811  return artificial_parameters.size();
95812}
95813
95814inline
95815const PIP_Tree_Node*
95816PIP_Decision_Node::child_node(bool b) const {
95817  return b ? true_child : false_child;
95818}
95819
95820inline
95821PIP_Tree_Node*
95822PIP_Decision_Node::child_node(bool b) {
95823  return b ? true_child : false_child;
95824}
95825
95826inline
95827PIP_Tree_Node::Artificial_Parameter::Artificial_Parameter()
95828  : Linear_Expression(), denom(1) {
95829  PPL_ASSERT(OK());
95830}
95831
95832inline
95833PIP_Tree_Node::Artificial_Parameter
95834::Artificial_Parameter(const Artificial_Parameter& y)
95835  : Linear_Expression(y), denom(y.denom) {
95836  PPL_ASSERT(OK());
95837}
95838
95839inline Coefficient_traits::const_reference
95840PIP_Tree_Node::Artificial_Parameter::denominator() const {
95841  return denom;
95842}
95843
95844inline void
95845PIP_Tree_Node::Artificial_Parameter::m_swap(Artificial_Parameter& y) {
95846  Linear_Expression::m_swap(y);
95847  using std::swap;
95848  swap(denom, y.denom);
95849}
95850
95851/*! \relates PIP_Tree_Node::Artificial_Parameter */
95852inline void
95853swap(PIP_Tree_Node::Artificial_Parameter& x,
95854     PIP_Tree_Node::Artificial_Parameter& y) {
95855  x.m_swap(y);
95856}
95857
95858} // namespace Parma_Polyhedra_Library
95859
95860/* Automatically generated from PPL source file ../src/PIP_Tree_defs.hh line 835. */
95861
95862/* Automatically generated from PPL source file ../src/BHRZ03_Certificate_defs.hh line 1. */
95863/* BHRZ03_Certificate class declaration.
95864*/
95865
95866
95867/* Automatically generated from PPL source file ../src/BHRZ03_Certificate_defs.hh line 30. */
95868#include <vector>
95869
95870//! The convergence certificate for the BHRZ03 widening operator.
95871/*! \ingroup PPL_CXX_interface
95872  Convergence certificates are used to instantiate the BHZ03 framework
95873  so as to define widening operators for the finite powerset domain.
95874
95875  \note
95876  Each convergence certificate has to be used together with a
95877  compatible widening operator. In particular, BHRZ03_Certificate
95878  can certify the convergence of both the BHRZ03 and the H79 widenings.
95879*/
95880class Parma_Polyhedra_Library::BHRZ03_Certificate {
95881public:
95882  //! Default constructor.
95883  BHRZ03_Certificate();
95884
95885  //! Constructor: computes the certificate for \p ph.
95886  BHRZ03_Certificate(const Polyhedron& ph);
95887
95888  //! Copy constructor.
95889  BHRZ03_Certificate(const BHRZ03_Certificate& y);
95890
95891  //! Destructor.
95892  ~BHRZ03_Certificate();
95893
95894  //! The comparison function for certificates.
95895  /*!
95896    \return
95897    \f$-1\f$, \f$0\f$ or \f$1\f$ depending on whether \p *this
95898    is smaller than, equal to, or greater than \p y, respectively.
95899
95900    Compares \p *this with \p y, using a total ordering which is a
95901    refinement of the limited growth ordering relation for the
95902    BHRZ03 widening.
95903  */
95904  int compare(const BHRZ03_Certificate& y) const;
95905
95906  //! Compares \p *this with the certificate for polyhedron \p ph.
95907  int compare(const Polyhedron& ph) const;
95908
95909#ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
95910  /*! \brief
95911    Returns <CODE>true</CODE> if and only if the certificate for
95912    polyhedron \p ph is strictly smaller than \p *this.
95913  */
95914#endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
95915  bool is_stabilizing(const Polyhedron& ph) const;
95916
95917  //! A total ordering on BHRZ03 certificates.
95918  /*! \ingroup PPL_CXX_interface
95919    This binary predicate defines a total ordering on BHRZ03 certificates
95920    which is used when storing information about sets of polyhedra.
95921  */
95922  struct Compare {
95923    //! Returns <CODE>true</CODE> if and only if \p x comes before \p y.
95924    bool operator()(const BHRZ03_Certificate& x,
95925                    const BHRZ03_Certificate& y) const;
95926  };
95927
95928#ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
95929  //! Check if gathered information is meaningful.
95930#endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
95931  bool OK() const;
95932
95933private:
95934  //! Affine dimension of the polyhedron.
95935  dimension_type affine_dim;
95936  //! Dimension of the lineality space of the polyhedron.
95937  dimension_type lin_space_dim;
95938  //! Cardinality of a non-redundant constraint system for the polyhedron.
95939  dimension_type num_constraints;
95940  /*! \brief
95941    Number of non-redundant points in a generator system
95942    for the polyhedron.
95943  */
95944  dimension_type num_points;
95945  /*! \brief
95946    A vector containing, for each index `0 <= i < space_dim',
95947    the number of non-redundant rays in a generator system of the
95948    polyhedron having exactly `i' null coordinates.
95949  */
95950  std::vector<dimension_type> num_rays_null_coord;
95951};
95952
95953/* Automatically generated from PPL source file ../src/BHRZ03_Certificate_inlines.hh line 1. */
95954/* BHRZ03_Certificate class implementation: inline functions.
95955*/
95956
95957
95958/* Automatically generated from PPL source file ../src/BHRZ03_Certificate_inlines.hh line 28. */
95959
95960namespace Parma_Polyhedra_Library {
95961
95962inline
95963BHRZ03_Certificate::BHRZ03_Certificate()
95964  : affine_dim(0), lin_space_dim(0), num_constraints(0), num_points(1),
95965    num_rays_null_coord() {
95966  // This is the certificate for a zero-dim universe polyhedron.
95967  PPL_ASSERT(OK());
95968}
95969
95970inline
95971BHRZ03_Certificate::BHRZ03_Certificate(const BHRZ03_Certificate& y)
95972  : affine_dim(y.affine_dim), lin_space_dim(y.lin_space_dim),
95973    num_constraints(y.num_constraints), num_points(y.num_points),
95974    num_rays_null_coord(y.num_rays_null_coord) {
95975}
95976
95977inline
95978BHRZ03_Certificate::~BHRZ03_Certificate() {
95979}
95980
95981inline bool
95982BHRZ03_Certificate::is_stabilizing(const Polyhedron& ph) const {
95983  return compare(ph) == 1;
95984}
95985
95986inline bool
95987BHRZ03_Certificate::Compare::operator()(const BHRZ03_Certificate& x,
95988                                        const BHRZ03_Certificate& y) const {
95989  // For an efficient evaluation of the multiset ordering based
95990  // on this LGO relation, we want larger elements to come first.
95991  return x.compare(y) == 1;
95992}
95993
95994} // namespace Parma_Polyhedra_Library
95995
95996/* Automatically generated from PPL source file ../src/BHRZ03_Certificate_defs.hh line 116. */
95997
95998/* Automatically generated from PPL source file ../src/H79_Certificate_defs.hh line 1. */
95999/* H79_Certificate class declaration.
96000*/
96001
96002
96003/* Automatically generated from PPL source file ../src/H79_Certificate_defs.hh line 30. */
96004#include <vector>
96005
96006//! A convergence certificate for the H79 widening operator.
96007/*! \ingroup PPL_CXX_interface
96008  Convergence certificates are used to instantiate the BHZ03 framework
96009  so as to define widening operators for the finite powerset domain.
96010  \note
96011  The convergence of the H79 widening can also be certified by
96012  BHRZ03_Certificate.
96013*/
96014class Parma_Polyhedra_Library::H79_Certificate {
96015public:
96016  //! Default constructor.
96017  H79_Certificate();
96018
96019  //! Constructor: computes the certificate for \p ph.
96020  template <typename PH>
96021  H79_Certificate(const PH& ph);
96022
96023  //! Constructor: computes the certificate for \p ph.
96024  H79_Certificate(const Polyhedron& ph);
96025
96026  //! Copy constructor.
96027  H79_Certificate(const H79_Certificate& y);
96028
96029  //! Destructor.
96030  ~H79_Certificate();
96031
96032  //! The comparison function for certificates.
96033  /*!
96034    \return
96035    \f$-1\f$, \f$0\f$ or \f$1\f$ depending on whether \p *this
96036    is smaller than, equal to, or greater than \p y, respectively.
96037
96038    Compares \p *this with \p y, using a total ordering which is a
96039    refinement of the limited growth ordering relation for the
96040    H79 widening.
96041  */
96042  int compare(const H79_Certificate& y) const;
96043
96044  //! Compares \p *this with the certificate for polyhedron \p ph.
96045  template <typename PH>
96046  int compare(const PH& ph) const;
96047
96048  //! Compares \p *this with the certificate for polyhedron \p ph.
96049  int compare(const Polyhedron& ph) const;
96050
96051  //! A total ordering on H79 certificates.
96052  /*! \ingroup PPL_CXX_interface
96053    This binary predicate defines a total ordering on H79 certificates
96054    which is used when storing information about sets of polyhedra.
96055  */
96056  struct Compare {
96057    //! Returns <CODE>true</CODE> if and only if \p x comes before \p y.
96058    bool operator()(const H79_Certificate& x,
96059                    const H79_Certificate& y) const;
96060  };
96061
96062private:
96063  //! Affine dimension of the polyhedron.
96064  dimension_type affine_dim;
96065  //! Cardinality of a non-redundant constraint system for the polyhedron.
96066  dimension_type num_constraints;
96067};
96068
96069/* Automatically generated from PPL source file ../src/H79_Certificate_inlines.hh line 1. */
96070/* H79_Certificate class implementation: inline functions.
96071*/
96072
96073
96074/* Automatically generated from PPL source file ../src/H79_Certificate_inlines.hh line 28. */
96075
96076namespace Parma_Polyhedra_Library {
96077
96078inline
96079H79_Certificate::H79_Certificate()
96080  : affine_dim(0), num_constraints(0) {
96081  // This is the certificate for a zero-dim universe polyhedron.
96082}
96083
96084inline
96085H79_Certificate::H79_Certificate(const H79_Certificate& y)
96086  : affine_dim(y.affine_dim), num_constraints(y.num_constraints) {
96087}
96088
96089inline
96090H79_Certificate::~H79_Certificate() {
96091}
96092
96093inline bool
96094H79_Certificate::Compare::operator()(const H79_Certificate& x,
96095                                     const H79_Certificate& y) const {
96096  // For an efficient evaluation of the multiset ordering based
96097  // on this LGO relation, we want larger elements to come first.
96098  return x.compare(y) == 1;
96099}
96100
96101template <typename PH>
96102inline
96103H79_Certificate::H79_Certificate(const PH& ph)
96104  : affine_dim(0), num_constraints(0) {
96105  H79_Certificate cert(Polyhedron(NECESSARILY_CLOSED, ph.constraints()));
96106  affine_dim = cert.affine_dim;
96107  num_constraints = cert.num_constraints;
96108}
96109
96110template <typename PH>
96111inline int
96112H79_Certificate::compare(const PH& ph) const {
96113  return this->compare(Polyhedron(NECESSARILY_CLOSED, ph.constraints()));
96114}
96115
96116} // namespace Parma_Polyhedra_Library
96117
96118/* Automatically generated from PPL source file ../src/H79_Certificate_defs.hh line 96. */
96119
96120/* Automatically generated from PPL source file ../src/Grid_Certificate_defs.hh line 1. */
96121/* Grid_Certificate class declaration.
96122*/
96123
96124
96125/* Automatically generated from PPL source file ../src/Grid_Certificate_defs.hh line 28. */
96126
96127/* Automatically generated from PPL source file ../src/Grid_Certificate_defs.hh line 31. */
96128#include <vector>
96129
96130//! The convergence certificate for the Grid widening operator.
96131/*! \ingroup PPL_CXX_interface
96132  Convergence certificates are used to instantiate the BHZ03 framework
96133  so as to define widening operators for the finite powerset domain.
96134
96135  \note
96136  Each convergence certificate has to be used together with a
96137  compatible widening operator. In particular, Grid_Certificate can
96138  certify the Grid widening.
96139*/
96140class Parma_Polyhedra_Library::Grid_Certificate {
96141public:
96142  //! Default constructor.
96143  Grid_Certificate();
96144
96145  //! Constructor: computes the certificate for \p gr.
96146  Grid_Certificate(const Grid& gr);
96147
96148  //! Copy constructor.
96149  Grid_Certificate(const Grid_Certificate& y);
96150
96151  //! Destructor.
96152  ~Grid_Certificate();
96153
96154  //! The comparison function for certificates.
96155  /*!
96156    \return
96157    \f$-1\f$, \f$0\f$ or \f$1\f$ depending on whether \p *this
96158    is smaller than, equal to, or greater than \p y, respectively.
96159  */
96160  int compare(const Grid_Certificate& y) const;
96161
96162  //! Compares \p *this with the certificate for grid \p gr.
96163  int compare(const Grid& gr) const;
96164
96165#ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
96166  /*! \brief
96167    Returns <CODE>true</CODE> if and only if the certificate for grid
96168    \p gr is strictly smaller than \p *this.
96169  */
96170#endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
96171  bool is_stabilizing(const Grid& gr) const;
96172
96173  //! A total ordering on Grid certificates.
96174  /*!
96175    This binary predicate defines a total ordering on Grid certificates
96176    which is used when storing information about sets of grids.
96177  */
96178  struct Compare {
96179    //! Returns <CODE>true</CODE> if and only if \p x comes before \p y.
96180    bool operator()(const Grid_Certificate& x,
96181                    const Grid_Certificate& y) const;
96182  };
96183
96184#ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
96185  //! Check if gathered information is meaningful.
96186#endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
96187  bool OK() const;
96188
96189private:
96190  //! Number of a equalities in a minimized congruence system for the
96191  //! grid.
96192  dimension_type num_equalities;
96193  //! Number of a proper congruences in a minimized congruence system
96194  //! for the grid.
96195  dimension_type num_proper_congruences;
96196};
96197
96198/* Automatically generated from PPL source file ../src/Grid_Certificate_inlines.hh line 1. */
96199/* Grid_Certificate class implementation: inline functions.
96200*/
96201
96202
96203/* Automatically generated from PPL source file ../src/Grid_Certificate_inlines.hh line 28. */
96204
96205namespace Parma_Polyhedra_Library {
96206
96207inline
96208Grid_Certificate::Grid_Certificate()
96209  : num_equalities(0), num_proper_congruences(0) {
96210  // This is the certificate for a zero-dim universe grid.
96211  PPL_ASSERT(OK());
96212}
96213
96214inline
96215Grid_Certificate::Grid_Certificate(const Grid_Certificate& y)
96216  : num_equalities(y.num_equalities),
96217    num_proper_congruences(y.num_proper_congruences) {
96218}
96219
96220inline
96221Grid_Certificate::~Grid_Certificate() {
96222}
96223
96224inline bool
96225Grid_Certificate::is_stabilizing(const Grid& gr) const {
96226  return compare(gr) == 1;
96227}
96228
96229inline bool
96230Grid_Certificate::Compare::operator()(const Grid_Certificate& x,
96231                                      const Grid_Certificate& y) const {
96232  // For an efficient evaluation of the multiset ordering based
96233  // on this LGO relation, we want larger elements to come first.
96234  return x.compare(y) == 1;
96235}
96236
96237} // namespace Parma_Polyhedra_Library
96238
96239/* Automatically generated from PPL source file ../src/Grid_Certificate_defs.hh line 102. */
96240
96241/* Automatically generated from PPL source file ../src/Partial_Function_defs.hh line 1. */
96242/* Partial_Function class declaration.
96243*/
96244
96245
96246/* Automatically generated from PPL source file ../src/Partial_Function_types.hh line 1. */
96247
96248
96249namespace Parma_Polyhedra_Library {
96250
96251class Partial_Function;
96252
96253} // namespace Parma_Polyhedra_Library
96254
96255/* Automatically generated from PPL source file ../src/Partial_Function_defs.hh line 29. */
96256#include <vector>
96257#ifndef NDEBUG
96258#include <set>
96259#endif
96260#include <iosfwd>
96261
96262namespace Parma_Polyhedra_Library {
96263
96264class Partial_Function {
96265public:
96266  /*! \brief
96267    Default constructor: builds a function with empty codomain
96268    (i.e., always undefined).
96269  */
96270  Partial_Function();
96271
96272  /*! \brief
96273    Returns \c true if and only if the represented partial function
96274    has an empty codomain (i.e., it is always undefined).
96275  */
96276  bool has_empty_codomain() const;
96277
96278  /*! \brief
96279    If the codomain is \e not empty, returns the maximum value in it.
96280
96281    \exception std::runtime_error
96282    Thrown if called when \p *this has an empty codomain.
96283  */
96284  dimension_type max_in_codomain() const;
96285
96286  /*! \brief
96287    If \p *this maps \p i to a value \c k, assigns \c k to \p j and
96288    returns \c true; otherwise, \p j is unchanged and \c false is returned.
96289  */
96290  bool maps(dimension_type i, dimension_type& j) const;
96291
96292  void print(std::ostream& s) const;
96293
96294  /*! \brief
96295    Modifies \p *this so that \p i is mapped to \p j.
96296
96297    \exception std::runtime_error
96298    Thrown if \p *this is already mapping \p j.
96299  */
96300  void insert(dimension_type i, dimension_type j);
96301
96302private:
96303  std::vector<dimension_type> vec;
96304  dimension_type max;
96305#ifndef NDEBUG
96306  std::set<dimension_type> codomain;
96307#endif
96308}; // class Partial_Function
96309
96310} // namespace Parma_Polyhedra_Library
96311
96312/* Automatically generated from PPL source file ../src/Partial_Function_inlines.hh line 1. */
96313/* Partial_Function class implementation: inline functions.
96314*/
96315
96316
96317/* Automatically generated from PPL source file ../src/Partial_Function_inlines.hh line 28. */
96318#include <stdexcept>
96319
96320namespace Parma_Polyhedra_Library {
96321
96322inline
96323Partial_Function::Partial_Function()
96324  : max(0) {
96325}
96326
96327inline bool
96328Partial_Function::has_empty_codomain() const {
96329  PPL_ASSERT(vec.empty() == codomain.empty());
96330  return vec.empty();
96331}
96332
96333inline dimension_type
96334Partial_Function::max_in_codomain() const {
96335  if (has_empty_codomain()) {
96336    throw std::runtime_error("Partial_Function::max_in_codomain() called"
96337                             " when has_empty_codomain()");
96338  }
96339  PPL_ASSERT(codomain.begin() != codomain.end()
96340             && max == *codomain.rbegin());
96341  return max;
96342}
96343
96344inline void
96345Partial_Function::insert(dimension_type i, dimension_type j) {
96346#ifndef NDEBUG
96347  // The partial function has to be an injective map.
96348  std::pair<std::set<dimension_type>::iterator, bool> s = codomain.insert(j);
96349  PPL_ASSERT(s.second);
96350#endif // #ifndef NDEBUG
96351
96352  // Expand `vec' if needed.
96353  const dimension_type sz = vec.size();
96354  if (i >= sz) {
96355    vec.insert(vec.end(), i - sz + 1, not_a_dimension());
96356  }
96357
96358  // We cannot remap the same index to another one.
96359  PPL_ASSERT(i < vec.size() && vec[i] == not_a_dimension());
96360  vec[i] = j;
96361
96362  // Maybe update `max'.
96363  if (j > max) {
96364    max = j;
96365  }
96366  PPL_ASSERT(codomain.begin() != codomain.end()
96367             && max == *codomain.rbegin());
96368}
96369
96370inline bool
96371Partial_Function::maps(dimension_type i, dimension_type& j) const {
96372  if (i >= vec.size()) {
96373    return false;
96374  }
96375  const dimension_type vec_i = vec[i];
96376  if (vec_i == not_a_dimension()) {
96377    return false;
96378  }
96379  j = vec_i;
96380  return true;
96381}
96382
96383} // namespace Parma_Polyhedra_Library
96384
96385/* Automatically generated from PPL source file ../src/Partial_Function_defs.hh line 86. */
96386
96387/* Automatically generated from PPL source file ../src/Widening_Function_defs.hh line 1. */
96388/* Widening_Function class declaration.
96389*/
96390
96391
96392/* Automatically generated from PPL source file ../src/Widening_Function_types.hh line 1. */
96393
96394
96395namespace Parma_Polyhedra_Library {
96396
96397template <typename PSET>
96398class Widening_Function;
96399
96400template <typename PSET, typename CSYS>
96401class Limited_Widening_Function;
96402
96403} // namespace Parma_Polyhedra_Library
96404
96405/* Automatically generated from PPL source file ../src/Widening_Function_defs.hh line 29. */
96406
96407#ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
96408//! Wraps a widening method into a function object.
96409/*! \ingroup PPL_CXX_interface */
96410#endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
96411template <typename PSET>
96412class Parma_Polyhedra_Library::Widening_Function {
96413public:
96414  //! The (parametric) type of a widening method.
96415  typedef void (PSET::* Widening_Method)(const PSET&, unsigned*);
96416
96417  //! Explicit unary constructor.
96418  explicit
96419  Widening_Function(Widening_Method wm);
96420
96421  //! Function-application operator.
96422  /*!
96423    Computes <CODE>(x.*wm)(y, tp)</CODE>, where \p wm is the widening
96424    method stored at construction time.
96425  */
96426  void operator()(PSET& x, const PSET& y, unsigned* tp = 0) const;
96427
96428private:
96429  //! The widening method.
96430  Widening_Method w_method;
96431};
96432
96433
96434#ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
96435//! Wraps a limited widening method into a function object.
96436/*! \ingroup PPL_CXX_interface */
96437#endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
96438template <typename PSET, typename CSYS>
96439class Parma_Polyhedra_Library::Limited_Widening_Function {
96440public:
96441  //! The (parametric) type of a limited widening method.
96442  typedef void (PSET::* Limited_Widening_Method)(const PSET&,
96443                                                 const CSYS&,
96444                                                 unsigned*);
96445
96446  //! Constructor.
96447  /*!
96448    \param lwm
96449    The limited widening method.
96450
96451    \param cs
96452    The constraint system limiting the widening.
96453  */
96454  Limited_Widening_Function(Limited_Widening_Method lwm,
96455                            const CSYS& cs);
96456
96457  //! Function-application operator.
96458  /*!
96459    Computes <CODE>(x.*lwm)(y, cs, tp)</CODE>, where \p lwm and \p cs
96460    are the limited widening method and the constraint system stored
96461    at construction time.
96462  */
96463  void operator()(PSET& x, const PSET& y, unsigned* tp = 0) const;
96464
96465private:
96466  //! The limited widening method.
96467  Limited_Widening_Method lw_method;
96468  //! A constant reference to the constraint system limiting the widening.
96469  const CSYS& limiting_cs;
96470};
96471
96472namespace Parma_Polyhedra_Library {
96473
96474//! Wraps a widening method into a function object.
96475/*!
96476  \relates Pointset_Powerset
96477
96478  \param wm
96479  The widening method.
96480*/
96481template <typename PSET>
96482Widening_Function<PSET>
96483widen_fun_ref(void (PSET::* wm)(const PSET&, unsigned*));
96484
96485//! Wraps a limited widening method into a function object.
96486/*!
96487  \relates Pointset_Powerset
96488
96489  \param lwm
96490  The limited widening method.
96491
96492  \param cs
96493  The constraint system limiting the widening.
96494*/
96495template <typename PSET, typename CSYS>
96496Limited_Widening_Function<PSET, CSYS>
96497widen_fun_ref(void (PSET::* lwm)(const PSET&, const CSYS&, unsigned*),
96498              const CSYS& cs);
96499
96500} // namespace Parma_Polyhedra_Library
96501
96502/* Automatically generated from PPL source file ../src/Widening_Function_inlines.hh line 1. */
96503/* Widening_Function class implementation: inline functions.
96504*/
96505
96506
96507/* Automatically generated from PPL source file ../src/Widening_Function_inlines.hh line 28. */
96508
96509namespace Parma_Polyhedra_Library {
96510
96511template <typename PSET>
96512Widening_Function<PSET>::Widening_Function(Widening_Method wm)
96513  : w_method(wm) {
96514}
96515
96516template <typename PSET>
96517inline void
96518Widening_Function<PSET>::
96519operator()(PSET& x, const PSET& y, unsigned* tp) const {
96520  (x.*w_method)(y, tp);
96521}
96522
96523template <typename PSET, typename CSYS>
96524Limited_Widening_Function<PSET, CSYS>::
96525Limited_Widening_Function(Limited_Widening_Method lwm,
96526                          const CSYS& cs)
96527  : lw_method(lwm), limiting_cs(cs) {
96528}
96529
96530template <typename PSET, typename CSYS>
96531inline void
96532Limited_Widening_Function<PSET, CSYS>::
96533operator()(PSET& x, const PSET& y, unsigned* tp) const {
96534  (x.*lw_method)(y, limiting_cs, tp);
96535}
96536
96537/*! \relates Pointset_Powerset */
96538template <typename PSET>
96539inline Widening_Function<PSET>
96540widen_fun_ref(void (PSET::* wm)(const PSET&, unsigned*)) {
96541  return Widening_Function<PSET>(wm);
96542}
96543
96544/*! \relates Pointset_Powerset */
96545template <typename PSET, typename CSYS>
96546inline Limited_Widening_Function<PSET, CSYS>
96547widen_fun_ref(void (PSET::* lwm)(const PSET&, const CSYS&, unsigned*),
96548              const CSYS& cs) {
96549  return Limited_Widening_Function<PSET, CSYS>(lwm, cs);
96550}
96551
96552} // namespace Parma_Polyhedra_Library
96553
96554
96555/* Automatically generated from PPL source file ../src/Widening_Function_defs.hh line 126. */
96556
96557/* Automatically generated from PPL source file ../src/max_space_dimension.hh line 1. */
96558/* Definition of functions yielding maximal space dimensions.
96559*/
96560
96561
96562/* Automatically generated from PPL source file ../src/NNC_Polyhedron_defs.hh line 1. */
96563/* NNC_Polyhedron class declaration.
96564*/
96565
96566
96567/* Automatically generated from PPL source file ../src/NNC_Polyhedron_defs.hh line 31. */
96568
96569//! A not necessarily closed convex polyhedron.
96570/*! \ingroup PPL_CXX_interface
96571    An object of the class NNC_Polyhedron represents a
96572    <EM>not necessarily closed</EM> (NNC) convex polyhedron
96573    in the vector space \f$\Rset^n\f$.
96574
96575    \note
96576    Since NNC polyhedra are a generalization of closed polyhedra,
96577    any object of the class C_Polyhedron can be (explicitly) converted
96578    into an object of the class NNC_Polyhedron.
96579    The reason for defining two different classes is that objects of
96580    the class C_Polyhedron are characterized by a more efficient
96581    implementation, requiring less time and memory resources.
96582*/
96583class Parma_Polyhedra_Library::NNC_Polyhedron : public Polyhedron {
96584public:
96585  //! Builds either the universe or the empty NNC polyhedron.
96586  /*!
96587    \param num_dimensions
96588    The number of dimensions of the vector space enclosing the NNC polyhedron;
96589
96590    \param kind
96591    Specifies whether a universe or an empty NNC polyhedron should be built.
96592
96593    \exception std::length_error
96594    Thrown if \p num_dimensions exceeds the maximum allowed space dimension.
96595
96596    Both parameters are optional:
96597    by default, a 0-dimension space universe NNC polyhedron is built.
96598  */
96599  explicit NNC_Polyhedron(dimension_type num_dimensions = 0,
96600                          Degenerate_Element kind = UNIVERSE);
96601
96602  //! Builds an NNC polyhedron from a system of constraints.
96603  /*!
96604    The polyhedron inherits the space dimension of the constraint system.
96605
96606    \param cs
96607    The system of constraints defining the polyhedron.
96608  */
96609  explicit NNC_Polyhedron(const Constraint_System& cs);
96610
96611  //! Builds an NNC polyhedron recycling a system of constraints.
96612  /*!
96613    The polyhedron inherits the space dimension of the constraint system.
96614
96615    \param cs
96616    The system of constraints defining the polyhedron.  It is not
96617    declared <CODE>const</CODE> because its data-structures may be
96618    recycled to build the polyhedron.
96619
96620    \param dummy
96621    A dummy tag to syntactically differentiate this one
96622    from the other constructors.
96623  */
96624  NNC_Polyhedron(Constraint_System& cs, Recycle_Input dummy);
96625
96626  //! Builds an NNC polyhedron from a system of generators.
96627  /*!
96628    The polyhedron inherits the space dimension of the generator system.
96629
96630    \param gs
96631    The system of generators defining the polyhedron.
96632
96633    \exception std::invalid_argument
96634    Thrown if the system of generators is not empty but has no points.
96635  */
96636  explicit NNC_Polyhedron(const Generator_System& gs);
96637
96638  //! Builds an NNC polyhedron recycling a system of generators.
96639  /*!
96640    The polyhedron inherits the space dimension of the generator system.
96641
96642    \param gs
96643    The system of generators defining the polyhedron.  It is not
96644    declared <CODE>const</CODE> because its data-structures may be
96645    recycled to build the polyhedron.
96646
96647    \param dummy
96648    A dummy tag to syntactically differentiate this one
96649    from the other constructors.
96650
96651    \exception std::invalid_argument
96652    Thrown if the system of generators is not empty but has no points.
96653  */
96654  NNC_Polyhedron(Generator_System& gs, Recycle_Input dummy);
96655
96656  //! Builds an NNC polyhedron from a system of congruences.
96657  /*!
96658    The polyhedron inherits the space dimension of the congruence system.
96659
96660    \param cgs
96661    The system of congruences defining the polyhedron.  It is not
96662    declared <CODE>const</CODE> because its data-structures may be
96663    recycled to build the polyhedron.
96664  */
96665  explicit NNC_Polyhedron(const Congruence_System& cgs);
96666
96667  //! Builds an NNC polyhedron recycling a system of congruences.
96668  /*!
96669    The polyhedron inherits the space dimension of the congruence
96670    system.
96671
96672    \param cgs
96673    The system of congruences defining the polyhedron.  It is not
96674    declared <CODE>const</CODE> because its data-structures may be
96675    recycled to build the polyhedron.
96676
96677    \param dummy
96678    A dummy tag to syntactically differentiate this one
96679    from the other constructors.
96680  */
96681  NNC_Polyhedron(Congruence_System& cgs, Recycle_Input dummy);
96682
96683  //! Builds an NNC polyhedron from the C polyhedron \p y.
96684  /*!
96685    \param y
96686    The C polyhedron to be used;
96687
96688    \param complexity
96689    This argument is ignored.
96690  */
96691  explicit NNC_Polyhedron(const C_Polyhedron& y,
96692                          Complexity_Class complexity = ANY_COMPLEXITY);
96693
96694  //! Builds an NNC polyhedron out of a box.
96695  /*!
96696    The polyhedron inherits the space dimension of the box
96697    and is the most precise that includes the box.
96698
96699    \param box
96700    The box representing the polyhedron to be built;
96701
96702    \param complexity
96703    This argument is ignored as the algorithm used has
96704    polynomial complexity.
96705
96706    \exception std::length_error
96707    Thrown if the space dimension of \p box exceeds the maximum allowed
96708    space dimension.
96709  */
96710  template <typename Interval>
96711  explicit NNC_Polyhedron(const Box<Interval>& box,
96712                          Complexity_Class complexity = ANY_COMPLEXITY);
96713
96714  //! Builds an NNC polyhedron out of a grid.
96715  /*!
96716    The polyhedron inherits the space dimension of the grid
96717    and is the most precise that includes the grid.
96718
96719    \param grid
96720    The grid used to build the polyhedron.
96721
96722    \param complexity
96723    This argument is ignored as the algorithm used has
96724    polynomial complexity.
96725  */
96726  explicit NNC_Polyhedron(const Grid& grid,
96727                          Complexity_Class complexity = ANY_COMPLEXITY);
96728
96729  //! Builds a NNC polyhedron out of a BD shape.
96730  /*!
96731    The polyhedron inherits the space dimension of the BD shape
96732    and is the most precise that includes the BD shape.
96733
96734    \param bd
96735    The BD shape used to build the polyhedron.
96736
96737    \param complexity
96738    This argument is ignored as the algorithm used has
96739    polynomial complexity.
96740  */
96741  template <typename U>
96742  explicit NNC_Polyhedron(const BD_Shape<U>& bd,
96743                          Complexity_Class complexity = ANY_COMPLEXITY);
96744
96745  //! Builds a NNC polyhedron out of an octagonal shape.
96746  /*!
96747    The polyhedron inherits the space dimension of the octagonal shape
96748    and is the most precise that includes the octagonal shape.
96749
96750    \param os
96751    The octagonal shape used to build the polyhedron.
96752
96753    \param complexity
96754    This argument is ignored as the algorithm used has
96755    polynomial complexity.
96756  */
96757  template <typename U>
96758  explicit NNC_Polyhedron(const Octagonal_Shape<U>& os,
96759                          Complexity_Class complexity = ANY_COMPLEXITY);
96760
96761  //! Ordinary copy constructor.
96762  NNC_Polyhedron(const NNC_Polyhedron& y,
96763                 Complexity_Class complexity = ANY_COMPLEXITY);
96764
96765  /*! \brief
96766    The assignment operator.
96767    (\p *this and \p y can be dimension-incompatible.)
96768  */
96769  NNC_Polyhedron& operator=(const NNC_Polyhedron& y);
96770
96771  //! Assigns to \p *this the C polyhedron \p y.
96772  NNC_Polyhedron& operator=(const C_Polyhedron& y);
96773
96774  //! Destructor.
96775  ~NNC_Polyhedron();
96776
96777  /*! \brief
96778    If the poly-hull of \p *this and \p y is exact it is assigned
96779    to \p *this and <CODE>true</CODE> is returned,
96780    otherwise <CODE>false</CODE> is returned.
96781
96782    \exception std::invalid_argument
96783    Thrown if \p *this and \p y are dimension-incompatible.
96784  */
96785  bool poly_hull_assign_if_exact(const NNC_Polyhedron& y);
96786
96787  //! Same as poly_hull_assign_if_exact(y).
96788  bool upper_bound_assign_if_exact(const NNC_Polyhedron& y);
96789
96790  /*! \brief
96791    Assigns to \p *this (the best approximation of) the result of
96792    computing the
96793    \ref Positive_Time_Elapse_Operator "positive time-elapse"
96794    between \p *this and \p y.
96795
96796    \exception std::invalid_argument
96797    Thrown if \p *this and \p y are dimension-incompatible.
96798  */
96799  void positive_time_elapse_assign(const Polyhedron& y);
96800};
96801
96802/* Automatically generated from PPL source file ../src/NNC_Polyhedron_inlines.hh line 1. */
96803/* NNC_Polyhedron class implementation: inline functions.
96804*/
96805
96806
96807/* Automatically generated from PPL source file ../src/NNC_Polyhedron_inlines.hh line 28. */
96808
96809namespace Parma_Polyhedra_Library {
96810
96811inline
96812NNC_Polyhedron::~NNC_Polyhedron() {
96813}
96814
96815inline
96816NNC_Polyhedron::NNC_Polyhedron(dimension_type num_dimensions,
96817                               Degenerate_Element kind)
96818  : Polyhedron(NOT_NECESSARILY_CLOSED,
96819               check_space_dimension_overflow(num_dimensions,
96820                                              NOT_NECESSARILY_CLOSED,
96821                                              "NNC_Polyhedron(n, k)",
96822                                              "n exceeds the maximum "
96823                                              "allowed space dimension"),
96824               kind) {
96825}
96826
96827inline
96828NNC_Polyhedron::NNC_Polyhedron(const Constraint_System& cs)
96829  : Polyhedron(NOT_NECESSARILY_CLOSED,
96830               check_obj_space_dimension_overflow(cs, NOT_NECESSARILY_CLOSED,
96831                                                  "NNC_Polyhedron(cs)",
96832                                                  "the space dimension of cs "
96833                                                  "exceeds the maximum allowed "
96834                                                  "space dimension")) {
96835}
96836
96837inline
96838NNC_Polyhedron::NNC_Polyhedron(Constraint_System& cs, Recycle_Input)
96839  : Polyhedron(NOT_NECESSARILY_CLOSED,
96840               check_obj_space_dimension_overflow(cs, NOT_NECESSARILY_CLOSED,
96841                                                  "NNC_Polyhedron(cs, recycle)",
96842                                                  "the space dimension of cs "
96843                                                  "exceeds the maximum allowed "
96844                                                  "space dimension"),
96845               Recycle_Input()) {
96846}
96847
96848inline
96849NNC_Polyhedron::NNC_Polyhedron(const Generator_System& gs)
96850  : Polyhedron(NOT_NECESSARILY_CLOSED,
96851               check_obj_space_dimension_overflow(gs, NOT_NECESSARILY_CLOSED,
96852                                                  "NNC_Polyhedron(gs)",
96853                                                  "the space dimension of gs "
96854                                                  "exceeds the maximum allowed "
96855                                                  "space dimension")) {
96856}
96857
96858inline
96859NNC_Polyhedron::NNC_Polyhedron(Generator_System& gs, Recycle_Input)
96860  : Polyhedron(NOT_NECESSARILY_CLOSED,
96861               check_obj_space_dimension_overflow(gs, NOT_NECESSARILY_CLOSED,
96862                                                  "NNC_Polyhedron(gs, recycle)",
96863                                                  "the space dimension of gs "
96864                                                  "exceeds the maximum allowed "
96865                                                  "space dimension"),
96866               Recycle_Input()) {
96867}
96868
96869template <typename Interval>
96870inline
96871NNC_Polyhedron::NNC_Polyhedron(const Box<Interval>& box, Complexity_Class)
96872  : Polyhedron(NOT_NECESSARILY_CLOSED,
96873               check_obj_space_dimension_overflow(box, NOT_NECESSARILY_CLOSED,
96874                                                  "NNC_Polyhedron(box)",
96875                                                  "the space dimension of box "
96876                                                  "exceeds the maximum allowed "
96877                                                  "space dimension")) {
96878}
96879
96880template <typename U>
96881inline
96882NNC_Polyhedron::NNC_Polyhedron(const BD_Shape<U>& bd, Complexity_Class)
96883  : Polyhedron(NOT_NECESSARILY_CLOSED,
96884               check_space_dimension_overflow(bd.space_dimension(),
96885                                              NOT_NECESSARILY_CLOSED,
96886                                              "NNC_Polyhedron(bd)",
96887                                              "the space dimension of bd "
96888                                              "exceeds the maximum allowed "
96889                                              "space dimension"),
96890               UNIVERSE) {
96891  add_constraints(bd.constraints());
96892}
96893
96894template <typename U>
96895inline
96896NNC_Polyhedron::NNC_Polyhedron(const Octagonal_Shape<U>& os, Complexity_Class)
96897  : Polyhedron(NOT_NECESSARILY_CLOSED,
96898               check_space_dimension_overflow(os.space_dimension(),
96899                                              NOT_NECESSARILY_CLOSED,
96900                                              "NNC_Polyhedron(os)",
96901                                              "the space dimension of os "
96902                                              "exceeds the maximum allowed "
96903                                              "space dimension"),
96904               UNIVERSE) {
96905  add_constraints(os.constraints());
96906}
96907
96908inline
96909NNC_Polyhedron::NNC_Polyhedron(const NNC_Polyhedron& y, Complexity_Class)
96910  : Polyhedron(y) {
96911}
96912
96913inline NNC_Polyhedron&
96914NNC_Polyhedron::operator=(const NNC_Polyhedron& y) {
96915  Polyhedron::operator=(y);
96916  return *this;
96917}
96918
96919inline NNC_Polyhedron&
96920NNC_Polyhedron::operator=(const C_Polyhedron& y) {
96921  NNC_Polyhedron nnc_y(y);
96922  m_swap(nnc_y);
96923  return *this;
96924}
96925
96926inline bool
96927NNC_Polyhedron::upper_bound_assign_if_exact(const NNC_Polyhedron& y) {
96928  return poly_hull_assign_if_exact(y);
96929}
96930
96931inline void
96932NNC_Polyhedron::positive_time_elapse_assign(const Polyhedron& y) {
96933  Polyhedron::positive_time_elapse_assign_impl(y);
96934}
96935
96936} // namespace Parma_Polyhedra_Library
96937
96938/* Automatically generated from PPL source file ../src/NNC_Polyhedron_defs.hh line 266. */
96939
96940/* Automatically generated from PPL source file ../src/Rational_Box.hh line 1. */
96941/* Rational_Box class declaration and implementation.
96942*/
96943
96944
96945/* Automatically generated from PPL source file ../src/Rational_Box.hh line 29. */
96946
96947namespace Parma_Polyhedra_Library {
96948
96949#ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
96950//! A box with rational, possibly open boundaries.
96951#endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
96952typedef Box<Rational_Interval> Rational_Box;
96953
96954} // namespace Parma_Polyhedra_Library
96955
96956/* Automatically generated from PPL source file ../src/max_space_dimension.hh line 34. */
96957#include <algorithm>
96958
96959namespace Parma_Polyhedra_Library {
96960
96961//! Returns the maximum space dimension this library can handle.
96962inline dimension_type
96963max_space_dimension() {
96964  // Note: we assume that the powerset and the ask-and-tell construction
96965  // do not limit the space dimension more than their parameters.
96966  static bool computed = false;
96967  static dimension_type d = not_a_dimension();
96968  if (!computed) {
96969    d = Variable::max_space_dimension();
96970    d = std::min(d, C_Polyhedron::max_space_dimension());
96971    d = std::min(d, NNC_Polyhedron::max_space_dimension());
96972    d = std::min(d, Grid::max_space_dimension());
96973    // FIXME: what about all other boxes?
96974    d = std::min(d, Rational_Box::max_space_dimension());
96975    d = std::min(d, BD_Shape<int8_t>::max_space_dimension());
96976    d = std::min(d, BD_Shape<int16_t>::max_space_dimension());
96977    d = std::min(d, BD_Shape<int32_t>::max_space_dimension());
96978    d = std::min(d, BD_Shape<int64_t>::max_space_dimension());
96979    d = std::min(d, BD_Shape<float>::max_space_dimension());
96980    d = std::min(d, BD_Shape<double>::max_space_dimension());
96981    d = std::min(d, BD_Shape<long double>::max_space_dimension());
96982    d = std::min(d, BD_Shape<mpz_class>::max_space_dimension());
96983    d = std::min(d, BD_Shape<mpq_class>::max_space_dimension());
96984    d = std::min(d, Octagonal_Shape<int8_t>::max_space_dimension());
96985    d = std::min(d, Octagonal_Shape<int16_t>::max_space_dimension());
96986    d = std::min(d, Octagonal_Shape<int32_t>::max_space_dimension());
96987    d = std::min(d, Octagonal_Shape<int64_t>::max_space_dimension());
96988    d = std::min(d, Octagonal_Shape<float>::max_space_dimension());
96989    d = std::min(d, Octagonal_Shape<double>::max_space_dimension());
96990    d = std::min(d, Octagonal_Shape<long double>::max_space_dimension());
96991    d = std::min(d, Octagonal_Shape<mpz_class>::max_space_dimension());
96992    d = std::min(d, Octagonal_Shape<mpq_class>::max_space_dimension());
96993    computed = true;
96994  }
96995  return d;
96996}
96997
96998} // namespace Parma_Polyhedra_Library
96999
97000/* Automatically generated from PPL source file ../src/algorithms.hh line 1. */
97001/* A collection of useful convex polyhedra algorithms: inline functions.
97002*/
97003
97004
97005/* Automatically generated from PPL source file ../src/Pointset_Powerset_defs.hh line 1. */
97006/* Pointset_Powerset class declaration.
97007*/
97008
97009
97010/* Automatically generated from PPL source file ../src/Pointset_Powerset_types.hh line 1. */
97011
97012
97013namespace Parma_Polyhedra_Library {
97014
97015template <typename PSET>
97016class Pointset_Powerset;
97017
97018} // namespace Parma_Polyhedra_Library
97019
97020/* Automatically generated from PPL source file ../src/Partially_Reduced_Product_defs.hh line 1. */
97021/* Partially_Reduced_Product class declaration.
97022*/
97023
97024
97025/* Automatically generated from PPL source file ../src/Partially_Reduced_Product_defs.hh line 49. */
97026
97027namespace Parma_Polyhedra_Library {
97028
97029namespace IO_Operators {
97030
97031//! Output operator.
97032/*!
97033  \relates Parma_Polyhedra_Library::Partially_Reduced_Product
97034  Writes a textual representation of \p dp on \p s.
97035*/
97036template <typename D1, typename D2, typename R>
97037std::ostream&
97038operator<<(std::ostream& s, const Partially_Reduced_Product<D1, D2, R>& dp);
97039
97040} // namespace IO_Operators
97041
97042//! Swaps \p x with \p y.
97043/*! \relates Partially_Reduced_Product */
97044template <typename D1, typename D2, typename R>
97045void swap(Partially_Reduced_Product<D1, D2, R>& x,
97046          Partially_Reduced_Product<D1, D2, R>& y);
97047
97048/*! \brief
97049  Returns <CODE>true</CODE> if and only if the components of \p x and \p y
97050  are pairwise equal.
97051
97052  \relates Partially_Reduced_Product
97053  Note that \p x and \p y may be dimension-incompatible: in
97054  those cases, the value <CODE>false</CODE> is returned.
97055*/
97056template <typename D1, typename D2, typename R>
97057bool operator==(const Partially_Reduced_Product<D1, D2, R>& x,
97058                const Partially_Reduced_Product<D1, D2, R>& y);
97059
97060/*! \brief
97061  Returns <CODE>true</CODE> if and only if the components of \p x and \p y
97062  are not pairwise equal.
97063
97064  \relates Partially_Reduced_Product
97065  Note that \p x and \p y may be dimension-incompatible: in
97066  those cases, the value <CODE>true</CODE> is returned.
97067*/
97068template <typename D1, typename D2, typename R>
97069bool operator!=(const Partially_Reduced_Product<D1, D2, R>& x,
97070                const Partially_Reduced_Product<D1, D2, R>& y);
97071
97072} // namespace Parma_Polyhedra_Library
97073
97074
97075/*! \brief
97076  This class provides the reduction method for the Smash_Product
97077  domain.
97078
97079  \ingroup PPL_CXX_interface
97080  The reduction classes are used to instantiate the Partially_Reduced_Product
97081  domain. This class propagates emptiness between its components.
97082*/
97083template <typename D1, typename D2>
97084class Parma_Polyhedra_Library::Smash_Reduction {
97085public:
97086  //! Default constructor.
97087  Smash_Reduction();
97088
97089  /*! \brief
97090    The smash reduction operator for propagating emptiness between the
97091    domain elements \p d1 and \p d2.
97092
97093    If either of the the domain elements \p d1 or \p d2 is empty
97094    then the other is also set empty.
97095
97096    \param d1
97097    A pointset domain element;
97098
97099    \param d2
97100    A pointset domain element;
97101  */
97102  void product_reduce(D1& d1, D2& d2);
97103
97104  //! Destructor.
97105  ~Smash_Reduction();
97106};
97107
97108/*! \brief
97109  This class provides the reduction method for the Constraints_Product
97110  domain.
97111
97112  \ingroup PPL_CXX_interface
97113  The reduction classes are used to instantiate the Partially_Reduced_Product
97114  domain. This class adds the constraints defining each of the component
97115  domains to the other component.
97116*/
97117template <typename D1, typename D2>
97118class Parma_Polyhedra_Library::Constraints_Reduction {
97119public:
97120  //! Default constructor.
97121  Constraints_Reduction();
97122
97123  /*! \brief
97124    The constraints reduction operator for sharing constraints between the
97125    domains.
97126
97127    The minimized constraint system defining the domain element \p d1
97128    is added to \p d2 and the minimized constraint system  defining \p d2
97129    is added to \p d1.
97130    In each case, the donor domain must provide a constraint system
97131    in minimal form; this must define a polyhedron in which the
97132    donor element is contained.
97133    The recipient domain selects a subset of these constraints
97134    that it can add to the recipient element.
97135    For example: if the domain \p D1 is the Grid domain and \p D2
97136    the NNC Polyhedron domain, then only the equality constraints are copied
97137    from \p d1 to \p d2 and from \p d2 to \p d1.
97138
97139    \param d1
97140    A pointset domain element;
97141
97142    \param d2
97143    A pointset domain element;
97144  */
97145  void product_reduce(D1& d1, D2& d2);
97146
97147  //! Destructor.
97148  ~Constraints_Reduction();
97149};
97150
97151/*! \brief
97152  This class provides the reduction method for the Congruences_Product
97153  domain.
97154
97155  \ingroup PPL_CXX_interface
97156  The reduction classes are used to instantiate the Partially_Reduced_Product
97157  domain.
97158
97159  This class uses the minimized congruences defining each of the components.
97160  For each of the congruences, it checks if the other component
97161  intersects none, one or more than one hyperplane defined by the congruence
97162  and adds equalities or emptiness as appropriate; in more detail:
97163  Letting the components be d1 and d2, then, for each congruence cg
97164  representing d1:
97165  - if more than one hyperplane defined by cg intersects
97166    d2, then d1 and d2 are unchanged;
97167  - if exactly one hyperplane intersects d2, then d1 and d2 are
97168    refined with the corresponding equality ;
97169  - otherwise, d1 and d2 are set to empty.
97170  Unless d1 and d2 are already empty, the process is repeated where the
97171  roles of d1 and d2 are reversed.
97172  If d1 or d2 is empty, then the emptiness is propagated.
97173
97174*/
97175template <typename D1, typename D2>
97176class Parma_Polyhedra_Library::Congruences_Reduction {
97177public:
97178  //! Default constructor.
97179  Congruences_Reduction();
97180
97181  /*! \brief
97182    The congruences reduction operator for detect emptiness or any equalities
97183    implied by each of the congruences defining one of the components
97184    and the bounds of the other component. It is assumed that the
97185    components are already constraints reduced.
97186
97187    The minimized congruence system defining the domain element \p d1
97188    is used to check if \p d2 intersects none, one or more than one
97189    of the hyperplanes defined by the congruences: if it intersects none,
97190    then product is set empty; if it intersects one, then the equality
97191    defining this hyperplane is added to both components; otherwise,
97192    the product is unchanged.
97193    In each case, the donor domain must provide a congruence system
97194    in minimal form.
97195
97196    \param d1
97197    A pointset domain element;
97198
97199    \param d2
97200    A pointset domain element;
97201  */
97202  void product_reduce(D1& d1, D2& d2);
97203
97204  //! Destructor.
97205  ~Congruences_Reduction();
97206};
97207
97208/*! \brief
97209  This class provides the reduction method for the Shape_Preserving_Product
97210  domain.
97211
97212  \ingroup PPL_CXX_interface
97213  The reduction classes are used to instantiate the Partially_Reduced_Product
97214  domain.
97215
97216  This reduction method includes the congruences reduction.
97217  This class uses the minimized constraints defining each of the components.
97218  For each of the constraints, it checks the frequency and value for the same
97219  linear expression in the other component. If the constraint does not satisfy
97220  the implied congruence, the inhomogeneous term is adjusted so that it does.
97221  Note that, unless the congruences reduction adds equalities, the
97222  shapes of the domains are unaltered.
97223
97224*/
97225template <typename D1, typename D2>
97226class Parma_Polyhedra_Library::Shape_Preserving_Reduction {
97227public:
97228  //! Default constructor.
97229  Shape_Preserving_Reduction();
97230
97231  /*! \brief
97232    The congruences reduction operator for detect emptiness or any equalities
97233    implied by each of the congruences defining one of the components
97234    and the bounds of the other component. It is assumed that the
97235    components are already constraints reduced.
97236
97237    The minimized congruence system defining the domain element \p d1
97238    is used to check if \p d2 intersects none, one or more than one
97239    of the hyperplanes defined by the congruences: if it intersects none,
97240    then product is set empty; if it intersects one, then the equality
97241    defining this hyperplane is added to both components; otherwise,
97242    the product is unchanged.
97243    In each case, the donor domain must provide a congruence system
97244    in minimal form.
97245
97246    \param d1
97247    A pointset domain element;
97248
97249    \param d2
97250    A pointset domain element;
97251  */
97252  void product_reduce(D1& d1, D2& d2);
97253
97254  //! Destructor.
97255  ~Shape_Preserving_Reduction();
97256};
97257
97258/*! \brief
97259  This class provides the reduction method for the Direct_Product domain.
97260
97261  \ingroup PPL_CXX_interface
97262  The reduction classes are used to instantiate the Partially_Reduced_Product
97263  domain template parameter \p R. This class does no reduction at all.
97264*/
97265template <typename D1, typename D2>
97266class Parma_Polyhedra_Library::No_Reduction {
97267public:
97268  //! Default constructor.
97269  No_Reduction();
97270
97271  /*! \brief
97272    The null reduction operator.
97273
97274    The parameters \p d1 and \p d2 are ignored.
97275  */
97276  void product_reduce(D1& d1, D2& d2);
97277
97278  //! Destructor.
97279  ~No_Reduction();
97280};
97281
97282//! The partially reduced product of two abstractions.
97283/*! \ingroup PPL_CXX_interface
97284
97285  \warning
97286  At present, the supported instantiations for the
97287  two domain templates \p D1 and \p D2 are the simple pointset domains:
97288  <CODE>C_Polyhedron</CODE>,
97289  <CODE>NNC_Polyhedron</CODE>,
97290  <CODE>Grid</CODE>,
97291  <CODE>Octagonal_Shape\<T\></CODE>,
97292  <CODE>BD_Shape\<T\></CODE>,
97293  <CODE>Box\<T\></CODE>.
97294
97295  An object of the class <CODE>Partially_Reduced_Product\<D1, D2, R\></CODE>
97296  represents the (partially reduced) product of two pointset domains \p D1
97297  and \p D2 where the form of any reduction is defined by the
97298  reduction class \p R.
97299
97300  Suppose \f$D_1\f$ and \f$D_2\f$ are two abstract domains
97301  with concretization functions:
97302  \f$\fund{\gamma_1}{D_1}{\Rset^n}\f$ and
97303  \f$\fund{\gamma_2}{D_2}{\Rset^n}\f$, respectively.
97304
97305  The partially reduced product \f$D = D_1 \times D_2\f$,
97306  for any reduction class \p R, has a concretization
97307  \f$\fund{\gamma}{D}{\Rset^n}\f$
97308  where, if \f$d = (d_1, d_2) \in D\f$
97309  \f[
97310    \gamma(d) = \gamma_1(d_1) \inters \gamma_2(d_2).
97311  \f]
97312
97313  The operations are defined to be the result of applying the corresponding
97314  operations on each of the components provided the product is already reduced
97315  by the reduction method defined by \p R.
97316  In particular, if \p R is the <CODE>No_Reduction\<D1, D2\></CODE> class,
97317  then the class <CODE>Partially_Reduced_Product\<D1, D2, R\></CODE> domain
97318  is the direct product as defined in \ref CC79 "[CC79]".
97319
97320  How the results on the components are interpreted and
97321  combined depend on the specific test.
97322  For example, the test for emptiness will first make sure
97323  the product is reduced (using the reduction method provided by \p R
97324  if it is not already known to be reduced) and then test if either component
97325  is empty; thus, if \p R defines no reduction between its components and
97326  \f$d = (G, P) \in (\Gset \times \Pset)\f$
97327  is a direct product in one dimension where \f$G\f$ denotes the set of
97328  numbers that are integral multiples of 3 while \f$P\f$ denotes the
97329  set of numbers between 1 and 2, then an operation that tests for
97330  emptiness should return false.
97331  However, the test for the universe returns true if and only if the
97332  test <CODE>is_universe()</CODE> on both components returns true.
97333
97334  \par
97335  In all the examples it is assumed that the template \c R is the
97336  <CODE>No_Reduction\<D1, D2\></CODE> class and that variables
97337  \c x and \c y are defined (where they are used) as follows:
97338  \code
97339  Variable x(0);
97340  Variable y(1);
97341  \endcode
97342
97343  \par Example 1
97344  The following code builds a direct product of a Grid and NNC Polyhedron,
97345  corresponding to the positive even integer
97346  pairs in \f$\Rset^2\f$, given as a system of congruences:
97347  \code
97348  Congruence_System cgs;
97349  cgs.insert((x %= 0) / 2);
97350  cgs.insert((y %= 0) / 2);
97351  Partially_Reduced_Product<Grid, NNC_Polyhedron, No_Reduction<D1, D2> >
97352    dp(cgs);
97353  dp.add_constraint(x >= 0);
97354  dp.add_constraint(y >= 0);
97355  \endcode
97356
97357  \par Example 2
97358  The following code builds the same product
97359  in \f$\Rset^2\f$:
97360  \code
97361  Partially_Reduced_Product<Grid, NNC_Polyhedron, No_Reduction<D1, D2> > dp(2);
97362  dp.add_constraint(x >= 0);
97363  dp.add_constraint(y >= 0);
97364  dp.add_congruence((x %= 0) / 2);
97365  dp.add_congruence((y %= 0) / 2);
97366  \endcode
97367
97368  \par Example 3
97369  The following code will write "dp is empty":
97370  \code
97371  Partially_Reduced_Product<Grid, NNC_Polyhedron, No_Reduction<D1, D2> > dp(1);
97372  dp.add_congruence((x %= 0) / 2);
97373  dp.add_congruence((x %= 1) / 2);
97374  if (dp.is_empty())
97375    cout << "dp is empty." << endl;
97376  else
97377    cout << "dp is not empty." << endl;
97378  \endcode
97379
97380  \par Example 4
97381  The following code will write "dp is not empty":
97382  \code
97383  Partially_Reduced_Product<Grid, NNC_Polyhedron, No_Reduction<D1, D2> > dp(1);
97384  dp.add_congruence((x %= 0) / 2);
97385  dp.add_constraint(x >= 1);
97386  dp.add_constraint(x <= 1);
97387  if (dp.is_empty())
97388    cout << "dp is empty." << endl;
97389  else
97390    cout << "dp is not empty." << endl;
97391  \endcode
97392*/
97393
97394template <typename D1, typename D2, typename R>
97395class Parma_Polyhedra_Library::Partially_Reduced_Product {
97396public:
97397  /*! \brief
97398    Returns the maximum space dimension this product
97399    can handle.
97400  */
97401  static dimension_type max_space_dimension();
97402
97403  //! Builds an object having the specified properties.
97404  /*!
97405    \param num_dimensions
97406    The number of dimensions of the vector space enclosing the pair;
97407
97408    \param kind
97409    Specifies whether a universe or an empty pair has to be built.
97410
97411    \exception std::length_error
97412    Thrown if \p num_dimensions exceeds the maximum allowed space
97413    dimension.
97414  */
97415  explicit Partially_Reduced_Product(dimension_type num_dimensions = 0,
97416                                     Degenerate_Element kind = UNIVERSE);
97417
97418  //! Builds a pair, copying a system of congruences.
97419  /*!
97420    The pair inherits the space dimension of the congruence system.
97421
97422    \param cgs
97423    The system of congruences to be approximated by the pair.
97424
97425    \exception std::length_error
97426    Thrown if \p num_dimensions exceeds the maximum allowed space
97427    dimension.
97428  */
97429  explicit Partially_Reduced_Product(const Congruence_System& cgs);
97430
97431  //! Builds a pair, recycling a system of congruences.
97432  /*!
97433    The pair inherits the space dimension of the congruence system.
97434
97435    \param cgs
97436    The system of congruences to be approximates by the pair.
97437    Its data-structures may be recycled to build the pair.
97438
97439    \exception std::length_error
97440    Thrown if \p num_dimensions exceeds the maximum allowed space
97441    dimension.
97442  */
97443  explicit Partially_Reduced_Product(Congruence_System& cgs);
97444
97445  //! Builds a pair, copying a system of constraints.
97446  /*!
97447    The pair inherits the space dimension of the constraint system.
97448
97449    \param cs
97450    The system of constraints to be approximated by the pair.
97451
97452    \exception std::length_error
97453    Thrown if \p num_dimensions exceeds the maximum allowed space
97454    dimension.
97455  */
97456  explicit Partially_Reduced_Product(const Constraint_System& cs);
97457
97458  //! Builds a pair, recycling a system of constraints.
97459  /*!
97460    The pair inherits the space dimension of the constraint system.
97461
97462    \param cs
97463    The system of constraints to be approximated by the pair.
97464
97465    \exception std::length_error
97466    Thrown if the space dimension of \p cs exceeds the maximum allowed
97467    space dimension.
97468  */
97469  explicit Partially_Reduced_Product(Constraint_System& cs);
97470
97471  //! Builds a product, from a C polyhedron.
97472  /*!
97473    Builds a product containing \p ph using algorithms whose
97474    complexity does not exceed the one specified by \p complexity.
97475    If \p complexity is \p ANY_COMPLEXITY, then the built product is the
97476    smallest one containing \p ph.
97477    The product inherits the space dimension of the polyhedron.
97478
97479    \param ph
97480    The polyhedron to be approximated by the product.
97481
97482    \param complexity
97483    The complexity that will not be exceeded.
97484
97485    \exception std::length_error
97486    Thrown if the space dimension of \p ph exceeds the maximum allowed
97487    space dimension.
97488  */
97489  explicit
97490  Partially_Reduced_Product(const C_Polyhedron& ph,
97491                            Complexity_Class complexity = ANY_COMPLEXITY);
97492
97493  //! Builds a product, from an NNC polyhedron.
97494  /*!
97495    Builds a product containing \p ph using algorithms whose
97496    complexity does not exceed the one specified by \p complexity.
97497    If \p complexity is \p ANY_COMPLEXITY, then the built product is the
97498    smallest one containing \p ph.
97499    The product inherits the space dimension of the polyhedron.
97500
97501    \param ph
97502    The polyhedron to be approximated by the product.
97503
97504    \param complexity
97505    The complexity that will not be exceeded.
97506
97507    \exception std::length_error
97508    Thrown if the space dimension of \p ph exceeds the maximum allowed
97509    space dimension.
97510  */
97511  explicit
97512  Partially_Reduced_Product(const NNC_Polyhedron& ph,
97513                            Complexity_Class complexity = ANY_COMPLEXITY);
97514
97515  //! Builds a product, from a grid.
97516  /*!
97517    Builds a product containing \p gr.
97518    The product inherits the space dimension of the grid.
97519
97520    \param gr
97521    The grid to be approximated by the product.
97522
97523    \param complexity
97524    The complexity is ignored.
97525
97526    \exception std::length_error
97527    Thrown if the space dimension of \p gr exceeds the maximum allowed
97528    space dimension.
97529  */
97530  explicit
97531  Partially_Reduced_Product(const Grid& gr,
97532                            Complexity_Class complexity = ANY_COMPLEXITY);
97533
97534  //! Builds a product out of a box.
97535  /*!
97536    Builds a product containing \p box.
97537    The product inherits the space dimension of the box.
97538
97539    \param box
97540    The box representing the pair to be built.
97541
97542    \param complexity
97543    The complexity is ignored.
97544
97545    \exception std::length_error
97546    Thrown if the space dimension of \p box exceeds the maximum
97547    allowed space dimension.
97548  */
97549  template <typename Interval>
97550  Partially_Reduced_Product(const Box<Interval>& box,
97551                            Complexity_Class complexity = ANY_COMPLEXITY);
97552
97553  //! Builds a product out of a BD shape.
97554  /*!
97555    Builds a product containing \p bd.
97556    The product inherits the space dimension of the BD shape.
97557
97558    \param bd
97559    The BD shape representing the product to be built.
97560
97561    \param complexity
97562    The complexity is ignored.
97563
97564    \exception std::length_error
97565    Thrown if the space dimension of \p bd exceeds the maximum
97566    allowed space dimension.
97567  */
97568  template <typename U>
97569  Partially_Reduced_Product(const BD_Shape<U>& bd,
97570                            Complexity_Class complexity = ANY_COMPLEXITY);
97571
97572  //! Builds a product out of an octagonal shape.
97573  /*!
97574    Builds a product containing \p os.
97575    The product inherits the space dimension of the octagonal shape.
97576
97577    \param os
97578    The octagonal shape representing the product to be built.
97579
97580    \param complexity
97581    The complexity is ignored.
97582
97583    \exception std::length_error
97584    Thrown if the space dimension of \p os exceeds the maximum
97585    allowed space dimension.
97586  */
97587  template <typename U>
97588  Partially_Reduced_Product(const Octagonal_Shape<U>& os,
97589                            Complexity_Class complexity = ANY_COMPLEXITY);
97590
97591  //! Ordinary copy constructor.
97592  Partially_Reduced_Product(const Partially_Reduced_Product& y,
97593                            Complexity_Class complexity = ANY_COMPLEXITY);
97594
97595  //! Builds a conservative, upward approximation of \p y.
97596  /*!
97597    The complexity argument is ignored.
97598  */
97599  template <typename E1, typename E2, typename S>
97600  explicit
97601  Partially_Reduced_Product(const Partially_Reduced_Product<E1, E2, S>& y,
97602                            Complexity_Class complexity = ANY_COMPLEXITY);
97603
97604  /*! \brief
97605    The assignment operator.  (\p *this and \p y can be
97606    dimension-incompatible.)
97607  */
97608  Partially_Reduced_Product& operator=(const Partially_Reduced_Product& y);
97609
97610  //! \name Member Functions that Do Not Modify the Partially_Reduced_Product
97611  //@{
97612
97613  //! Returns the dimension of the vector space enclosing \p *this.
97614  dimension_type space_dimension() const;
97615
97616  /*! \brief
97617    Returns the minimum \ref Affine_Independence_and_Affine_Dimension
97618    "affine dimension"
97619    (see also \ref Grid_Affine_Dimension "grid affine dimension")
97620    of the components of \p *this.
97621  */
97622  dimension_type affine_dimension() const;
97623
97624  //! Returns a constant reference to the first of the pair.
97625  const D1& domain1() const;
97626
97627  //! Returns a constant reference to the second of the pair.
97628  const D2& domain2() const;
97629
97630  //! Returns a system of constraints which approximates \p *this.
97631  Constraint_System constraints() const;
97632
97633  /*! \brief
97634    Returns a system of constraints which approximates \p *this, in
97635    reduced form.
97636  */
97637  Constraint_System minimized_constraints() const;
97638
97639  //! Returns a system of congruences which approximates \p *this.
97640  Congruence_System congruences() const;
97641
97642  /*! \brief
97643    Returns a system of congruences which approximates \p *this, in
97644    reduced form.
97645  */
97646  Congruence_System minimized_congruences() const;
97647
97648  //! Returns the relations holding between \p *this and \p c.
97649  /*
97650    \exception std::invalid_argument
97651    Thrown if \p *this and congruence \p cg are dimension-incompatible.
97652
97653    Returns the Poly_Con_Relation \p r for \p *this:
97654    suppose the first component returns \p r1 and the second \p r2,
97655    then \p r implies <CODE>is_included()</CODE>
97656    if and only if one or both of \p r1 and \p r2 imply
97657    <CODE>is_included()</CODE>;
97658    \p r implies <CODE>saturates()</CODE>
97659    if and only if one or both of \p r1 and \p r2 imply
97660    <CODE>saturates()</CODE>;
97661    \p r implies <CODE>is_disjoint()</CODE>
97662    if and only if one or both of \p r1 and \p r2 imply
97663    <CODE>is_disjoint()</CODE>;
97664    and \p r implies <CODE>nothing()</CODE>
97665    if and only if both \p r1 and \p r2 imply
97666    <CODE>strictly_intersects()</CODE>.
97667  */
97668  Poly_Con_Relation relation_with(const Constraint& c) const;
97669
97670  //! Returns the relations holding between \p *this and \p cg.
97671  /*
97672    \exception std::invalid_argument
97673    Thrown if \p *this and congruence \p cg are dimension-incompatible.
97674  */
97675  Poly_Con_Relation relation_with(const Congruence& cg) const;
97676
97677  //! Returns the relations holding between \p *this and \p g.
97678  /*
97679    \exception std::invalid_argument
97680    Thrown if \p *this and generator \p g are dimension-incompatible.
97681
97682    Returns the Poly_Gen_Relation \p r for \p *this:
97683    suppose the first component returns \p r1 and the second \p r2,
97684    then \p r = <CODE>subsumes()</CODE>
97685    if and only if \p r1 = \p r2 = <CODE>subsumes()</CODE>;
97686    and \p r = <CODE>nothing()</CODE>
97687    if and only if one or both of \p r1 and \p r2 = <CODE>nothing()</CODE>;
97688  */
97689  Poly_Gen_Relation relation_with(const Generator& g) const;
97690
97691  /*! \brief
97692    Returns <CODE>true</CODE> if and only if either of the components
97693    of \p *this are empty.
97694  */
97695  bool is_empty() const;
97696
97697  /*! \brief
97698    Returns <CODE>true</CODE> if and only if both of the components
97699    of \p *this are the universe.
97700  */
97701  bool is_universe() const;
97702
97703  /*! \brief
97704    Returns <CODE>true</CODE> if and only if both of the components
97705    of \p *this are topologically closed subsets of the vector space.
97706  */
97707  bool is_topologically_closed() const;
97708
97709  /*! \brief
97710    Returns <CODE>true</CODE> if and only if \p *this and \p y are
97711    componentwise disjoint.
97712
97713    \exception std::invalid_argument
97714    Thrown if \p x and \p y are dimension-incompatible.
97715  */
97716  bool is_disjoint_from(const Partially_Reduced_Product& y) const;
97717
97718  /*! \brief
97719    Returns <CODE>true</CODE> if and only if a component of \p *this
97720    is discrete.
97721  */
97722  bool is_discrete() const;
97723
97724  /*! \brief
97725    Returns <CODE>true</CODE> if and only if a component of \p *this
97726    is bounded.
97727  */
97728  bool is_bounded() const;
97729
97730  /*! \brief
97731    Returns <CODE>true</CODE> if and only if \p var is constrained in
97732    \p *this.
97733
97734    \exception std::invalid_argument
97735    Thrown if \p var is not a space dimension of \p *this.
97736  */
97737  bool constrains(Variable var) const;
97738
97739  //! Returns <CODE>true</CODE> if and only if \p expr is bounded in \p *this.
97740  /*!
97741    This method is the same as bounds_from_below.
97742
97743    \exception std::invalid_argument
97744    Thrown if \p expr and \p *this are dimension-incompatible.
97745  */
97746  bool bounds_from_above(const Linear_Expression& expr) const;
97747
97748  //! Returns <CODE>true</CODE> if and only if \p expr is bounded in \p *this.
97749  /*!
97750    This method is the same as bounds_from_above.
97751
97752    \exception std::invalid_argument
97753    Thrown if \p expr and \p *this are dimension-incompatible.
97754  */
97755  bool bounds_from_below(const Linear_Expression& expr) const;
97756
97757  /*! \brief
97758    Returns <CODE>true</CODE> if and only if \p *this is not empty and
97759    \p expr is bounded from above in \p *this, in which case the
97760    supremum value is computed.
97761
97762    \param expr
97763    The linear expression to be maximized subject to \p *this;
97764
97765    \param sup_n
97766    The numerator of the supremum value;
97767
97768    \param sup_d
97769    The denominator of the supremum value;
97770
97771    \param maximum
97772    <CODE>true</CODE> if the supremum value can be reached in \p this.
97773
97774    \exception std::invalid_argument
97775    Thrown if \p expr and \p *this are dimension-incompatible.
97776
97777    If \p *this is empty or \p expr is not bounded by \p *this,
97778    <CODE>false</CODE> is returned and \p sup_n, \p sup_d and \p
97779    maximum are left untouched.
97780  */
97781  bool maximize(const Linear_Expression& expr,
97782                Coefficient& sup_n, Coefficient& sup_d, bool& maximum) const;
97783
97784  /*! \brief
97785    Returns <CODE>true</CODE> if and only if \p *this is not empty and
97786    \p expr is bounded from above in \p *this, in which case the
97787    supremum value and a point where \p expr reaches it are computed.
97788
97789    \param expr
97790    The linear expression to be maximized subject to \p *this;
97791
97792    \param sup_n
97793    The numerator of the supremum value;
97794
97795    \param sup_d
97796    The denominator of the supremum value;
97797
97798    \param maximum
97799    <CODE>true</CODE> if the supremum value can be reached in \p this.
97800
97801    \param g
97802    When maximization succeeds, will be assigned the point or
97803    closure point where \p expr reaches its supremum value.
97804
97805    \exception std::invalid_argument
97806    Thrown if \p expr and \p *this are dimension-incompatible.
97807
97808    If \p *this is empty or \p expr is not bounded by \p *this,
97809    <CODE>false</CODE> is returned and \p sup_n, \p sup_d, \p maximum
97810    and \p g are left untouched.
97811  */
97812  bool maximize(const Linear_Expression& expr,
97813                Coefficient& sup_n, Coefficient& sup_d, bool& maximum,
97814                Generator& g) const;
97815
97816  /*! \brief
97817    Returns <CODE>true</CODE> if and only if \p *this is not empty and
97818    \p expr is bounded from below i \p *this, in which case the
97819    infimum value is computed.
97820
97821    \param expr
97822    The linear expression to be minimized subject to \p *this;
97823
97824    \param inf_n
97825    The numerator of the infimum value;
97826
97827    \param inf_d
97828    The denominator of the infimum value;
97829
97830    \param minimum
97831    <CODE>true</CODE> if the infimum value can be reached in \p this.
97832
97833    \exception std::invalid_argument
97834    Thrown if \p expr and \p *this are dimension-incompatible.
97835
97836    If \p *this is empty or \p expr is not bounded from below,
97837    <CODE>false</CODE> is returned and \p inf_n, \p inf_d
97838    and \p minimum are left untouched.
97839  */
97840  bool minimize(const Linear_Expression& expr,
97841                Coefficient& inf_n, Coefficient& inf_d, bool& minimum) const;
97842
97843  /*! \brief
97844    Returns <CODE>true</CODE> if and only if \p *this is not empty and
97845    \p expr is bounded from below in \p *this, in which case the
97846    infimum value and a point where \p expr reaches it are computed.
97847
97848    \param expr
97849    The linear expression to be minimized subject to \p *this;
97850
97851    \param inf_n
97852    The numerator of the infimum value;
97853
97854    \param inf_d
97855    The denominator of the infimum value;
97856
97857    \param minimum
97858    <CODE>true</CODE> if the infimum value can be reached in \p this.
97859
97860    \param g
97861    When minimization succeeds, will be assigned the point or closure
97862    point where \p expr reaches its infimum value.
97863
97864    \exception std::invalid_argument
97865    Thrown if \p expr and \p *this are dimension-incompatible.
97866
97867    If \p *this is empty or \p expr is not bounded from below,
97868    <CODE>false</CODE> is returned and \p inf_n, \p inf_d, \p minimum
97869    and \p point are left untouched.
97870  */
97871  bool minimize(const Linear_Expression& expr,
97872                Coefficient& inf_n, Coefficient& inf_d, bool& minimum,
97873                Generator& g) const;
97874
97875  /*! \brief
97876    Returns <CODE>true</CODE> if and only if each component of \p *this
97877    contains the corresponding component of \p y.
97878
97879    \exception std::invalid_argument
97880    Thrown if \p *this and \p y are dimension-incompatible.
97881  */
97882  bool contains(const Partially_Reduced_Product& y) const;
97883
97884  /*! \brief
97885    Returns <CODE>true</CODE> if and only if each component of \p *this
97886    strictly contains the corresponding component of \p y.
97887
97888    \exception std::invalid_argument
97889    Thrown if \p *this and \p y are dimension-incompatible.
97890  */
97891  bool strictly_contains(const Partially_Reduced_Product& y) const;
97892
97893  //! Checks if all the invariants are satisfied.
97894  bool OK() const;
97895
97896  //@} // Member Functions that Do Not Modify the Partially_Reduced_Product
97897
97898  //! \name Space Dimension Preserving Member Functions that May Modify the Partially_Reduced_Product
97899  //@{
97900
97901  //! Adds constraint \p c to \p *this.
97902  /*!
97903    \exception std::invalid_argument
97904    Thrown if \p *this and \p c are dimension-incompatible.
97905  */
97906  void add_constraint(const Constraint& c);
97907
97908  /*! \brief
97909    Use the constraint \p c to refine \p *this.
97910
97911    \param c
97912    The constraint to be used for refinement.
97913
97914    \exception std::invalid_argument
97915    Thrown if \p *this and \p c are dimension-incompatible.
97916  */
97917  void refine_with_constraint(const Constraint& c);
97918
97919  //! Adds a copy of congruence \p cg to \p *this.
97920  /*!
97921    \exception std::invalid_argument
97922    Thrown if \p *this and congruence \p cg are
97923    dimension-incompatible.
97924  */
97925  void add_congruence(const Congruence& cg);
97926
97927  /*! \brief
97928    Use the congruence \p cg to refine \p *this.
97929
97930    \param cg
97931    The congruence to be used for refinement.
97932
97933    \exception std::invalid_argument
97934    Thrown if \p *this and \p cg are dimension-incompatible.
97935  */
97936  void refine_with_congruence(const Congruence& cg);
97937
97938  //! Adds a copy of the congruences in \p cgs to \p *this.
97939  /*!
97940    \param cgs
97941    The congruence system to be added.
97942
97943    \exception std::invalid_argument
97944    Thrown if \p *this and \p cgs are dimension-incompatible.
97945  */
97946  void add_congruences(const Congruence_System& cgs);
97947
97948  /*! \brief
97949    Use the congruences in \p cgs to refine \p *this.
97950
97951    \param  cgs
97952    The congruences to be used for refinement.
97953
97954    \exception std::invalid_argument
97955    Thrown if \p *this and \p cgs are dimension-incompatible.
97956  */
97957  void refine_with_congruences(const Congruence_System& cgs);
97958
97959  //! Adds the congruences in \p cgs to *this.
97960  /*!
97961    \param cgs
97962    The congruence system to be added that may be recycled.
97963
97964    \exception std::invalid_argument
97965    Thrown if \p *this and \p cs are dimension-incompatible.
97966
97967    \warning
97968    The only assumption that can be made about \p cgs upon successful
97969    or exceptional return is that it can be safely destroyed.
97970  */
97971  void add_recycled_congruences(Congruence_System& cgs);
97972
97973  //! Adds a copy of the constraint system in \p cs to \p *this.
97974  /*!
97975    \param cs
97976    The constraint system to be added.
97977
97978    \exception std::invalid_argument
97979    Thrown if \p *this and \p cs are dimension-incompatible.
97980  */
97981  void add_constraints(const Constraint_System& cs);
97982
97983  /*! \brief
97984    Use the constraints in \p cs to refine \p *this.
97985
97986    \param  cs
97987     The constraints to be used for refinement.
97988
97989     \exception std::invalid_argument
97990     Thrown if \p *this and \p cs are dimension-incompatible.
97991  */
97992  void refine_with_constraints(const Constraint_System& cs);
97993
97994  //! Adds the constraint system in \p cs to \p *this.
97995  /*!
97996    \param cs
97997    The constraint system to be added that may be recycled.
97998
97999    \exception std::invalid_argument
98000    Thrown if \p *this and \p cs are dimension-incompatible.
98001
98002    \warning
98003    The only assumption that can be made about \p cs upon successful
98004    or exceptional return is that it can be safely destroyed.
98005  */
98006  void add_recycled_constraints(Constraint_System& cs);
98007
98008  /*! \brief
98009    Computes the \ref Cylindrification "cylindrification" of \p *this with
98010    respect to space dimension \p var, assigning the result to \p *this.
98011
98012    \param var
98013    The space dimension that will be unconstrained.
98014
98015    \exception std::invalid_argument
98016    Thrown if \p var is not a space dimension of \p *this.
98017  */
98018  void unconstrain(Variable var);
98019
98020  /*! \brief
98021    Computes the \ref Cylindrification "cylindrification" of \p *this with
98022    respect to the set of space dimensions \p vars,
98023    assigning the result to \p *this.
98024
98025    \param vars
98026    The set of space dimension that will be unconstrained.
98027
98028    \exception std::invalid_argument
98029    Thrown if \p *this is dimension-incompatible with one of the
98030    Variable objects contained in \p vars.
98031  */
98032  void unconstrain(const Variables_Set& vars);
98033
98034  /*! \brief
98035    Assigns to \p *this the componentwise intersection of \p *this and \p y.
98036
98037    \exception std::invalid_argument
98038    Thrown if \p *this and \p y are dimension-incompatible.
98039  */
98040  void intersection_assign(const Partially_Reduced_Product& y);
98041
98042  /*! \brief
98043    Assigns to \p *this an upper bound of \p *this and \p y
98044    computed on the corresponding components.
98045
98046    \exception std::invalid_argument
98047    Thrown if \p *this and \p y are dimension-incompatible.
98048  */
98049  void upper_bound_assign(const Partially_Reduced_Product& y);
98050
98051  /*! \brief
98052    Assigns to \p *this an upper bound of \p *this and \p y
98053    computed on the corresponding components.
98054    If it is exact on each of the components of \p *this, <CODE>true</CODE>
98055    is returned, otherwise <CODE>false</CODE> is returned.
98056
98057    \exception std::invalid_argument
98058    Thrown if \p *this and \p y are dimension-incompatible.
98059  */
98060  bool upper_bound_assign_if_exact(const Partially_Reduced_Product& y);
98061
98062  /*! \brief
98063    Assigns to \p *this an approximation of the set-theoretic difference
98064    of \p *this and \p y.
98065
98066    \exception std::invalid_argument
98067    Thrown if \p *this and \p y are dimension-incompatible.
98068  */
98069  void difference_assign(const Partially_Reduced_Product& y);
98070
98071  /*! \brief
98072    Assigns to \p *this the \ref Single_Update_Affine_Functions
98073    "affine image" of \p
98074    *this under the function mapping variable \p var to the affine
98075    expression specified by \p expr and \p denominator.
98076
98077    \param var
98078    The variable to which the affine expression is assigned;
98079
98080    \param expr
98081    The numerator of the affine expression;
98082
98083    \param denominator
98084    The denominator of the affine expression (optional argument with
98085    default value 1).
98086
98087    \exception std::invalid_argument
98088    Thrown if \p denominator is zero or if \p expr and \p *this are
98089    dimension-incompatible or if \p var is not a space dimension of
98090    \p *this.
98091
98092  */
98093  void affine_image(Variable var,
98094                    const Linear_Expression& expr,
98095                    Coefficient_traits::const_reference denominator
98096                    = Coefficient_one());
98097
98098  /*! \brief
98099    Assigns to \p *this the \ref  Single_Update_Affine_Functions
98100    "affine preimage" of
98101    \p *this under the function mapping variable \p var to the affine
98102    expression specified by \p expr and \p denominator.
98103
98104    \param var
98105    The variable to which the affine expression is substituted;
98106
98107    \param expr
98108    The numerator of the affine expression;
98109
98110    \param denominator
98111    The denominator of the affine expression (optional argument with
98112    default value 1).
98113
98114    \exception std::invalid_argument
98115    Thrown if \p denominator is zero or if \p expr and \p *this are
98116    dimension-incompatible or if \p var is not a space dimension of \p *this.
98117  */
98118  void affine_preimage(Variable var,
98119                       const Linear_Expression& expr,
98120                       Coefficient_traits::const_reference denominator
98121                         = Coefficient_one());
98122
98123  /*! \brief
98124    Assigns to \p *this the image of \p *this with respect to the
98125    \ref Generalized_Affine_Relations "generalized affine relation"
98126    \f$\mathrm{var}' \relsym \frac{\mathrm{expr}}{\mathrm{denominator}}\f$,
98127    where \f$\mathord{\relsym}\f$ is the relation symbol encoded
98128    by \p relsym
98129    (see also \ref Grid_Generalized_Image "generalized affine relation".)
98130
98131    \param var
98132    The left hand side variable of the generalized affine relation;
98133
98134    \param relsym
98135    The relation symbol;
98136
98137    \param expr
98138    The numerator of the right hand side affine expression;
98139
98140    \param denominator
98141    The denominator of the right hand side affine expression (optional
98142    argument with default value 1).
98143
98144    \exception std::invalid_argument
98145    Thrown if \p denominator is zero or if \p expr and \p *this are
98146    dimension-incompatible or if \p var is not a space dimension of \p *this
98147    or if \p *this is a C_Polyhedron and \p relsym is a strict
98148    relation symbol.
98149  */
98150  void generalized_affine_image(Variable var,
98151                                Relation_Symbol relsym,
98152                                const Linear_Expression& expr,
98153                                Coefficient_traits::const_reference denominator
98154                                = Coefficient_one());
98155
98156  /*! \brief
98157    Assigns to \p *this the preimage of \p *this with respect to the
98158    \ref Generalized_Affine_Relations "generalized affine relation"
98159    \f$\mathrm{var}' \relsym \frac{\mathrm{expr}}{\mathrm{denominator}}\f$,
98160    where \f$\mathord{\relsym}\f$ is the relation symbol encoded
98161    by \p relsym.
98162   (see also \ref Grid_Generalized_Image "generalized affine relation".)
98163
98164    \param var
98165    The left hand side variable of the generalized affine relation;
98166
98167    \param relsym
98168    The relation symbol;
98169
98170    \param expr
98171    The numerator of the right hand side affine expression;
98172
98173    \param denominator
98174    The denominator of the right hand side affine expression (optional
98175    argument with default value 1).
98176
98177    \exception std::invalid_argument
98178    Thrown if \p denominator is zero or if \p expr and \p *this are
98179    dimension-incompatible or if \p var is not a space dimension of \p *this
98180    or if \p *this is a C_Polyhedron and \p relsym is a strict
98181    relation symbol.
98182  */
98183  void
98184  generalized_affine_preimage(Variable var,
98185                              Relation_Symbol relsym,
98186                              const Linear_Expression& expr,
98187                              Coefficient_traits::const_reference denominator
98188                              = Coefficient_one());
98189
98190  /*! \brief
98191    Assigns to \p *this the image of \p *this with respect to the
98192    \ref Generalized_Affine_Relations "generalized affine relation"
98193    \f$\mathrm{lhs}' \relsym \mathrm{rhs}\f$, where
98194    \f$\mathord{\relsym}\f$ is the relation symbol encoded by \p relsym.
98195   (see also \ref Grid_Generalized_Image "generalized affine relation".)
98196
98197    \param lhs
98198    The left hand side affine expression;
98199
98200    \param relsym
98201    The relation symbol;
98202
98203    \param rhs
98204    The right hand side affine expression.
98205
98206    \exception std::invalid_argument
98207    Thrown if \p *this is dimension-incompatible with \p lhs or \p rhs
98208    or if \p *this is a C_Polyhedron and \p relsym is a strict
98209    relation symbol.
98210  */
98211  void generalized_affine_image(const Linear_Expression& lhs,
98212                                Relation_Symbol relsym,
98213                                const Linear_Expression& rhs);
98214
98215  /*! \brief
98216    Assigns to \p *this the preimage of \p *this with respect to the
98217    \ref Generalized_Affine_Relations "generalized affine relation"
98218    \f$\mathrm{lhs}' \relsym \mathrm{rhs}\f$, where
98219    \f$\mathord{\relsym}\f$ is the relation symbol encoded by \p relsym.
98220   (see also \ref Grid_Generalized_Image "generalized affine relation".)
98221
98222    \param lhs
98223    The left hand side affine expression;
98224
98225    \param relsym
98226    The relation symbol;
98227
98228    \param rhs
98229    The right hand side affine expression.
98230
98231    \exception std::invalid_argument
98232    Thrown if \p *this is dimension-incompatible with \p lhs or \p rhs
98233    or if \p *this is a C_Polyhedron and \p relsym is a strict
98234    relation symbol.
98235  */
98236  void generalized_affine_preimage(const Linear_Expression& lhs,
98237                                   Relation_Symbol relsym,
98238                                   const Linear_Expression& rhs);
98239
98240  /*!
98241    \brief
98242    Assigns to \p *this the image of \p *this with respect to the
98243    \ref Single_Update_Bounded_Affine_Relations "bounded affine relation"
98244    \f$\frac{\mathrm{lb\_expr}}{\mathrm{denominator}}
98245         \leq \mathrm{var}'
98246           \leq \frac{\mathrm{ub\_expr}}{\mathrm{denominator}}\f$.
98247
98248    \param var
98249    The variable updated by the affine relation;
98250
98251    \param lb_expr
98252    The numerator of the lower bounding affine expression;
98253
98254    \param ub_expr
98255    The numerator of the upper bounding affine expression;
98256
98257    \param denominator
98258    The (common) denominator for the lower and upper bounding
98259    affine expressions (optional argument with default value 1).
98260
98261    \exception std::invalid_argument
98262    Thrown if \p denominator is zero or if \p lb_expr (resp., \p ub_expr)
98263    and \p *this are dimension-incompatible or if \p var is not a space
98264    dimension of \p *this.
98265  */
98266  void bounded_affine_image(Variable var,
98267                            const Linear_Expression& lb_expr,
98268                            const Linear_Expression& ub_expr,
98269                            Coefficient_traits::const_reference denominator
98270                            = Coefficient_one());
98271
98272  /*!
98273    \brief
98274    Assigns to \p *this the preimage of \p *this with respect to the
98275    \ref Single_Update_Bounded_Affine_Relations "bounded affine relation"
98276    \f$\frac{\mathrm{lb\_expr}}{\mathrm{denominator}}
98277         \leq \mathrm{var}'
98278           \leq \frac{\mathrm{ub\_expr}}{\mathrm{denominator}}\f$.
98279
98280    \param var
98281    The variable updated by the affine relation;
98282
98283    \param lb_expr
98284    The numerator of the lower bounding affine expression;
98285
98286    \param ub_expr
98287    The numerator of the upper bounding affine expression;
98288
98289    \param denominator
98290    The (common) denominator for the lower and upper bounding
98291    affine expressions (optional argument with default value 1).
98292
98293    \exception std::invalid_argument
98294    Thrown if \p denominator is zero or if \p lb_expr (resp., \p ub_expr)
98295    and \p *this are dimension-incompatible or if \p var is not a space
98296    dimension of \p *this.
98297  */
98298  void bounded_affine_preimage(Variable var,
98299                               const Linear_Expression& lb_expr,
98300                               const Linear_Expression& ub_expr,
98301                               Coefficient_traits::const_reference denominator
98302                               = Coefficient_one());
98303
98304  /*! \brief
98305    Assigns to \p *this the result of computing the \ref Time_Elapse_Operator
98306    "time-elapse" between \p *this and \p y.
98307    (See also \ref Grid_Time_Elapse "time-elapse".)
98308
98309    \exception std::invalid_argument
98310    Thrown if \p *this and \p y are dimension-incompatible.
98311  */
98312  void time_elapse_assign(const Partially_Reduced_Product& y);
98313
98314  //! Assigns to \p *this its topological closure.
98315  void topological_closure_assign();
98316
98317  // TODO: Add a way to call other widenings.
98318
98319  // CHECKME: This may not be a real widening; it depends on the reduction
98320  //          class R and the widening used.
98321
98322  /*! \brief
98323    Assigns to \p *this the result of computing the
98324    "widening" between \p *this and \p y.
98325
98326    This widening uses either the congruence or generator systems
98327    depending on which of the systems describing x and y
98328    are up to date and minimized.
98329
98330    \param y
98331    A product that <EM>must</EM> be contained in \p *this;
98332
98333    \param tp
98334    An optional pointer to an unsigned variable storing the number of
98335    available tokens (to be used when applying the
98336    \ref Widening_with_Tokens "widening with tokens" delay technique).
98337
98338    \exception std::invalid_argument
98339    Thrown if \p *this and \p y are dimension-incompatible.
98340  */
98341  void widening_assign(const Partially_Reduced_Product& y,
98342                       unsigned* tp = NULL);
98343
98344  /*! \brief
98345    Possibly tightens \p *this by dropping some points with non-integer
98346    coordinates.
98347
98348    \param complexity
98349    The maximal complexity of any algorithms used.
98350
98351    \note
98352    Currently there is no optimality guarantee, not even if
98353    \p complexity is <CODE>ANY_COMPLEXITY</CODE>.
98354  */
98355  void drop_some_non_integer_points(Complexity_Class complexity
98356                                    = ANY_COMPLEXITY);
98357
98358  /*! \brief
98359    Possibly tightens \p *this by dropping some points with non-integer
98360    coordinates for the space dimensions corresponding to \p vars.
98361
98362    \param vars
98363    Points with non-integer coordinates for these variables/space-dimensions
98364    can be discarded.
98365
98366    \param complexity
98367    The maximal complexity of any algorithms used.
98368
98369    \note
98370    Currently there is no optimality guarantee, not even if
98371    \p complexity is <CODE>ANY_COMPLEXITY</CODE>.
98372  */
98373  void drop_some_non_integer_points(const Variables_Set& vars,
98374                                    Complexity_Class complexity
98375                                    = ANY_COMPLEXITY);
98376
98377  //@} // Space Dimension Preserving Member Functions that May Modify [...]
98378
98379  //! \name Member Functions that May Modify the Dimension of the Vector Space
98380  //@{
98381
98382  /*! \brief
98383    Adds \p m new space dimensions and embeds the components
98384    of \p *this in the new vector space.
98385
98386    \param m
98387    The number of dimensions to add.
98388
98389    \exception std::length_error
98390    Thrown if adding \p m new space dimensions would cause the vector
98391    space to exceed dimension <CODE>max_space_dimension()</CODE>.
98392 */
98393  void add_space_dimensions_and_embed(dimension_type m);
98394
98395  /*! \brief
98396    Adds \p m new space dimensions and does not embed the components
98397    in the new vector space.
98398
98399    \param m
98400    The number of space dimensions to add.
98401
98402    \exception std::length_error
98403    Thrown if adding \p m new space dimensions would cause the
98404    vector space to exceed dimension <CODE>max_space_dimension()</CODE>.
98405  */
98406  void add_space_dimensions_and_project(dimension_type m);
98407
98408  /*! \brief
98409    Assigns to the first (resp., second) component of \p *this
98410    the "concatenation" of the first (resp., second) components
98411    of \p *this and \p y, taken in this order.
98412    See also \ref Concatenating_Polyhedra.
98413
98414    \exception std::length_error
98415    Thrown if the concatenation would cause the vector space
98416    to exceed dimension <CODE>max_space_dimension()</CODE>.
98417  */
98418  void concatenate_assign(const Partially_Reduced_Product& y);
98419
98420  //! Removes all the specified dimensions from the vector space.
98421  /*!
98422    \param vars
98423    The set of Variable objects corresponding to the space dimensions
98424    to be removed.
98425
98426    \exception std::invalid_argument
98427    Thrown if \p *this is dimension-incompatible with one of the
98428    Variable objects contained in \p vars.
98429  */
98430  void remove_space_dimensions(const Variables_Set& vars);
98431
98432  /*! \brief
98433    Removes the higher dimensions of the vector space so that the
98434    resulting space will have dimension \p new_dimension.
98435
98436    \exception std::invalid_argument
98437    Thrown if \p new_dimensions is greater than the space dimension of
98438    \p *this.
98439  */
98440  void remove_higher_space_dimensions(dimension_type new_dimension);
98441
98442  /*! \brief
98443    Remaps the dimensions of the vector space according to
98444    a \ref Mapping_the_Dimensions_of_the_Vector_Space "partial function".
98445
98446    If \p pfunc maps only some of the dimensions of \p *this then the
98447    rest will be projected away.
98448
98449    If the highest dimension mapped to by \p pfunc is higher than the
98450    highest dimension in \p *this then the number of dimensions in \p
98451    *this will be increased to the highest dimension mapped to by \p
98452    pfunc.
98453
98454    \param pfunc
98455    The partial function specifying the destiny of each space
98456    dimension.
98457
98458    The template class <CODE>Partial_Function</CODE> must provide the following
98459    methods.
98460    \code
98461      bool has_empty_codomain() const
98462    \endcode
98463    returns <CODE>true</CODE> if and only if the represented partial
98464    function has an empty codomain (i.e., it is always undefined).
98465    The <CODE>has_empty_codomain()</CODE> method will always be called
98466    before the methods below.  However, if
98467    <CODE>has_empty_codomain()</CODE> returns <CODE>true</CODE>, none
98468    of the functions below will be called.
98469    \code
98470      dimension_type max_in_codomain() const
98471    \endcode
98472    returns the maximum value that belongs to the codomain of the
98473    partial function.
98474    The <CODE>max_in_codomain()</CODE> method is called at most once.
98475    \code
98476      bool maps(dimension_type i, dimension_type& j) const
98477    \endcode
98478    Let \f$f\f$ be the represented function and \f$k\f$ be the value
98479    of \p i.  If \f$f\f$ is defined in \f$k\f$, then \f$f(k)\f$ is
98480    assigned to \p j and <CODE>true</CODE> is returned.  If \f$f\f$ is
98481    undefined in \f$k\f$, then <CODE>false</CODE> is returned.
98482    This method is called at most \f$n\f$ times, where \f$n\f$ is the
98483    dimension of the vector space enclosing \p *this.
98484
98485    The result is undefined if \p pfunc does not encode a partial
98486    function with the properties described in
98487    \ref Mapping_the_Dimensions_of_the_Vector_Space
98488    "specification of the mapping operator".
98489  */
98490  template <typename Partial_Function>
98491  void map_space_dimensions(const Partial_Function& pfunc);
98492
98493  //! Creates \p m copies of the space dimension corresponding to \p var.
98494  /*!
98495    \param var
98496    The variable corresponding to the space dimension to be replicated;
98497
98498    \param m
98499    The number of replicas to be created.
98500
98501    \exception std::invalid_argument
98502    Thrown if \p var does not correspond to a dimension of the vector
98503    space.
98504
98505    \exception std::length_error
98506    Thrown if adding \p m new space dimensions would cause the vector
98507    space to exceed dimension <CODE>max_space_dimension()</CODE>.
98508
98509    If \p *this has space dimension \f$n\f$, with \f$n > 0\f$,
98510    and <CODE>var</CODE> has space dimension \f$k \leq n\f$,
98511    then the \f$k\f$-th space dimension is
98512    \ref Expanding_One_Dimension_of_the_Vector_Space_to_Multiple_Dimensions
98513    "expanded" to \p m new space dimensions
98514    \f$n\f$, \f$n+1\f$, \f$\dots\f$, \f$n+m-1\f$.
98515  */
98516  void expand_space_dimension(Variable var, dimension_type m);
98517
98518  //! Folds the space dimensions in \p vars into \p dest.
98519  /*!
98520    \param vars
98521    The set of Variable objects corresponding to the space dimensions
98522    to be folded;
98523
98524    \param dest
98525    The variable corresponding to the space dimension that is the
98526    destination of the folding operation.
98527
98528    \exception std::invalid_argument
98529    Thrown if \p *this is dimension-incompatible with \p dest or with
98530    one of the Variable objects contained in \p vars.  Also
98531    thrown if \p dest is contained in \p vars.
98532
98533    If \p *this has space dimension \f$n\f$, with \f$n > 0\f$,
98534    <CODE>dest</CODE> has space dimension \f$k \leq n\f$,
98535    \p vars is a set of variables whose maximum space dimension
98536    is also less than or equal to \f$n\f$, and \p dest is not a member
98537    of \p vars, then the space dimensions corresponding to
98538    variables in \p vars are
98539    \ref Folding_Multiple_Dimensions_of_the_Vector_Space_into_One_Dimension
98540    "folded" into the \f$k\f$-th space dimension.
98541  */
98542  void fold_space_dimensions(const Variables_Set& vars, Variable dest);
98543
98544  //@} // Member Functions that May Modify the Dimension of the Vector Space
98545
98546  friend bool operator==<>(const Partially_Reduced_Product<D1, D2, R>& x,
98547                           const Partially_Reduced_Product<D1, D2, R>& y);
98548
98549  friend std::ostream&
98550  Parma_Polyhedra_Library::IO_Operators::
98551  operator<<<>(std::ostream& s, const Partially_Reduced_Product<D1, D2, R>& dp);
98552
98553  //! \name Miscellaneous Member Functions
98554  //@{
98555
98556  //! Destructor.
98557  ~Partially_Reduced_Product();
98558
98559  /*! \brief
98560    Swaps \p *this with product \p y.  (\p *this and \p y can be
98561    dimension-incompatible.)
98562  */
98563  void m_swap(Partially_Reduced_Product& y);
98564
98565  PPL_OUTPUT_DECLARATIONS
98566
98567  /*! \brief
98568    Loads from \p s an ASCII representation (as produced by
98569    ascii_dump(std::ostream&) const) and sets \p *this accordingly.
98570    Returns <CODE>true</CODE> if successful, <CODE>false</CODE> otherwise.
98571  */
98572  bool ascii_load(std::istream& s);
98573
98574  //! Returns the total size in bytes of the memory occupied by \p *this.
98575  memory_size_type total_memory_in_bytes() const;
98576
98577  //! Returns the size in bytes of the memory managed by \p *this.
98578  memory_size_type external_memory_in_bytes() const;
98579
98580  /*! \brief
98581    Returns a 32-bit hash code for \p *this.
98582
98583    If \p x and \p y are such that <CODE>x == y</CODE>,
98584    then <CODE>x.hash_code() == y.hash_code()</CODE>.
98585  */
98586  int32_t hash_code() const;
98587
98588  //@} // Miscellaneous Member Functions
98589
98590  //! Reduce.
98591  /*
98592    \return
98593    <CODE>true</CODE> if and only if either of the resulting component
98594    is strictly contained in the respective original.
98595  */
98596  bool reduce() const;
98597
98598protected:
98599  //! The type of the first component.
98600  typedef D1 Domain1;
98601
98602  //! The type of the second component.
98603  typedef D2 Domain2;
98604
98605  //! The first component.
98606  D1 d1;
98607
98608  //! The second component.
98609  D2 d2;
98610
98611protected:
98612  //! Clears the reduced flag.
98613  void clear_reduced_flag() const;
98614
98615  //! Sets the reduced flag.
98616  void set_reduced_flag() const;
98617
98618  //! Return <CODE>true</CODE> if and only if the reduced flag is set.
98619  bool is_reduced() const;
98620
98621  /*! \brief
98622    Flag to record whether the components are reduced with respect
98623    to each other and the reduction class.
98624  */
98625  bool reduced;
98626
98627private:
98628  void throw_space_dimension_overflow(const char* method,
98629                                      const char* reason);
98630};
98631
98632namespace Parma_Polyhedra_Library {
98633
98634/*! \brief
98635  This class is temporary and will be removed when template typedefs will
98636  be supported in C++.
98637
98638  When template typedefs will be supported in C++, what now is verbosely
98639  denoted by <CODE>Domain_Product\<Domain1, Domain2\>::%Direct_Product</CODE>
98640  will simply be denoted by <CODE>Direct_Product\<Domain1, Domain2\></CODE>.
98641*/
98642template <typename D1, typename D2>
98643class Domain_Product {
98644public:
98645  typedef Partially_Reduced_Product<D1, D2, No_Reduction<D1, D2> >
98646  Direct_Product;
98647
98648  typedef Partially_Reduced_Product<D1, D2, Smash_Reduction<D1, D2> >
98649  Smash_Product;
98650
98651  typedef Partially_Reduced_Product<D1, D2, Constraints_Reduction<D1, D2> >
98652  Constraints_Product;
98653
98654  typedef Partially_Reduced_Product<D1, D2, Congruences_Reduction<D1, D2> >
98655  Congruences_Product;
98656
98657  typedef Partially_Reduced_Product<D1, D2, Shape_Preserving_Reduction<D1, D2> >
98658  Shape_Preserving_Product;
98659};
98660
98661} // namespace Parma_Polyhedra_Library
98662
98663/* Automatically generated from PPL source file ../src/Partially_Reduced_Product_inlines.hh line 1. */
98664/* Partially_Reduced_Product class implementation: inline functions.
98665*/
98666
98667
98668/* Automatically generated from PPL source file ../src/Partially_Reduced_Product_inlines.hh line 32. */
98669
98670namespace Parma_Polyhedra_Library {
98671
98672template <typename D1, typename D2, typename R>
98673inline dimension_type
98674Partially_Reduced_Product<D1, D2, R>::max_space_dimension() {
98675  return (D1::max_space_dimension() < D2::max_space_dimension())
98676    ? D1::max_space_dimension()
98677    : D2::max_space_dimension();
98678}
98679
98680template <typename D1, typename D2, typename R>
98681inline
98682Partially_Reduced_Product<D1, D2, R>
98683::Partially_Reduced_Product(dimension_type num_dimensions,
98684                            const Degenerate_Element kind)
98685  : d1(num_dimensions <= max_space_dimension()
98686       ? num_dimensions
98687       : (throw_space_dimension_overflow("Partially_Reduced_Product(n, k)",
98688                                         "n exceeds the maximum "
98689                                         "allowed space dimension"),
98690          num_dimensions),
98691       kind),
98692    d2(num_dimensions, kind) {
98693  set_reduced_flag();
98694}
98695
98696template <typename D1, typename D2, typename R>
98697inline
98698Partially_Reduced_Product<D1, D2, R>
98699::Partially_Reduced_Product(const Congruence_System& cgs)
98700  : d1(cgs), d2(cgs) {
98701  clear_reduced_flag();
98702}
98703
98704template <typename D1, typename D2, typename R>
98705inline
98706Partially_Reduced_Product<D1, D2, R>
98707::Partially_Reduced_Product(Congruence_System& cgs)
98708  : d1(const_cast<const Congruence_System&>(cgs)), d2(cgs) {
98709  clear_reduced_flag();
98710}
98711
98712template <typename D1, typename D2, typename R>
98713inline
98714Partially_Reduced_Product<D1, D2, R>
98715::Partially_Reduced_Product(const Constraint_System& cs)
98716  : d1(cs), d2(cs) {
98717  clear_reduced_flag();
98718}
98719
98720template <typename D1, typename D2, typename R>
98721inline
98722Partially_Reduced_Product<D1, D2, R>
98723::Partially_Reduced_Product(Constraint_System& cs)
98724  : d1(const_cast<const Constraint_System&>(cs)), d2(cs) {
98725  clear_reduced_flag();
98726}
98727
98728template <typename D1, typename D2, typename R>
98729inline
98730Partially_Reduced_Product<D1, D2, R>
98731::Partially_Reduced_Product(const C_Polyhedron& ph,
98732                            Complexity_Class complexity)
98733  : d1(ph, complexity), d2(ph, complexity) {
98734  set_reduced_flag();
98735}
98736
98737template <typename D1, typename D2, typename R>
98738inline
98739Partially_Reduced_Product<D1, D2, R>
98740::Partially_Reduced_Product(const NNC_Polyhedron& ph,
98741                            Complexity_Class complexity)
98742  : d1(ph, complexity), d2(ph, complexity) {
98743  set_reduced_flag();
98744}
98745
98746template <typename D1, typename D2, typename R>
98747inline
98748Partially_Reduced_Product<D1, D2, R>
98749::Partially_Reduced_Product(const Grid& gr, Complexity_Class)
98750  : d1(gr), d2(gr) {
98751  set_reduced_flag();
98752}
98753
98754template <typename D1, typename D2, typename R>
98755template <typename Interval>
98756inline
98757Partially_Reduced_Product<D1, D2, R>
98758::Partially_Reduced_Product(const Box<Interval>& box, Complexity_Class)
98759  : d1(box), d2(box) {
98760  set_reduced_flag();
98761}
98762
98763template <typename D1, typename D2, typename R>
98764template <typename U>
98765inline
98766Partially_Reduced_Product<D1, D2, R>
98767::Partially_Reduced_Product(const BD_Shape<U>& bd, Complexity_Class)
98768  : d1(bd), d2(bd) {
98769  set_reduced_flag();
98770}
98771
98772template <typename D1, typename D2, typename R>
98773template <typename U>
98774inline
98775Partially_Reduced_Product<D1, D2, R>
98776::Partially_Reduced_Product(const Octagonal_Shape<U>& os, Complexity_Class)
98777  : d1(os), d2(os) {
98778  set_reduced_flag();
98779}
98780
98781template <typename D1, typename D2, typename R>
98782inline
98783Partially_Reduced_Product<D1, D2, R>
98784::Partially_Reduced_Product(const Partially_Reduced_Product& y,
98785                            Complexity_Class)
98786  : d1(y.d1), d2(y.d2) {
98787  reduced = y.reduced;
98788}
98789
98790template <typename D1, typename D2, typename R>
98791template <typename E1, typename E2, typename S>
98792inline
98793Partially_Reduced_Product<D1, D2, R>
98794::Partially_Reduced_Product(const Partially_Reduced_Product<E1, E2, S>& y,
98795                            Complexity_Class complexity)
98796  : d1(y.space_dimension()), d2(y.space_dimension()), reduced(false) {
98797  Partially_Reduced_Product<D1, D2, R> pg1(y.domain1(), complexity);
98798  Partially_Reduced_Product<D1, D2, R> pg2(y.domain2(), complexity);
98799  pg1.intersection_assign(pg2);
98800  m_swap(pg1);
98801}
98802
98803template <typename D1, typename D2, typename R>
98804inline
98805Partially_Reduced_Product<D1, D2, R>::~Partially_Reduced_Product() {
98806}
98807
98808template <typename D1, typename D2, typename R>
98809inline memory_size_type
98810Partially_Reduced_Product<D1, D2, R>::external_memory_in_bytes() const {
98811  return d1.external_memory_in_bytes() + d2.external_memory_in_bytes();
98812}
98813
98814template <typename D1, typename D2, typename R>
98815inline memory_size_type
98816Partially_Reduced_Product<D1, D2, R>::total_memory_in_bytes() const {
98817  return sizeof(*this) + external_memory_in_bytes();
98818}
98819
98820template <typename D1, typename D2, typename R>
98821inline dimension_type
98822Partially_Reduced_Product<D1, D2, R>::space_dimension() const {
98823  PPL_ASSERT(d1.space_dimension() == d2.space_dimension());
98824  return d1.space_dimension();
98825}
98826
98827template <typename D1, typename D2, typename R>
98828inline dimension_type
98829Partially_Reduced_Product<D1, D2, R>::affine_dimension() const {
98830  reduce();
98831  const dimension_type d1_dim = d1.affine_dimension();
98832  const dimension_type d2_dim = d2.affine_dimension();
98833  return std::min(d1_dim, d2_dim);
98834}
98835
98836template <typename D1, typename D2, typename R>
98837inline void
98838Partially_Reduced_Product<D1, D2, R>
98839::unconstrain(const Variable var) {
98840  reduce();
98841  d1.unconstrain(var);
98842  d2.unconstrain(var);
98843}
98844
98845template <typename D1, typename D2, typename R>
98846inline void
98847Partially_Reduced_Product<D1, D2, R>::unconstrain(const Variables_Set& vars) {
98848  reduce();
98849  d1.unconstrain(vars);
98850  d2.unconstrain(vars);
98851}
98852
98853template <typename D1, typename D2, typename R>
98854inline void
98855Partially_Reduced_Product<D1, D2, R>
98856::intersection_assign(const Partially_Reduced_Product& y) {
98857  d1.intersection_assign(y.d1);
98858  d2.intersection_assign(y.d2);
98859  clear_reduced_flag();
98860}
98861
98862template <typename D1, typename D2, typename R>
98863inline void
98864Partially_Reduced_Product<D1, D2, R>
98865::difference_assign(const Partially_Reduced_Product& y) {
98866  reduce();
98867  y.reduce();
98868  d1.difference_assign(y.d1);
98869  d2.difference_assign(y.d2);
98870  clear_reduced_flag();
98871}
98872
98873template <typename D1, typename D2, typename R>
98874inline void
98875Partially_Reduced_Product<D1, D2, R>
98876::upper_bound_assign(const Partially_Reduced_Product& y) {
98877  reduce();
98878  y.reduce();
98879  d1.upper_bound_assign(y.d1);
98880  d2.upper_bound_assign(y.d2);
98881}
98882
98883template <typename D1, typename D2, typename R>
98884inline bool
98885Partially_Reduced_Product<D1, D2, R>
98886::upper_bound_assign_if_exact(const Partially_Reduced_Product& y) {
98887  reduce();
98888  y.reduce();
98889  D1 d1_copy = d1;
98890  bool ub_exact = d1_copy.upper_bound_assign_if_exact(y.d1);
98891  if (!ub_exact) {
98892    return false;
98893  }
98894  ub_exact = d2.upper_bound_assign_if_exact(y.d2);
98895  if (!ub_exact) {
98896    return false;
98897  }
98898  using std::swap;
98899  swap(d1, d1_copy);
98900  return true;
98901}
98902
98903template <typename D1, typename D2, typename R>
98904inline void
98905Partially_Reduced_Product<D1, D2, R>
98906::affine_image(Variable var,
98907               const Linear_Expression& expr,
98908               Coefficient_traits::const_reference denominator) {
98909  d1.affine_image(var, expr, denominator);
98910  d2.affine_image(var, expr, denominator);
98911  clear_reduced_flag();
98912}
98913
98914template <typename D1, typename D2, typename R>
98915inline void
98916Partially_Reduced_Product<D1, D2, R>
98917::affine_preimage(Variable var,
98918                  const Linear_Expression& expr,
98919                  Coefficient_traits::const_reference denominator) {
98920  d1.affine_preimage(var, expr, denominator);
98921  d2.affine_preimage(var, expr, denominator);
98922  clear_reduced_flag();
98923}
98924
98925template <typename D1, typename D2, typename R>
98926inline void
98927Partially_Reduced_Product<D1, D2, R>
98928::generalized_affine_image(Variable var,
98929                           const Relation_Symbol relsym,
98930                           const Linear_Expression& expr,
98931                           Coefficient_traits::const_reference denominator) {
98932  d1.generalized_affine_image(var, relsym, expr, denominator);
98933  d2.generalized_affine_image(var, relsym, expr, denominator);
98934  clear_reduced_flag();
98935}
98936
98937template <typename D1, typename D2, typename R>
98938inline void
98939Partially_Reduced_Product<D1, D2, R>
98940::generalized_affine_preimage(Variable var,
98941                              const Relation_Symbol relsym,
98942                              const Linear_Expression& expr,
98943                              Coefficient_traits::const_reference denominator) {
98944  d1.generalized_affine_preimage(var, relsym, expr, denominator);
98945  d2.generalized_affine_preimage(var, relsym, expr, denominator);
98946  clear_reduced_flag();
98947}
98948
98949template <typename D1, typename D2, typename R>
98950inline void
98951Partially_Reduced_Product<D1, D2, R>
98952::generalized_affine_image(const Linear_Expression& lhs,
98953                           const Relation_Symbol relsym,
98954                           const Linear_Expression& rhs) {
98955  d1.generalized_affine_image(lhs, relsym, rhs);
98956  d2.generalized_affine_image(lhs, relsym, rhs);
98957  clear_reduced_flag();
98958}
98959
98960template <typename D1, typename D2, typename R>
98961inline void
98962Partially_Reduced_Product<D1, D2, R>
98963::generalized_affine_preimage(const Linear_Expression& lhs,
98964                              const Relation_Symbol relsym,
98965                              const Linear_Expression& rhs) {
98966  d1.generalized_affine_preimage(lhs, relsym, rhs);
98967  d2.generalized_affine_preimage(lhs, relsym, rhs);
98968  clear_reduced_flag();
98969}
98970
98971
98972template <typename D1, typename D2, typename R>
98973inline void
98974Partially_Reduced_Product<D1, D2, R>
98975::bounded_affine_image(Variable var,
98976                       const Linear_Expression& lb_expr,
98977                       const Linear_Expression& ub_expr,
98978                       Coefficient_traits::const_reference denominator) {
98979  d1.bounded_affine_image(var, lb_expr, ub_expr, denominator);
98980  d2.bounded_affine_image(var, lb_expr, ub_expr, denominator);
98981  clear_reduced_flag();
98982}
98983
98984template <typename D1, typename D2, typename R>
98985inline void
98986Partially_Reduced_Product<D1, D2, R>
98987::bounded_affine_preimage(Variable var,
98988                          const Linear_Expression& lb_expr,
98989                          const Linear_Expression& ub_expr,
98990                          Coefficient_traits::const_reference denominator) {
98991  d1.bounded_affine_preimage(var, lb_expr, ub_expr, denominator);
98992  d2.bounded_affine_preimage(var, lb_expr, ub_expr, denominator);
98993  clear_reduced_flag();
98994}
98995
98996template <typename D1, typename D2, typename R>
98997inline void
98998Partially_Reduced_Product<D1, D2, R>
98999::time_elapse_assign(const Partially_Reduced_Product& y) {
99000  reduce();
99001  y.reduce();
99002  d1.time_elapse_assign(y.d1);
99003  d2.time_elapse_assign(y.d2);
99004  PPL_ASSERT_HEAVY(OK());
99005}
99006
99007template <typename D1, typename D2, typename R>
99008inline void
99009Partially_Reduced_Product<D1, D2, R>::topological_closure_assign() {
99010  d1.topological_closure_assign();
99011  d2.topological_closure_assign();
99012}
99013
99014template <typename D1, typename D2, typename R>
99015inline void
99016Partially_Reduced_Product<D1, D2, R>::m_swap(Partially_Reduced_Product& y) {
99017  using std::swap;
99018  swap(d1, y.d1);
99019  swap(d2, y.d2);
99020  swap(reduced, y.reduced);
99021}
99022
99023template <typename D1, typename D2, typename R>
99024inline void
99025Partially_Reduced_Product<D1, D2, R>::add_constraint(const Constraint& c) {
99026  d1.add_constraint(c);
99027  d2.add_constraint(c);
99028  clear_reduced_flag();
99029}
99030
99031template <typename D1, typename D2, typename R>
99032inline void
99033Partially_Reduced_Product<D1, D2, R>::refine_with_constraint(const Constraint& c) {
99034  d1.refine_with_constraint(c);
99035  d2.refine_with_constraint(c);
99036  clear_reduced_flag();
99037}
99038
99039template <typename D1, typename D2, typename R>
99040inline void
99041Partially_Reduced_Product<D1, D2, R>::add_congruence(const Congruence& cg) {
99042  d1.add_congruence(cg);
99043  d2.add_congruence(cg);
99044  clear_reduced_flag();
99045}
99046
99047template <typename D1, typename D2, typename R>
99048inline void
99049Partially_Reduced_Product<D1, D2, R>::refine_with_congruence(const Congruence& cg) {
99050  d1.refine_with_congruence(cg);
99051  d2.refine_with_congruence(cg);
99052  clear_reduced_flag();
99053}
99054
99055template <typename D1, typename D2, typename R>
99056inline void
99057Partially_Reduced_Product<D1, D2, R>
99058::add_constraints(const Constraint_System& cs) {
99059  d1.add_constraints(cs);
99060  d2.add_constraints(cs);
99061  clear_reduced_flag();
99062}
99063
99064template <typename D1, typename D2, typename R>
99065inline void
99066Partially_Reduced_Product<D1, D2, R>
99067::refine_with_constraints(const Constraint_System& cs) {
99068  d1.refine_with_constraints(cs);
99069  d2.refine_with_constraints(cs);
99070  clear_reduced_flag();
99071}
99072
99073template <typename D1, typename D2, typename R>
99074inline void
99075Partially_Reduced_Product<D1, D2, R>
99076::add_congruences(const Congruence_System& cgs) {
99077  d1.add_congruences(cgs);
99078  d2.add_congruences(cgs);
99079  clear_reduced_flag();
99080}
99081
99082template <typename D1, typename D2, typename R>
99083inline void
99084Partially_Reduced_Product<D1, D2, R>
99085::refine_with_congruences(const Congruence_System& cgs) {
99086  d1.refine_with_congruences(cgs);
99087  d2.refine_with_congruences(cgs);
99088  clear_reduced_flag();
99089}
99090
99091template <typename D1, typename D2, typename R>
99092inline void
99093Partially_Reduced_Product<D1, D2, R>
99094::drop_some_non_integer_points(Complexity_Class complexity) {
99095  reduce();
99096  d1.drop_some_non_integer_points(complexity);
99097  d2.drop_some_non_integer_points(complexity);
99098  clear_reduced_flag();
99099}
99100
99101template <typename D1, typename D2, typename R>
99102inline void
99103Partially_Reduced_Product<D1, D2, R>
99104::drop_some_non_integer_points(const Variables_Set& vars,
99105                                    Complexity_Class complexity) {
99106  reduce();
99107  d1.drop_some_non_integer_points(vars, complexity);
99108  d2.drop_some_non_integer_points(vars, complexity);
99109  clear_reduced_flag();
99110}
99111
99112template <typename D1, typename D2, typename R>
99113inline Partially_Reduced_Product<D1, D2, R>&
99114Partially_Reduced_Product<D1, D2, R>
99115::operator=(const Partially_Reduced_Product& y) {
99116  d1 = y.d1;
99117  d2 = y.d2;
99118  reduced = y.reduced;
99119  return *this;
99120}
99121
99122template <typename D1, typename D2, typename R>
99123inline const D1&
99124Partially_Reduced_Product<D1, D2, R>::domain1() const {
99125  reduce();
99126  return d1;
99127}
99128
99129template <typename D1, typename D2, typename R>
99130inline const D2&
99131Partially_Reduced_Product<D1, D2, R>::domain2() const {
99132  reduce();
99133  return d2;
99134}
99135
99136template <typename D1, typename D2, typename R>
99137inline bool
99138Partially_Reduced_Product<D1, D2, R>::is_empty() const {
99139  reduce();
99140  return d1.is_empty() || d2.is_empty();
99141}
99142
99143template <typename D1, typename D2, typename R>
99144inline bool
99145Partially_Reduced_Product<D1, D2, R>::is_universe() const {
99146  return d1.is_universe() && d2.is_universe();
99147}
99148
99149template <typename D1, typename D2, typename R>
99150inline bool
99151Partially_Reduced_Product<D1, D2, R>::is_topologically_closed() const {
99152  reduce();
99153  return d1.is_topologically_closed() && d2.is_topologically_closed();
99154}
99155
99156template <typename D1, typename D2, typename R>
99157inline bool
99158Partially_Reduced_Product<D1, D2, R>
99159::is_disjoint_from(const Partially_Reduced_Product& y) const {
99160  reduce();
99161  y.reduce();
99162  return d1.is_disjoint_from(y.d1) || d2.is_disjoint_from(y.d2);
99163}
99164
99165template <typename D1, typename D2, typename R>
99166inline bool
99167Partially_Reduced_Product<D1, D2, R>::is_discrete() const {
99168  reduce();
99169  return d1.is_discrete() || d2.is_discrete();
99170}
99171
99172template <typename D1, typename D2, typename R>
99173inline bool
99174Partially_Reduced_Product<D1, D2, R>::is_bounded() const {
99175  reduce();
99176  return d1.is_bounded() || d2.is_bounded();
99177}
99178
99179template <typename D1, typename D2, typename R>
99180inline bool
99181Partially_Reduced_Product<D1, D2, R>
99182::bounds_from_above(const Linear_Expression& expr) const {
99183  reduce();
99184  return d1.bounds_from_above(expr) || d2.bounds_from_above(expr);
99185}
99186
99187template <typename D1, typename D2, typename R>
99188inline bool
99189Partially_Reduced_Product<D1, D2, R>
99190::bounds_from_below(const Linear_Expression& expr) const {
99191  reduce();
99192  return d1.bounds_from_below(expr) || d2.bounds_from_below(expr);
99193}
99194
99195template <typename D1, typename D2, typename R>
99196inline bool
99197Partially_Reduced_Product<D1, D2, R>::constrains(Variable var) const {
99198  reduce();
99199  return d1.constrains(var) || d2.constrains(var);
99200}
99201
99202template <typename D1, typename D2, typename R>
99203inline void
99204Partially_Reduced_Product<D1, D2, R>
99205::widening_assign(const Partially_Reduced_Product& y,
99206                  unsigned* tp) {
99207  // FIXME(0.10.1): In general this is _NOT_ a widening since the reduction
99208  //        may mean that the sequence does not satisfy the ascending
99209  //        chain condition.
99210  //        However, for the direct, smash and constraints product
99211  //        it may be ok - but this still needs checking.
99212  reduce();
99213  y.reduce();
99214  d1.widening_assign(y.d1, tp);
99215  d2.widening_assign(y.d2, tp);
99216}
99217
99218template <typename D1, typename D2, typename R>
99219inline void
99220Partially_Reduced_Product<D1, D2, R>
99221::add_space_dimensions_and_embed(dimension_type m) {
99222  d1.add_space_dimensions_and_embed(m);
99223  d2.add_space_dimensions_and_embed(m);
99224}
99225
99226template <typename D1, typename D2, typename R>
99227inline void
99228Partially_Reduced_Product<D1, D2, R>
99229::add_space_dimensions_and_project(dimension_type m) {
99230  d1.add_space_dimensions_and_project(m);
99231  d2.add_space_dimensions_and_project(m);
99232}
99233
99234template <typename D1, typename D2, typename R>
99235inline void
99236Partially_Reduced_Product<D1, D2, R>
99237::concatenate_assign(const Partially_Reduced_Product& y) {
99238  d1.concatenate_assign(y.d1);
99239  d2.concatenate_assign(y.d2);
99240  if (!is_reduced() || !y.is_reduced()) {
99241    clear_reduced_flag();
99242  }
99243}
99244
99245template <typename D1, typename D2, typename R>
99246inline void
99247Partially_Reduced_Product<D1, D2, R>
99248::remove_space_dimensions(const Variables_Set& vars) {
99249  d1.remove_space_dimensions(vars);
99250  d2.remove_space_dimensions(vars);
99251}
99252
99253template <typename D1, typename D2, typename R>
99254inline void
99255Partially_Reduced_Product<D1, D2, R>
99256::remove_higher_space_dimensions(dimension_type new_dimension) {
99257  d1.remove_higher_space_dimensions(new_dimension);
99258  d2.remove_higher_space_dimensions(new_dimension);
99259}
99260
99261template <typename D1, typename D2, typename R>
99262template <typename Partial_Function>
99263inline void
99264Partially_Reduced_Product<D1, D2, R>
99265::map_space_dimensions(const Partial_Function& pfunc) {
99266  d1.map_space_dimensions(pfunc);
99267  d2.map_space_dimensions(pfunc);
99268}
99269
99270template <typename D1, typename D2, typename R>
99271inline void
99272Partially_Reduced_Product<D1, D2, R>
99273::expand_space_dimension(Variable var, dimension_type m) {
99274  d1.expand_space_dimension(var, m);
99275  d2.expand_space_dimension(var, m);
99276}
99277
99278template <typename D1, typename D2, typename R>
99279inline void
99280Partially_Reduced_Product<D1, D2, R>
99281::fold_space_dimensions(const Variables_Set& vars,
99282                        Variable dest) {
99283  d1.fold_space_dimensions(vars, dest);
99284  d2.fold_space_dimensions(vars, dest);
99285}
99286
99287template <typename D1, typename D2, typename R>
99288inline bool
99289Partially_Reduced_Product<D1, D2, R>
99290::contains(const Partially_Reduced_Product& y) const {
99291  reduce();
99292  y.reduce();
99293  return d1.contains(y.d1) && d2.contains(y.d2);
99294}
99295
99296template <typename D1, typename D2, typename R>
99297inline bool
99298Partially_Reduced_Product<D1, D2, R>
99299::strictly_contains(const Partially_Reduced_Product& y) const {
99300  reduce();
99301  y.reduce();
99302  return (d1.contains(y.d1) && d2.strictly_contains(y.d2))
99303    || (d2.contains(y.d2) && d1.strictly_contains(y.d1));
99304}
99305
99306template <typename D1, typename D2, typename R>
99307inline bool
99308Partially_Reduced_Product<D1, D2, R>::reduce() const {
99309  Partially_Reduced_Product& dp
99310    = const_cast<Partially_Reduced_Product&>(*this);
99311  if (dp.is_reduced()) {
99312    return false;
99313  }
99314  R r;
99315  r.product_reduce(dp.d1, dp.d2);
99316  set_reduced_flag();
99317  return true;
99318}
99319
99320template <typename D1, typename D2, typename R>
99321inline bool
99322Partially_Reduced_Product<D1, D2, R>::is_reduced() const {
99323  return reduced;
99324}
99325
99326template <typename D1, typename D2, typename R>
99327inline void
99328Partially_Reduced_Product<D1, D2, R>::clear_reduced_flag() const {
99329  const_cast<Partially_Reduced_Product&>(*this).reduced = false;
99330}
99331
99332template <typename D1, typename D2, typename R>
99333inline void
99334Partially_Reduced_Product<D1, D2, R>::set_reduced_flag() const {
99335  const_cast<Partially_Reduced_Product&>(*this).reduced = true;
99336}
99337
99338PPL_OUTPUT_3_PARAM_TEMPLATE_DEFINITIONS(D1, D2, R, Partially_Reduced_Product)
99339
99340template <typename D1, typename D2, typename R>
99341inline void
99342Partially_Reduced_Product<D1, D2, R>::ascii_dump(std::ostream& s) const {
99343  const char yes = '+';
99344  const char no = '-';
99345  s << "Partially_Reduced_Product\n";
99346  s << (reduced ? yes : no) << "reduced\n";
99347  s << "Domain 1:\n";
99348  d1.ascii_dump(s);
99349  s << "Domain 2:\n";
99350  d2.ascii_dump(s);
99351}
99352
99353template <typename D1, typename D2, typename R>
99354inline int32_t
99355Partially_Reduced_Product<D1, D2, R>::hash_code() const {
99356  return hash_code_from_dimension(space_dimension());
99357}
99358
99359/*! \relates Parma_Polyhedra_Library::Partially_Reduced_Product */
99360template <typename D1, typename D2, typename R>
99361inline bool
99362operator==(const Partially_Reduced_Product<D1, D2, R>& x,
99363           const Partially_Reduced_Product<D1, D2, R>& y) {
99364  x.reduce();
99365  y.reduce();
99366  return x.d1 == y.d1 && x.d2 == y.d2;
99367}
99368
99369/*! \relates Parma_Polyhedra_Library::Partially_Reduced_Product */
99370template <typename D1, typename D2, typename R>
99371inline bool
99372operator!=(const Partially_Reduced_Product<D1, D2, R>& x,
99373           const Partially_Reduced_Product<D1, D2, R>& y) {
99374  return !(x == y);
99375}
99376
99377/*! \relates Parma_Polyhedra_Library::Partially_Reduced_Product */
99378template <typename D1, typename D2, typename R>
99379inline std::ostream&
99380IO_Operators::operator<<(std::ostream& s,
99381                         const Partially_Reduced_Product<D1, D2, R>& dp) {
99382  return s << "Domain 1:\n"
99383           << dp.d1
99384           << "Domain 2:\n"
99385           << dp.d2;
99386}
99387
99388} // namespace Parma_Polyhedra_Library
99389
99390namespace Parma_Polyhedra_Library {
99391
99392template <typename D1, typename D2>
99393inline
99394No_Reduction<D1, D2>::No_Reduction() {
99395}
99396
99397template <typename D1, typename D2>
99398void No_Reduction<D1, D2>::product_reduce(D1&, D2&) {
99399}
99400
99401template <typename D1, typename D2>
99402inline
99403No_Reduction<D1, D2>::~No_Reduction() {
99404}
99405
99406template <typename D1, typename D2>
99407inline
99408Smash_Reduction<D1, D2>::Smash_Reduction() {
99409}
99410
99411template <typename D1, typename D2>
99412inline
99413Smash_Reduction<D1, D2>::~Smash_Reduction() {
99414}
99415
99416template <typename D1, typename D2>
99417inline
99418Constraints_Reduction<D1, D2>::Constraints_Reduction() {
99419}
99420
99421template <typename D1, typename D2>
99422inline
99423Constraints_Reduction<D1, D2>::~Constraints_Reduction() {
99424}
99425
99426template <typename D1, typename D2>
99427inline
99428Congruences_Reduction<D1, D2>::Congruences_Reduction() {
99429}
99430
99431template <typename D1, typename D2>
99432inline
99433Congruences_Reduction<D1, D2>::~Congruences_Reduction() {
99434}
99435
99436template <typename D1, typename D2>
99437inline
99438Shape_Preserving_Reduction<D1, D2>::Shape_Preserving_Reduction() {
99439}
99440
99441template <typename D1, typename D2>
99442inline
99443Shape_Preserving_Reduction<D1, D2>::~Shape_Preserving_Reduction() {
99444}
99445
99446/*! \relates Partially_Reduced_Product */
99447template <typename D1, typename D2, typename R>
99448inline void
99449swap(Partially_Reduced_Product<D1, D2, R>& x,
99450     Partially_Reduced_Product<D1, D2, R>& y) {
99451  x.m_swap(y);
99452}
99453
99454} // namespace Parma_Polyhedra_Library
99455
99456/* Automatically generated from PPL source file ../src/Partially_Reduced_Product_templates.hh line 1. */
99457/* Partially_Reduced_Product class implementation:
99458   non-inline template functions.
99459*/
99460
99461
99462/* Automatically generated from PPL source file ../src/Partially_Reduced_Product_templates.hh line 31. */
99463#include <algorithm>
99464#include <deque>
99465
99466namespace Parma_Polyhedra_Library {
99467
99468template <typename D1, typename D2, typename R>
99469void
99470Partially_Reduced_Product<D1, D2, R>
99471::throw_space_dimension_overflow(const char* method,
99472                                 const char* reason) {
99473  std::ostringstream s;
99474  s << "PPL::Partially_Reduced_Product::" << method << ":" << std::endl
99475    << reason << ".";
99476  throw std::length_error(s.str());
99477}
99478
99479template <typename D1, typename D2, typename R>
99480Constraint_System
99481Partially_Reduced_Product<D1, D2, R>::constraints() const {
99482  reduce();
99483  Constraint_System cs = d2.constraints();
99484  const Constraint_System& cs1 = d1.constraints();
99485  for (Constraint_System::const_iterator i = cs1.begin(),
99486         cs_end = cs1.end(); i != cs_end; ++i) {
99487    cs.insert(*i);
99488  }
99489  return cs;
99490}
99491
99492template <typename D1, typename D2, typename R>
99493Constraint_System
99494Partially_Reduced_Product<D1, D2, R>::minimized_constraints() const {
99495  reduce();
99496  Constraint_System cs = d2.constraints();
99497  const Constraint_System& cs1 = d1.constraints();
99498  for (Constraint_System::const_iterator i = cs1.begin(),
99499         cs_end = cs1.end(); i != cs_end; ++i) {
99500    cs.insert(*i);
99501  }
99502  if (cs.has_strict_inequalities()) {
99503    NNC_Polyhedron ph(cs);
99504    return ph.minimized_constraints();
99505  }
99506  else {
99507    C_Polyhedron ph(cs);
99508    return ph.minimized_constraints();
99509  }
99510}
99511
99512template <typename D1, typename D2, typename R>
99513Congruence_System
99514Partially_Reduced_Product<D1, D2, R>::congruences() const {
99515  reduce();
99516  Congruence_System cgs = d2.congruences();
99517  const Congruence_System& cgs1 = d1.congruences();
99518  for (Congruence_System::const_iterator i = cgs1.begin(),
99519         cgs_end = cgs1.end(); i != cgs_end; ++i) {
99520    cgs.insert(*i);
99521  }
99522  return cgs;
99523}
99524
99525template <typename D1, typename D2, typename R>
99526Congruence_System
99527Partially_Reduced_Product<D1, D2, R>::minimized_congruences() const {
99528  reduce();
99529  Congruence_System cgs = d2.congruences();
99530  const Congruence_System& cgs1 = d1.congruences();
99531  for (Congruence_System::const_iterator i = cgs1.begin(),
99532         cgs_end = cgs1.end(); i != cgs_end; ++i) {
99533    cgs.insert(*i);
99534  }
99535  Grid gr(cgs);
99536  return gr.minimized_congruences();
99537}
99538
99539template <typename D1, typename D2, typename R>
99540void
99541Partially_Reduced_Product<D1, D2, R>
99542::add_recycled_constraints(Constraint_System& cs) {
99543  if (d1.can_recycle_constraint_systems()) {
99544    d2.refine_with_constraints(cs);
99545    d1.add_recycled_constraints(cs);
99546  }
99547  else {
99548    if (d2.can_recycle_constraint_systems()) {
99549      d1.refine_with_constraints(cs);
99550      d2.add_recycled_constraints(cs);
99551    }
99552    else {
99553      d1.add_constraints(cs);
99554      d2.add_constraints(cs);
99555    }
99556  }
99557  clear_reduced_flag();
99558}
99559
99560template <typename D1, typename D2, typename R>
99561void
99562Partially_Reduced_Product<D1, D2, R>
99563::add_recycled_congruences(Congruence_System& cgs) {
99564  if (d1.can_recycle_congruence_systems()) {
99565    d2.refine_with_congruences(cgs);
99566    d1.add_recycled_congruences(cgs);
99567  }
99568  else {
99569    if (d2.can_recycle_congruence_systems()) {
99570      d1.refine_with_congruences(cgs);
99571      d2.add_recycled_congruences(cgs);
99572    }
99573    else {
99574      d1.add_congruences(cgs);
99575      d2.add_congruences(cgs);
99576    }
99577  }
99578  clear_reduced_flag();
99579}
99580
99581template <typename D1, typename D2, typename R>
99582Poly_Gen_Relation
99583Partially_Reduced_Product<D1, D2, R>
99584::relation_with(const Generator& g) const {
99585  reduce();
99586  if (Poly_Gen_Relation::nothing() == d1.relation_with(g)
99587      || Poly_Gen_Relation::nothing() == d2.relation_with(g)) {
99588    return Poly_Gen_Relation::nothing();
99589  }
99590  else {
99591    return Poly_Gen_Relation::subsumes();
99592  }
99593}
99594
99595template <typename D1, typename D2, typename R>
99596Poly_Con_Relation
99597Partially_Reduced_Product<D1, D2, R>
99598::relation_with(const Constraint& c) const {
99599  reduce();
99600  Poly_Con_Relation relation1 = d1.relation_with(c);
99601  Poly_Con_Relation relation2 = d2.relation_with(c);
99602
99603  Poly_Con_Relation result = Poly_Con_Relation::nothing();
99604
99605  if (relation1.implies(Poly_Con_Relation::is_included())) {
99606    result = result && Poly_Con_Relation::is_included();
99607  }
99608  else if (relation2.implies(Poly_Con_Relation::is_included())) {
99609    result = result && Poly_Con_Relation::is_included();
99610  }
99611  if (relation1.implies(Poly_Con_Relation::saturates())) {
99612    result = result && Poly_Con_Relation::saturates();
99613  }
99614  else if (relation2.implies(Poly_Con_Relation::saturates())) {
99615    result = result && Poly_Con_Relation::saturates();
99616  }
99617  if (relation1.implies(Poly_Con_Relation::is_disjoint())) {
99618    result = result && Poly_Con_Relation::is_disjoint();
99619  }
99620  else if (relation2.implies(Poly_Con_Relation::is_disjoint())) {
99621    result = result && Poly_Con_Relation::is_disjoint();
99622  }
99623
99624  return result;
99625}
99626
99627template <typename D1, typename D2, typename R>
99628Poly_Con_Relation
99629Partially_Reduced_Product<D1, D2, R>
99630::relation_with(const Congruence& cg) const {
99631  reduce();
99632  Poly_Con_Relation relation1 = d1.relation_with(cg);
99633  Poly_Con_Relation relation2 = d2.relation_with(cg);
99634
99635  Poly_Con_Relation result = Poly_Con_Relation::nothing();
99636
99637  if (relation1.implies(Poly_Con_Relation::is_included())) {
99638    result = result && Poly_Con_Relation::is_included();
99639  }
99640  else if (relation2.implies(Poly_Con_Relation::is_included())) {
99641    result = result && Poly_Con_Relation::is_included();
99642  }
99643  if (relation1.implies(Poly_Con_Relation::saturates())) {
99644    result = result && Poly_Con_Relation::saturates();
99645  }
99646  else if (relation2.implies(Poly_Con_Relation::saturates())) {
99647    result = result && Poly_Con_Relation::saturates();
99648  }
99649  if (relation1.implies(Poly_Con_Relation::is_disjoint())) {
99650    result = result && Poly_Con_Relation::is_disjoint();
99651  }
99652  else if (relation2.implies(Poly_Con_Relation::is_disjoint())) {
99653    result = result && Poly_Con_Relation::is_disjoint();
99654  }
99655
99656  return result;
99657}
99658
99659template <typename D1, typename D2, typename R>
99660bool
99661Partially_Reduced_Product<D1, D2, R>
99662::maximize(const Linear_Expression& expr,
99663           Coefficient& sup_n,
99664           Coefficient& sup_d,
99665           bool& maximum) const {
99666  reduce();
99667
99668  if (is_empty()) {
99669    return false;
99670  }
99671
99672  PPL_DIRTY_TEMP_COEFFICIENT(sup1_n);
99673  PPL_DIRTY_TEMP_COEFFICIENT(sup1_d);
99674  PPL_DIRTY_TEMP_COEFFICIENT(sup2_n);
99675  PPL_DIRTY_TEMP_COEFFICIENT(sup2_d);
99676  bool maximum1;
99677  bool maximum2;
99678  bool r1 = d1.maximize(expr, sup1_n, sup1_d, maximum1);
99679  bool r2 = d2.maximize(expr, sup2_n, sup2_d, maximum2);
99680  // If neither is bounded from above, return false.
99681  if (!r1 && !r2) {
99682    return false;
99683  }
99684  // If only d2 is bounded from above, then use the values for d2.
99685  if (!r1) {
99686    sup_n = sup2_n;
99687    sup_d = sup2_d;
99688    maximum = maximum2;
99689    return true;
99690  }
99691  // If only d1 is bounded from above, then use the values for d1.
99692  if (!r2) {
99693    sup_n = sup1_n;
99694    sup_d = sup1_d;
99695    maximum = maximum1;
99696    return true;
99697  }
99698  // If both d1 and d2 are bounded from above, then use the minimum values.
99699  if (sup2_d * sup1_n >= sup1_d * sup2_n) {
99700    sup_n = sup1_n;
99701    sup_d = sup1_d;
99702    maximum = maximum1;
99703  }
99704  else {
99705    sup_n = sup2_n;
99706    sup_d = sup2_d;
99707    maximum = maximum2;
99708  }
99709  return true;
99710}
99711
99712template <typename D1, typename D2, typename R>
99713bool
99714Partially_Reduced_Product<D1, D2, R>
99715::minimize(const Linear_Expression& expr,
99716           Coefficient& inf_n,
99717           Coefficient& inf_d,
99718           bool& minimum) const {
99719  reduce();
99720
99721  if (is_empty()) {
99722    return false;
99723  }
99724  PPL_ASSERT(reduced);
99725
99726  PPL_DIRTY_TEMP_COEFFICIENT(inf1_n);
99727  PPL_DIRTY_TEMP_COEFFICIENT(inf1_d);
99728  PPL_DIRTY_TEMP_COEFFICIENT(inf2_n);
99729  PPL_DIRTY_TEMP_COEFFICIENT(inf2_d);
99730  bool minimum1;
99731  bool minimum2;
99732  bool r1 = d1.minimize(expr, inf1_n, inf1_d, minimum1);
99733  bool r2 = d2.minimize(expr, inf2_n, inf2_d, minimum2);
99734  // If neither is bounded from below, return false.
99735  if (!r1 && !r2) {
99736    return false;
99737  }
99738  // If only d2 is bounded from below, then use the values for d2.
99739  if (!r1) {
99740    inf_n = inf2_n;
99741    inf_d = inf2_d;
99742    minimum = minimum2;
99743    return true;
99744  }
99745  // If only d1 is bounded from below, then use the values for d1.
99746  if (!r2) {
99747    inf_n = inf1_n;
99748    inf_d = inf1_d;
99749    minimum = minimum1;
99750    return true;
99751  }
99752  // If both d1 and d2 are bounded from below, then use the minimum values.
99753  if (inf2_d * inf1_n <= inf1_d * inf2_n) {
99754    inf_n = inf1_n;
99755    inf_d = inf1_d;
99756    minimum = minimum1;
99757  }
99758  else {
99759    inf_n = inf2_n;
99760    inf_d = inf2_d;
99761    minimum = minimum2;
99762  }
99763  return true;
99764}
99765
99766template <typename D1, typename D2, typename R>
99767bool
99768Partially_Reduced_Product<D1, D2, R>
99769::maximize(const Linear_Expression& expr,
99770           Coefficient& sup_n,
99771           Coefficient& sup_d,
99772           bool& maximum,
99773           Generator& g) const {
99774  reduce();
99775
99776  if (is_empty()) {
99777    return false;
99778  }
99779  PPL_ASSERT(reduced);
99780
99781  PPL_DIRTY_TEMP_COEFFICIENT(sup1_n);
99782  PPL_DIRTY_TEMP_COEFFICIENT(sup1_d);
99783  PPL_DIRTY_TEMP_COEFFICIENT(sup2_n);
99784  PPL_DIRTY_TEMP_COEFFICIENT(sup2_d);
99785  bool maximum1;
99786  bool maximum2;
99787  Generator g1(point());
99788  Generator g2(point());
99789  bool r1 = d1.maximize(expr, sup1_n, sup1_d, maximum1, g1);
99790  bool r2 = d2.maximize(expr, sup2_n, sup2_d, maximum2, g2);
99791  // If neither is bounded from above, return false.
99792  if (!r1 && !r2) {
99793    return false;
99794  }
99795  // If only d2 is bounded from above, then use the values for d2.
99796  if (!r1) {
99797    sup_n = sup2_n;
99798    sup_d = sup2_d;
99799    maximum = maximum2;
99800    g = g2;
99801    return true;
99802  }
99803  // If only d1 is bounded from above, then use the values for d1.
99804  if (!r2) {
99805    sup_n = sup1_n;
99806    sup_d = sup1_d;
99807    maximum = maximum1;
99808    g = g1;
99809    return true;
99810  }
99811  // If both d1 and d2 are bounded from above, then use the minimum values.
99812  if (sup2_d * sup1_n >= sup1_d * sup2_n) {
99813    sup_n = sup1_n;
99814    sup_d = sup1_d;
99815    maximum = maximum1;
99816    g = g1;
99817  }
99818  else {
99819    sup_n = sup2_n;
99820    sup_d = sup2_d;
99821    maximum = maximum2;
99822    g = g2;
99823  }
99824  return true;
99825}
99826
99827template <typename D1, typename D2, typename R>
99828bool
99829Partially_Reduced_Product<D1, D2, R>
99830::minimize(const Linear_Expression& expr,
99831           Coefficient& inf_n,
99832           Coefficient& inf_d,
99833           bool& minimum,
99834           Generator& g) const {
99835  reduce();
99836
99837  if (is_empty()) {
99838    return false;
99839  }
99840  PPL_ASSERT(reduced);
99841
99842  PPL_DIRTY_TEMP_COEFFICIENT(inf1_n);
99843  PPL_DIRTY_TEMP_COEFFICIENT(inf1_d);
99844  PPL_DIRTY_TEMP_COEFFICIENT(inf2_n);
99845  PPL_DIRTY_TEMP_COEFFICIENT(inf2_d);
99846  bool minimum1;
99847  bool minimum2;
99848  Generator g1(point());
99849  Generator g2(point());
99850  bool r1 = d1.minimize(expr, inf1_n, inf1_d, minimum1, g1);
99851  bool r2 = d2.minimize(expr, inf2_n, inf2_d, minimum2, g2);
99852  // If neither is bounded from below, return false.
99853  if (!r1 && !r2) {
99854    return false;
99855  }
99856  // If only d2 is bounded from below, then use the values for d2.
99857  if (!r1) {
99858    inf_n = inf2_n;
99859    inf_d = inf2_d;
99860    minimum = minimum2;
99861    g = g2;
99862    return true;
99863  }
99864  // If only d1 is bounded from below, then use the values for d1.
99865  if (!r2) {
99866    inf_n = inf1_n;
99867    inf_d = inf1_d;
99868    minimum = minimum1;
99869    g = g1;
99870    return true;
99871  }
99872  // If both d1 and d2 are bounded from below, then use the minimum values.
99873  if (inf2_d * inf1_n <= inf1_d * inf2_n) {
99874    inf_n = inf1_n;
99875    inf_d = inf1_d;
99876    minimum = minimum1;
99877    g = g1;
99878  }
99879  else {
99880    inf_n = inf2_n;
99881    inf_d = inf2_d;
99882    minimum = minimum2;
99883    g = g2;
99884  }
99885  return true;
99886}
99887
99888template <typename D1, typename D2, typename R>
99889inline bool
99890Partially_Reduced_Product<D1, D2, R>::OK() const {
99891  if (reduced) {
99892    Partially_Reduced_Product<D1, D2, R> dp1 = *this;
99893    Partially_Reduced_Product<D1, D2, R> dp2 = *this;
99894    /* Force dp1 reduction */
99895    dp1.clear_reduced_flag();
99896    dp1.reduce();
99897    if (dp1 != dp2) {
99898      return false;
99899    }
99900  }
99901  return d1.OK() && d2.OK();
99902}
99903
99904template <typename D1, typename D2, typename R>
99905bool
99906Partially_Reduced_Product<D1, D2, R>::ascii_load(std::istream& s) {
99907  const char yes = '+';
99908  const char no = '-';
99909  std::string str;
99910  if (!(s >> str) || str != "Partially_Reduced_Product") {
99911    return false;
99912  }
99913  if (!(s >> str)
99914      || (str[0] != yes && str[0] != no)
99915      || str.substr(1) != "reduced") {
99916    return false;
99917  }
99918  reduced = (str[0] == yes);
99919  if (!(s >> str) || str != "Domain") {
99920    return false;
99921  }
99922  if (!(s >> str) || str != "1:") {
99923    return false;
99924  }
99925  if (!d1.ascii_load(s)) {
99926    return false;
99927  }
99928  if (!(s >> str) || str != "Domain") {
99929    return false;
99930  }
99931  if (!(s >> str) || str != "2:") {
99932    return false;
99933  }
99934  return d2.ascii_load(s);
99935}
99936
99937template <typename D1, typename D2>
99938void Smash_Reduction<D1, D2>::product_reduce(D1& d1, D2& d2) {
99939  using std::swap;
99940  if (d2.is_empty()) {
99941    if (!d1.is_empty()) {
99942      D1 new_d1(d1.space_dimension(), EMPTY);
99943      swap(d1, new_d1);
99944    }
99945  }
99946  else if (d1.is_empty()) {
99947    D2 new_d2(d2.space_dimension(), EMPTY);
99948    swap(d2, new_d2);
99949  }
99950}
99951
99952template <typename D1, typename D2>
99953void Constraints_Reduction<D1, D2>::product_reduce(D1& d1, D2& d2) {
99954  if (d1.is_empty() || d2.is_empty()) {
99955    // If one of the components is empty, do the smash reduction and return.
99956    Parma_Polyhedra_Library::Smash_Reduction<D1, D2> sr;
99957    sr.product_reduce(d1, d2);
99958    return;
99959  }
99960  else {
99961    using std::swap;
99962    dimension_type space_dim = d1.space_dimension();
99963    d1.refine_with_constraints(d2.minimized_constraints());
99964    if (d1.is_empty()) {
99965      D2 new_d2(space_dim, EMPTY);
99966      swap(d2, new_d2);
99967      return;
99968    }
99969    d2.refine_with_constraints(d1.minimized_constraints());
99970    if (d2.is_empty()) {
99971      D1 new_d1(space_dim, EMPTY);
99972      swap(d1, new_d1);
99973    }
99974  }
99975}
99976
99977/* Auxiliary procedure for the Congruences_Reduction() method.
99978   If more than one hyperplane defined by congruence cg intersect
99979   d2, then d1 and d2 are unchanged; if exactly one intersects d2, then
99980   the corresponding equality is added to d1 and d2;
99981   otherwise d1 and d2 are set empty. */
99982template <typename D1, typename D2>
99983bool shrink_to_congruence_no_check(D1& d1, D2& d2, const Congruence& cg) {
99984  // It is assumed that cg is a proper congruence.
99985  PPL_ASSERT(cg.modulus() != 0);
99986  // It is assumed that cg is satisfied by all points in d1.
99987  PPL_ASSERT(d1.relation_with(cg) == Poly_Con_Relation::is_included());
99988
99989  Linear_Expression e(cg.expression());
99990
99991  // Find the maximum and minimum bounds for the domain element d with the
99992  // linear expression e.
99993  PPL_DIRTY_TEMP_COEFFICIENT(max_numer);
99994  PPL_DIRTY_TEMP_COEFFICIENT(max_denom);
99995  bool max_included;
99996  PPL_DIRTY_TEMP_COEFFICIENT(min_numer);
99997  PPL_DIRTY_TEMP_COEFFICIENT(min_denom);
99998  if (d2.maximize(e, max_numer, max_denom, max_included)) {
99999    bool min_included;
100000    if (d2.minimize(e, min_numer, min_denom, min_included)) {
100001      // Adjust values to allow for the denominators max_denom and min_denom.
100002      max_numer *= min_denom;
100003      min_numer *= max_denom;
100004      PPL_DIRTY_TEMP_COEFFICIENT(denom);
100005      PPL_DIRTY_TEMP_COEFFICIENT(mod);
100006      denom = max_denom * min_denom;
100007      mod = cg.modulus() * denom;
100008      // If the difference between the maximum and minimum bounds is more than
100009      // twice the modulus, then there will be two neighboring hyperplanes
100010      // defined by cg that are intersected by the domain element d;
100011      // there is no possible reduction in this case.
100012      PPL_DIRTY_TEMP_COEFFICIENT(mod2);
100013      mod2 = 2 * mod;
100014      if (max_numer - min_numer < mod2
100015          || (max_numer - min_numer == mod2 && (!max_included || !min_included)))
100016        {
100017          PPL_DIRTY_TEMP_COEFFICIENT(shrink_amount);
100018          PPL_DIRTY_TEMP_COEFFICIENT(max_decreased);
100019          PPL_DIRTY_TEMP_COEFFICIENT(min_increased);
100020          // Find the amount by which the maximum value may be decreased.
100021          shrink_amount = max_numer % mod;
100022          if (!max_included && shrink_amount == 0) {
100023            shrink_amount = mod;
100024          }
100025          if (shrink_amount < 0) {
100026            shrink_amount += mod;
100027          }
100028          max_decreased = max_numer - shrink_amount;
100029          // Find the amount by which the minimum value may be increased.
100030          shrink_amount = min_numer % mod;
100031          if (!min_included && shrink_amount == 0) {
100032            shrink_amount = - mod;
100033          }
100034          if (shrink_amount > 0) {
100035            shrink_amount -= mod;
100036          }
100037          min_increased = min_numer - shrink_amount;
100038          if (max_decreased == min_increased) {
100039            // The domain element d2 intersects exactly one hyperplane
100040            // defined by cg, so add the equality to d1 and d2.
100041            Constraint new_c(denom * e == min_increased);
100042            d1.refine_with_constraint(new_c);
100043            d2.refine_with_constraint(new_c);
100044            return true;
100045          }
100046          else {
100047            if (max_decreased < min_increased) {
100048              using std::swap;
100049              // In this case, d intersects no hyperplanes defined by cg,
100050              // so set d to empty and return false.
100051              D1 new_d1(d1.space_dimension(), EMPTY);
100052              swap(d1, new_d1);
100053              D2 new_d2(d2.space_dimension(), EMPTY);
100054              swap(d2, new_d2);
100055              return false;
100056            }
100057          }
100058        }
100059    }
100060  }
100061  return true;
100062}
100063
100064template <typename D1, typename D2>
100065void
100066Congruences_Reduction<D1, D2>::product_reduce(D1& d1, D2& d2) {
100067  if (d1.is_empty() || d2.is_empty()) {
100068    // If one of the components is empty, do the smash reduction and return.
100069    Parma_Polyhedra_Library::Smash_Reduction<D1, D2> sr;
100070    sr.product_reduce(d1, d2);
100071    return;
100072  }
100073  // Use the congruences representing d1 to shrink both components.
100074  const Congruence_System cgs1 = d1.minimized_congruences();
100075  for (Congruence_System::const_iterator i = cgs1.begin(),
100076         cgs_end = cgs1.end(); i != cgs_end; ++i) {
100077    const Congruence& cg1 = *i;
100078    if (cg1.is_equality()) {
100079      d2.refine_with_congruence(cg1);
100080    }
100081    else {
100082      if (!Parma_Polyhedra_Library::
100083          shrink_to_congruence_no_check(d1, d2, cg1)) {
100084        // The product is empty.
100085        return;
100086      }
100087    }
100088  }
100089  // Use the congruences representing d2 to shrink both components.
100090  const Congruence_System cgs2 = d2.minimized_congruences();
100091  for (Congruence_System::const_iterator i = cgs2.begin(),
100092         cgs_end = cgs2.end(); i != cgs_end; ++i) {
100093    const Congruence& cg2 = *i;
100094    if (cg2.is_equality()) {
100095      d1.refine_with_congruence(cg2);
100096    }
100097    else {
100098      if (!Parma_Polyhedra_Library::
100099          shrink_to_congruence_no_check(d2, d1, cg2)) {
100100        // The product is empty.
100101        return;
100102      }
100103    }
100104  }
100105}
100106
100107template <typename D1, typename D2>
100108void
100109Shape_Preserving_Reduction<D1, D2>::product_reduce(D1& d1, D2& d2) {
100110  // First do the congruences reduction.
100111  Parma_Polyhedra_Library::Congruences_Reduction<D1, D2> cgr;
100112  cgr.product_reduce(d1, d2);
100113  if (d1.is_empty()) {
100114    return;
100115  }
100116
100117  PPL_DIRTY_TEMP_COEFFICIENT(freq_n);
100118  PPL_DIRTY_TEMP_COEFFICIENT(freq_d);
100119  PPL_DIRTY_TEMP_COEFFICIENT(val_n);
100120  PPL_DIRTY_TEMP_COEFFICIENT(val_d);
100121
100122  // Use the constraints representing d2.
100123  Constraint_System cs = d2.minimized_constraints();
100124  Constraint_System refining_cs;
100125  for (Constraint_System::const_iterator i = cs.begin(),
100126         cs_end = cs.end(); i != cs_end; ++i) {
100127    const Constraint& c = *i;
100128    if (c.is_equality()) {
100129      continue;
100130    }
100131    // Check the frequency and value of the linear expression for
100132    // the constraint `c'.
100133    Linear_Expression le(c.expression());
100134    if (!d1.frequency(le, freq_n, freq_d, val_n, val_d)) {
100135      // Nothing to do.
100136      continue;
100137    }
100138    if (val_n == 0) {
100139      // Nothing to do.
100140      continue;
100141    }
100142    // Adjust the value of the inhomogeneous term to satisfy
100143    // the implied congruence.
100144    if (val_n < 0) {
100145      val_n = val_n*freq_d + val_d*freq_n;
100146      val_d *= freq_d;
100147    }
100148    le *= val_d;
100149    le -= val_n;
100150    refining_cs.insert(le >= 0);
100151  }
100152  d2.refine_with_constraints(refining_cs);
100153
100154  // Use the constraints representing d1.
100155  cs = d1.minimized_constraints();
100156  refining_cs.clear();
100157  for (Constraint_System::const_iterator i = cs.begin(),
100158         cs_end = cs.end(); i != cs_end; ++i) {
100159    const Constraint& c = *i;
100160    if (c.is_equality()) {
100161      // Equalities already shared.
100162      continue;
100163    }
100164    // Check the frequency and value of the linear expression for
100165    // the constraint `c'.
100166    Linear_Expression le(c.expression());
100167    if (!d2.frequency(le, freq_n, freq_d, val_n, val_d)) {
100168      // Nothing to do.
100169      continue;
100170    }
100171    if (val_n == 0) {
100172      // Nothing to do.
100173      continue;
100174    }
100175    // Adjust the value of the inhomogeneous term to satisfy
100176    // the implied congruence.
100177    if (val_n < 0) {
100178      val_n = val_n*freq_d + val_d*freq_n;
100179      val_d *= freq_d;
100180    }
100181    le *= val_d;
100182    le -= val_n;
100183    refining_cs.insert(le >= 0);
100184  }
100185  d1.refine_with_constraints(refining_cs);
100186
100187  // The reduction may have introduced additional equalities
100188  // so these must be shared with the other component.
100189  Parma_Polyhedra_Library::Constraints_Reduction<D1, D2> cr;
100190  cr.product_reduce(d1, d2);
100191}
100192
100193} // namespace Parma_Polyhedra_Library
100194
100195/* Automatically generated from PPL source file ../src/Partially_Reduced_Product_defs.hh line 1688. */
100196
100197/* Automatically generated from PPL source file ../src/Determinate_defs.hh line 1. */
100198/* Determinate class declaration.
100199*/
100200
100201
100202/* Automatically generated from PPL source file ../src/Determinate_types.hh line 1. */
100203
100204
100205namespace Parma_Polyhedra_Library {
100206
100207template <typename PSET>
100208class Determinate;
100209
100210} // namespace Parma_Polyhedra_Library
100211
100212/* Automatically generated from PPL source file ../src/Determinate_defs.hh line 32. */
100213#include <iosfwd>
100214
100215namespace Parma_Polyhedra_Library {
100216
100217//! Swaps \p x with \p y.
100218/*! \relates Determinate */
100219template <typename PSET>
100220void swap(Determinate<PSET>& x, Determinate<PSET>& y);
100221
100222/*! \brief
100223  Returns <CODE>true</CODE> if and only if \p x and \p y are the same
100224  COW-wrapped pointset.
100225
100226  \relates Determinate
100227*/
100228template <typename PSET>
100229bool operator==(const Determinate<PSET>& x, const Determinate<PSET>& y);
100230
100231/*! \brief
100232  Returns <CODE>true</CODE> if and only if \p x and \p y are different
100233  COW-wrapped pointsets.
100234
100235  \relates Determinate
100236*/
100237template <typename PSET>
100238bool operator!=(const Determinate<PSET>& x, const Determinate<PSET>& y);
100239
100240namespace IO_Operators {
100241
100242//! Output operator.
100243/*! \relates Parma_Polyhedra_Library::Determinate */
100244template <typename PSET>
100245std::ostream&
100246operator<<(std::ostream&, const Determinate<PSET>&);
100247
100248} // namespace IO_Operators
100249
100250} // namespace Parma_Polyhedra_Library
100251
100252/*! \brief
100253  A wrapper for PPL pointsets, providing them with a
100254  <EM>determinate constraint system</EM> interface, as defined
100255  in \ref Bag98 "[Bag98]".
100256
100257  The implementation uses a copy-on-write optimization, making the
100258  class suitable for constructions, like the <EM>finite powerset</EM>
100259  and <EM>ask-and-tell</EM> of \ref Bag98 "[Bag98]", that are likely
100260  to perform many copies.
100261
100262  \ingroup PPL_CXX_interface
100263*/
100264template <typename PSET>
100265class Parma_Polyhedra_Library::Determinate {
100266public:
100267  //! \name Constructors and Destructor
100268  //@{
100269
100270  /*! \brief
100271    Constructs a COW-wrapped object corresponding to the pointset \p pset.
100272  */
100273  Determinate(const PSET& pset);
100274
100275  /*! \brief
100276    Constructs a COW-wrapped object corresponding to the pointset
100277    defined by \p cs.
100278  */
100279  Determinate(const Constraint_System& cs);
100280
100281  /*! \brief
100282    Constructs a COW-wrapped object corresponding to the pointset
100283    defined by \p cgs.
100284  */
100285  Determinate(const Congruence_System& cgs);
100286
100287  //! Copy constructor.
100288  Determinate(const Determinate& y);
100289
100290  //! Destructor.
100291  ~Determinate();
100292
100293  //@} // Constructors and Destructor
100294
100295  //! \name Member Functions that Do Not Modify the Domain Element
100296  //@{
100297
100298  //! Returns a const reference to the embedded pointset.
100299  const PSET& pointset() const;
100300
100301  /*! \brief
100302    Returns <CODE>true</CODE> if and only if \p *this embeds the universe
100303    element \p PSET.
100304  */
100305  bool is_top() const;
100306
100307  /*! \brief
100308    Returns <CODE>true</CODE> if and only if \p *this embeds the empty
100309    element of \p PSET.
100310  */
100311  bool is_bottom() const;
100312
100313  //! Returns <CODE>true</CODE> if and only if \p *this entails \p y.
100314  bool definitely_entails(const Determinate& y) const;
100315
100316  /*! \brief
100317    Returns <CODE>true</CODE> if and only if \p *this and \p y
100318    are definitely equivalent.
100319  */
100320  bool is_definitely_equivalent_to(const Determinate& y) const;
100321
100322  /*! \brief
100323    Returns a lower bound to the total size in bytes of the memory
100324    occupied by \p *this.
100325  */
100326  memory_size_type total_memory_in_bytes() const;
100327
100328  /*! \brief
100329    Returns a lower bound to the size in bytes of the memory
100330    managed by \p *this.
100331  */
100332  memory_size_type external_memory_in_bytes() const;
100333
100334  /*!
100335    Returns <CODE>true</CODE> if and only if this domain
100336    has a nontrivial weakening operator.
100337  */
100338  static bool has_nontrivial_weakening();
100339
100340  //! Checks if all the invariants are satisfied.
100341  bool OK() const;
100342
100343  //@} // Member Functions that Do Not Modify the Domain Element
100344
100345
100346  //! \name Member Functions that May Modify the Domain Element
100347  //@{
100348
100349  //! Assigns to \p *this the upper bound of \p *this and \p y.
100350  void upper_bound_assign(const Determinate& y);
100351
100352  //! Assigns to \p *this the meet of \p *this and \p y.
100353  void meet_assign(const Determinate& y);
100354
100355  //! Assigns to \p *this the result of weakening \p *this with \p y.
100356  void weakening_assign(const Determinate& y);
100357
100358  /*! \brief
100359    Assigns to \p *this the \ref Concatenating_Polyhedra "concatenation"
100360    of \p *this and \p y, taken in this order.
100361  */
100362  void concatenate_assign(const Determinate& y);
100363
100364  //! Returns a reference to the embedded element.
100365  PSET& pointset();
100366
100367#ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
100368  /*! \brief
100369    On return from this method, the representation of \p *this
100370    is not shared by different Determinate objects.
100371  */
100372#endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
100373  void mutate();
100374
100375  //! Assignment operator.
100376  Determinate& operator=(const Determinate& y);
100377
100378  //! Swaps \p *this with \p y.
100379  void m_swap(Determinate& y);
100380
100381  //@} // Member Functions that May Modify the Domain Element
100382
100383#ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
100384  //! A function adapter for the Determinate class.
100385  /*! \ingroup PPL_CXX_interface
100386    It lifts a Binary_Operator_Assign function object, taking arguments
100387    of type PSET, producing the corresponding function object taking
100388    arguments of type Determinate<PSET>.
100389
100390    The template parameter Binary_Operator_Assign is supposed to
100391    implement an <EM>apply and assign</EM> function, i.e., a function
100392    having signature <CODE>void foo(PSET& x, const PSET& y)</CODE> that
100393    applies an operator to \c x and \c y and assigns the result to \c x.
100394    For instance, such a function object is obtained by
100395    <CODE>std::mem_fun_ref(&C_Polyhedron::intersection_assign)</CODE>.
100396  */
100397#endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
100398  template <typename Binary_Operator_Assign>
100399  class Binary_Operator_Assign_Lifter {
100400  public:
100401    //! Explicit unary constructor.
100402    explicit
100403    Binary_Operator_Assign_Lifter(Binary_Operator_Assign op_assign);
100404
100405    //! Function-application operator.
100406    void operator()(Determinate& x, const Determinate& y) const;
100407
100408  private:
100409    //! The function object to be lifted.
100410    Binary_Operator_Assign op_assign_;
100411  };
100412
100413#ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
100414  /*! \brief
100415    Helper function returning a Binary_Operator_Assign_Lifter object,
100416    also allowing for the deduction of template arguments.
100417  */
100418#endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
100419  template <typename Binary_Operator_Assign>
100420  static Binary_Operator_Assign_Lifter<Binary_Operator_Assign>
100421  lift_op_assign(Binary_Operator_Assign op_assign);
100422
100423private:
100424  //! The possibly shared representation of a Determinate object.
100425  /*! \ingroup PPL_CXX_interface
100426    By adopting the <EM>copy-on-write</EM> technique, a single
100427    representation of the base-level object may be shared by more than
100428    one object of the class Determinate.
100429  */
100430  class Rep {
100431  private:
100432    /*! \brief
100433      Count the number of references:
100434      -   0: leaked, \p pset is non-const;
100435      -   1: one reference, \p pset is non-const;
100436      - > 1: more than one reference, \p pset is const.
100437    */
100438    mutable unsigned long references;
100439
100440    //! Private and unimplemented: assignment not allowed.
100441    Rep& operator=(const Rep& y);
100442
100443    //! Private and unimplemented: copies not allowed.
100444    Rep(const Rep& y);
100445
100446    //! Private and unimplemented: default construction not allowed.
100447    Rep();
100448
100449  public:
100450    //! The possibly shared, embedded pointset.
100451    PSET pset;
100452
100453    /*! \brief
100454      Builds a new representation by creating a pointset
100455      of the specified kind, in the specified vector space.
100456    */
100457    Rep(dimension_type num_dimensions, Degenerate_Element kind);
100458
100459    //! Builds a new representation by copying the pointset \p p.
100460    Rep(const PSET& p);
100461
100462    //! Builds a new representation by copying the constraints in \p cs.
100463    Rep(const Constraint_System& cs);
100464
100465    //! Builds a new representation by copying the constraints in \p cgs.
100466    Rep(const Congruence_System& cgs);
100467
100468    //! Destructor.
100469    ~Rep();
100470
100471    //! Registers a new reference.
100472    void new_reference() const;
100473
100474    /*! \brief
100475      Unregisters one reference; returns <CODE>true</CODE> if and only if
100476      the representation has become unreferenced.
100477    */
100478    bool del_reference() const;
100479
100480    //! True if and only if this representation is currently shared.
100481    bool is_shared() const;
100482
100483    /*! \brief
100484      Returns a lower bound to the total size in bytes of the memory
100485      occupied by \p *this.
100486    */
100487    memory_size_type total_memory_in_bytes() const;
100488
100489    /*! \brief
100490      Returns a lower bound to the size in bytes of the memory
100491      managed by \p *this.
100492    */
100493    memory_size_type external_memory_in_bytes() const;
100494  };
100495
100496  /*! \brief
100497    A pointer to the possibly shared representation of
100498    the base-level domain element.
100499  */
100500  Rep* prep;
100501
100502  friend bool
100503  operator==<PSET>(const Determinate<PSET>& x, const Determinate<PSET>& y);
100504
100505  friend bool
100506  operator!=<PSET>(const Determinate<PSET>& x, const Determinate<PSET>& y);
100507};
100508
100509/* Automatically generated from PPL source file ../src/Determinate_inlines.hh line 1. */
100510/* Determinate class implementation: inline functions.
100511*/
100512
100513
100514/* Automatically generated from PPL source file ../src/Determinate_inlines.hh line 28. */
100515
100516namespace Parma_Polyhedra_Library {
100517
100518template <typename PSET>
100519inline
100520Determinate<PSET>::Rep::Rep(dimension_type num_dimensions,
100521                          Degenerate_Element kind)
100522  : references(0), pset(num_dimensions, kind) {
100523}
100524
100525template <typename PSET>
100526inline
100527Determinate<PSET>::Rep::Rep(const PSET& p)
100528  : references(0), pset(p) {
100529}
100530
100531template <typename PSET>
100532inline
100533Determinate<PSET>::Rep::Rep(const Constraint_System& cs)
100534  : references(0), pset(cs) {
100535}
100536
100537template <typename PSET>
100538inline
100539Determinate<PSET>::Rep::Rep(const Congruence_System& cgs)
100540  : references(0), pset(cgs) {
100541}
100542
100543template <typename PSET>
100544inline
100545Determinate<PSET>::Rep::~Rep() {
100546  PPL_ASSERT(references == 0);
100547}
100548
100549template <typename PSET>
100550inline void
100551Determinate<PSET>::Rep::new_reference() const {
100552  ++references;
100553}
100554
100555template <typename PSET>
100556inline bool
100557Determinate<PSET>::Rep::del_reference() const {
100558  return --references == 0;
100559}
100560
100561template <typename PSET>
100562inline bool
100563Determinate<PSET>::Rep::is_shared() const {
100564  return references > 1;
100565}
100566
100567template <typename PSET>
100568inline memory_size_type
100569Determinate<PSET>::Rep::external_memory_in_bytes() const {
100570  return pset.external_memory_in_bytes();
100571}
100572
100573template <typename PSET>
100574inline memory_size_type
100575Determinate<PSET>::Rep::total_memory_in_bytes() const {
100576  return sizeof(*this) + external_memory_in_bytes();
100577}
100578
100579template <typename PSET>
100580inline
100581Determinate<PSET>::Determinate(const PSET& pset)
100582  : prep(new Rep(pset)) {
100583  prep->new_reference();
100584}
100585
100586template <typename PSET>
100587inline
100588Determinate<PSET>::Determinate(const Constraint_System& cs)
100589  : prep(new Rep(cs)) {
100590  prep->new_reference();
100591}
100592
100593template <typename PSET>
100594inline
100595Determinate<PSET>::Determinate(const Congruence_System& cgs)
100596  : prep(new Rep(cgs)) {
100597  prep->new_reference();
100598}
100599
100600template <typename PSET>
100601inline
100602Determinate<PSET>::Determinate(const Determinate& y)
100603  : prep(y.prep) {
100604  prep->new_reference();
100605}
100606
100607template <typename PSET>
100608inline
100609Determinate<PSET>::~Determinate() {
100610  if (prep->del_reference()) {
100611    delete prep;
100612  }
100613}
100614
100615template <typename PSET>
100616inline Determinate<PSET>&
100617Determinate<PSET>::operator=(const Determinate& y) {
100618  y.prep->new_reference();
100619  if (prep->del_reference()) {
100620    delete prep;
100621  }
100622  prep = y.prep;
100623  return *this;
100624}
100625
100626template <typename PSET>
100627inline void
100628Determinate<PSET>::m_swap(Determinate& y) {
100629  using std::swap;
100630  swap(prep, y.prep);
100631}
100632
100633template <typename PSET>
100634inline void
100635Determinate<PSET>::mutate() {
100636  if (prep->is_shared()) {
100637    Rep* const new_prep = new Rep(prep->pset);
100638    (void) prep->del_reference();
100639    new_prep->new_reference();
100640    prep = new_prep;
100641  }
100642}
100643
100644template <typename PSET>
100645inline const PSET&
100646Determinate<PSET>::pointset() const {
100647  return prep->pset;
100648}
100649
100650template <typename PSET>
100651inline PSET&
100652Determinate<PSET>::pointset() {
100653  mutate();
100654  return prep->pset;
100655}
100656
100657template <typename PSET>
100658inline void
100659Determinate<PSET>::upper_bound_assign(const Determinate& y) {
100660  pointset().upper_bound_assign(y.pointset());
100661}
100662
100663template <typename PSET>
100664inline void
100665Determinate<PSET>::meet_assign(const Determinate& y) {
100666  pointset().intersection_assign(y.pointset());
100667}
100668
100669template <typename PSET>
100670inline bool
100671Determinate<PSET>::has_nontrivial_weakening() {
100672  // FIXME: the following should be turned into a query to PSET.  This
100673  // can be postponed until the time the ask-and-tell construction is
100674  // revived.
100675  return false;
100676}
100677
100678template <typename PSET>
100679inline void
100680Determinate<PSET>::weakening_assign(const Determinate& y) {
100681  // FIXME: the following should be turned into a proper
100682  // implementation.  This can be postponed until the time the
100683  // ask-and-tell construction is revived.
100684  pointset().difference_assign(y.pointset());
100685}
100686
100687template <typename PSET>
100688inline void
100689Determinate<PSET>::concatenate_assign(const Determinate& y) {
100690  pointset().concatenate_assign(y.pointset());
100691}
100692
100693template <typename PSET>
100694inline bool
100695Determinate<PSET>::definitely_entails(const Determinate& y) const {
100696  return prep == y.prep || y.prep->pset.contains(prep->pset);
100697}
100698
100699template <typename PSET>
100700inline bool
100701Determinate<PSET>::is_definitely_equivalent_to(const Determinate& y) const {
100702  return prep == y.prep || prep->pset == y.prep->pset;
100703}
100704
100705template <typename PSET>
100706inline bool
100707Determinate<PSET>::is_top() const {
100708  return prep->pset.is_universe();
100709}
100710
100711template <typename PSET>
100712inline bool
100713Determinate<PSET>::is_bottom() const {
100714  return prep->pset.is_empty();
100715}
100716
100717template <typename PSET>
100718inline memory_size_type
100719Determinate<PSET>::external_memory_in_bytes() const {
100720  return prep->total_memory_in_bytes();
100721}
100722
100723template <typename PSET>
100724inline memory_size_type
100725Determinate<PSET>::total_memory_in_bytes() const {
100726  return sizeof(*this) + external_memory_in_bytes();
100727}
100728
100729template <typename PSET>
100730inline bool
100731Determinate<PSET>::OK() const {
100732  return prep->pset.OK();
100733}
100734
100735namespace IO_Operators {
100736
100737/*! \relates Parma_Polyhedra_Library::Determinate */
100738template <typename PSET>
100739inline std::ostream&
100740operator<<(std::ostream& s, const Determinate<PSET>& x) {
100741  s << x.pointset();
100742  return s;
100743}
100744
100745} // namespace IO_Operators
100746
100747/*! \relates Determinate */
100748template <typename PSET>
100749inline bool
100750operator==(const Determinate<PSET>& x, const Determinate<PSET>& y) {
100751  return x.prep == y.prep || x.prep->pset == y.prep->pset;
100752}
100753
100754/*! \relates Determinate */
100755template <typename PSET>
100756inline bool
100757operator!=(const Determinate<PSET>& x, const Determinate<PSET>& y) {
100758  return x.prep != y.prep && x.prep->pset != y.prep->pset;
100759}
100760
100761template <typename PSET>
100762template <typename Binary_Operator_Assign>
100763inline
100764Determinate<PSET>::Binary_Operator_Assign_Lifter<Binary_Operator_Assign>::
100765Binary_Operator_Assign_Lifter(Binary_Operator_Assign op_assign)
100766  : op_assign_(op_assign) {
100767}
100768
100769template <typename PSET>
100770template <typename Binary_Operator_Assign>
100771inline void
100772Determinate<PSET>::Binary_Operator_Assign_Lifter<Binary_Operator_Assign>::
100773operator()(Determinate& x, const Determinate& y) const {
100774  op_assign_(x.pointset(), y.pointset());
100775}
100776
100777template <typename PSET>
100778template <typename Binary_Operator_Assign>
100779inline
100780Determinate<PSET>::Binary_Operator_Assign_Lifter<Binary_Operator_Assign>
100781Determinate<PSET>::lift_op_assign(Binary_Operator_Assign op_assign) {
100782  return Binary_Operator_Assign_Lifter<Binary_Operator_Assign>(op_assign);
100783}
100784
100785/*! \relates Determinate */
100786template <typename PSET>
100787inline void
100788swap(Determinate<PSET>& x, Determinate<PSET>& y) {
100789  x.m_swap(y);
100790}
100791
100792} // namespace Parma_Polyhedra_Library
100793
100794/* Automatically generated from PPL source file ../src/Determinate_defs.hh line 329. */
100795
100796/* Automatically generated from PPL source file ../src/Powerset_defs.hh line 1. */
100797/* Powerset class declaration.
100798*/
100799
100800
100801/* Automatically generated from PPL source file ../src/Powerset_types.hh line 1. */
100802
100803
100804namespace Parma_Polyhedra_Library {
100805
100806template <typename D>
100807class Powerset;
100808
100809} // namespace Parma_Polyhedra_Library
100810
100811/* Automatically generated from PPL source file ../src/iterator_to_const_defs.hh line 1. */
100812/* iterator_to_const and const_iterator_to_const class declarations.
100813*/
100814
100815
100816/* Automatically generated from PPL source file ../src/iterator_to_const_types.hh line 1. */
100817
100818
100819namespace Parma_Polyhedra_Library {
100820
100821template <typename Container>
100822class iterator_to_const;
100823
100824template <typename Container>
100825class const_iterator_to_const;
100826
100827} // namespace Parma_Polyhedra_Library
100828
100829/* Automatically generated from PPL source file ../src/iterator_to_const_defs.hh line 29. */
100830#include <iterator>
100831
100832#ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
100833//! An iterator on a sequence of read-only objects.
100834/*! \ingroup PPL_CXX_interface
100835  This template class implements a bidirectional <EM>read-only</EM>
100836  iterator on the sequence of objects <CODE>Container</CODE>.
100837  By using this iterator class it is not possible to modify the objects
100838  contained in <CODE>Container</CODE>; rather, object modification has
100839  to be implemented by object replacement, i.e., by using the methods
100840  provided by <CODE>Container</CODE> to remove/insert objects.
100841  Such a policy (a modifiable container of read-only objects) allows
100842  for a reliable enforcement of invariants (such as sortedness of the
100843  objects in the sequence).
100844
100845  \note
100846  For any developers' need, suitable friend declarations allow for
100847  accessing the low-level iterators on the sequence of objects.
100848*/
100849#endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
100850template <typename Container>
100851class Parma_Polyhedra_Library::iterator_to_const {
100852private:
100853  //! The type of the underlying mutable iterator.
100854  typedef typename Container::iterator Base;
100855
100856  //! A shortcut for naming the const_iterator traits.
100857  typedef typename
100858  std::iterator_traits<typename Container::const_iterator> Traits;
100859
100860  //! A (mutable) iterator on the sequence of elements.
100861  Base base;
100862
100863  //! Constructs from the lower-level iterator.
100864  iterator_to_const(const Base& b);
100865
100866  friend class const_iterator_to_const<Container>;
100867  template <typename T> friend class Powerset;
100868
100869public:
100870  // Same traits of the const_iterator, therefore
100871  // forbidding the direct modification of sequence elements.
100872  typedef typename Traits::iterator_category iterator_category;
100873  typedef typename Traits::value_type value_type;
100874  typedef typename Traits::difference_type difference_type;
100875  typedef typename Traits::pointer pointer;
100876  typedef typename Traits::reference reference;
100877
100878  //! Default constructor.
100879  iterator_to_const();
100880
100881  //! Copy constructor.
100882  iterator_to_const(const iterator_to_const& y);
100883
100884  //! Dereference operator.
100885  reference operator*() const;
100886
100887  //! Indirect access operator.
100888  pointer operator->() const;
100889
100890  //! Prefix increment operator.
100891  iterator_to_const& operator++();
100892
100893  //! Postfix increment operator.
100894  iterator_to_const operator++(int);
100895
100896  //! Prefix decrement operator.
100897  iterator_to_const& operator--();
100898
100899  //! Postfix decrement operator.
100900  iterator_to_const operator--(int);
100901
100902  /*! \brief
100903    Returns <CODE>true</CODE> if and only if
100904    \p *this and \p y are identical.
100905  */
100906  bool operator==(const iterator_to_const& y) const;
100907
100908  /*! \brief
100909    Returns <CODE>true</CODE> if and only if
100910    \p *this and \p y are different.
100911  */
100912  bool operator!=(const iterator_to_const& y) const;
100913};
100914
100915#ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
100916//! A %const_iterator on a sequence of read-only objects.
100917/*! \ingroup PPL_CXX_interface
100918  This class, besides implementing a read-only bidirectional iterator
100919  on a read-only sequence of objects, ensures interoperability
100920  with template class iterator_to_const.
100921*/
100922#endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
100923template <typename Container>
100924class Parma_Polyhedra_Library::const_iterator_to_const {
100925private:
100926  //! The type of the underlying %const_iterator.
100927  typedef typename Container::const_iterator Base;
100928
100929  //! A shortcut for naming traits.
100930  typedef typename std::iterator_traits<Base> Traits;
100931
100932  //! A %const_iterator on the sequence of elements.
100933  Base base;
100934
100935  //! Constructs from the lower-level const_iterator.
100936  const_iterator_to_const(const Base& b);
100937
100938  friend class iterator_to_const<Container>;
100939  template <typename T> friend class Powerset;
100940
100941public:
100942  // Same traits of the underlying const_iterator.
100943  typedef typename Traits::iterator_category iterator_category;
100944  typedef typename Traits::value_type value_type;
100945  typedef typename Traits::difference_type difference_type;
100946  typedef typename Traits::pointer pointer;
100947  typedef typename Traits::reference reference;
100948
100949  //! Default constructor.
100950  const_iterator_to_const();
100951
100952  //! Copy constructor.
100953  const_iterator_to_const(const const_iterator_to_const& y);
100954
100955  //! Constructs from the corresponding non-const iterator.
100956  const_iterator_to_const(const iterator_to_const<Container>& y);
100957
100958  //! Dereference operator.
100959  reference operator*() const;
100960
100961  //! Indirect member selector.
100962  pointer operator->() const;
100963
100964  //! Prefix increment operator.
100965  const_iterator_to_const& operator++();
100966
100967  //! Postfix increment operator.
100968  const_iterator_to_const operator++(int);
100969
100970  //! Prefix decrement operator.
100971  const_iterator_to_const& operator--();
100972
100973  //! Postfix decrement operator.
100974  const_iterator_to_const operator--(int);
100975
100976  /*! \brief
100977    Returns <CODE>true</CODE> if and only if
100978    \p *this and \p y are identical.
100979  */
100980  bool operator==(const const_iterator_to_const& y) const;
100981
100982  /*! \brief
100983    Returns <CODE>true</CODE> if and only if
100984    \p *this and \p y are different.
100985  */
100986  bool operator!=(const const_iterator_to_const& y) const;
100987};
100988
100989namespace Parma_Polyhedra_Library {
100990
100991#ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
100992/*! \brief
100993  Mixed comparison operator: returns <CODE>true</CODE> if and only
100994  if (the const version of) \p x is identical to \p y.
100995
100996  \relates const_iterator_to_const
100997*/
100998#endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
100999template <typename Container>
101000bool
101001operator==(const iterator_to_const<Container>& x,
101002           const const_iterator_to_const<Container>& y);
101003
101004#ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
101005/*! \brief
101006  Mixed comparison operator: returns <CODE>true</CODE> if and only
101007  if (the const version of) \p x is different from \p y.
101008
101009  \relates const_iterator_to_const
101010*/
101011#endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
101012template <typename Container>
101013bool
101014operator!=(const iterator_to_const<Container>& x,
101015           const const_iterator_to_const<Container>& y);
101016
101017} // namespace Parma_Polyhedra_Library
101018
101019/* Automatically generated from PPL source file ../src/iterator_to_const_inlines.hh line 1. */
101020/* iterator_to_const and const_iterator_to_const class implementations:
101021   inline functions.
101022*/
101023
101024
101025namespace Parma_Polyhedra_Library {
101026
101027template <typename Container>
101028inline
101029iterator_to_const<Container>::iterator_to_const()
101030  : base() {
101031}
101032
101033template <typename Container>
101034inline
101035iterator_to_const<Container>::iterator_to_const(const iterator_to_const& y)
101036  : base(y.base) {
101037}
101038
101039template <typename Container>
101040inline
101041iterator_to_const<Container>::iterator_to_const(const Base& b)
101042  : base(b) {
101043}
101044
101045template <typename Container>
101046inline typename iterator_to_const<Container>::reference
101047iterator_to_const<Container>::operator*() const {
101048  return *base;
101049}
101050
101051template <typename Container>
101052inline typename iterator_to_const<Container>::pointer
101053iterator_to_const<Container>::operator->() const {
101054  return &*base;
101055}
101056
101057template <typename Container>
101058inline iterator_to_const<Container>&
101059iterator_to_const<Container>::operator++() {
101060  ++base;
101061  return *this;
101062}
101063
101064template <typename Container>
101065inline iterator_to_const<Container>
101066iterator_to_const<Container>::operator++(int) {
101067  iterator_to_const tmp = *this;
101068  operator++();
101069  return tmp;
101070}
101071
101072template <typename Container>
101073inline iterator_to_const<Container>&
101074iterator_to_const<Container>::operator--() {
101075  --base;
101076  return *this;
101077}
101078
101079template <typename Container>
101080inline iterator_to_const<Container>
101081iterator_to_const<Container>::operator--(int) {
101082  iterator_to_const tmp = *this;
101083  operator--();
101084  return tmp;
101085}
101086
101087template <typename Container>
101088inline bool
101089iterator_to_const<Container>::operator==(const iterator_to_const& y) const {
101090  return base == y.base;
101091}
101092
101093template <typename Container>
101094inline bool
101095iterator_to_const<Container>::operator!=(const iterator_to_const& y) const {
101096  return !operator==(y);
101097}
101098
101099template <typename Container>
101100inline
101101const_iterator_to_const<Container>::const_iterator_to_const()
101102  : base() {
101103}
101104
101105template <typename Container>
101106inline
101107const_iterator_to_const<Container>
101108::const_iterator_to_const(const const_iterator_to_const& y)
101109  : base(y.base) {
101110}
101111
101112template <typename Container>
101113inline
101114const_iterator_to_const<Container>::const_iterator_to_const(const Base& b)
101115  : base(b) {
101116}
101117
101118template <typename Container>
101119inline typename const_iterator_to_const<Container>::reference
101120const_iterator_to_const<Container>::operator*() const {
101121  return *base;
101122}
101123
101124template <typename Container>
101125inline typename const_iterator_to_const<Container>::pointer
101126const_iterator_to_const<Container>::operator->() const {
101127  return &*base;
101128}
101129
101130template <typename Container>
101131inline const_iterator_to_const<Container>&
101132const_iterator_to_const<Container>::operator++() {
101133  ++base;
101134  return *this;
101135}
101136
101137template <typename Container>
101138inline const_iterator_to_const<Container>
101139const_iterator_to_const<Container>::operator++(int) {
101140  const_iterator_to_const tmp = *this;
101141  operator++();
101142  return tmp;
101143}
101144
101145template <typename Container>
101146inline const_iterator_to_const<Container>&
101147const_iterator_to_const<Container>::operator--() {
101148  --base;
101149  return *this;
101150}
101151
101152template <typename Container>
101153inline const_iterator_to_const<Container>
101154const_iterator_to_const<Container>::operator--(int) {
101155  const_iterator_to_const tmp = *this;
101156  operator--();
101157  return tmp;
101158}
101159
101160template <typename Container>
101161inline bool
101162const_iterator_to_const<Container>
101163::operator==(const const_iterator_to_const& y) const {
101164  return base == y.base;
101165}
101166
101167template <typename Container>
101168inline bool
101169const_iterator_to_const<Container>
101170::operator!=(const const_iterator_to_const& y) const {
101171  return !operator==(y);
101172}
101173
101174template <typename Container>
101175inline
101176const_iterator_to_const<Container>
101177::const_iterator_to_const(const iterator_to_const<Container>& y)
101178  : base(y.base) {
101179}
101180
101181/*! \relates const_iterator_to_const */
101182template <typename Container>
101183inline bool
101184operator==(const iterator_to_const<Container>& x,
101185           const const_iterator_to_const<Container>& y) {
101186  return const_iterator_to_const<Container>(x).operator==(y);
101187}
101188
101189/*! \relates const_iterator_to_const */
101190template <typename Container>
101191inline bool
101192operator!=(const iterator_to_const<Container>& x,
101193           const const_iterator_to_const<Container>& y) {
101194  return !(x == y);
101195}
101196
101197} // namespace Parma_Polyhedra_Library
101198
101199/* Automatically generated from PPL source file ../src/iterator_to_const_defs.hh line 219. */
101200
101201/* Automatically generated from PPL source file ../src/Powerset_defs.hh line 30. */
101202#include <iosfwd>
101203#include <iterator>
101204#include <list>
101205
101206namespace Parma_Polyhedra_Library {
101207
101208//! Swaps \p x with \p y.
101209/*! \relates Powerset */
101210template <typename D>
101211void swap(Powerset<D>& x, Powerset<D>& y);
101212
101213//! Returns <CODE>true</CODE> if and only if \p x and \p y are equivalent.
101214/*! \relates Powerset */
101215template <typename D>
101216bool
101217operator==(const Powerset<D>& x, const Powerset<D>& y);
101218
101219//! Returns <CODE>true</CODE> if and only if \p x and \p y are not equivalent.
101220/*! \relates Powerset */
101221template <typename D>
101222bool
101223operator!=(const Powerset<D>& x, const Powerset<D>& y);
101224
101225namespace IO_Operators {
101226
101227//! Output operator.
101228/*! \relates Parma_Polyhedra_Library::Powerset */
101229template <typename D>
101230std::ostream&
101231operator<<(std::ostream& s, const Powerset<D>& x);
101232
101233} // namespace IO_Operators
101234
101235} // namespace Parma_Polyhedra_Library
101236
101237
101238//! The powerset construction on a base-level domain.
101239/*! \ingroup PPL_CXX_interface
101240  This class offers a generic implementation of a
101241  <EM>powerset</EM> domain as defined in Section \ref powerset.
101242
101243  Besides invoking the available methods on the disjuncts of a Powerset,
101244  this class also provides bidirectional iterators that allow for a
101245  direct inspection of these disjuncts. For a consistent handling of
101246  Omega-reduction, all the iterators are <EM>read-only</EM>, meaning
101247  that the disjuncts cannot be overwritten. Rather, by using the class
101248  <CODE>iterator</CODE>, it is possible to drop one or more disjuncts
101249  (possibly so as to later add back modified versions).  As an example
101250  of iterator usage, the following template function drops from
101251  powerset \p ps all the disjuncts that would have become redundant by
101252  the addition of an external element \p d.
101253
101254  \code
101255template <typename D>
101256void
101257drop_subsumed(Powerset<D>& ps, const D& d) {
101258  for (typename Powerset<D>::iterator i = ps.begin(),
101259         ps_end = ps.end(), i != ps_end; )
101260    if (i->definitely_entails(d))
101261      i = ps.drop_disjunct(i);
101262    else
101263      ++i;
101264}
101265  \endcode
101266
101267  The template class D must provide the following methods.
101268  \code
101269    memory_size_type total_memory_in_bytes() const
101270  \endcode
101271  Returns a lower bound on the total size in bytes of the memory
101272  occupied by the instance of D.
101273  \code
101274    bool is_top() const
101275  \endcode
101276  Returns <CODE>true</CODE> if and only if the instance of D is the top
101277  element of the domain.
101278  \code
101279    bool is_bottom() const
101280  \endcode
101281  Returns <CODE>true</CODE> if and only if the instance of D is the
101282  bottom element of the domain.
101283  \code
101284    bool definitely_entails(const D& y) const
101285  \endcode
101286  Returns <CODE>true</CODE> if the instance of D definitely entails
101287  <CODE>y</CODE>.  Returns <CODE>false</CODE> if the instance may not
101288  entail <CODE>y</CODE> (i.e., if the instance does not entail
101289  <CODE>y</CODE> or if entailment could not be decided).
101290  \code
101291    void upper_bound_assign(const D& y)
101292  \endcode
101293  Assigns to the instance of D an upper bound of the instance and
101294  <CODE>y</CODE>.
101295  \code
101296    void meet_assign(const D& y)
101297  \endcode
101298  Assigns to the instance of D the meet of the instance and
101299  <CODE>y</CODE>.
101300  \code
101301    bool OK() const
101302  \endcode
101303  Returns <CODE>true</CODE> if the instance of D is in a consistent
101304  state, else returns <CODE>false</CODE>.
101305
101306  The following operators on the template class D must be defined.
101307  \code
101308    operator<<(std::ostream& s, const D& x)
101309  \endcode
101310  Writes a textual representation of the instance of D on
101311  <CODE>s</CODE>.
101312  \code
101313    operator==(const D& x, const D& y)
101314  \endcode
101315  Returns <CODE>true</CODE> if and only if <CODE>x</CODE> and
101316  <CODE>y</CODE> are equivalent D's.
101317  \code
101318    operator!=(const D& x, const D& y)
101319  \endcode
101320  Returns <CODE>true</CODE> if and only if <CODE>x</CODE> and
101321  <CODE>y</CODE> are different D's.
101322*/
101323template <typename D>
101324class Parma_Polyhedra_Library::Powerset {
101325public:
101326  //! \name Constructors and Destructor
101327  //@{
101328
101329  /*! \brief
101330    Default constructor: builds the bottom of the powerset constraint
101331    system (i.e., the empty powerset).
101332  */
101333  Powerset();
101334
101335  //! Copy constructor.
101336  Powerset(const Powerset& y);
101337
101338  /*! \brief
101339    If \p d is not bottom, builds a powerset containing only \p d.
101340    Builds the empty powerset otherwise.
101341  */
101342  explicit Powerset(const D& d);
101343
101344  //! Destructor.
101345  ~Powerset();
101346
101347  //@} // Constructors and Destructor
101348
101349  //! \name Member Functions that Do Not Modify the Powerset Object
101350  //@{
101351
101352  /*! \brief
101353    Returns <CODE>true</CODE> if \p *this definitely entails \p y.
101354    Returns <CODE>false</CODE> if \p *this may not entail \p y
101355    (i.e., if \p *this does not entail \p y or if entailment could
101356    not be decided).
101357  */
101358  bool definitely_entails(const Powerset& y) const;
101359
101360  /*! \brief
101361    Returns <CODE>true</CODE> if and only if \p *this is the top
101362    element of the powerset constraint system (i.e., it represents
101363    the universe).
101364  */
101365  bool is_top() const;
101366
101367  /*! \brief
101368    Returns <CODE>true</CODE> if and only if \p *this is the bottom
101369    element of the powerset constraint system (i.e., it represents
101370    the empty set).
101371  */
101372  bool is_bottom() const;
101373
101374  /*! \brief
101375    Returns a lower bound to the total size in bytes of the memory
101376    occupied by \p *this.
101377  */
101378  memory_size_type total_memory_in_bytes() const;
101379
101380  /*! \brief
101381    Returns a lower bound to the size in bytes of the memory
101382    managed by \p *this.
101383  */
101384  memory_size_type external_memory_in_bytes() const;
101385
101386  //! Checks if all the invariants are satisfied.
101387  // FIXME: document and perhaps use an enum instead of a bool.
101388  bool OK(bool disallow_bottom = false) const;
101389
101390  //@} // Member Functions that Do Not Modify the Powerset Object
101391
101392protected:
101393  //! A powerset is implemented as a sequence of elements.
101394  /*!
101395    The particular sequence employed must support efficient deletion
101396    in any position and efficient back insertion.
101397  */
101398  typedef std::list<D> Sequence;
101399
101400  //! Alias for the low-level iterator on the disjuncts.
101401  typedef typename Sequence::iterator Sequence_iterator;
101402
101403  //! Alias for the low-level %const_iterator on the disjuncts.
101404  typedef typename Sequence::const_iterator Sequence_const_iterator;
101405
101406  //! The sequence container holding powerset's elements.
101407  Sequence sequence;
101408
101409  //! If <CODE>true</CODE>, \p *this is Omega-reduced.
101410  mutable bool reduced;
101411
101412public:
101413  // Sequence manipulation types, accessors and modifiers
101414  typedef typename Sequence::size_type size_type;
101415  typedef typename Sequence::value_type value_type;
101416
101417  /*! \brief
101418    Alias for a <EM>read-only</EM> bidirectional %iterator on the
101419    disjuncts of a Powerset element.
101420
101421    By using this iterator type, the disjuncts cannot be overwritten,
101422    but they can be removed using methods
101423    <CODE>drop_disjunct(iterator position)</CODE> and
101424    <CODE>drop_disjuncts(iterator first, iterator last)</CODE>,
101425    while still ensuring a correct handling of Omega-reduction.
101426  */
101427  typedef iterator_to_const<Sequence> iterator;
101428
101429  //! A bidirectional %const_iterator on the disjuncts of a Powerset element.
101430  typedef const_iterator_to_const<Sequence> const_iterator;
101431
101432  //! The reverse iterator type built from Powerset::iterator.
101433  typedef std::reverse_iterator<iterator> reverse_iterator;
101434
101435  //! The reverse iterator type built from Powerset::const_iterator.
101436  typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
101437
101438  //! \name Member Functions for the Direct Manipulation of Disjuncts
101439  //@{
101440
101441  /*! \brief
101442    Drops from the sequence of disjuncts in \p *this all the
101443    non-maximal elements so that \p *this is non-redundant.
101444
101445    This method is declared <CODE>const</CODE> because, even though
101446    Omega-reduction may change the syntactic representation of \p *this,
101447    its semantics will be unchanged.
101448  */
101449  void omega_reduce() const;
101450
101451  //! Returns the number of disjuncts.
101452  size_type size() const;
101453
101454  /*! \brief
101455    Returns <CODE>true</CODE> if and only if there are no disjuncts in
101456    \p *this.
101457  */
101458  bool empty() const;
101459
101460  /*! \brief
101461    Returns an iterator pointing to the first disjunct, if \p *this
101462    is not empty; otherwise, returns the past-the-end iterator.
101463  */
101464  iterator begin();
101465
101466  //! Returns the past-the-end iterator.
101467  iterator end();
101468
101469  /*! \brief
101470    Returns a const_iterator pointing to the first disjunct, if \p *this
101471    is not empty; otherwise, returns the past-the-end const_iterator.
101472  */
101473  const_iterator begin() const;
101474
101475  //! Returns the past-the-end const_iterator.
101476  const_iterator end() const;
101477
101478  /*! \brief
101479    Returns a reverse_iterator pointing to the last disjunct, if \p *this
101480    is not empty; otherwise, returns the before-the-start reverse_iterator.
101481  */
101482  reverse_iterator rbegin();
101483
101484  //! Returns the before-the-start reverse_iterator.
101485  reverse_iterator rend();
101486
101487  /*! \brief
101488    Returns a const_reverse_iterator pointing to the last disjunct,
101489    if \p *this is not empty; otherwise, returns the before-the-start
101490    const_reverse_iterator.
101491  */
101492  const_reverse_iterator rbegin() const;
101493
101494  //! Returns the before-the-start const_reverse_iterator.
101495  const_reverse_iterator rend() const;
101496
101497  //! Adds to \p *this the disjunct \p d.
101498  void add_disjunct(const D& d);
101499
101500  /*! \brief
101501    Drops the disjunct in \p *this pointed to by \p position, returning
101502    an iterator to the disjunct following \p position.
101503  */
101504  iterator drop_disjunct(iterator position);
101505
101506  //! Drops all the disjuncts from \p first to \p last (excluded).
101507  void drop_disjuncts(iterator first, iterator last);
101508
101509  //! Drops all the disjuncts, making \p *this an empty powerset.
101510  void clear();
101511
101512  //@} // Member Functions for the Direct Manipulation of Disjuncts
101513
101514  //! \name Member Functions that May Modify the Powerset Object
101515  //@{
101516
101517  //! The assignment operator.
101518  Powerset& operator=(const Powerset& y);
101519
101520  //! Swaps \p *this with \p y.
101521  void m_swap(Powerset& y);
101522
101523  //! Assigns to \p *this the least upper bound of \p *this and \p y.
101524  void least_upper_bound_assign(const Powerset& y);
101525
101526  //! Assigns to \p *this an upper bound of \p *this and \p y.
101527  /*!
101528    The result will be the least upper bound of \p *this and \p y.
101529  */
101530  void upper_bound_assign(const Powerset& y);
101531
101532  /*! \brief
101533    Assigns to \p *this the least upper bound of \p *this and \p y
101534    and returns \c true.
101535
101536    \exception std::invalid_argument
101537    Thrown if \p *this and \p y are dimension-incompatible.
101538  */
101539  bool upper_bound_assign_if_exact(const Powerset& y);
101540
101541  //! Assigns to \p *this the meet of \p *this and \p y.
101542  void meet_assign(const Powerset& y);
101543
101544  /*! \brief
101545    If \p *this is not empty (i.e., it is not the bottom element),
101546    it is reduced to a singleton obtained by computing an upper-bound
101547    of all the disjuncts.
101548  */
101549  void collapse();
101550
101551  //@} // Member Functions that May Modify the Powerset element
101552
101553protected:
101554  /*! \brief
101555    Returns <CODE>true</CODE> if and only if \p *this does not contain
101556    non-maximal elements.
101557  */
101558  bool is_omega_reduced() const;
101559
101560  /*! \brief Upon return, \p *this will contain at most \p
101561    max_disjuncts elements; the set of disjuncts in positions greater
101562    than or equal to \p max_disjuncts, will be replaced at that
101563    position by their upper-bound.
101564  */
101565  void collapse(unsigned max_disjuncts);
101566
101567  /*! \brief
101568    Adds to \p *this the disjunct \p d,
101569    assuming \p d is not the bottom element and ensuring
101570    partial Omega-reduction.
101571
101572    If \p d is not the bottom element and is not Omega-redundant with
101573    respect to elements in positions between \p first and \p last, all
101574    elements in these positions that would be made Omega-redundant by the
101575    addition of \p d are dropped and \p d is added to the reduced
101576    sequence.
101577    If \p *this is reduced before an invocation of this method,
101578    it will be reduced upon successful return from the method.
101579  */
101580  iterator add_non_bottom_disjunct_preserve_reduction(const D& d,
101581                                                      iterator first,
101582                                                      iterator last);
101583
101584  /*! \brief
101585    Adds to \p *this the disjunct \p d, assuming \p d is not the
101586    bottom element and preserving Omega-reduction.
101587
101588    If \p *this is reduced before an invocation of this method,
101589    it will be reduced upon successful return from the method.
101590  */
101591  void add_non_bottom_disjunct_preserve_reduction(const D& d);
101592
101593  /*! \brief
101594    Assigns to \p *this the result of applying \p op_assign pairwise
101595    to the elements in \p *this and \p y.
101596
101597    The elements of the powerset result are obtained by applying
101598    \p op_assign to each pair of elements whose components are drawn
101599    from \p *this and \p y, respectively.
101600  */
101601  template <typename Binary_Operator_Assign>
101602  void pairwise_apply_assign(const Powerset& y,
101603                             Binary_Operator_Assign op_assign);
101604
101605private:
101606  /*! \brief
101607    Does the hard work of checking whether \p *this contains non-maximal
101608    elements and returns <CODE>true</CODE> if and only if it does not.
101609  */
101610  bool check_omega_reduced() const;
101611
101612  /*! \brief
101613    Replaces the disjunct \p *sink by an upper bound of itself and
101614    all the disjuncts following it.
101615  */
101616  void collapse(Sequence_iterator sink);
101617};
101618
101619/* Automatically generated from PPL source file ../src/Powerset_inlines.hh line 1. */
101620/* Powerset class implementation: inline functions.
101621*/
101622
101623
101624/* Automatically generated from PPL source file ../src/Powerset_inlines.hh line 28. */
101625#include <algorithm>
101626
101627namespace Parma_Polyhedra_Library {
101628
101629template <typename D>
101630inline typename Powerset<D>::iterator
101631Powerset<D>::begin() {
101632  return sequence.begin();
101633}
101634
101635template <typename D>
101636inline typename Powerset<D>::iterator
101637Powerset<D>::end() {
101638  return sequence.end();
101639}
101640
101641template <typename D>
101642inline typename Powerset<D>::const_iterator
101643Powerset<D>::begin() const {
101644  return sequence.begin();
101645}
101646
101647template <typename D>
101648inline typename Powerset<D>::const_iterator
101649Powerset<D>::end() const {
101650  return sequence.end();
101651}
101652
101653template <typename D>
101654inline typename Powerset<D>::reverse_iterator
101655Powerset<D>::rbegin() {
101656  return reverse_iterator(end());
101657}
101658
101659template <typename D>
101660inline typename Powerset<D>::reverse_iterator
101661Powerset<D>::rend() {
101662  return reverse_iterator(begin());
101663}
101664
101665template <typename D>
101666inline typename Powerset<D>::const_reverse_iterator
101667Powerset<D>::rbegin() const {
101668  return const_reverse_iterator(end());
101669}
101670
101671template <typename D>
101672inline typename Powerset<D>::const_reverse_iterator
101673Powerset<D>::rend() const {
101674  return const_reverse_iterator(begin());
101675}
101676
101677template <typename D>
101678inline typename Powerset<D>::size_type
101679Powerset<D>::size() const {
101680  return sequence.size();
101681}
101682
101683template <typename D>
101684inline bool
101685Powerset<D>::empty() const {
101686  return sequence.empty();
101687}
101688
101689template <typename D>
101690inline typename Powerset<D>::iterator
101691Powerset<D>::drop_disjunct(iterator position) {
101692  return sequence.erase(position.base);
101693}
101694
101695template <typename D>
101696inline void
101697Powerset<D>::drop_disjuncts(iterator first, iterator last) {
101698  sequence.erase(first.base, last.base);
101699}
101700
101701template <typename D>
101702inline void
101703Powerset<D>::clear() {
101704  sequence.clear();
101705}
101706
101707template <typename D>
101708inline
101709Powerset<D>::Powerset(const Powerset& y)
101710  : sequence(y.sequence), reduced(y.reduced) {
101711}
101712
101713template <typename D>
101714inline Powerset<D>&
101715Powerset<D>::operator=(const Powerset& y) {
101716  sequence = y.sequence;
101717  reduced = y.reduced;
101718  return *this;
101719}
101720
101721template <typename D>
101722inline void
101723Powerset<D>::m_swap(Powerset& y) {
101724  std::swap(sequence, y.sequence);
101725  std::swap(reduced, y.reduced);
101726}
101727
101728template <typename D>
101729inline
101730Powerset<D>::Powerset()
101731  : sequence(), reduced(true) {
101732}
101733
101734template <typename D>
101735inline
101736Powerset<D>::Powerset(const D& d)
101737  : sequence(), reduced(false) {
101738  sequence.push_back(d);
101739  PPL_ASSERT_HEAVY(OK());
101740}
101741
101742template <typename D>
101743inline
101744Powerset<D>::~Powerset() {
101745}
101746
101747template <typename D>
101748inline void
101749Powerset<D>::add_non_bottom_disjunct_preserve_reduction(const D& d) {
101750  // !d.is_bottom() is asserted by the callee.
101751  add_non_bottom_disjunct_preserve_reduction(d, begin(), end());
101752}
101753
101754template <typename D>
101755inline void
101756Powerset<D>::add_disjunct(const D& d) {
101757  sequence.push_back(d);
101758  reduced = false;
101759}
101760
101761/*! \relates Powerset */
101762template <typename D>
101763inline
101764bool operator!=(const Powerset<D>& x, const Powerset<D>& y) {
101765  return !(x == y);
101766}
101767
101768template <typename D>
101769inline bool
101770Powerset<D>::is_top() const {
101771  // Must perform omega-reduction for correctness.
101772  omega_reduce();
101773  const_iterator xi = begin();
101774  const_iterator x_end = end();
101775  return xi != x_end && xi->is_top() && ++xi == x_end;
101776}
101777
101778template <typename D>
101779inline bool
101780Powerset<D>::is_bottom() const {
101781  // Must perform omega-reduction for correctness.
101782  omega_reduce();
101783  return empty();
101784}
101785
101786template <typename D>
101787inline void
101788Powerset<D>::collapse() {
101789  if (!empty()) {
101790    collapse(sequence.begin());
101791  }
101792}
101793
101794template <typename D>
101795inline void
101796Powerset<D>::meet_assign(const Powerset& y) {
101797  pairwise_apply_assign(y, std::mem_fun_ref(&D::meet_assign));
101798}
101799
101800template <typename D>
101801inline void
101802Powerset<D>::upper_bound_assign(const Powerset& y) {
101803  least_upper_bound_assign(y);
101804}
101805
101806template <typename D>
101807inline bool
101808Powerset<D>::upper_bound_assign_if_exact(const Powerset& y) {
101809  least_upper_bound_assign(y);
101810  return true;
101811}
101812
101813template <typename D>
101814inline memory_size_type
101815Powerset<D>::total_memory_in_bytes() const {
101816  return sizeof(*this) + external_memory_in_bytes();
101817}
101818
101819/*! \relates Powerset */
101820template <typename D>
101821inline void
101822swap(Powerset<D>& x, Powerset<D>& y) {
101823  x.m_swap(y);
101824}
101825
101826} // namespace Parma_Polyhedra_Library
101827
101828/* Automatically generated from PPL source file ../src/Powerset_templates.hh line 1. */
101829/* Powerset class implementation: non-inline template functions.
101830*/
101831
101832
101833/* Automatically generated from PPL source file ../src/Powerset_templates.hh line 29. */
101834#include <iostream>
101835#include <algorithm>
101836
101837namespace Parma_Polyhedra_Library {
101838
101839template <typename D>
101840void
101841Powerset<D>::collapse(const Sequence_iterator sink) {
101842  PPL_ASSERT(sink != sequence.end());
101843  D& d = *sink;
101844  iterator x_sink = sink;
101845  iterator next_x_sink = x_sink;
101846  ++next_x_sink;
101847  iterator x_end = end();
101848  for (const_iterator xi = next_x_sink; xi != x_end; ++xi) {
101849    d.upper_bound_assign(*xi);
101850  }
101851  // Drop the surplus disjuncts.
101852  drop_disjuncts(next_x_sink, x_end);
101853
101854  // Ensure omega-reduction.
101855  for (iterator xi = begin(); xi != x_sink; ) {
101856    if (xi->definitely_entails(d)) {
101857      xi = drop_disjunct(xi);
101858    }
101859    else {
101860      ++xi;
101861    }
101862  }
101863
101864  PPL_ASSERT_HEAVY(OK());
101865}
101866
101867template <typename D>
101868void
101869Powerset<D>::omega_reduce() const {
101870  if (reduced) {
101871    return;
101872  }
101873  Powerset& x = const_cast<Powerset&>(*this);
101874  // First remove all bottom elements.
101875  for (iterator xi = x.begin(), x_end = x.end(); xi != x_end; ) {
101876    if (xi->is_bottom()) {
101877      xi = x.drop_disjunct(xi);
101878    }
101879    else {
101880      ++xi;
101881    }
101882  }
101883  // Then remove non-maximal elements.
101884  for (iterator xi = x.begin(); xi != x.end(); ) {
101885    const D& xv = *xi;
101886    bool dropping_xi = false;
101887    for (iterator yi = x.begin(); yi != x.end(); ) {
101888      if (xi == yi) {
101889        ++yi;
101890      }
101891      else {
101892        const D& yv = *yi;
101893        if (yv.definitely_entails(xv)) {
101894          yi = x.drop_disjunct(yi);
101895        }
101896        else if (xv.definitely_entails(yv)) {
101897          dropping_xi = true;
101898          break;
101899        }
101900        else {
101901          ++yi;
101902        }
101903      }
101904    }
101905    if (dropping_xi) {
101906      xi = x.drop_disjunct(xi);
101907    }
101908    else {
101909      ++xi;
101910    }
101911    if (abandon_expensive_computations != 0 && xi != x.end()) {
101912      // Hurry up!
101913      x.collapse(xi.base);
101914      break;
101915    }
101916  }
101917  reduced = true;
101918  PPL_ASSERT_HEAVY(OK());
101919}
101920
101921template <typename D>
101922void
101923Powerset<D>::collapse(const unsigned max_disjuncts) {
101924  PPL_ASSERT(max_disjuncts > 0);
101925  // Omega-reduce before counting the number of disjuncts.
101926  omega_reduce();
101927  size_type n = size();
101928  if (n > max_disjuncts) {
101929    // Let `i' point to the last disjunct that will survive.
101930    iterator i = begin();
101931    std::advance(i, max_disjuncts-1);
101932    // This disjunct will be assigned an upper-bound of itself and of
101933    // all the disjuncts that follow.
101934    collapse(i.base);
101935  }
101936  PPL_ASSERT_HEAVY(OK());
101937  PPL_ASSERT(is_omega_reduced());
101938}
101939
101940template <typename D>
101941bool
101942Powerset<D>::check_omega_reduced() const {
101943  for (const_iterator x_begin = begin(), x_end = end(),
101944         xi = x_begin; xi != x_end; ++xi) {
101945    const D& xv = *xi;
101946    if (xv.is_bottom()) {
101947      return false;
101948    }
101949    for (const_iterator yi = x_begin; yi != x_end; ++yi) {
101950      if (xi == yi) {
101951        continue;
101952      }
101953      const D& yv = *yi;
101954      if (xv.definitely_entails(yv) || yv.definitely_entails(xv)) {
101955        return false;
101956      }
101957    }
101958  }
101959  return true;
101960}
101961
101962template <typename D>
101963bool
101964Powerset<D>::is_omega_reduced() const {
101965  if (!reduced && check_omega_reduced()) {
101966    reduced = true;
101967  }
101968  return reduced;
101969}
101970
101971template <typename D>
101972typename Powerset<D>::iterator
101973Powerset<D>::add_non_bottom_disjunct_preserve_reduction(const D& d,
101974                                                        iterator first,
101975                                                        iterator last) {
101976  PPL_ASSERT_HEAVY(!d.is_bottom());
101977  for (iterator xi = first; xi != last; ) {
101978    const D& xv = *xi;
101979    if (d.definitely_entails(xv)) {
101980      return first;
101981    }
101982    else if (xv.definitely_entails(d)) {
101983      if (xi == first) {
101984        ++first;
101985      }
101986      xi = drop_disjunct(xi);
101987    }
101988    else {
101989      ++xi;
101990    }
101991  }
101992  sequence.push_back(d);
101993  PPL_ASSERT_HEAVY(OK());
101994  return first;
101995}
101996
101997template <typename D>
101998bool
101999Powerset<D>::definitely_entails(const Powerset& y) const {
102000  const Powerset<D>& x = *this;
102001  bool found = true;
102002  for (const_iterator xi = x.begin(),
102003         x_end = x.end(); found && xi != x_end; ++xi) {
102004    found = false;
102005    for (const_iterator yi = y.begin(),
102006           y_end = y.end(); !found && yi != y_end; ++yi) {
102007      found = (*xi).definitely_entails(*yi);
102008    }
102009  }
102010  return found;
102011}
102012
102013/*! \relates Powerset */
102014template <typename D>
102015bool
102016operator==(const Powerset<D>& x, const Powerset<D>& y) {
102017  x.omega_reduce();
102018  y.omega_reduce();
102019  if (x.size() != y.size()) {
102020    return false;
102021  }
102022  // Take a copy of `y' and work with it.
102023  Powerset<D> z = y;
102024  for (typename Powerset<D>::const_iterator xi = x.begin(),
102025         x_end = x.end(); xi != x_end; ++xi) {
102026    typename Powerset<D>::iterator zi = z.begin();
102027    typename Powerset<D>::iterator z_end = z.end();
102028    zi = std::find(zi, z_end, *xi);
102029    if (zi == z_end) {
102030      return false;
102031    }
102032    else {
102033      z.drop_disjunct(zi);
102034    }
102035  }
102036  return true;
102037}
102038
102039template <typename D>
102040template <typename Binary_Operator_Assign>
102041void
102042Powerset<D>::pairwise_apply_assign(const Powerset& y,
102043                                   Binary_Operator_Assign op_assign) {
102044  // Ensure omega-reduction here, since what follows has quadratic complexity.
102045  omega_reduce();
102046  y.omega_reduce();
102047  Sequence new_sequence;
102048  for (const_iterator xi = begin(), x_end = end(),
102049         y_begin = y.begin(), y_end = y.end(); xi != x_end; ++xi) {
102050    for (const_iterator yi = y_begin; yi != y_end; ++yi) {
102051      D zi = *xi;
102052      op_assign(zi, *yi);
102053      if (!zi.is_bottom()) {
102054        new_sequence.push_back(zi);
102055      }
102056    }
102057  }
102058  // Put the new sequence in place.
102059  std::swap(sequence, new_sequence);
102060  reduced = false;
102061  PPL_ASSERT_HEAVY(OK());
102062}
102063
102064template <typename D>
102065void
102066Powerset<D>::least_upper_bound_assign(const Powerset& y) {
102067  // Ensure omega-reduction here, since what follows has quadratic complexity.
102068  omega_reduce();
102069  y.omega_reduce();
102070  iterator old_begin = begin();
102071  iterator old_end = end();
102072  for (const_iterator i = y.begin(), y_end = y.end(); i != y_end; ++i) {
102073    old_begin = add_non_bottom_disjunct_preserve_reduction(*i,
102074                                                           old_begin,
102075                                                           old_end);
102076  }
102077  PPL_ASSERT_HEAVY(OK());
102078}
102079
102080namespace IO_Operators {
102081
102082/*! \relates Parma_Polyhedra_Library::Powerset */
102083template <typename D>
102084std::ostream&
102085operator<<(std::ostream& s, const Powerset<D>& x) {
102086  if (x.is_bottom()) {
102087    s << "false";
102088  }
102089  else if (x.is_top()) {
102090    s << "true";
102091  }
102092  else {
102093    for (typename Powerset<D>::const_iterator i = x.begin(),
102094           x_end = x.end(); i != x_end; ) {
102095      s << "{ " << *i << " }";
102096      ++i;
102097      if (i != x_end) {
102098        s << ", ";
102099      }
102100    }
102101  }
102102  return s;
102103}
102104
102105} // namespace IO_Operators
102106
102107template <typename D>
102108memory_size_type
102109Powerset<D>::external_memory_in_bytes() const {
102110  memory_size_type bytes = 0;
102111  for (const_iterator xi = begin(), x_end = end(); xi != x_end; ++xi) {
102112    bytes += xi->total_memory_in_bytes();
102113    // We assume there is at least a forward and a backward link, and
102114    // that the pointers implementing them are at least the size of
102115    // pointers to `D'.
102116    bytes += 2*sizeof(D*);
102117  }
102118  return bytes;
102119}
102120
102121template <typename D>
102122bool
102123Powerset<D>::OK(const bool disallow_bottom) const {
102124  for (const_iterator xi = begin(), x_end = end(); xi != x_end; ++xi) {
102125    if (!xi->OK()) {
102126      return false;
102127    }
102128    if (disallow_bottom && xi->is_bottom()) {
102129#ifndef NDEBUG
102130      std::cerr << "Bottom element in powerset!"
102131                << std::endl;
102132#endif
102133      return false;
102134    }
102135  }
102136  if (reduced && !check_omega_reduced()) {
102137#ifndef NDEBUG
102138    std::cerr << "Powerset claims to be reduced, but it is not!"
102139              << std::endl;
102140#endif
102141    return false;
102142  }
102143  return true;
102144}
102145
102146} // namespace Parma_Polyhedra_Library
102147
102148/* Automatically generated from PPL source file ../src/Powerset_defs.hh line 449. */
102149
102150/* Automatically generated from PPL source file ../src/Pointset_Powerset_defs.hh line 44. */
102151#include <iosfwd>
102152#include <list>
102153#include <map>
102154
102155//! The powerset construction instantiated on PPL pointset domains.
102156/*! \ingroup PPL_CXX_interface
102157  \warning
102158  At present, the supported instantiations for the
102159  disjunct domain template \p PSET are the simple pointset domains:
102160  <CODE>C_Polyhedron</CODE>,
102161  <CODE>NNC_Polyhedron</CODE>,
102162  <CODE>Grid</CODE>,
102163  <CODE>Octagonal_Shape\<T\></CODE>,
102164  <CODE>BD_Shape\<T\></CODE>,
102165  <CODE>Box\<T\></CODE>.
102166*/
102167template <typename PSET>
102168class Parma_Polyhedra_Library::Pointset_Powerset
102169  : public Parma_Polyhedra_Library::Powerset
102170<Parma_Polyhedra_Library::Determinate<PSET> > {
102171public:
102172  typedef PSET element_type;
102173
102174private:
102175  typedef Determinate<PSET> Det_PSET;
102176  typedef Powerset<Det_PSET> Base;
102177
102178public:
102179  //! Returns the maximum space dimension a Pointset_Powerset<PSET> can handle.
102180  static dimension_type max_space_dimension();
102181
102182  //! \name Constructors
102183  //@{
102184
102185  //! Builds a universe (top) or empty (bottom) Pointset_Powerset.
102186  /*!
102187    \param num_dimensions
102188    The number of dimensions of the vector space enclosing the powerset;
102189
102190    \param kind
102191    Specifies whether the universe or the empty powerset has to be built.
102192  */
102193  explicit
102194  Pointset_Powerset(dimension_type num_dimensions = 0,
102195                    Degenerate_Element kind = UNIVERSE);
102196
102197  //! Ordinary copy constructor.
102198  /*!
102199    The complexity argument is ignored.
102200  */
102201  Pointset_Powerset(const Pointset_Powerset& y,
102202                    Complexity_Class complexity = ANY_COMPLEXITY);
102203
102204  /*! \brief
102205    Conversion constructor: the type <CODE>QH</CODE> of the disjuncts
102206    in the source powerset is different from <CODE>PSET</CODE>.
102207
102208    \param y
102209    The powerset to be used to build the new powerset.
102210
102211    \param complexity
102212    The maximal complexity of any algorithms used.
102213  */
102214  template <typename QH>
102215  explicit Pointset_Powerset(const Pointset_Powerset<QH>& y,
102216                             Complexity_Class complexity = ANY_COMPLEXITY);
102217
102218  /*! \brief
102219    Creates a Pointset_Powerset from a product
102220    This will be created as a single disjunct of type PSET that
102221    approximates the product.
102222  */
102223  template <typename QH1, typename QH2, typename R>
102224  explicit
102225  Pointset_Powerset(const Partially_Reduced_Product<QH1, QH2, R>& prp,
102226                    Complexity_Class complexity = ANY_COMPLEXITY);
102227
102228  /*! \brief
102229    Creates a Pointset_Powerset with a single disjunct approximating
102230    the system of constraints \p cs.
102231  */
102232  explicit Pointset_Powerset(const Constraint_System& cs);
102233
102234  /*! \brief
102235    Creates a Pointset_Powerset with a single disjunct approximating
102236    the system of congruences \p cgs.
102237  */
102238  explicit Pointset_Powerset(const Congruence_System& cgs);
102239
102240
102241  //! Builds a pointset_powerset out of a closed polyhedron.
102242  /*!
102243    Builds a powerset that is either empty (if the polyhedron is found
102244    to be empty) or contains a single disjunct approximating the
102245    polyhedron; this must only use algorithms that do not exceed the
102246    specified complexity.  The powerset inherits the space dimension
102247    of the polyhedron.
102248
102249    \param ph
102250    The closed polyhedron to be used to build the powerset.
102251
102252    \param complexity
102253    The maximal complexity of any algorithms used.
102254
102255    \exception std::length_error
102256    Thrown if the space dimension of \p ph exceeds the maximum
102257    allowed space dimension.
102258  */
102259  explicit Pointset_Powerset(const C_Polyhedron& ph,
102260                             Complexity_Class complexity = ANY_COMPLEXITY);
102261
102262  //! Builds a pointset_powerset out of an nnc polyhedron.
102263  /*!
102264    Builds a powerset that is either empty (if the polyhedron is found
102265    to be empty) or contains a single disjunct approximating the
102266    polyhedron; this must only use algorithms that do not exceed the
102267    specified complexity.  The powerset inherits the space dimension
102268    of the polyhedron.
102269
102270    \param ph
102271    The closed polyhedron to be used to build the powerset.
102272
102273    \param complexity
102274    The maximal complexity of any algorithms used.
102275
102276    \exception std::length_error
102277    Thrown if the space dimension of \p ph exceeds the maximum
102278    allowed space dimension.
102279  */
102280  explicit Pointset_Powerset(const NNC_Polyhedron& ph,
102281                             Complexity_Class complexity = ANY_COMPLEXITY);
102282
102283
102284  //! Builds a pointset_powerset out of a grid.
102285  /*!
102286    If the grid is nonempty, builds a powerset containing a single
102287    disjunct approximating the grid. Builds the empty powerset
102288    otherwise. The powerset inherits the space dimension of the grid.
102289
102290    \param gr
102291    The grid to be used to build the powerset.
102292
102293    \param complexity
102294    This argument is ignored.
102295
102296    \exception std::length_error
102297    Thrown if the space dimension of \p gr exceeds the maximum
102298    allowed space dimension.
102299  */
102300  explicit Pointset_Powerset(const Grid& gr,
102301                             Complexity_Class complexity = ANY_COMPLEXITY);
102302
102303  //! Builds a pointset_powerset out of an octagonal shape.
102304  /*!
102305    If the octagonal shape is nonempty, builds a powerset
102306    containing a single disjunct approximating the octagonal
102307    shape. Builds the empty powerset otherwise. The powerset
102308    inherits the space dimension of the octagonal shape.
102309
102310    \param os
102311    The octagonal shape to be used to build the powerset.
102312
102313    \param complexity
102314    This argument is ignored.
102315
102316    \exception std::length_error
102317    Thrown if the space dimension of \p os exceeds the maximum
102318    allowed space dimension.
102319  */
102320  template <typename T>
102321  explicit Pointset_Powerset(const Octagonal_Shape<T>& os,
102322                             Complexity_Class complexity = ANY_COMPLEXITY);
102323
102324  //! Builds a pointset_powerset out of a bd shape.
102325  /*!
102326    If the bd shape is nonempty, builds a powerset containing a
102327    single disjunct approximating the bd shape. Builds the empty
102328    powerset otherwise.  The powerset inherits the space dimension
102329    of the bd shape.
102330
102331    \param bds
102332    The bd shape to be used to build the powerset.
102333
102334    \param complexity
102335    This argument is ignored.
102336
102337    \exception std::length_error
102338    Thrown if the space dimension of \p bds exceeds the maximum
102339    allowed space dimension.
102340  */
102341  template <typename T>
102342  explicit Pointset_Powerset(const BD_Shape<T>& bds,
102343                             Complexity_Class complexity = ANY_COMPLEXITY);
102344
102345  //! Builds a pointset_powerset out of a box.
102346  /*!
102347    If the box is nonempty, builds a powerset containing a single
102348    disjunct approximating the box. Builds the empty powerset
102349    otherwise.  The powerset inherits the space dimension of the box.
102350
102351    \param box
102352    The box to be used to build the powerset.
102353
102354    \param complexity
102355    This argument is ignored.
102356
102357    \exception std::length_error
102358    Thrown if the space dimension of \p box exceeds the maximum
102359    allowed space dimension.
102360  */
102361  template <typename Interval>
102362  explicit Pointset_Powerset(const Box<Interval>& box,
102363                             Complexity_Class complexity = ANY_COMPLEXITY);
102364
102365  //@} // Constructors and Destructor
102366
102367  //! \name Member Functions that Do Not Modify the Pointset_Powerset
102368  //@{
102369
102370  //! Returns the dimension of the vector space enclosing \p *this.
102371  dimension_type space_dimension() const;
102372
102373  //! Returns the dimension of the vector space enclosing \p *this.
102374  dimension_type affine_dimension() const;
102375
102376  /*! \brief
102377    Returns <CODE>true</CODE> if and only if \p *this is
102378    an empty powerset.
102379  */
102380  bool is_empty() const;
102381
102382  /*! \brief
102383    Returns <CODE>true</CODE> if and only if \p *this
102384    is the top element of the powerset lattice.
102385  */
102386  bool is_universe() const;
102387
102388  /*! \brief
102389    Returns <CODE>true</CODE> if and only if all the disjuncts
102390    in \p *this are topologically closed.
102391  */
102392  bool is_topologically_closed() const;
102393
102394  /*! \brief
102395    Returns <CODE>true</CODE> if and only if all elements in \p *this
102396    are bounded.
102397  */
102398  bool is_bounded() const;
102399
102400  //! Returns <CODE>true</CODE> if and only if \p *this and \p y are disjoint.
102401  /*!
102402    \exception std::invalid_argument
102403    Thrown if \p x and \p y are topology-incompatible or
102404    dimension-incompatible.
102405  */
102406  bool is_disjoint_from(const Pointset_Powerset& y) const;
102407
102408  //! Returns <CODE>true</CODE> if and only if \p *this is discrete.
102409  bool is_discrete() const;
102410
102411  /*! \brief
102412    Returns <CODE>true</CODE> if and only if \p var is constrained in
102413    \p *this.
102414
102415    \exception std::invalid_argument
102416    Thrown if \p var is not a space dimension of \p *this.
102417
102418    \note
102419    A variable is constrained if there exists a non-redundant disjunct
102420    that is constraining the variable: this definition relies on the
102421    powerset lattice structure and may be somewhat different from the
102422    geometric intuition.
102423    For instance, variable \f$x\f$ is constrained in the powerset
102424    \f[
102425      \mathit{ps} = \bigl\{ \{ x \geq 0 \}, \{ x \leq 0 \} \bigr\},
102426    \f]
102427    even though \f$\mathit{ps}\f$ is geometrically equal to the
102428    whole vector space.
102429  */
102430  bool constrains(Variable var) const;
102431
102432  /*! \brief
102433    Returns <CODE>true</CODE> if and only if \p expr is
102434    bounded from above in \p *this.
102435
102436    \exception std::invalid_argument
102437    Thrown if \p expr and \p *this are dimension-incompatible.
102438  */
102439  bool bounds_from_above(const Linear_Expression& expr) const;
102440
102441  /*! \brief
102442    Returns <CODE>true</CODE> if and only if \p expr is
102443    bounded from below in \p *this.
102444
102445    \exception std::invalid_argument
102446    Thrown if \p expr and \p *this are dimension-incompatible.
102447  */
102448  bool bounds_from_below(const Linear_Expression& expr) const;
102449
102450  /*! \brief
102451    Returns <CODE>true</CODE> if and only if \p *this is not empty
102452    and \p expr is bounded from above in \p *this, in which case
102453    the supremum value is computed.
102454
102455    \param expr
102456    The linear expression to be maximized subject to \p *this;
102457
102458    \param sup_n
102459    The numerator of the supremum value;
102460
102461    \param sup_d
102462    The denominator of the supremum value;
102463
102464    \param maximum
102465    <CODE>true</CODE> if and only if the supremum is also the maximum value.
102466
102467    \exception std::invalid_argument
102468    Thrown if \p expr and \p *this are dimension-incompatible.
102469
102470    If \p *this is empty or \p expr is not bounded from above,
102471    <CODE>false</CODE> is returned and \p sup_n, \p sup_d
102472    and \p maximum are left untouched.
102473  */
102474  bool maximize(const Linear_Expression& expr,
102475                Coefficient& sup_n, Coefficient& sup_d, bool& maximum) const;
102476
102477  /*! \brief
102478    Returns <CODE>true</CODE> if and only if \p *this is not empty
102479    and \p expr is bounded from above in \p *this, in which case
102480    the supremum value and a point where \p expr reaches it are computed.
102481
102482    \param expr
102483    The linear expression to be maximized subject to \p *this;
102484
102485    \param sup_n
102486    The numerator of the supremum value;
102487
102488    \param sup_d
102489    The denominator of the supremum value;
102490
102491    \param maximum
102492    <CODE>true</CODE> if and only if the supremum is also the maximum value;
102493
102494    \param g
102495    When maximization succeeds, will be assigned the point or
102496    closure point where \p expr reaches its supremum value.
102497
102498    \exception std::invalid_argument
102499    Thrown if \p expr and \p *this are dimension-incompatible.
102500
102501    If \p *this is empty or \p expr is not bounded from above,
102502    <CODE>false</CODE> is returned and \p sup_n, \p sup_d, \p maximum
102503    and \p g are left untouched.
102504  */
102505  bool maximize(const Linear_Expression& expr,
102506                Coefficient& sup_n, Coefficient& sup_d, bool& maximum,
102507                Generator& g) const;
102508
102509  /*! \brief
102510    Returns <CODE>true</CODE> if and only if \p *this is not empty
102511    and \p expr is bounded from below in \p *this, in which case
102512    the infimum value is computed.
102513
102514    \param expr
102515    The linear expression to be minimized subject to \p *this;
102516
102517    \param inf_n
102518    The numerator of the infimum value;
102519
102520    \param inf_d
102521    The denominator of the infimum value;
102522
102523    \param minimum
102524    <CODE>true</CODE> if and only if the infimum is also the minimum value.
102525
102526    \exception std::invalid_argument
102527    Thrown if \p expr and \p *this are dimension-incompatible.
102528
102529    If \p *this is empty or \p expr is not bounded from below,
102530    <CODE>false</CODE> is returned and \p inf_n, \p inf_d
102531    and \p minimum are left untouched.
102532  */
102533  bool minimize(const Linear_Expression& expr,
102534                Coefficient& inf_n, Coefficient& inf_d, bool& minimum) const;
102535
102536
102537  /*! \brief
102538    Returns <CODE>true</CODE> if and only if \p *this is not empty
102539    and \p expr is bounded from below in \p *this, in which case
102540    the infimum value and a point where \p expr reaches it are computed.
102541
102542    \param expr
102543    The linear expression to be minimized subject to \p *this;
102544
102545    \param inf_n
102546    The numerator of the infimum value;
102547
102548    \param inf_d
102549    The denominator of the infimum value;
102550
102551    \param minimum
102552    <CODE>true</CODE> if and only if the infimum is also the minimum value;
102553
102554    \param g
102555    When minimization succeeds, will be assigned a point or
102556    closure point where \p expr reaches its infimum value.
102557
102558    \exception std::invalid_argument
102559    Thrown if \p expr and \p *this are dimension-incompatible.
102560
102561    If \p *this is empty or \p expr is not bounded from below,
102562    <CODE>false</CODE> is returned and \p inf_n, \p inf_d, \p minimum
102563    and \p g are left untouched.
102564  */
102565  bool minimize(const Linear_Expression& expr,
102566                Coefficient& inf_n, Coefficient& inf_d, bool& minimum,
102567                Generator& g) const;
102568
102569  /*! \brief
102570    Returns <CODE>true</CODE> if and only if \p *this geometrically
102571    covers \p y, i.e., if any point (in some element) of \p y is also
102572    a point (of some element) of \p *this.
102573
102574    \exception std::invalid_argument
102575    Thrown if \p *this and \p y are dimension-incompatible.
102576
102577    \warning
102578    This may be <EM>really</EM> expensive!
102579  */
102580  bool geometrically_covers(const Pointset_Powerset& y) const;
102581
102582  /*! \brief
102583    Returns <CODE>true</CODE> if and only if \p *this is geometrically
102584    equal to \p y, i.e., if (the elements of) \p *this and \p y
102585    contain the same set of points.
102586
102587    \exception std::invalid_argument
102588    Thrown if \p *this and \p y are dimension-incompatible.
102589
102590    \warning
102591    This may be <EM>really</EM> expensive!
102592  */
102593  bool geometrically_equals(const Pointset_Powerset& y) const;
102594
102595  /*! \brief
102596    Returns <CODE>true</CODE> if and only if each disjunct
102597      of \p y is contained in a disjunct of \p *this.
102598
102599    \exception std::invalid_argument
102600    Thrown if \p *this and \p y are topology-incompatible or
102601    dimension-incompatible.
102602  */
102603  bool contains(const Pointset_Powerset& y) const;
102604
102605  /*! \brief
102606    Returns <CODE>true</CODE> if and only if each disjunct
102607      of \p y is strictly contained in a disjunct of \p *this.
102608
102609    \exception std::invalid_argument
102610    Thrown if \p *this and \p y are topology-incompatible or
102611    dimension-incompatible.
102612  */
102613  bool strictly_contains(const Pointset_Powerset& y) const;
102614
102615  /*! \brief
102616    Returns <CODE>true</CODE> if and only if \p *this
102617    contains at least one integer point.
102618  */
102619  bool contains_integer_point() const;
102620
102621  /*! \brief
102622    Returns the relations holding between the powerset \p *this
102623    and the constraint \p c.
102624
102625    \exception std::invalid_argument
102626    Thrown if \p *this and constraint \p c are dimension-incompatible.
102627  */
102628  Poly_Con_Relation relation_with(const Constraint& c) const;
102629
102630  /*! \brief
102631    Returns the relations holding between the powerset \p *this
102632    and the generator \p g.
102633
102634    \exception std::invalid_argument
102635    Thrown if \p *this and generator \p g are dimension-incompatible.
102636  */
102637  Poly_Gen_Relation relation_with(const Generator& g) const;
102638
102639  /*! \brief
102640    Returns the relations holding between the powerset \p *this
102641    and the congruence \p c.
102642
102643    \exception std::invalid_argument
102644    Thrown if \p *this and congruence \p c are dimension-incompatible.
102645  */
102646  Poly_Con_Relation relation_with(const Congruence& cg) const;
102647
102648  /*! \brief
102649    Returns a lower bound to the total size in bytes of the memory
102650    occupied by \p *this.
102651  */
102652  memory_size_type total_memory_in_bytes() const;
102653
102654  /*! \brief
102655    Returns a lower bound to the size in bytes of the memory
102656    managed by \p *this.
102657  */
102658  memory_size_type external_memory_in_bytes() const;
102659
102660  /*! \brief
102661    Returns a 32-bit hash code for \p *this.
102662
102663    If \p x and \p y are such that <CODE>x == y</CODE>,
102664    then <CODE>x.hash_code() == y.hash_code()</CODE>.
102665  */
102666  int32_t hash_code() const;
102667
102668  //! Checks if all the invariants are satisfied.
102669  bool OK() const;
102670
102671  //@} // Member Functions that Do Not Modify the Pointset_Powerset
102672
102673  //! \name Space Dimension Preserving Member Functions that May Modify the Pointset_Powerset
102674  //@{
102675
102676  //! Adds to \p *this the disjunct \p ph.
102677  /*!
102678    \exception std::invalid_argument
102679    Thrown if \p *this and \p ph are dimension-incompatible.
102680  */
102681  void add_disjunct(const PSET& ph);
102682
102683  //! Intersects \p *this with constraint \p c.
102684  /*!
102685    \exception std::invalid_argument
102686    Thrown if \p *this and constraint \p c are topology-incompatible
102687    or dimension-incompatible.
102688  */
102689  void add_constraint(const Constraint& c);
102690
102691  /*! \brief
102692    Use the constraint \p c to refine \p *this.
102693
102694    \param c
102695    The constraint to be used for refinement.
102696
102697    \exception std::invalid_argument
102698    Thrown if \p *this and \p c are dimension-incompatible.
102699  */
102700  void refine_with_constraint(const Constraint& c);
102701
102702  //! Intersects \p *this with the constraints in \p cs.
102703  /*!
102704    \param cs
102705    The constraints to intersect with.
102706
102707    \exception std::invalid_argument
102708    Thrown if \p *this and \p cs are topology-incompatible or
102709    dimension-incompatible.
102710  */
102711  void add_constraints(const Constraint_System& cs);
102712
102713  /*! \brief
102714    Use the constraints in \p cs to refine \p *this.
102715
102716    \param  cs
102717     The constraints to be used for refinement.
102718
102719     \exception std::invalid_argument
102720     Thrown if \p *this and \p cs are dimension-incompatible.
102721  */
102722  void refine_with_constraints(const Constraint_System& cs);
102723
102724  //! Intersects \p *this with congruence \p cg.
102725  /*!
102726    \exception std::invalid_argument
102727    Thrown if \p *this and congruence \p cg are topology-incompatible
102728    or dimension-incompatible.
102729  */
102730  void add_congruence(const Congruence& cg);
102731
102732  /*! \brief
102733    Use the congruence \p cg to refine \p *this.
102734
102735    \param cg
102736    The congruence to be used for refinement.
102737
102738    \exception std::invalid_argument
102739    Thrown if \p *this and \p cg are dimension-incompatible.
102740  */
102741  void refine_with_congruence(const Congruence& cg);
102742
102743  //! Intersects \p *this with the congruences in \p cgs.
102744  /*!
102745    \param cgs
102746    The congruences to intersect with.
102747
102748    \exception std::invalid_argument
102749    Thrown if \p *this and \p cgs are topology-incompatible or
102750    dimension-incompatible.
102751  */
102752  void add_congruences(const Congruence_System& cgs);
102753
102754  /*! \brief
102755    Use the congruences in \p cgs to refine \p *this.
102756
102757    \param  cgs
102758    The congruences to be used for refinement.
102759
102760    \exception std::invalid_argument
102761    Thrown if \p *this and \p cgs are dimension-incompatible.
102762  */
102763  void refine_with_congruences(const Congruence_System& cgs);
102764
102765  /*! \brief
102766    Computes the \ref Cylindrification "cylindrification" of \p *this with
102767    respect to space dimension \p var, assigning the result to \p *this.
102768
102769    \param var
102770    The space dimension that will be unconstrained.
102771
102772    \exception std::invalid_argument
102773    Thrown if \p var is not a space dimension of \p *this.
102774  */
102775  void unconstrain(Variable var);
102776
102777  /*! \brief
102778    Computes the \ref Cylindrification "cylindrification" of \p *this with
102779    respect to the set of space dimensions \p vars,
102780    assigning the result to \p *this.
102781
102782    \param vars
102783    The set of space dimension that will be unconstrained.
102784
102785    \exception std::invalid_argument
102786    Thrown if \p *this is dimension-incompatible with one of the
102787    Variable objects contained in \p vars.
102788  */
102789  void unconstrain(const Variables_Set& vars);
102790
102791  /*! \brief
102792    Possibly tightens \p *this by dropping some points with non-integer
102793    coordinates.
102794
102795    \param complexity
102796    The maximal complexity of any algorithms used.
102797
102798    \note
102799    Currently there is no optimality guarantee, not even if
102800    \p complexity is <CODE>ANY_COMPLEXITY</CODE>.
102801  */
102802  void drop_some_non_integer_points(Complexity_Class complexity
102803                                    = ANY_COMPLEXITY);
102804
102805  /*! \brief
102806    Possibly tightens \p *this by dropping some points with non-integer
102807    coordinates for the space dimensions corresponding to \p vars.
102808
102809    \param vars
102810    Points with non-integer coordinates for these variables/space-dimensions
102811    can be discarded.
102812
102813    \param complexity
102814    The maximal complexity of any algorithms used.
102815
102816    \note
102817    Currently there is no optimality guarantee, not even if
102818    \p complexity is <CODE>ANY_COMPLEXITY</CODE>.
102819  */
102820  void drop_some_non_integer_points(const Variables_Set& vars,
102821                                    Complexity_Class complexity
102822                                    = ANY_COMPLEXITY);
102823
102824  //! Assigns to \p *this its topological closure.
102825  void topological_closure_assign();
102826
102827  //! Assigns to \p *this the intersection of \p *this and \p y.
102828  /*!
102829    The result is obtained by intersecting each disjunct in \p *this
102830    with each disjunct in \p y and collecting all these intersections.
102831  */
102832  void intersection_assign(const Pointset_Powerset& y);
102833
102834  /*! \brief
102835    Assigns to \p *this an (a smallest)
102836    over-approximation as a powerset of the disjunct domain of the
102837    set-theoretical difference of \p *this and \p y.
102838
102839    \exception std::invalid_argument
102840    Thrown if \p *this and \p y are dimension-incompatible.
102841  */
102842  void difference_assign(const Pointset_Powerset& y);
102843
102844  /*! \brief
102845    Assigns to \p *this a \ref Powerset_Meet_Preserving_Simplification
102846    "meet-preserving simplification" of \p *this with respect to \p y.
102847    If \c false is returned, then the intersection is empty.
102848
102849    \exception std::invalid_argument
102850    Thrown if \p *this and \p y are topology-incompatible or
102851    dimension-incompatible.
102852  */
102853  bool simplify_using_context_assign(const Pointset_Powerset& y);
102854
102855  /*! \brief
102856    Assigns to \p *this the
102857    \ref Single_Update_Affine_Functions "affine image"
102858    of \p *this under the function mapping variable \p var to the
102859    affine expression specified by \p expr and \p denominator.
102860
102861    \param var
102862    The variable to which the affine expression is assigned;
102863
102864    \param expr
102865    The numerator of the affine expression;
102866
102867    \param denominator
102868    The denominator of the affine expression (optional argument with
102869    default value 1).
102870
102871    \exception std::invalid_argument
102872    Thrown if \p denominator is zero or if \p expr and \p *this are
102873    dimension-incompatible or if \p var is not a space dimension of
102874    \p *this.
102875  */
102876  void affine_image(Variable var,
102877                    const Linear_Expression& expr,
102878                    Coefficient_traits::const_reference denominator
102879                      = Coefficient_one());
102880
102881  /*! \brief
102882    Assigns to \p *this the
102883    \ref Single_Update_Affine_Functions "affine preimage"
102884    of \p *this under the function mapping variable \p var to the
102885    affine expression specified by \p expr and \p denominator.
102886
102887    \param var
102888    The variable to which the affine expression is assigned;
102889
102890    \param expr
102891    The numerator of the affine expression;
102892
102893    \param denominator
102894    The denominator of the affine expression (optional argument with
102895    default value 1).
102896
102897    \exception std::invalid_argument
102898    Thrown if \p denominator is zero or if \p expr and \p *this are
102899    dimension-incompatible or if \p var is not a space dimension of
102900    \p *this.
102901  */
102902  void affine_preimage(Variable var,
102903                    const Linear_Expression& expr,
102904                    Coefficient_traits::const_reference denominator
102905                      = Coefficient_one());
102906
102907  /*! \brief
102908    Assigns to \p *this the image of \p *this with respect to the
102909    \ref Generalized_Affine_Relations "generalized affine relation"
102910    \f$\mathrm{var}' \relsym \frac{\mathrm{expr}}{\mathrm{denominator}}\f$,
102911    where \f$\mathord{\relsym}\f$ is the relation symbol encoded
102912    by \p relsym.
102913
102914    \param var
102915    The left hand side variable of the generalized affine relation;
102916
102917    \param relsym
102918    The relation symbol;
102919
102920    \param expr
102921    The numerator of the right hand side affine expression;
102922
102923    \param denominator
102924    The denominator of the right hand side affine expression (optional
102925    argument with default value 1).
102926
102927    \exception std::invalid_argument
102928    Thrown if \p denominator is zero or if \p expr and \p *this are
102929    dimension-incompatible or if \p var is not a space dimension of \p *this
102930    or if \p *this is a C_Polyhedron and \p relsym is a strict
102931    relation symbol.
102932  */
102933  void generalized_affine_image(Variable var,
102934                                Relation_Symbol relsym,
102935                                const Linear_Expression& expr,
102936                                Coefficient_traits::const_reference denominator
102937                                  = Coefficient_one());
102938
102939  /*! \brief
102940    Assigns to \p *this the preimage of \p *this with respect to the
102941    \ref Generalized_Affine_Relations "generalized affine relation"
102942    \f$\mathrm{var}' \relsym \frac{\mathrm{expr}}{\mathrm{denominator}}\f$,
102943    where \f$\mathord{\relsym}\f$ is the relation symbol encoded
102944    by \p relsym.
102945
102946    \param var
102947    The left hand side variable of the generalized affine relation;
102948
102949    \param relsym
102950    The relation symbol;
102951
102952    \param expr
102953    The numerator of the right hand side affine expression;
102954
102955    \param denominator
102956    The denominator of the right hand side affine expression (optional
102957    argument with default value 1).
102958
102959    \exception std::invalid_argument
102960    Thrown if \p denominator is zero or if \p expr and \p *this are
102961    dimension-incompatible or if \p var is not a space dimension of \p *this
102962    or if \p *this is a C_Polyhedron and \p relsym is a strict
102963    relation symbol.
102964  */
102965  void
102966  generalized_affine_preimage(Variable var,
102967                              Relation_Symbol relsym,
102968                              const Linear_Expression& expr,
102969                              Coefficient_traits::const_reference denominator
102970                              = Coefficient_one());
102971
102972  /*! \brief
102973    Assigns to \p *this the image of \p *this with respect to the
102974    \ref Generalized_Affine_Relations "generalized affine relation"
102975    \f$\mathrm{lhs}' \relsym \mathrm{rhs}\f$, where
102976    \f$\mathord{\relsym}\f$ is the relation symbol encoded by \p relsym.
102977
102978    \param lhs
102979    The left hand side affine expression;
102980
102981    \param relsym
102982    The relation symbol;
102983
102984    \param rhs
102985    The right hand side affine expression.
102986
102987    \exception std::invalid_argument
102988    Thrown if \p *this is dimension-incompatible with \p lhs or \p rhs
102989    or if \p *this is a C_Polyhedron and \p relsym is a strict
102990    relation symbol.
102991  */
102992  void generalized_affine_image(const Linear_Expression& lhs,
102993                                Relation_Symbol relsym,
102994                                const Linear_Expression& rhs);
102995
102996  /*! \brief
102997    Assigns to \p *this the preimage of \p *this with respect to the
102998    \ref Generalized_Affine_Relations "generalized affine relation"
102999    \f$\mathrm{lhs}' \relsym \mathrm{rhs}\f$, where
103000    \f$\mathord{\relsym}\f$ is the relation symbol encoded by \p relsym.
103001
103002    \param lhs
103003    The left hand side affine expression;
103004
103005    \param relsym
103006    The relation symbol;
103007
103008    \param rhs
103009    The right hand side affine expression.
103010
103011    \exception std::invalid_argument
103012    Thrown if \p *this is dimension-incompatible with \p lhs or \p rhs
103013    or if \p *this is a C_Polyhedron and \p relsym is a strict
103014    relation symbol.
103015  */
103016  void generalized_affine_preimage(const Linear_Expression& lhs,
103017                                   Relation_Symbol relsym,
103018                                   const Linear_Expression& rhs);
103019
103020  /*!
103021    \brief
103022    Assigns to \p *this the image of \p *this with respect to the
103023    \ref Single_Update_Bounded_Affine_Relations "bounded affine relation"
103024    \f$\frac{\mathrm{lb\_expr}}{\mathrm{denominator}}
103025         \leq \mathrm{var}'
103026           \leq \frac{\mathrm{ub\_expr}}{\mathrm{denominator}}\f$.
103027
103028    \param var
103029    The variable updated by the affine relation;
103030
103031    \param lb_expr
103032    The numerator of the lower bounding affine expression;
103033
103034    \param ub_expr
103035    The numerator of the upper bounding affine expression;
103036
103037    \param denominator
103038    The (common) denominator for the lower and upper bounding
103039    affine expressions (optional argument with default value 1).
103040
103041    \exception std::invalid_argument
103042    Thrown if \p denominator is zero or if \p lb_expr (resp., \p ub_expr)
103043    and \p *this are dimension-incompatible or if \p var is not a space
103044    dimension of \p *this.
103045  */
103046  void bounded_affine_image(Variable var,
103047                            const Linear_Expression& lb_expr,
103048                            const Linear_Expression& ub_expr,
103049                            Coefficient_traits::const_reference denominator
103050                            = Coefficient_one());
103051
103052  /*!
103053    \brief
103054    Assigns to \p *this the preimage of \p *this with respect to the
103055    \ref Single_Update_Bounded_Affine_Relations "bounded affine relation"
103056    \f$\frac{\mathrm{lb\_expr}}{\mathrm{denominator}}
103057         \leq \mathrm{var}'
103058           \leq \frac{\mathrm{ub\_expr}}{\mathrm{denominator}}\f$.
103059
103060    \param var
103061    The variable updated by the affine relation;
103062
103063    \param lb_expr
103064    The numerator of the lower bounding affine expression;
103065
103066    \param ub_expr
103067    The numerator of the upper bounding affine expression;
103068
103069    \param denominator
103070    The (common) denominator for the lower and upper bounding
103071    affine expressions (optional argument with default value 1).
103072
103073    \exception std::invalid_argument
103074    Thrown if \p denominator is zero or if \p lb_expr (resp., \p ub_expr)
103075    and \p *this are dimension-incompatible or if \p var is not a space
103076    dimension of \p *this.
103077  */
103078  void bounded_affine_preimage(Variable var,
103079                               const Linear_Expression& lb_expr,
103080                               const Linear_Expression& ub_expr,
103081                               Coefficient_traits::const_reference denominator
103082                               = Coefficient_one());
103083
103084  /*! \brief
103085    Assigns to \p *this the result of computing the
103086    \ref Time_Elapse_Operator "time-elapse" between \p *this and \p y.
103087
103088    The result is obtained by computing the pairwise
103089    \ref Time_Elapse_Operator "time elapse" of each disjunct
103090    in \p *this with each disjunct in \p y.
103091  */
103092  void time_elapse_assign(const Pointset_Powerset& y);
103093
103094  /*! \brief
103095    \ref Wrapping_Operator "Wraps" the specified dimensions of the
103096    vector space.
103097
103098    \param vars
103099    The set of Variable objects corresponding to the space dimensions
103100    to be wrapped.
103101
103102    \param w
103103    The width of the bounded integer type corresponding to
103104    all the dimensions to be wrapped.
103105
103106    \param r
103107    The representation of the bounded integer type corresponding to
103108    all the dimensions to be wrapped.
103109
103110    \param o
103111    The overflow behavior of the bounded integer type corresponding to
103112    all the dimensions to be wrapped.
103113
103114    \param cs_p
103115    Possibly null pointer to a constraint system whose variables
103116    are contained in \p vars.  If <CODE>*cs_p</CODE> depends on
103117    variables not in \p vars, the behavior is undefined.
103118    When non-null, the pointed-to constraint system is assumed to
103119    represent the conditional or looping construct guard with respect
103120    to which wrapping is performed.  Since wrapping requires the
103121    computation of upper bounds and due to non-distributivity of
103122    constraint refinement over upper bounds, passing a constraint
103123    system in this way can be more precise than refining the result of
103124    the wrapping operation with the constraints in <CODE>*cs_p</CODE>.
103125
103126    \param complexity_threshold
103127    A precision parameter of the \ref Wrapping_Operator "wrapping operator":
103128    higher values result in possibly improved precision.
103129
103130    \param wrap_individually
103131    <CODE>true</CODE> if the dimensions should be wrapped individually
103132    (something that results in much greater efficiency to the detriment of
103133    precision).
103134
103135    \exception std::invalid_argument
103136    Thrown if <CODE>*cs_p</CODE> is dimension-incompatible with
103137    \p vars, or if \p *this is dimension-incompatible \p vars or with
103138    <CODE>*cs_p</CODE>.
103139  */
103140  void wrap_assign(const Variables_Set& vars,
103141                   Bounded_Integer_Type_Width w,
103142                   Bounded_Integer_Type_Representation r,
103143                   Bounded_Integer_Type_Overflow o,
103144                   const Constraint_System* cs_p = 0,
103145                   unsigned complexity_threshold = 16,
103146                   bool wrap_individually = true);
103147
103148  /*! \brief
103149    Assign to \p *this the result of (recursively) merging together
103150    the pairs of disjuncts whose upper-bound is the same as their
103151    set-theoretical union.
103152
103153    On exit, for all the pairs \f$\cP\f$, \f$\cQ\f$ of different disjuncts
103154    in \p *this, we have \f$\cP \uplus \cQ \neq \cP \union \cQ\f$.
103155  */
103156  void pairwise_reduce();
103157
103158  /*! \brief
103159    Assigns to \p *this the result of applying the
103160    \ref pps_bgp99_extrapolation "BGP99 extrapolation operator"
103161    to \p *this and \p y, using the widening function \p widen_fun
103162    and the cardinality threshold \p max_disjuncts.
103163
103164    \param y
103165    A powerset that <EM>must</EM> definitely entail \p *this;
103166
103167    \param widen_fun
103168    The widening function to be used on polyhedra objects. It is obtained
103169    from the corresponding widening method by using the helper function
103170    Parma_Polyhedra_Library::widen_fun_ref. Legal values are, e.g.,
103171    <CODE>widen_fun_ref(&Polyhedron::H79_widening_assign)</CODE> and
103172    <CODE>widen_fun_ref(&Polyhedron::limited_H79_extrapolation_assign, cs)</CODE>;
103173
103174    \param max_disjuncts
103175    The maximum number of disjuncts occurring in the powerset \p *this
103176    <EM>before</EM> starting the computation. If this number is exceeded,
103177    some of the disjuncts in \p *this are collapsed (i.e., joined together).
103178
103179    \exception std::invalid_argument
103180    Thrown if \p *this and \p y are dimension-incompatible.
103181
103182    For a description of the extrapolation operator,
103183    see \ref BGP99 "[BGP99]" and \ref BHZ03b "[BHZ03b]".
103184  */
103185  template <typename Widening>
103186  void BGP99_extrapolation_assign(const Pointset_Powerset& y,
103187                                  Widening widen_fun,
103188                                  unsigned max_disjuncts);
103189
103190  /*! \brief
103191    Assigns to \p *this the result of computing the
103192    \ref pps_certificate_widening "BHZ03-widening"
103193    between \p *this and \p y, using the widening function \p widen_fun
103194    certified by the convergence certificate \p Cert.
103195
103196    \param y
103197    The finite powerset computed in the previous iteration step.
103198    It <EM>must</EM> definitely entail \p *this;
103199
103200    \param widen_fun
103201    The widening function to be used on disjuncts.
103202    It is obtained from the corresponding widening method by using
103203    the helper function widen_fun_ref. Legal values are, e.g.,
103204    <CODE>widen_fun_ref(&Polyhedron::H79_widening_assign)</CODE> and
103205    <CODE>widen_fun_ref(&Polyhedron::limited_H79_extrapolation_assign, cs)</CODE>.
103206
103207    \exception std::invalid_argument
103208    Thrown if \p *this and \p y are dimension-incompatible.
103209
103210    \warning
103211    In order to obtain a proper widening operator, the template parameter
103212    \p Cert should be a finite convergence certificate for the base-level
103213    widening function \p widen_fun; otherwise, an extrapolation operator is
103214    obtained.
103215    For a description of the methods that should be provided
103216    by \p Cert, see BHRZ03_Certificate or H79_Certificate.
103217  */
103218  template <typename Cert, typename Widening>
103219  void BHZ03_widening_assign(const Pointset_Powerset& y, Widening widen_fun);
103220
103221  //@} // Space Dimension Preserving Member Functions that May Modify [...]
103222
103223  //! \name Member Functions that May Modify the Dimension of the Vector Space
103224  //@{
103225
103226  /*! \brief
103227    The assignment operator
103228    (\p *this and \p y can be dimension-incompatible).
103229  */
103230  Pointset_Powerset& operator=(const Pointset_Powerset& y);
103231
103232  /*! \brief
103233    Conversion assignment: the type <CODE>QH</CODE> of the disjuncts
103234    in the source powerset is different from <CODE>PSET</CODE>
103235    (\p *this and \p y can be dimension-incompatible).
103236  */
103237  template <typename QH>
103238  Pointset_Powerset& operator=(const Pointset_Powerset<QH>& y);
103239
103240  //! Swaps \p *this with \p y.
103241  void m_swap(Pointset_Powerset& y);
103242
103243  /*! \brief
103244    Adds \p m new dimensions to the vector space containing \p *this
103245    and embeds each disjunct in \p *this in the new space.
103246  */
103247  void add_space_dimensions_and_embed(dimension_type m);
103248
103249  /*! \brief
103250    Adds \p m new dimensions to the vector space containing \p *this
103251    without embedding the disjuncts in \p *this in the new space.
103252  */
103253  void add_space_dimensions_and_project(dimension_type m);
103254
103255  //! Assigns to \p *this the concatenation of \p *this and \p y.
103256  /*!
103257    The result is obtained by computing the pairwise
103258    \ref Concatenating_Polyhedra "concatenation" of each disjunct
103259    in \p *this with each disjunct in \p y.
103260  */
103261  void concatenate_assign(const Pointset_Powerset& y);
103262
103263  //! Removes all the specified space dimensions.
103264  /*!
103265    \param vars
103266    The set of Variable objects corresponding to the space dimensions
103267    to be removed.
103268
103269    \exception std::invalid_argument
103270    Thrown if \p *this is dimension-incompatible with one of the
103271    Variable objects contained in \p vars.
103272  */
103273  void remove_space_dimensions(const Variables_Set& vars);
103274
103275  /*! \brief
103276    Removes the higher space dimensions so that the resulting space
103277    will have dimension \p new_dimension.
103278
103279    \exception std::invalid_argument
103280    Thrown if \p new_dimensions is greater than the space dimension
103281    of \p *this.
103282  */
103283  void remove_higher_space_dimensions(dimension_type new_dimension);
103284
103285  /*! \brief
103286    Remaps the dimensions of the vector space according to
103287    a partial function.
103288
103289    See also Polyhedron::map_space_dimensions.
103290  */
103291  template <typename Partial_Function>
103292  void map_space_dimensions(const Partial_Function& pfunc);
103293
103294  //! Creates \p m copies of the space dimension corresponding to \p var.
103295  /*!
103296    \param var
103297    The variable corresponding to the space dimension to be replicated;
103298
103299    \param m
103300    The number of replicas to be created.
103301
103302    \exception std::invalid_argument
103303    Thrown if \p var does not correspond to a dimension of the vector
103304    space.
103305
103306    \exception std::length_error
103307    Thrown if adding \p m new space dimensions would cause the vector
103308    space to exceed dimension <CODE>max_space_dimension()</CODE>.
103309
103310    If \p *this has space dimension \f$n\f$, with \f$n > 0\f$,
103311    and <CODE>var</CODE> has space dimension \f$k \leq n\f$,
103312    then the \f$k\f$-th space dimension is
103313    \ref Expanding_One_Dimension_of_the_Vector_Space_to_Multiple_Dimensions
103314    "expanded" to \p m new space dimensions
103315    \f$n\f$, \f$n+1\f$, \f$\dots\f$, \f$n+m-1\f$.
103316  */
103317  void expand_space_dimension(Variable var, dimension_type m);
103318
103319  //! Folds the space dimensions in \p vars into \p dest.
103320  /*!
103321    \param vars
103322    The set of Variable objects corresponding to the space dimensions
103323    to be folded;
103324
103325    \param dest
103326    The variable corresponding to the space dimension that is the
103327    destination of the folding operation.
103328
103329    \exception std::invalid_argument
103330    Thrown if \p *this is dimension-incompatible with \p dest or with
103331    one of the Variable objects contained in \p vars.  Also
103332    thrown if \p dest is contained in \p vars.
103333
103334    If \p *this has space dimension \f$n\f$, with \f$n > 0\f$,
103335    <CODE>dest</CODE> has space dimension \f$k \leq n\f$,
103336    \p vars is a set of variables whose maximum space dimension
103337    is also less than or equal to \f$n\f$, and \p dest is not a member
103338    of \p vars, then the space dimensions corresponding to
103339    variables in \p vars are
103340    \ref Folding_Multiple_Dimensions_of_the_Vector_Space_into_One_Dimension
103341    "folded" into the \f$k\f$-th space dimension.
103342  */
103343  void fold_space_dimensions(const Variables_Set& vars, Variable dest);
103344
103345  //@} // Member Functions that May Modify the Dimension of the Vector Space
103346
103347public:
103348  typedef typename Base::size_type size_type;
103349  typedef typename Base::value_type value_type;
103350  typedef typename Base::iterator iterator;
103351  typedef typename Base::const_iterator const_iterator;
103352  typedef typename Base::reverse_iterator reverse_iterator;
103353  typedef typename Base::const_reverse_iterator const_reverse_iterator;
103354
103355  PPL_OUTPUT_DECLARATIONS
103356
103357  /*! \brief
103358    Loads from \p s an ASCII representation (as produced by
103359    ascii_dump(std::ostream&) const) and sets \p *this accordingly.
103360    Returns <CODE>true</CODE> if successful, <CODE>false</CODE> otherwise.
103361  */
103362  bool ascii_load(std::istream& s);
103363
103364private:
103365  typedef typename Base::Sequence Sequence;
103366  typedef typename Base::Sequence_iterator Sequence_iterator;
103367  typedef typename Base::Sequence_const_iterator Sequence_const_iterator;
103368
103369  //! The number of dimensions of the enclosing vector space.
103370  dimension_type space_dim;
103371
103372  /*! \brief
103373    Assigns to \p dest a \ref Powerset_Meet_Preserving_Simplification
103374    "powerset meet-preserving enlargement" of itself with respect to
103375    \p *this.  If \c false is returned, then the intersection is empty.
103376
103377    \note
103378    It is assumed that \p *this and \p dest are topology-compatible
103379    and dimension-compatible.
103380  */
103381  bool intersection_preserving_enlarge_element(PSET& dest) const;
103382
103383  /*! \brief
103384    Assigns to \p *this the result of applying the BGP99 heuristics
103385    to \p *this and \p y, using the widening function \p widen_fun.
103386  */
103387  template <typename Widening>
103388  void BGP99_heuristics_assign(const Pointset_Powerset& y, Widening widen_fun);
103389
103390  //! Records in \p cert_ms the certificates for this set of disjuncts.
103391  template <typename Cert>
103392  void collect_certificates(std::map<Cert, size_type,
103393                                     typename Cert::Compare>& cert_ms) const;
103394
103395  /*! \brief
103396    Returns <CODE>true</CODE> if and only if the current set of disjuncts
103397    is stabilizing with respect to the multiset of certificates \p y_cert_ms.
103398  */
103399  template <typename Cert>
103400  bool is_cert_multiset_stabilizing(const std::map<Cert, size_type,
103401                                                   typename Cert::Compare>&
103402                                    y_cert_ms) const;
103403
103404  /*! \brief
103405    Template helper: common implementation for constraints
103406    and congruences.
103407  */
103408  template <typename Cons_or_Congr>
103409  Poly_Con_Relation relation_with_aux(const Cons_or_Congr& c) const;
103410
103411  // FIXME: here it should be enough to befriend the template constructor
103412  // template <typename QH>
103413  // Pointset_Powerset(const Pointset_Powerset<QH>&),
103414  // but, apparently, this cannot be done.
103415  friend class Pointset_Powerset<NNC_Polyhedron>;
103416};
103417
103418namespace Parma_Polyhedra_Library {
103419
103420//! Swaps \p x with \p y.
103421/*! \relates Pointset_Powerset */
103422template <typename PSET>
103423void swap(Pointset_Powerset<PSET>& x, Pointset_Powerset<PSET>& y);
103424
103425//! Partitions \p q with respect to \p p.
103426/*! \relates Pointset_Powerset
103427  Let \p p and \p q be two polyhedra.
103428  The function returns an object <CODE>r</CODE> of type
103429  <CODE>std::pair\<PSET, Pointset_Powerset\<NNC_Polyhedron\> \></CODE>
103430  such that
103431  - <CODE>r.first</CODE> is the intersection of \p p and \p q;
103432  - <CODE>r.second</CODE> has the property that all its elements are
103433    pairwise disjoint and disjoint from \p p;
103434  - the set-theoretical union of <CODE>r.first</CODE> with all the
103435    elements of <CODE>r.second</CODE> gives \p q (i.e., <CODE>r</CODE>
103436    is the representation of a partition of \p q).
103437
103438  \if Include_Implementation_Details
103439
103440  See
103441  <A HREF="http://bugseng.com/products/ppl/Documentation/bibliography#Srivastava93">
103442  this paper</A> for more information about the implementation.
103443  \endif
103444*/
103445template <typename PSET>
103446std::pair<PSET, Pointset_Powerset<NNC_Polyhedron> >
103447linear_partition(const PSET& p, const PSET& q);
103448
103449/*! \brief
103450  Returns <CODE>true</CODE> if and only if the union of
103451  the NNC polyhedra in \p ps contains the NNC polyhedron \p ph.
103452
103453  \relates Pointset_Powerset
103454*/
103455bool
103456check_containment(const NNC_Polyhedron& ph,
103457                  const Pointset_Powerset<NNC_Polyhedron>& ps);
103458
103459
103460/*! \brief
103461  Partitions the grid \p q with respect to grid \p p if and only if
103462  such a partition is finite.
103463
103464  \relates Parma_Polyhedra_Library::Pointset_Powerset
103465  Let \p p and \p q be two grids.
103466  The function returns an object <CODE>r</CODE> of type
103467  <CODE>std::pair\<PSET, Pointset_Powerset\<Grid\> \></CODE>
103468  such that
103469  - <CODE>r.first</CODE> is the intersection of \p p and \p q;
103470  - If there is a finite partition of \p q with respect to \p p
103471    the Boolean <CODE>finite_partition</CODE> is set to true and
103472    <CODE>r.second</CODE> has the property that all its elements are
103473    pairwise disjoint and disjoint from \p p and the set-theoretical
103474    union of <CODE>r.first</CODE> with all the elements of
103475    <CODE>r.second</CODE> gives \p q (i.e., <CODE>r</CODE>
103476    is the representation of a partition of \p q).
103477  - Otherwise the Boolean <CODE>finite_partition</CODE> is set to false
103478    and the singleton set that contains \p q is stored in
103479    <CODE>r.second</CODE>r.
103480*/
103481std::pair<Grid, Pointset_Powerset<Grid> >
103482approximate_partition(const Grid& p, const Grid& q, bool& finite_partition);
103483
103484/*! \brief
103485  Returns <CODE>true</CODE> if and only if the union of
103486  the grids \p ps contains the grid \p g.
103487
103488  \relates Pointset_Powerset
103489*/
103490bool
103491check_containment(const Grid& ph,
103492                  const Pointset_Powerset<Grid>& ps);
103493
103494/*! \brief
103495  Returns <CODE>true</CODE> if and only if the union of
103496  the objects in \p ps contains \p ph.
103497
103498  \relates Pointset_Powerset
103499  \note
103500  It is assumed that the template parameter PSET can be converted
103501  without precision loss into an NNC_Polyhedron; otherwise,
103502  an incorrect result might be obtained.
103503*/
103504template <typename PSET>
103505bool
103506check_containment(const PSET& ph, const Pointset_Powerset<PSET>& ps);
103507
103508// CHECKME: according to the Intel compiler, the declaration of the
103509// following specialization (of the class template parameter) should come
103510// before the declaration of the corresponding full specialization
103511// (where the member template parameter is specialized too).
103512template <>
103513template <typename QH>
103514Pointset_Powerset<NNC_Polyhedron>
103515::Pointset_Powerset(const Pointset_Powerset<QH>& y,
103516                    Complexity_Class);
103517
103518// Non-inline full specializations should be declared here
103519// so as to inhibit multiple instantiations of the generic template.
103520template <>
103521template <>
103522Pointset_Powerset<NNC_Polyhedron>
103523::Pointset_Powerset(const Pointset_Powerset<C_Polyhedron>& y,
103524                    Complexity_Class);
103525
103526template <>
103527template <>
103528Pointset_Powerset<NNC_Polyhedron>
103529::Pointset_Powerset(const Pointset_Powerset<Grid>& y,
103530                    Complexity_Class);
103531
103532template <>
103533template <>
103534Pointset_Powerset<C_Polyhedron>
103535::Pointset_Powerset(const Pointset_Powerset<NNC_Polyhedron>& y,
103536                    Complexity_Class);
103537
103538template <>
103539void
103540Pointset_Powerset<NNC_Polyhedron>
103541::difference_assign(const Pointset_Powerset& y);
103542
103543template <>
103544void
103545Pointset_Powerset<Grid>
103546::difference_assign(const Pointset_Powerset& y);
103547
103548template <>
103549bool
103550Pointset_Powerset<NNC_Polyhedron>
103551::geometrically_covers(const Pointset_Powerset& y) const;
103552
103553template <>
103554bool
103555Pointset_Powerset<Grid>
103556::geometrically_covers(const Pointset_Powerset& y) const;
103557
103558} // namespace Parma_Polyhedra_Library
103559
103560/* Automatically generated from PPL source file ../src/Pointset_Powerset_inlines.hh line 1. */
103561/* Pointset_Powerset class implementation: inline functions.
103562*/
103563
103564
103565/* Automatically generated from PPL source file ../src/Pointset_Powerset_inlines.hh line 35. */
103566#include <algorithm>
103567#include <deque>
103568
103569namespace Parma_Polyhedra_Library {
103570
103571template <typename PSET>
103572inline dimension_type
103573Pointset_Powerset<PSET>::space_dimension() const {
103574  return space_dim;
103575}
103576
103577template <typename PSET>
103578inline dimension_type
103579Pointset_Powerset<PSET>::max_space_dimension() {
103580  return PSET::max_space_dimension();
103581}
103582
103583template <typename PSET>
103584inline
103585Pointset_Powerset<PSET>::Pointset_Powerset(dimension_type num_dimensions,
103586                                           Degenerate_Element kind)
103587  : Base(), space_dim(num_dimensions) {
103588  Pointset_Powerset& x = *this;
103589  if (kind == UNIVERSE) {
103590    x.sequence.push_back(Determinate<PSET>(PSET(num_dimensions, kind)));
103591  }
103592  PPL_ASSERT_HEAVY(x.OK());
103593}
103594
103595template <typename PSET>
103596inline
103597Pointset_Powerset<PSET>::Pointset_Powerset(const Pointset_Powerset& y,
103598                                           Complexity_Class)
103599  : Base(y), space_dim(y.space_dim) {
103600}
103601
103602template <typename PSET>
103603inline
103604Pointset_Powerset<PSET>::Pointset_Powerset(const C_Polyhedron& ph,
103605                                           Complexity_Class complexity)
103606  : Base(), space_dim(ph.space_dimension()) {
103607  Pointset_Powerset& x = *this;
103608  if (complexity == ANY_COMPLEXITY) {
103609    if (ph.is_empty()) {
103610      return;
103611    }
103612  }
103613  else {
103614    x.reduced = false;
103615  }
103616  x.sequence.push_back(Determinate<PSET>(PSET(ph, complexity)));
103617  x.reduced = false;
103618  PPL_ASSERT_HEAVY(OK());
103619}
103620
103621template <typename PSET>
103622inline
103623Pointset_Powerset<PSET>::Pointset_Powerset(const NNC_Polyhedron& ph,
103624                                           Complexity_Class complexity)
103625  : Base(), space_dim(ph.space_dimension()) {
103626  Pointset_Powerset& x = *this;
103627  if (complexity == ANY_COMPLEXITY) {
103628    if (ph.is_empty()) {
103629      return;
103630    }
103631  }
103632  else {
103633    x.reduced = false;
103634  }
103635  x.sequence.push_back(Determinate<PSET>(PSET(ph, complexity)));
103636  PPL_ASSERT_HEAVY(OK());
103637}
103638
103639template <typename PSET>
103640inline
103641Pointset_Powerset<PSET>::Pointset_Powerset(const Grid& gr,
103642                                           Complexity_Class)
103643  : Base(), space_dim(gr.space_dimension()) {
103644  Pointset_Powerset& x = *this;
103645  if (!gr.is_empty()) {
103646    x.sequence.push_back(Determinate<PSET>(PSET(gr)));
103647  }
103648  PPL_ASSERT_HEAVY(OK());
103649}
103650
103651template <typename PSET>
103652template <typename QH1, typename QH2, typename R>
103653inline
103654Pointset_Powerset<PSET>
103655::Pointset_Powerset(const Partially_Reduced_Product<QH1, QH2, R>& prp,
103656                    Complexity_Class complexity)
103657  : Base(), space_dim(prp.space_dimension()) {
103658  Pointset_Powerset& x = *this;
103659  if (complexity == ANY_COMPLEXITY) {
103660    if (prp.is_empty()) {
103661      return;
103662    }
103663  }
103664  else {
103665    x.reduced = false;
103666  }
103667  x.sequence.push_back(Determinate<PSET>(PSET(prp, complexity)));
103668  x.reduced = false;
103669  PPL_ASSERT_HEAVY(OK());
103670}
103671
103672template <typename PSET>
103673template <typename Interval>
103674Pointset_Powerset<PSET>::Pointset_Powerset(const Box<Interval>& box,
103675                                           Complexity_Class)
103676  : Base(), space_dim(box.space_dimension()) {
103677  Pointset_Powerset& x = *this;
103678  if (!box.is_empty()) {
103679    x.sequence.push_back(Determinate<PSET>(PSET(box)));
103680  }
103681  PPL_ASSERT_HEAVY(OK());
103682}
103683
103684template <typename PSET>
103685template <typename T>
103686Pointset_Powerset<PSET>::Pointset_Powerset(const Octagonal_Shape<T>& os,
103687                                           Complexity_Class)
103688  : Base(), space_dim(os.space_dimension()) {
103689  Pointset_Powerset& x = *this;
103690  if (!os.is_empty()) {
103691    x.sequence.push_back(Determinate<PSET>(PSET(os)));
103692  }
103693  PPL_ASSERT_HEAVY(OK());
103694}
103695
103696template <typename PSET>
103697template <typename T>
103698Pointset_Powerset<PSET>::Pointset_Powerset(const BD_Shape<T>& bds,
103699                                           Complexity_Class)
103700  : Base(), space_dim(bds.space_dimension()) {
103701  Pointset_Powerset& x = *this;
103702  if (!bds.is_empty()) {
103703    x.sequence.push_back(Determinate<PSET>(PSET(bds)));
103704  }
103705  PPL_ASSERT_HEAVY(OK());
103706}
103707
103708template <typename PSET>
103709inline
103710Pointset_Powerset<PSET>::Pointset_Powerset(const Constraint_System& cs)
103711  : Base(Determinate<PSET>(cs)), space_dim(cs.space_dimension()) {
103712  PPL_ASSERT_HEAVY(OK());
103713}
103714
103715template <typename PSET>
103716inline
103717Pointset_Powerset<PSET>::Pointset_Powerset(const Congruence_System& cgs)
103718  : Base(Determinate<PSET>(cgs)), space_dim(cgs.space_dimension()) {
103719  PPL_ASSERT_HEAVY(OK());
103720}
103721
103722template <typename PSET>
103723inline Pointset_Powerset<PSET>&
103724Pointset_Powerset<PSET>::operator=(const Pointset_Powerset& y) {
103725  Pointset_Powerset& x = *this;
103726  x.Base::operator=(y);
103727  x.space_dim = y.space_dim;
103728  return x;
103729}
103730
103731template <typename PSET>
103732inline void
103733Pointset_Powerset<PSET>::m_swap(Pointset_Powerset& y) {
103734  Pointset_Powerset& x = *this;
103735  x.Base::m_swap(y);
103736  using std::swap;
103737  swap(x.space_dim, y.space_dim);
103738}
103739
103740template <typename PSET>
103741template <typename QH>
103742inline Pointset_Powerset<PSET>&
103743Pointset_Powerset<PSET>::operator=(const Pointset_Powerset<QH>& y) {
103744  Pointset_Powerset& x = *this;
103745  Pointset_Powerset<PSET> ps(y);
103746  swap(x, ps);
103747  return x;
103748}
103749
103750template <typename PSET>
103751inline void
103752Pointset_Powerset<PSET>::intersection_assign(const Pointset_Powerset& y) {
103753  Pointset_Powerset& x = *this;
103754  x.pairwise_apply_assign(y,
103755                          Det_PSET::lift_op_assign(std::mem_fun_ref(&PSET::intersection_assign)));
103756}
103757
103758template <typename PSET>
103759inline void
103760Pointset_Powerset<PSET>::time_elapse_assign(const Pointset_Powerset& y) {
103761  Pointset_Powerset& x = *this;
103762  x.pairwise_apply_assign(y,
103763                          Det_PSET::lift_op_assign(std::mem_fun_ref(&PSET::time_elapse_assign)));
103764}
103765
103766template <typename PSET>
103767inline Poly_Con_Relation
103768Pointset_Powerset<PSET>::relation_with(const Constraint& c) const {
103769  return relation_with_aux(c);
103770}
103771
103772template <typename PSET>
103773inline Poly_Con_Relation
103774Pointset_Powerset<PSET>::relation_with(const Congruence& cg) const {
103775  return relation_with_aux(cg);
103776}
103777
103778template <typename PSET>
103779inline bool
103780Pointset_Powerset<PSET>
103781::geometrically_covers(const Pointset_Powerset& y) const {
103782  // This code is only used when PSET is an abstraction of NNC_Polyhedron.
103783  const Pointset_Powerset<NNC_Polyhedron> xx(*this);
103784  const Pointset_Powerset<NNC_Polyhedron> yy(y);
103785  return xx.geometrically_covers(yy);
103786}
103787
103788template <typename PSET>
103789inline bool
103790Pointset_Powerset<PSET>
103791::geometrically_equals(const Pointset_Powerset& y) const {
103792  // This code is only used when PSET is an abstraction of NNC_Polyhedron.
103793  const Pointset_Powerset<NNC_Polyhedron> xx(*this);
103794  const Pointset_Powerset<NNC_Polyhedron> yy(y);
103795  return xx.geometrically_covers(yy) && yy.geometrically_covers(xx);
103796}
103797
103798template <>
103799inline bool
103800Pointset_Powerset<Grid>
103801::geometrically_equals(const Pointset_Powerset& y) const {
103802  const Pointset_Powerset& x = *this;
103803  return x.geometrically_covers(y) && y.geometrically_covers(x);
103804}
103805
103806template <>
103807inline bool
103808Pointset_Powerset<NNC_Polyhedron>
103809::geometrically_equals(const Pointset_Powerset& y) const {
103810  const Pointset_Powerset& x = *this;
103811  return x.geometrically_covers(y) && y.geometrically_covers(x);
103812}
103813
103814template <typename PSET>
103815inline memory_size_type
103816Pointset_Powerset<PSET>::external_memory_in_bytes() const {
103817  return Base::external_memory_in_bytes();
103818}
103819
103820template <typename PSET>
103821inline memory_size_type
103822Pointset_Powerset<PSET>::total_memory_in_bytes() const {
103823  return sizeof(*this) + external_memory_in_bytes();
103824}
103825
103826template <typename PSET>
103827inline int32_t
103828Pointset_Powerset<PSET>::hash_code() const {
103829  return hash_code_from_dimension(space_dimension());
103830}
103831
103832template <typename PSET>
103833inline void
103834Pointset_Powerset<PSET>
103835::difference_assign(const Pointset_Powerset& y) {
103836  // This code is only used when PSET is an abstraction of NNC_Polyhedron.
103837  Pointset_Powerset<NNC_Polyhedron> nnc_this(*this);
103838  Pointset_Powerset<NNC_Polyhedron> nnc_y(y);
103839  nnc_this.difference_assign(nnc_y);
103840  *this = nnc_this;
103841}
103842
103843/*! \relates Pointset_Powerset */
103844template <typename PSET>
103845inline bool
103846check_containment(const PSET& ph, const Pointset_Powerset<PSET>& ps) {
103847  // This code is only used when PSET is an abstraction of NNC_Polyhedron.
103848  const NNC_Polyhedron ph_nnc = NNC_Polyhedron(ph.constraints());
103849  const Pointset_Powerset<NNC_Polyhedron> ps_nnc(ps);
103850  return check_containment(ph_nnc, ps_nnc);
103851}
103852
103853/*! \relates Pointset_Powerset */
103854template <>
103855inline bool
103856check_containment(const C_Polyhedron& ph,
103857                  const Pointset_Powerset<C_Polyhedron>& ps) {
103858  return check_containment(NNC_Polyhedron(ph),
103859                           Pointset_Powerset<NNC_Polyhedron>(ps));
103860}
103861
103862/*! \relates Pointset_Powerset */
103863template <typename PSET>
103864inline void
103865swap(Pointset_Powerset<PSET>& x, Pointset_Powerset<PSET>& y) {
103866  x.m_swap(y);
103867}
103868
103869} // namespace Parma_Polyhedra_Library
103870
103871/* Automatically generated from PPL source file ../src/Pointset_Powerset_templates.hh line 1. */
103872/* Pointset_Powerset class implementation: non-inline template functions.
103873*/
103874
103875
103876/* Automatically generated from PPL source file ../src/Pointset_Powerset_templates.hh line 33. */
103877#include <algorithm>
103878#include <deque>
103879#include <string>
103880#include <iostream>
103881#include <sstream>
103882#include <stdexcept>
103883
103884namespace Parma_Polyhedra_Library {
103885
103886template <typename PSET>
103887void
103888Pointset_Powerset<PSET>::add_disjunct(const PSET& ph) {
103889  Pointset_Powerset& x = *this;
103890  if (x.space_dimension() != ph.space_dimension()) {
103891    std::ostringstream s;
103892    s << "PPL::Pointset_Powerset<PSET>::add_disjunct(ph):\n"
103893      << "this->space_dimension() == " << x.space_dimension() << ", "
103894      << "ph.space_dimension() == " << ph.space_dimension() << ".";
103895    throw std::invalid_argument(s.str());
103896  }
103897  x.sequence.push_back(Determinate<PSET>(ph));
103898  x.reduced = false;
103899  PPL_ASSERT_HEAVY(x.OK());
103900}
103901
103902template <>
103903template <typename QH>
103904Pointset_Powerset<NNC_Polyhedron>
103905::Pointset_Powerset(const Pointset_Powerset<QH>& y,
103906                    Complexity_Class complexity)
103907  : Base(), space_dim(y.space_dimension()) {
103908  Pointset_Powerset& x = *this;
103909  for (typename Pointset_Powerset<QH>::const_iterator i = y.begin(),
103910         y_end = y.end(); i != y_end; ++i) {
103911    x.sequence.push_back(Determinate<NNC_Polyhedron>
103912                         (NNC_Polyhedron(i->pointset(), complexity)));
103913
103914  }
103915  // FIXME: If the domain elements can be represented _exactly_ as NNC
103916  // polyhedra, then having x.reduced = y.reduced is correct. This is
103917  // the case if the domains are both linear and convex which holds
103918  // for all the currently supported instantiations except for
103919  // Grids; for this reason the Grid specialization has a
103920  // separate implementation.  For any non-linear or non-convex
103921  // domains (e.g., a domain of Intervals with restrictions or a
103922  // domain of circles) that may be supported in the future, the
103923  // assignment x.reduced = y.reduced will be a bug.
103924  x.reduced = y.reduced;
103925
103926  PPL_ASSERT_HEAVY(x.OK());
103927}
103928
103929template <typename PSET>
103930template <typename QH>
103931Pointset_Powerset<PSET>
103932::Pointset_Powerset(const Pointset_Powerset<QH>& y,
103933                    Complexity_Class complexity)
103934  : Base(), space_dim(y.space_dimension()) {
103935  Pointset_Powerset& x = *this;
103936  for (typename Pointset_Powerset<QH>::const_iterator i = y.begin(),
103937         y_end = y.end(); i != y_end; ++i) {
103938    x.sequence.push_back(Determinate<PSET>(PSET(i->pointset(), complexity)));
103939  }
103940  // Note: this might be non-reduced even when `y' is known to be
103941  // omega-reduced, because the constructor of PSET may have made
103942  // different QH elements to become comparable.
103943  x.reduced = false;
103944  PPL_ASSERT_HEAVY(x.OK());
103945}
103946
103947template <typename PSET>
103948void
103949Pointset_Powerset<PSET>::concatenate_assign(const Pointset_Powerset& y) {
103950  Pointset_Powerset& x = *this;
103951  // Ensure omega-reduction here, since what follows has quadratic complexity.
103952  x.omega_reduce();
103953  y.omega_reduce();
103954  Pointset_Powerset<PSET> new_x(x.space_dim + y.space_dim, EMPTY);
103955  for (const_iterator xi = x.begin(), x_end = x.end(),
103956         y_begin = y.begin(), y_end = y.end(); xi != x_end; ) {
103957    for (const_iterator yi = y_begin; yi != y_end; ++yi) {
103958      Det_PSET zi = *xi;
103959      zi.concatenate_assign(*yi);
103960      PPL_ASSERT_HEAVY(!zi.is_bottom());
103961      new_x.sequence.push_back(zi);
103962    }
103963    ++xi;
103964    if ((abandon_expensive_computations != 0)
103965        && (xi != x_end) && (y_begin != y_end)) {
103966      // Hurry up!
103967      PSET x_ph = xi->pointset();
103968      for (++xi; xi != x_end; ++xi) {
103969        x_ph.upper_bound_assign(xi->pointset());
103970      }
103971      const_iterator yi = y_begin;
103972      PSET y_ph = yi->pointset();
103973      for (++yi; yi != y_end; ++yi) {
103974        y_ph.upper_bound_assign(yi->pointset());
103975      }
103976      x_ph.concatenate_assign(y_ph);
103977      swap(x, new_x);
103978      x.add_disjunct(x_ph);
103979      PPL_ASSERT_HEAVY(x.OK());
103980      return;
103981    }
103982  }
103983  swap(x, new_x);
103984  PPL_ASSERT_HEAVY(x.OK());
103985}
103986
103987template <typename PSET>
103988void
103989Pointset_Powerset<PSET>::add_constraint(const Constraint& c) {
103990  Pointset_Powerset& x = *this;
103991  for (Sequence_iterator si = x.sequence.begin(),
103992         s_end = x.sequence.end(); si != s_end; ++si) {
103993    si->pointset().add_constraint(c);
103994  }
103995  x.reduced = false;
103996  PPL_ASSERT_HEAVY(x.OK());
103997}
103998
103999template <typename PSET>
104000void
104001Pointset_Powerset<PSET>::refine_with_constraint(const Constraint& c) {
104002  Pointset_Powerset& x = *this;
104003  for (Sequence_iterator si = x.sequence.begin(),
104004         s_end = x.sequence.end(); si != s_end; ++si) {
104005    si->pointset().refine_with_constraint(c);
104006  }
104007  x.reduced = false;
104008  PPL_ASSERT_HEAVY(x.OK());
104009}
104010
104011template <typename PSET>
104012void
104013Pointset_Powerset<PSET>::add_constraints(const Constraint_System& cs) {
104014  Pointset_Powerset& x = *this;
104015  for (Sequence_iterator si = x.sequence.begin(),
104016         s_end = x.sequence.end(); si != s_end; ++si) {
104017    si->pointset().add_constraints(cs);
104018  }
104019  x.reduced = false;
104020  PPL_ASSERT_HEAVY(x.OK());
104021}
104022
104023template <typename PSET>
104024void
104025Pointset_Powerset<PSET>::refine_with_constraints(const Constraint_System& cs) {
104026  Pointset_Powerset& x = *this;
104027  for (Sequence_iterator si = x.sequence.begin(),
104028         s_end = x.sequence.end(); si != s_end; ++si) {
104029    si->pointset().refine_with_constraints(cs);
104030  }
104031  x.reduced = false;
104032  PPL_ASSERT_HEAVY(x.OK());
104033}
104034
104035template <typename PSET>
104036void
104037Pointset_Powerset<PSET>::add_congruence(const Congruence& cg) {
104038  Pointset_Powerset& x = *this;
104039  for (Sequence_iterator si = x.sequence.begin(),
104040         s_end = x.sequence.end(); si != s_end; ++si) {
104041    si->pointset().add_congruence(cg);
104042  }
104043  x.reduced = false;
104044  PPL_ASSERT_HEAVY(x.OK());
104045}
104046
104047template <typename PSET>
104048void
104049Pointset_Powerset<PSET>::refine_with_congruence(const Congruence& cg) {
104050  Pointset_Powerset& x = *this;
104051  for (Sequence_iterator si = x.sequence.begin(),
104052         s_end = x.sequence.end(); si != s_end; ++si) {
104053    si->pointset().refine_with_congruence(cg);
104054  }
104055  x.reduced = false;
104056  PPL_ASSERT_HEAVY(x.OK());
104057}
104058
104059template <typename PSET>
104060void
104061Pointset_Powerset<PSET>::add_congruences(const Congruence_System& cgs) {
104062  Pointset_Powerset& x = *this;
104063  for (Sequence_iterator si = x.sequence.begin(),
104064         s_end = x.sequence.end(); si != s_end; ++si) {
104065    si->pointset().add_congruences(cgs);
104066  }
104067  x.reduced = false;
104068  PPL_ASSERT_HEAVY(x.OK());
104069}
104070
104071template <typename PSET>
104072void
104073Pointset_Powerset<PSET>::refine_with_congruences(const Congruence_System& cgs) {
104074  Pointset_Powerset& x = *this;
104075  for (Sequence_iterator si = x.sequence.begin(),
104076         s_end = x.sequence.end(); si != s_end; ++si) {
104077    si->pointset().refine_with_congruences(cgs);
104078  }
104079  x.reduced = false;
104080  PPL_ASSERT_HEAVY(x.OK());
104081}
104082
104083template <typename PSET>
104084void
104085Pointset_Powerset<PSET>::unconstrain(const Variable var) {
104086  Pointset_Powerset& x = *this;
104087  for (Sequence_iterator si = x.sequence.begin(),
104088         s_end = x.sequence.end(); si != s_end; ++si) {
104089    si->pointset().unconstrain(var);
104090    x.reduced = false;
104091  }
104092  PPL_ASSERT_HEAVY(x.OK());
104093}
104094
104095template <typename PSET>
104096void
104097Pointset_Powerset<PSET>::unconstrain(const Variables_Set& vars) {
104098  Pointset_Powerset& x = *this;
104099  for (Sequence_iterator si = x.sequence.begin(),
104100         s_end = x.sequence.end(); si != s_end; ++si) {
104101    si->pointset().unconstrain(vars);
104102    x.reduced = false;
104103  }
104104  PPL_ASSERT_HEAVY(x.OK());
104105}
104106
104107template <typename PSET>
104108void
104109Pointset_Powerset<PSET>::add_space_dimensions_and_embed(dimension_type m) {
104110  Pointset_Powerset& x = *this;
104111  for (Sequence_iterator si = x.sequence.begin(),
104112         s_end = x.sequence.end(); si != s_end; ++si) {
104113    si->pointset().add_space_dimensions_and_embed(m);
104114  }
104115  x.space_dim += m;
104116  PPL_ASSERT_HEAVY(x.OK());
104117}
104118
104119template <typename PSET>
104120void
104121Pointset_Powerset<PSET>::add_space_dimensions_and_project(dimension_type m) {
104122  Pointset_Powerset& x = *this;
104123  for (Sequence_iterator si = x.sequence.begin(),
104124         s_end = x.sequence.end(); si != s_end; ++si) {
104125    si->pointset().add_space_dimensions_and_project(m);
104126  }
104127  x.space_dim += m;
104128  PPL_ASSERT_HEAVY(x.OK());
104129}
104130
104131template <typename PSET>
104132void
104133Pointset_Powerset<PSET>::remove_space_dimensions(const Variables_Set& vars) {
104134  Pointset_Powerset& x = *this;
104135  Variables_Set::size_type num_removed = vars.size();
104136  if (num_removed > 0) {
104137    for (Sequence_iterator si = x.sequence.begin(),
104138           s_end = x.sequence.end(); si != s_end; ++si) {
104139      si->pointset().remove_space_dimensions(vars);
104140      x.reduced = false;
104141    }
104142    x.space_dim -= num_removed;
104143    PPL_ASSERT_HEAVY(x.OK());
104144  }
104145}
104146
104147template <typename PSET>
104148void
104149Pointset_Powerset<PSET>
104150::remove_higher_space_dimensions(dimension_type new_dimension) {
104151  Pointset_Powerset& x = *this;
104152  if (new_dimension < x.space_dim) {
104153    for (Sequence_iterator si = x.sequence.begin(),
104154           s_end = x.sequence.end(); si != s_end; ++si) {
104155      si->pointset().remove_higher_space_dimensions(new_dimension);
104156      x.reduced = false;
104157    }
104158    x.space_dim = new_dimension;
104159    PPL_ASSERT_HEAVY(x.OK());
104160  }
104161}
104162
104163template <typename PSET>
104164template <typename Partial_Function>
104165void
104166Pointset_Powerset<PSET>::map_space_dimensions(const Partial_Function& pfunc) {
104167  Pointset_Powerset& x = *this;
104168  if (x.is_bottom()) {
104169    dimension_type n = 0;
104170    for (dimension_type i = x.space_dim; i-- > 0; ) {
104171      dimension_type new_i;
104172      if (pfunc.maps(i, new_i)) {
104173        ++n;
104174      }
104175    }
104176    x.space_dim = n;
104177  }
104178  else {
104179    Sequence_iterator s_begin = x.sequence.begin();
104180    for (Sequence_iterator si = s_begin,
104181           s_end = x.sequence.end(); si != s_end; ++si) {
104182      si->pointset().map_space_dimensions(pfunc);
104183    }
104184    x.space_dim = s_begin->pointset().space_dimension();
104185    x.reduced = false;
104186  }
104187  PPL_ASSERT_HEAVY(x.OK());
104188}
104189
104190template <typename PSET>
104191void
104192Pointset_Powerset<PSET>::expand_space_dimension(Variable var,
104193                                                dimension_type m) {
104194  Pointset_Powerset& x = *this;
104195  for (Sequence_iterator si = x.sequence.begin(),
104196         s_end = x.sequence.end(); si != s_end; ++si) {
104197    si->pointset().expand_space_dimension(var, m);
104198  }
104199  x.space_dim += m;
104200  PPL_ASSERT_HEAVY(x.OK());
104201}
104202
104203template <typename PSET>
104204void
104205Pointset_Powerset<PSET>::fold_space_dimensions(const Variables_Set& vars,
104206                                               Variable dest) {
104207  Pointset_Powerset& x = *this;
104208  Variables_Set::size_type num_folded = vars.size();
104209  if (num_folded > 0) {
104210    for (Sequence_iterator si = x.sequence.begin(),
104211           s_end = x.sequence.end(); si != s_end; ++si) {
104212      si->pointset().fold_space_dimensions(vars, dest);
104213    }
104214  }
104215  x.space_dim -= num_folded;
104216  PPL_ASSERT_HEAVY(x.OK());
104217}
104218
104219template <typename PSET>
104220void
104221Pointset_Powerset<PSET>::affine_image(Variable var,
104222                                      const Linear_Expression& expr,
104223                                      Coefficient_traits::const_reference
104224                                      denominator) {
104225  Pointset_Powerset& x = *this;
104226  for (Sequence_iterator si = x.sequence.begin(),
104227         s_end = x.sequence.end(); si != s_end; ++si) {
104228    si->pointset().affine_image(var, expr, denominator);
104229    // Note that the underlying domain can apply conservative approximation:
104230    // that is why it would not be correct to make the loss of reduction
104231    // conditional on `var' and `expr'.
104232    x.reduced = false;
104233  }
104234  PPL_ASSERT_HEAVY(x.OK());
104235}
104236
104237template <typename PSET>
104238void
104239Pointset_Powerset<PSET>::affine_preimage(Variable var,
104240                                         const Linear_Expression& expr,
104241                                         Coefficient_traits::const_reference
104242                                         denominator) {
104243  Pointset_Powerset& x = *this;
104244  for (Sequence_iterator si = x.sequence.begin(),
104245         s_end = x.sequence.end(); si != s_end; ++si) {
104246    si->pointset().affine_preimage(var, expr, denominator);
104247    // Note that the underlying domain can apply conservative approximation:
104248    // that is why it would not be correct to make the loss of reduction
104249    // conditional on `var' and `expr'.
104250    x.reduced = false;
104251  }
104252  PPL_ASSERT_HEAVY(x.OK());
104253}
104254
104255
104256template <typename PSET>
104257void
104258Pointset_Powerset<PSET>
104259::generalized_affine_image(const Linear_Expression& lhs,
104260                           const Relation_Symbol relsym,
104261                           const Linear_Expression& rhs) {
104262  Pointset_Powerset& x = *this;
104263  for (Sequence_iterator si = x.sequence.begin(),
104264         s_end = x.sequence.end(); si != s_end; ++si) {
104265    si->pointset().generalized_affine_image(lhs, relsym, rhs);
104266    x.reduced = false;
104267  }
104268  PPL_ASSERT_HEAVY(x.OK());
104269}
104270
104271template <typename PSET>
104272void
104273Pointset_Powerset<PSET>
104274::generalized_affine_preimage(const Linear_Expression& lhs,
104275                              const Relation_Symbol relsym,
104276                              const Linear_Expression& rhs) {
104277  Pointset_Powerset& x = *this;
104278  for (Sequence_iterator si = x.sequence.begin(),
104279         s_end = x.sequence.end(); si != s_end; ++si) {
104280    si->pointset().generalized_affine_preimage(lhs, relsym, rhs);
104281    x.reduced = false;
104282  }
104283  PPL_ASSERT_HEAVY(x.OK());
104284}
104285
104286template <typename PSET>
104287void
104288Pointset_Powerset<PSET>
104289::generalized_affine_image(Variable var,
104290                           const Relation_Symbol relsym,
104291                           const Linear_Expression& expr,
104292                           Coefficient_traits::const_reference denominator) {
104293  Pointset_Powerset& x = *this;
104294  for (Sequence_iterator si = x.sequence.begin(),
104295         s_end = x.sequence.end(); si != s_end; ++si) {
104296    si->pointset().generalized_affine_image(var, relsym, expr, denominator);
104297    x.reduced = false;
104298  }
104299  PPL_ASSERT_HEAVY(x.OK());
104300}
104301
104302template <typename PSET>
104303void
104304Pointset_Powerset<PSET>
104305::generalized_affine_preimage(Variable var,
104306                              const Relation_Symbol relsym,
104307                              const Linear_Expression& expr,
104308                              Coefficient_traits::const_reference
104309                              denominator) {
104310  Pointset_Powerset& x = *this;
104311  for (Sequence_iterator si = x.sequence.begin(),
104312         s_end = x.sequence.end(); si != s_end; ++si) {
104313    si->pointset().generalized_affine_preimage(var, relsym, expr, denominator);
104314    x.reduced = false;
104315  }
104316  PPL_ASSERT_HEAVY(x.OK());
104317}
104318
104319
104320template <typename PSET>
104321void
104322Pointset_Powerset<PSET>
104323::bounded_affine_image(Variable var,
104324                       const Linear_Expression& lb_expr,
104325                       const Linear_Expression& ub_expr,
104326                       Coefficient_traits::const_reference denominator) {
104327  Pointset_Powerset& x = *this;
104328  for (Sequence_iterator si = x.sequence.begin(),
104329         s_end = x.sequence.end(); si != s_end; ++si) {
104330    si->pointset().bounded_affine_image(var, lb_expr, ub_expr, denominator);
104331    x.reduced = false;
104332  }
104333  PPL_ASSERT_HEAVY(x.OK());
104334}
104335
104336template <typename PSET>
104337void
104338Pointset_Powerset<PSET>
104339::bounded_affine_preimage(Variable var,
104340                          const Linear_Expression& lb_expr,
104341                          const Linear_Expression& ub_expr,
104342                          Coefficient_traits::const_reference denominator) {
104343  Pointset_Powerset& x = *this;
104344  for (Sequence_iterator si = x.sequence.begin(),
104345         s_end = x.sequence.end(); si != s_end; ++si) {
104346    si->pointset().bounded_affine_preimage(var, lb_expr, ub_expr,
104347                                          denominator);
104348    x.reduced = false;
104349  }
104350  PPL_ASSERT_HEAVY(x.OK());
104351}
104352
104353template <typename PSET>
104354dimension_type
104355Pointset_Powerset<PSET>::affine_dimension() const {
104356  // The affine dimension of the powerset is the affine dimension of
104357  // the smallest vector space in which it can be embedded.
104358  const Pointset_Powerset& x = *this;
104359  C_Polyhedron x_ph(space_dim, EMPTY);
104360
104361  for (Sequence_const_iterator si = x.sequence.begin(),
104362         s_end = x.sequence.end(); si != s_end; ++si) {
104363    PSET pi(si->pointset());
104364    if (!pi.is_empty()) {
104365      C_Polyhedron phi(space_dim);
104366      const Constraint_System& cs = pi.minimized_constraints();
104367      for (Constraint_System::const_iterator i = cs.begin(),
104368             cs_end = cs.end(); i != cs_end; ++i) {
104369        const Constraint& c = *i;
104370        if (c.is_equality()) {
104371          phi.add_constraint(c);
104372        }
104373      }
104374      x_ph.poly_hull_assign(phi);
104375    }
104376  }
104377
104378  return x_ph.affine_dimension();
104379}
104380
104381template <typename PSET>
104382bool
104383Pointset_Powerset<PSET>::is_universe() const {
104384  const Pointset_Powerset& x = *this;
104385  // Exploit omega-reduction, if already computed.
104386  if (x.is_omega_reduced()) {
104387    return x.size() == 1 && x.begin()->pointset().is_universe();
104388  }
104389
104390  // A powerset is universe iff one of its disjuncts is.
104391  for (const_iterator x_i = x.begin(), x_end = x.end();
104392       x_i != x_end; ++x_i) {
104393    if (x_i->pointset().is_universe()) {
104394      // Speculative omega-reduction, if it is worth.
104395      if (x.size() > 1) {
104396        Pointset_Powerset<PSET> universe(x.space_dimension(), UNIVERSE);
104397        Pointset_Powerset& xx = const_cast<Pointset_Powerset&>(x);
104398        swap(xx, universe);
104399      }
104400      return true;
104401    }
104402  }
104403  return false;
104404}
104405
104406template <typename PSET>
104407bool
104408Pointset_Powerset<PSET>::is_empty() const {
104409  const Pointset_Powerset& x = *this;
104410  for (Sequence_const_iterator si = x.sequence.begin(),
104411         s_end = x.sequence.end(); si != s_end; ++si) {
104412    if (!si->pointset().is_empty()) {
104413      return false;
104414    }
104415  }
104416  return true;
104417}
104418
104419template <typename PSET>
104420bool
104421Pointset_Powerset<PSET>::is_discrete() const {
104422  const Pointset_Powerset& x = *this;
104423  for (Sequence_const_iterator si = x.sequence.begin(),
104424         s_end = x.sequence.end(); si != s_end; ++si) {
104425    if (!si->pointset().is_discrete()) {
104426      return false;
104427    }
104428  }
104429  return true;
104430}
104431
104432template <typename PSET>
104433bool
104434Pointset_Powerset<PSET>::is_topologically_closed() const {
104435  const Pointset_Powerset& x = *this;
104436  // The powerset must be omega-reduced before checking
104437  // topological closure.
104438  x.omega_reduce();
104439  for (Sequence_const_iterator si = x.sequence.begin(),
104440         s_end = x.sequence.end(); si != s_end; ++si) {
104441    if (!si->pointset().is_topologically_closed()) {
104442      return false;
104443    }
104444  }
104445  return true;
104446}
104447
104448template <typename PSET>
104449bool
104450Pointset_Powerset<PSET>::is_bounded() const {
104451  const Pointset_Powerset& x = *this;
104452  for (Sequence_const_iterator si = x.sequence.begin(),
104453         s_end = x.sequence.end(); si != s_end; ++si) {
104454    if (!si->pointset().is_bounded()) {
104455      return false;
104456    }
104457  }
104458  return true;
104459}
104460
104461template <typename PSET>
104462bool
104463Pointset_Powerset<PSET>::constrains(Variable var) const {
104464  const Pointset_Powerset& x = *this;
104465  // `var' should be one of the dimensions of the powerset.
104466  const dimension_type var_space_dim = var.space_dimension();
104467  if (x.space_dimension() < var_space_dim) {
104468    std::ostringstream s;
104469    s << "PPL::Pointset_Powerset<PSET>::constrains(v):\n"
104470      << "this->space_dimension() == " << x.space_dimension() << ", "
104471      << "v.space_dimension() == " << var_space_dim << ".";
104472    throw std::invalid_argument(s.str());
104473  }
104474  // omega_reduction needed, since a redundant disjunct may constrain var.
104475  x.omega_reduce();
104476  // An empty powerset constrains all variables.
104477  if (x.is_empty()) {
104478    return true;
104479  }
104480  for (const_iterator x_i = x.begin(), x_end = x.end();
104481       x_i != x_end; ++x_i) {
104482    if (x_i->pointset().constrains(var)) {
104483      return true;
104484    }
104485  }
104486  return false;
104487}
104488
104489template <typename PSET>
104490bool
104491Pointset_Powerset<PSET>::is_disjoint_from(const Pointset_Powerset& y) const {
104492  const Pointset_Powerset& x = *this;
104493  for (Sequence_const_iterator si = x.sequence.begin(),
104494         x_s_end = x.sequence.end(); si != x_s_end; ++si) {
104495    const PSET& pi = si->pointset();
104496    for (Sequence_const_iterator sj = y.sequence.begin(),
104497           y_s_end = y.sequence.end(); sj != y_s_end; ++sj) {
104498      const PSET& pj = sj->pointset();
104499      if (!pi.is_disjoint_from(pj)) {
104500        return false;
104501      }
104502    }
104503  }
104504  return true;
104505}
104506
104507template <typename PSET>
104508void
104509Pointset_Powerset<PSET>
104510::drop_some_non_integer_points(const Variables_Set& vars,
104511                               Complexity_Class complexity) {
104512  Pointset_Powerset& x = *this;
104513  for (Sequence_iterator si = x.sequence.begin(),
104514         s_end = x.sequence.end(); si != s_end; ++si) {
104515    si->pointset().drop_some_non_integer_points(vars, complexity);
104516  }
104517  x.reduced = false;
104518  PPL_ASSERT_HEAVY(x.OK());
104519}
104520
104521template <typename PSET>
104522void
104523Pointset_Powerset<PSET>
104524::drop_some_non_integer_points(Complexity_Class complexity) {
104525  Pointset_Powerset& x = *this;
104526  for (Sequence_iterator si = x.sequence.begin(),
104527         s_end = x.sequence.end(); si != s_end; ++si) {
104528    si->pointset().drop_some_non_integer_points(complexity);
104529  }
104530  x.reduced = false;
104531  PPL_ASSERT_HEAVY(x.OK());
104532}
104533
104534template <typename PSET>
104535void
104536Pointset_Powerset<PSET>::topological_closure_assign() {
104537  Pointset_Powerset& x = *this;
104538  for (Sequence_iterator si = x.sequence.begin(),
104539         s_end = x.sequence.end(); si != s_end; ++si) {
104540    si->pointset().topological_closure_assign();
104541  }
104542  PPL_ASSERT_HEAVY(x.OK());
104543}
104544
104545template <typename PSET>
104546bool
104547Pointset_Powerset<PSET>
104548::intersection_preserving_enlarge_element(PSET& dest) const {
104549  // FIXME: this is just an executable specification.
104550  const Pointset_Powerset& context = *this;
104551  PPL_ASSERT(context.space_dimension() == dest.space_dimension());
104552  bool nonempty_intersection = false;
104553  // TODO: maybe use a *sorted* constraint system?
104554  PSET enlarged(context.space_dimension(), UNIVERSE);
104555  for (Sequence_const_iterator si = context.sequence.begin(),
104556         s_end = context.sequence.end(); si != s_end; ++si) {
104557    PSET context_i(si->pointset());
104558    context_i.intersection_assign(enlarged);
104559    PSET enlarged_i(dest);
104560    if (enlarged_i.simplify_using_context_assign(context_i)) {
104561      nonempty_intersection = true;
104562    }
104563    // TODO: merge the sorted constraints of `enlarged' and `enlarged_i'?
104564    enlarged.intersection_assign(enlarged_i);
104565  }
104566  swap(dest, enlarged);
104567  return nonempty_intersection;
104568}
104569
104570template <typename PSET>
104571bool
104572Pointset_Powerset<PSET>
104573::simplify_using_context_assign(const Pointset_Powerset& y) {
104574  Pointset_Powerset& x = *this;
104575
104576  // Omega reduction is required.
104577  // TODO: check whether it would be more efficient to Omega-reduce x
104578  // during the simplification process: when examining *si, we check
104579  // if it has been made redundant by any of the elements preceding it
104580  // (which have been already simplified).
104581  x.omega_reduce();
104582  if (x.is_empty()) {
104583    return false;
104584  }
104585  y.omega_reduce();
104586  if (y.is_empty()) {
104587    x = y;
104588    return false;
104589  }
104590
104591  if (y.size() == 1) {
104592    // More efficient, special handling of the singleton context case.
104593    const PSET& y_i = y.sequence.begin()->pointset();
104594    for (Sequence_iterator si = x.sequence.begin(),
104595           s_end = x.sequence.end(); si != s_end; ) {
104596      PSET& x_i = si->pointset();
104597      if (x_i.simplify_using_context_assign(y_i)) {
104598        ++si;
104599      }
104600      else {
104601        // Intersection is empty: drop the disjunct.
104602        si = x.sequence.erase(si);
104603      }
104604    }
104605  }
104606  else {
104607    // The context is not a singleton.
104608    for (Sequence_iterator si = x.sequence.begin(),
104609           s_end = x.sequence.end(); si != s_end; ) {
104610      if (y.intersection_preserving_enlarge_element(si->pointset())) {
104611        ++si;
104612      }
104613      else {
104614        // Intersection with `*si' is empty: drop the disjunct.
104615        si = x.sequence.erase(si);
104616      }
104617    }
104618  }
104619  x.reduced = false;
104620  PPL_ASSERT_HEAVY(x.OK());
104621  return !x.sequence.empty();
104622}
104623
104624template <typename PSET>
104625bool
104626Pointset_Powerset<PSET>::contains(const Pointset_Powerset& y) const {
104627  const Pointset_Powerset& x = *this;
104628  for (Sequence_const_iterator si = y.sequence.begin(),
104629         y_s_end = y.sequence.end(); si != y_s_end; ++si) {
104630    const PSET& pi = si->pointset();
104631    bool pi_is_contained = false;
104632    for (Sequence_const_iterator sj = x.sequence.begin(),
104633           x_s_end = x.sequence.end();
104634         (sj != x_s_end && !pi_is_contained);
104635         ++sj) {
104636      const PSET& pj = sj->pointset();
104637      if (pj.contains(pi)) {
104638        pi_is_contained = true;
104639      }
104640    }
104641    if (!pi_is_contained) {
104642      return false;
104643    }
104644  }
104645  return true;
104646}
104647
104648template <typename PSET>
104649bool
104650Pointset_Powerset<PSET>::strictly_contains(const Pointset_Powerset& y) const {
104651  /* omega reduction ensures that a disjunct of y cannot be strictly
104652     contained in one disjunct and also contained but not strictly
104653     contained in another disjunct of *this */
104654  const Pointset_Powerset& x = *this;
104655  x.omega_reduce();
104656  for (Sequence_const_iterator si = y.sequence.begin(),
104657         y_s_end = y.sequence.end(); si != y_s_end; ++si) {
104658    const PSET& pi = si->pointset();
104659    bool pi_is_strictly_contained = false;
104660    for (Sequence_const_iterator sj = x.sequence.begin(),
104661           x_s_end = x.sequence.end();
104662         (sj != x_s_end && !pi_is_strictly_contained); ++sj) {
104663      const PSET& pj = sj->pointset();
104664      if (pj.strictly_contains(pi)) {
104665        pi_is_strictly_contained = true;
104666      }
104667    }
104668    if (!pi_is_strictly_contained) {
104669      return false;
104670    }
104671  }
104672  return true;
104673}
104674
104675template <typename PSET>
104676template <typename Cons_or_Congr>
104677Poly_Con_Relation
104678Pointset_Powerset<PSET>::relation_with_aux(const Cons_or_Congr& c) const {
104679  const Pointset_Powerset& x = *this;
104680
104681  /* *this is included in c if every disjunct is included in c */
104682  bool is_included = true;
104683  /* *this is disjoint with c if every disjunct is disjoint with c */
104684  bool is_disjoint = true;
104685  /* *this strictly_intersects with c if:
104686       - some disjunct strictly intersects with c
104687     or
104688       - there exists two disjoints d1 and d2
104689         such that d1 is included in c and d2 is disjoint with c
104690  */
104691  bool is_strictly_intersecting = false;
104692  bool included_once = false;
104693  bool disjoint_once = false;
104694  /* *this saturates c if all disjuncts saturate c */
104695  bool saturates = true;
104696  for (Sequence_const_iterator si = x.sequence.begin(),
104697         s_end = x.sequence.end(); si != s_end; ++si) {
104698    Poly_Con_Relation relation_i = si->pointset().relation_with(c);
104699    if (relation_i.implies(Poly_Con_Relation::is_included())) {
104700      included_once = true;
104701    }
104702    else {
104703      is_included = false;
104704    }
104705    if (relation_i.implies(Poly_Con_Relation::is_disjoint())) {
104706      disjoint_once = true;
104707    }
104708    else {
104709      is_disjoint = false;
104710    }
104711    if (relation_i.implies(Poly_Con_Relation::strictly_intersects())) {
104712      is_strictly_intersecting = true;
104713    }
104714    if (!relation_i.implies(Poly_Con_Relation::saturates())) {
104715      saturates = false;
104716    }
104717  }
104718
104719  Poly_Con_Relation result = Poly_Con_Relation::nothing();
104720  if (is_included) {
104721    result = result && Poly_Con_Relation::is_included();
104722  }
104723  if (is_disjoint) {
104724    result = result && Poly_Con_Relation::is_disjoint();
104725  }
104726  if (is_strictly_intersecting || (included_once && disjoint_once)) {
104727    result = result && Poly_Con_Relation::strictly_intersects();
104728  }
104729  if (saturates) {
104730    result = result && Poly_Con_Relation::saturates();
104731  }
104732  return result;
104733}
104734
104735template <typename PSET>
104736Poly_Gen_Relation
104737Pointset_Powerset<PSET>::relation_with(const Generator& g) const {
104738  const Pointset_Powerset& x = *this;
104739
104740  for (Sequence_const_iterator si = x.sequence.begin(),
104741         s_end = x.sequence.end(); si != s_end; ++si) {
104742    Poly_Gen_Relation relation_i = si->pointset().relation_with(g);
104743    if (relation_i.implies(Poly_Gen_Relation::subsumes())) {
104744      return Poly_Gen_Relation::subsumes();
104745    }
104746  }
104747
104748  return Poly_Gen_Relation::nothing();
104749}
104750
104751template <typename PSET>
104752bool
104753Pointset_Powerset<PSET>
104754::bounds_from_above(const Linear_Expression& expr) const {
104755  const Pointset_Powerset& x = *this;
104756  x.omega_reduce();
104757  for (Sequence_const_iterator si = x.sequence.begin(),
104758         s_end = x.sequence.end(); si != s_end; ++si) {
104759    if (!si->pointset().bounds_from_above(expr)) {
104760      return false;
104761    }
104762  }
104763  return true;
104764}
104765
104766template <typename PSET>
104767bool
104768Pointset_Powerset<PSET>
104769::bounds_from_below(const Linear_Expression& expr) const {
104770  const Pointset_Powerset& x = *this;
104771  x.omega_reduce();
104772  for (Sequence_const_iterator si = x.sequence.begin(),
104773         s_end = x.sequence.end(); si != s_end; ++si) {
104774    if (!si->pointset().bounds_from_below(expr)) {
104775      return false;
104776    }
104777  }
104778  return true;
104779}
104780
104781template <typename PSET>
104782bool
104783Pointset_Powerset<PSET>::maximize(const Linear_Expression& expr,
104784                                  Coefficient& sup_n,
104785                                  Coefficient& sup_d,
104786                                  bool& maximum) const {
104787  const Pointset_Powerset& x = *this;
104788  x.omega_reduce();
104789  if (x.is_empty()) {
104790    return false;
104791  }
104792
104793  bool first = true;
104794
104795  PPL_DIRTY_TEMP_COEFFICIENT(best_sup_n);
104796  PPL_DIRTY_TEMP_COEFFICIENT(best_sup_d);
104797  best_sup_n = 0;
104798  best_sup_d = 1;
104799  bool best_max = false;
104800
104801  PPL_DIRTY_TEMP_COEFFICIENT(iter_sup_n);
104802  PPL_DIRTY_TEMP_COEFFICIENT(iter_sup_d);
104803  iter_sup_n = 0;
104804  iter_sup_d = 1;
104805  bool iter_max = false;
104806
104807  PPL_DIRTY_TEMP_COEFFICIENT(tmp);
104808
104809  for (Sequence_const_iterator si = x.sequence.begin(),
104810         s_end = x.sequence.end(); si != s_end; ++si) {
104811    if (!si->pointset().maximize(expr, iter_sup_n, iter_sup_d, iter_max)) {
104812      return false;
104813    }
104814    else
104815      if (first) {
104816        first = false;
104817        best_sup_n = iter_sup_n;
104818        best_sup_d = iter_sup_d;
104819        best_max = iter_max;
104820      }
104821      else {
104822        tmp = (best_sup_n * iter_sup_d) - (iter_sup_n * best_sup_d);
104823        if (tmp < 0) {
104824          best_sup_n = iter_sup_n;
104825          best_sup_d = iter_sup_d;
104826          best_max = iter_max;
104827        }
104828        else if (tmp == 0) {
104829          best_max = (best_max || iter_max);
104830        }
104831      }
104832  }
104833  sup_n = best_sup_n;
104834  sup_d = best_sup_d;
104835  maximum = best_max;
104836  return true;
104837}
104838
104839template <typename PSET>
104840bool
104841Pointset_Powerset<PSET>::maximize(const Linear_Expression& expr,
104842                                  Coefficient& sup_n,
104843                                  Coefficient& sup_d,
104844                                  bool& maximum,
104845                                  Generator& g) const {
104846  const Pointset_Powerset& x = *this;
104847  x.omega_reduce();
104848  if (x.is_empty()) {
104849    return false;
104850  }
104851
104852  bool first = true;
104853
104854  PPL_DIRTY_TEMP_COEFFICIENT(best_sup_n);
104855  PPL_DIRTY_TEMP_COEFFICIENT(best_sup_d);
104856  best_sup_n = 0;
104857  best_sup_d = 1;
104858  bool best_max = false;
104859  Generator best_g = point();
104860
104861  PPL_DIRTY_TEMP_COEFFICIENT(iter_sup_n);
104862  PPL_DIRTY_TEMP_COEFFICIENT(iter_sup_d);
104863  iter_sup_n = 0;
104864  iter_sup_d = 1;
104865  bool iter_max = false;
104866  Generator iter_g = point();
104867
104868  PPL_DIRTY_TEMP_COEFFICIENT(tmp);
104869
104870  for (Sequence_const_iterator si = x.sequence.begin(),
104871         s_end = x.sequence.end(); si != s_end; ++si) {
104872    if (!si->pointset().maximize(expr,
104873                                 iter_sup_n, iter_sup_d, iter_max, iter_g)) {
104874      return false;
104875    }
104876    else {
104877      if (first) {
104878        first = false;
104879        best_sup_n = iter_sup_n;
104880        best_sup_d = iter_sup_d;
104881        best_max = iter_max;
104882        best_g = iter_g;
104883      }
104884      else {
104885        tmp = (best_sup_n * iter_sup_d) - (iter_sup_n * best_sup_d);
104886        if (tmp < 0) {
104887          best_sup_n = iter_sup_n;
104888          best_sup_d = iter_sup_d;
104889          best_max = iter_max;
104890          best_g = iter_g;
104891        }
104892        else if (tmp == 0) {
104893          best_max = (best_max || iter_max);
104894          best_g = iter_g;
104895        }
104896      }
104897    }
104898  }
104899  sup_n = best_sup_n;
104900  sup_d = best_sup_d;
104901  maximum = best_max;
104902  g = best_g;
104903  return true;
104904}
104905
104906template <typename PSET>
104907bool
104908Pointset_Powerset<PSET>::minimize(const Linear_Expression& expr,
104909                                  Coefficient& inf_n,
104910                                  Coefficient& inf_d,
104911                                  bool& minimum) const {
104912  const Pointset_Powerset& x = *this;
104913  x.omega_reduce();
104914  if (x.is_empty()) {
104915    return false;
104916  }
104917
104918  bool first = true;
104919
104920  PPL_DIRTY_TEMP_COEFFICIENT(best_inf_n);
104921  PPL_DIRTY_TEMP_COEFFICIENT(best_inf_d);
104922  best_inf_n = 0;
104923  best_inf_d = 1;
104924  bool best_min = false;
104925
104926  PPL_DIRTY_TEMP_COEFFICIENT(iter_inf_n);
104927  PPL_DIRTY_TEMP_COEFFICIENT(iter_inf_d);
104928  iter_inf_n = 0;
104929  iter_inf_d = 1;
104930  bool iter_min = false;
104931
104932  PPL_DIRTY_TEMP_COEFFICIENT(tmp);
104933
104934  for (Sequence_const_iterator si = x.sequence.begin(),
104935         s_end = x.sequence.end(); si != s_end; ++si) {
104936    if (!si->pointset().minimize(expr, iter_inf_n, iter_inf_d, iter_min)) {
104937      return false;
104938    }
104939    else {
104940      if (first) {
104941        first = false;
104942        best_inf_n = iter_inf_n;
104943        best_inf_d = iter_inf_d;
104944        best_min = iter_min;
104945      }
104946      else {
104947        tmp = (best_inf_n * iter_inf_d) - (iter_inf_n * best_inf_d);
104948        if (tmp > 0) {
104949          best_inf_n = iter_inf_n;
104950          best_inf_d = iter_inf_d;
104951          best_min = iter_min;
104952        }
104953        else if (tmp == 0) {
104954          best_min = (best_min || iter_min);
104955        }
104956      }
104957    }
104958  }
104959  inf_n = best_inf_n;
104960  inf_d = best_inf_d;
104961  minimum = best_min;
104962  return true;
104963}
104964
104965template <typename PSET>
104966bool
104967Pointset_Powerset<PSET>::minimize(const Linear_Expression& expr,
104968                                  Coefficient& inf_n,
104969                                  Coefficient& inf_d,
104970                                  bool& minimum,
104971                                  Generator& g) const {
104972  const Pointset_Powerset& x = *this;
104973  x.omega_reduce();
104974  if (x.is_empty()) {
104975    return false;
104976  }
104977
104978  bool first = true;
104979
104980  PPL_DIRTY_TEMP_COEFFICIENT(best_inf_n);
104981  PPL_DIRTY_TEMP_COEFFICIENT(best_inf_d);
104982  best_inf_n = 0;
104983  best_inf_d = 1;
104984  bool best_min = false;
104985  Generator best_g = point();
104986
104987  PPL_DIRTY_TEMP_COEFFICIENT(iter_inf_n);
104988  PPL_DIRTY_TEMP_COEFFICIENT(iter_inf_d);
104989  iter_inf_n = 0;
104990  iter_inf_d = 1;
104991  bool iter_min = false;
104992  Generator iter_g = point();
104993
104994  PPL_DIRTY_TEMP_COEFFICIENT(tmp);
104995
104996  for (Sequence_const_iterator si = x.sequence.begin(),
104997         s_end = x.sequence.end(); si != s_end; ++si) {
104998    if (!si->pointset().minimize(expr,
104999                                 iter_inf_n, iter_inf_d, iter_min, iter_g)) {
105000      return false;
105001    }
105002    else {
105003      if (first) {
105004        first = false;
105005        best_inf_n = iter_inf_n;
105006        best_inf_d = iter_inf_d;
105007        best_min = iter_min;
105008        best_g = iter_g;
105009      }
105010      else {
105011        tmp = (best_inf_n * iter_inf_d) - (iter_inf_n * best_inf_d);
105012        if (tmp > 0) {
105013          best_inf_n = iter_inf_n;
105014          best_inf_d = iter_inf_d;
105015          best_min = iter_min;
105016          best_g = iter_g;
105017        }
105018        else if (tmp == 0) {
105019          best_min = (best_min || iter_min);
105020          best_g = iter_g;
105021        }
105022      }
105023    }
105024  }
105025  inf_n = best_inf_n;
105026  inf_d = best_inf_d;
105027  minimum = best_min;
105028  g = best_g;
105029  return true;
105030}
105031
105032template <typename PSET>
105033bool
105034Pointset_Powerset<PSET>::contains_integer_point() const {
105035  const Pointset_Powerset& x = *this;
105036  for (Sequence_const_iterator si = x.sequence.begin(),
105037         s_end = x.sequence.end(); si != s_end; ++si) {
105038    if (si->pointset().contains_integer_point()) {
105039      return true;
105040    }
105041  }
105042  return false;
105043}
105044
105045template <typename PSET>
105046void
105047Pointset_Powerset<PSET>::wrap_assign(const Variables_Set& vars,
105048                                     Bounded_Integer_Type_Width w,
105049                                     Bounded_Integer_Type_Representation r,
105050                                     Bounded_Integer_Type_Overflow o,
105051                                     const Constraint_System* cs_p,
105052                                     unsigned complexity_threshold,
105053                                     bool wrap_individually) {
105054  Pointset_Powerset& x = *this;
105055  for (Sequence_iterator si = x.sequence.begin(),
105056         s_end = x.sequence.end(); si != s_end; ++si) {
105057    si->pointset().wrap_assign(vars, w, r, o, cs_p,
105058                               complexity_threshold, wrap_individually);
105059  }
105060  x.reduced = false;
105061  PPL_ASSERT_HEAVY(x.OK());
105062}
105063
105064template <typename PSET>
105065void
105066Pointset_Powerset<PSET>::pairwise_reduce() {
105067  Pointset_Powerset& x = *this;
105068  // It is wise to omega-reduce before pairwise-reducing.
105069  x.omega_reduce();
105070
105071  size_type n = x.size();
105072  size_type deleted;
105073  do {
105074    Pointset_Powerset new_x(x.space_dim, EMPTY);
105075    std::deque<bool> marked(n, false);
105076    deleted = 0;
105077    Sequence_iterator s_begin = x.sequence.begin();
105078    Sequence_iterator s_end = x.sequence.end();
105079    unsigned si_index = 0;
105080    for (Sequence_iterator si = s_begin; si != s_end; ++si, ++si_index) {
105081      if (marked[si_index]) {
105082        continue;
105083      }
105084      PSET& pi = si->pointset();
105085      Sequence_const_iterator sj = si;
105086      unsigned sj_index = si_index;
105087      for (++sj, ++sj_index; sj != s_end; ++sj, ++sj_index) {
105088        if (marked[sj_index]) {
105089          continue;
105090        }
105091        const PSET& pj = sj->pointset();
105092        if (pi.upper_bound_assign_if_exact(pj)) {
105093          marked[si_index] = true;
105094          marked[sj_index] = true;
105095          new_x.add_non_bottom_disjunct_preserve_reduction(pi);
105096          ++deleted;
105097          goto next;
105098        }
105099      }
105100    next:
105101      ;
105102    }
105103    iterator new_x_begin = new_x.begin();
105104    iterator new_x_end = new_x.end();
105105    unsigned xi_index = 0;
105106    for (const_iterator xi = x.begin(),
105107           x_end = x.end(); xi != x_end; ++xi, ++xi_index) {
105108      if (!marked[xi_index]) {
105109        new_x_begin
105110          = new_x.add_non_bottom_disjunct_preserve_reduction(*xi,
105111                                                             new_x_begin,
105112                                                             new_x_end);
105113      }
105114    }
105115    using std::swap;
105116    swap(x.sequence, new_x.sequence);
105117    n -= deleted;
105118  } while (deleted > 0);
105119  PPL_ASSERT_HEAVY(x.OK());
105120}
105121
105122template <typename PSET>
105123template <typename Widening>
105124void
105125Pointset_Powerset<PSET>::
105126BGP99_heuristics_assign(const Pointset_Powerset& y, Widening widen_fun) {
105127  // `x' is the current iteration value.
105128  Pointset_Powerset& x = *this;
105129
105130#ifndef NDEBUG
105131  {
105132    // We assume that `y' entails `x'.
105133    const Pointset_Powerset<PSET> x_copy = x;
105134    const Pointset_Powerset<PSET> y_copy = y;
105135    PPL_ASSERT_HEAVY(y_copy.definitely_entails(x_copy));
105136  }
105137#endif
105138
105139  size_type n = x.size();
105140  Pointset_Powerset new_x(x.space_dim, EMPTY);
105141  std::deque<bool> marked(n, false);
105142  const_iterator x_begin = x.begin();
105143  const_iterator x_end = x.end();
105144  unsigned i_index = 0;
105145  for (const_iterator i = x_begin,
105146         y_begin = y.begin(), y_end = y.end();
105147         i != x_end; ++i, ++i_index) {
105148    for (const_iterator j = y_begin; j != y_end; ++j) {
105149      const PSET& pi = i->pointset();
105150      const PSET& pj = j->pointset();
105151      if (pi.contains(pj)) {
105152        PSET pi_copy = pi;
105153        widen_fun(pi_copy, pj);
105154        new_x.add_non_bottom_disjunct_preserve_reduction(pi_copy);
105155        marked[i_index] = true;
105156      }
105157    }
105158  }
105159  iterator new_x_begin = new_x.begin();
105160  iterator new_x_end = new_x.end();
105161  i_index = 0;
105162  for (const_iterator i = x_begin; i != x_end; ++i, ++i_index) {
105163    if (!marked[i_index]) {
105164      new_x_begin
105165        = new_x.add_non_bottom_disjunct_preserve_reduction(*i,
105166                                                           new_x_begin,
105167                                                           new_x_end);
105168    }
105169  }
105170  using std::swap;
105171  swap(x.sequence, new_x.sequence);
105172  PPL_ASSERT_HEAVY(x.OK());
105173  PPL_ASSERT(x.is_omega_reduced());
105174}
105175
105176template <typename PSET>
105177template <typename Widening>
105178void
105179Pointset_Powerset<PSET>::
105180BGP99_extrapolation_assign(const Pointset_Powerset& y,
105181                           Widening widen_fun,
105182                           unsigned max_disjuncts) {
105183  // `x' is the current iteration value.
105184  Pointset_Powerset& x = *this;
105185
105186#ifndef NDEBUG
105187  {
105188    // We assume that `y' entails `x'.
105189    const Pointset_Powerset<PSET> x_copy = x;
105190    const Pointset_Powerset<PSET> y_copy = y;
105191    PPL_ASSERT_HEAVY(y_copy.definitely_entails(x_copy));
105192  }
105193#endif
105194
105195  x.pairwise_reduce();
105196  if (max_disjuncts != 0) {
105197    x.collapse(max_disjuncts);
105198  }
105199  x.BGP99_heuristics_assign(y, widen_fun);
105200}
105201
105202template <typename PSET>
105203template <typename Cert>
105204void
105205Pointset_Powerset<PSET>::
105206collect_certificates(std::map<Cert, size_type,
105207                     typename Cert::Compare>& cert_ms) const {
105208  const Pointset_Powerset& x = *this;
105209  PPL_ASSERT(x.is_omega_reduced());
105210  PPL_ASSERT(cert_ms.size() == 0);
105211  for (const_iterator i = x.begin(), end = x.end(); i != end; ++i) {
105212    Cert ph_cert(i->pointset());
105213    ++cert_ms[ph_cert];
105214  }
105215}
105216
105217template <typename PSET>
105218template <typename Cert>
105219bool
105220Pointset_Powerset<PSET>::
105221is_cert_multiset_stabilizing(const std::map<Cert, size_type,
105222                             typename Cert::Compare>& y_cert_ms) const {
105223  typedef std::map<Cert, size_type, typename Cert::Compare> Cert_Multiset;
105224  Cert_Multiset x_cert_ms;
105225  collect_certificates(x_cert_ms);
105226  typename Cert_Multiset::const_iterator xi = x_cert_ms.begin();
105227  typename Cert_Multiset::const_iterator x_cert_ms_end = x_cert_ms.end();
105228  typename Cert_Multiset::const_iterator yi = y_cert_ms.begin();
105229  typename Cert_Multiset::const_iterator y_cert_ms_end = y_cert_ms.end();
105230  while (xi != x_cert_ms_end && yi != y_cert_ms_end) {
105231    const Cert& xi_cert = xi->first;
105232    const Cert& yi_cert = yi->first;
105233    switch (xi_cert.compare(yi_cert)) {
105234    case 0:
105235      // xi_cert == yi_cert: check the number of multiset occurrences.
105236      {
105237        const size_type& xi_count = xi->second;
105238        const size_type& yi_count = yi->second;
105239        if (xi_count == yi_count) {
105240          // Same number of occurrences: compare the next pair.
105241          ++xi;
105242          ++yi;
105243        }
105244        else {
105245          // Different number of occurrences: can decide ordering.
105246          return xi_count < yi_count;
105247        }
105248        break;
105249      }
105250    case 1:
105251      // xi_cert > yi_cert: it is not stabilizing.
105252      return false;
105253
105254    case -1:
105255      // xi_cert < yi_cert: it is stabilizing.
105256      return true;
105257    }
105258  }
105259  // Here xi == x_cert_ms_end or yi == y_cert_ms_end.
105260  // Stabilization is achieved if `y_cert_ms' still has other elements.
105261  return yi != y_cert_ms_end;
105262}
105263
105264template <typename PSET>
105265template <typename Cert, typename Widening>
105266void
105267Pointset_Powerset<PSET>::BHZ03_widening_assign(const Pointset_Powerset& y,
105268                                               Widening widen_fun) {
105269  // `x' is the current iteration value.
105270  Pointset_Powerset& x = *this;
105271
105272#ifndef NDEBUG
105273  {
105274    // We assume that `y' entails `x'.
105275    const Pointset_Powerset<PSET> x_copy = x;
105276    const Pointset_Powerset<PSET> y_copy = y;
105277    PPL_ASSERT_HEAVY(y_copy.definitely_entails(x_copy));
105278  }
105279#endif
105280
105281  // First widening technique: do nothing.
105282
105283  // If `y' is the empty collection, do nothing.
105284  PPL_ASSERT(x.size() > 0);
105285  if (y.size() == 0) {
105286    return;
105287  }
105288
105289  // Compute the poly-hull of `x'.
105290  PSET x_hull(x.space_dim, EMPTY);
105291  for (const_iterator i = x.begin(), x_end = x.end(); i != x_end; ++i) {
105292    x_hull.upper_bound_assign(i->pointset());
105293  }
105294
105295  // Compute the poly-hull of `y'.
105296  PSET y_hull(y.space_dim, EMPTY);
105297  for (const_iterator i = y.begin(), y_end = y.end(); i != y_end; ++i) {
105298    y_hull.upper_bound_assign(i->pointset());
105299  }
105300  // Compute the certificate for `y_hull'.
105301  const Cert y_hull_cert(y_hull);
105302
105303  // If the hull is stabilizing, do nothing.
105304  int hull_stabilization = y_hull_cert.compare(x_hull);
105305  if (hull_stabilization == 1) {
105306    return;
105307  }
105308
105309  // Multiset ordering is only useful when `y' is not a singleton.
105310  const bool y_is_not_a_singleton = y.size() > 1;
105311
105312  // The multiset certificate for `y':
105313  // we want to be lazy about its computation.
105314  typedef std::map<Cert, size_type, typename Cert::Compare> Cert_Multiset;
105315  Cert_Multiset y_cert_ms;
105316  bool y_cert_ms_computed = false;
105317
105318  if (hull_stabilization == 0 && y_is_not_a_singleton) {
105319    // Collect the multiset certificate for `y'.
105320    y.collect_certificates(y_cert_ms);
105321    y_cert_ms_computed = true;
105322    // If multiset ordering is stabilizing, do nothing.
105323    if (x.is_cert_multiset_stabilizing(y_cert_ms)) {
105324      return;
105325    }
105326  }
105327
105328  // Second widening technique: try the BGP99 powerset heuristics.
105329  Pointset_Powerset<PSET> bgp99_heuristics = x;
105330  bgp99_heuristics.BGP99_heuristics_assign(y, widen_fun);
105331
105332  // Compute the poly-hull of `bgp99_heuristics'.
105333  PSET bgp99_heuristics_hull(x.space_dim, EMPTY);
105334  for (const_iterator i = bgp99_heuristics.begin(),
105335         b_h_end = bgp99_heuristics.end(); i != b_h_end; ++i) {
105336    bgp99_heuristics_hull.upper_bound_assign(i->pointset());
105337  }
105338
105339  // Check for stabilization and, if successful,
105340  // commit to the result of the extrapolation.
105341  hull_stabilization = y_hull_cert.compare(bgp99_heuristics_hull);
105342  if (hull_stabilization == 1) {
105343    // The poly-hull is stabilizing.
105344    swap(x, bgp99_heuristics);
105345    return;
105346  }
105347  else if (hull_stabilization == 0 && y_is_not_a_singleton) {
105348    // If not already done, compute multiset certificate for `y'.
105349    if (!y_cert_ms_computed) {
105350      y.collect_certificates(y_cert_ms);
105351      y_cert_ms_computed = true;
105352    }
105353    if (bgp99_heuristics.is_cert_multiset_stabilizing(y_cert_ms)) {
105354      swap(x, bgp99_heuristics);
105355      return;
105356    }
105357    // Third widening technique: pairwise-reduction on `bgp99_heuristics'.
105358    // Note that pairwise-reduction does not affect the computation
105359    // of the poly-hulls, so that we only have to check the multiset
105360    // certificate relation.
105361    Pointset_Powerset<PSET> reduced_bgp99_heuristics(bgp99_heuristics);
105362    reduced_bgp99_heuristics.pairwise_reduce();
105363    if (reduced_bgp99_heuristics.is_cert_multiset_stabilizing(y_cert_ms)) {
105364      swap(x, reduced_bgp99_heuristics);
105365      return;
105366    }
105367  }
105368
105369  // Fourth widening technique: this is applicable only when
105370  // `y_hull' is a proper subset of `bgp99_heuristics_hull'.
105371  if (bgp99_heuristics_hull.strictly_contains(y_hull)) {
105372    // Compute (y_hull \widen bgp99_heuristics_hull).
105373    PSET ph = bgp99_heuristics_hull;
105374    widen_fun(ph, y_hull);
105375    // Compute the difference between `ph' and `bgp99_heuristics_hull'.
105376    ph.difference_assign(bgp99_heuristics_hull);
105377    x.add_disjunct(ph);
105378    return;
105379  }
105380
105381  // Fall back to the computation of the poly-hull.
105382  Pointset_Powerset<PSET> x_hull_singleton(x.space_dim, EMPTY);
105383  x_hull_singleton.add_disjunct(x_hull);
105384  swap(x, x_hull_singleton);
105385}
105386
105387template <typename PSET>
105388void
105389Pointset_Powerset<PSET>::ascii_dump(std::ostream& s) const {
105390  const Pointset_Powerset& x = *this;
105391  s << "size " << x.size()
105392    << "\nspace_dim " << x.space_dim
105393    << "\n";
105394  for (const_iterator xi = x.begin(), x_end = x.end();
105395       xi != x_end; ++xi) {
105396    xi->pointset().ascii_dump(s);
105397  }
105398}
105399
105400PPL_OUTPUT_TEMPLATE_DEFINITIONS(PSET, Pointset_Powerset<PSET>)
105401
105402template <typename PSET>
105403bool
105404Pointset_Powerset<PSET>::ascii_load(std::istream& s) {
105405  Pointset_Powerset& x = *this;
105406  std::string str;
105407
105408  if (!(s >> str) || str != "size") {
105409    return false;
105410  }
105411
105412  size_type sz;
105413
105414  if (!(s >> sz)) {
105415    return false;
105416  }
105417
105418  if (!(s >> str) || str != "space_dim") {
105419    return false;
105420  }
105421
105422  if (!(s >> x.space_dim)) {
105423    return false;
105424  }
105425
105426  Pointset_Powerset new_x(x.space_dim, EMPTY);
105427  while (sz-- > 0) {
105428    PSET ph;
105429    if (!ph.ascii_load(s)) {
105430      return false;
105431    }
105432    new_x.add_disjunct(ph);
105433  }
105434  swap(x, new_x);
105435
105436  // Check invariants.
105437  PPL_ASSERT_HEAVY(x.OK());
105438  return true;
105439}
105440
105441template <typename PSET>
105442bool
105443Pointset_Powerset<PSET>::OK() const {
105444  const Pointset_Powerset& x = *this;
105445  for (const_iterator xi = x.begin(), x_end = x.end(); xi != x_end; ++xi) {
105446    const PSET& pi = xi->pointset();
105447    if (pi.space_dimension() != x.space_dim) {
105448#ifndef NDEBUG
105449      std::cerr << "Space dimension mismatch: is " << pi.space_dimension()
105450                << " in an element of the sequence,\nshould be "
105451                << x.space_dim << "."
105452                << std::endl;
105453#endif
105454      return false;
105455    }
105456  }
105457  return x.Base::OK();
105458}
105459
105460namespace Implementation {
105461
105462namespace Pointset_Powersets {
105463
105464#ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
105465//! Partitions polyhedron \p pset according to constraint \p c.
105466/*! \relates Parma_Polyhedra_Library::Pointset_Powerset
105467  On exit, the intersection of \p pset and constraint \p c is stored
105468  in \p pset, whereas the intersection of \p pset with the negation of \p c
105469  is added as a new disjunct of the powerset \p r.
105470*/
105471#endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
105472template <typename PSET>
105473void
105474linear_partition_aux(const Constraint& c,
105475                     PSET& pset,
105476                     Pointset_Powerset<NNC_Polyhedron>& r) {
105477  const Linear_Expression le(c.expression());
105478  const Constraint& neg_c = c.is_strict_inequality() ? (le <= 0) : (le < 0);
105479  NNC_Polyhedron nnc_ph_pset(pset);
105480  nnc_ph_pset.add_constraint(neg_c);
105481  if (!nnc_ph_pset.is_empty()) {
105482    r.add_disjunct(nnc_ph_pset);
105483  }
105484  pset.add_constraint(c);
105485}
105486
105487} // namespace Pointset_Powersets
105488
105489} // namespace Implementation
105490
105491
105492/*! \relates Pointset_Powerset */
105493template <typename PSET>
105494std::pair<PSET, Pointset_Powerset<NNC_Polyhedron> >
105495linear_partition(const PSET& p, const PSET& q) {
105496  using Implementation::Pointset_Powersets::linear_partition_aux;
105497
105498  Pointset_Powerset<NNC_Polyhedron> r(p.space_dimension(), EMPTY);
105499  PSET pset = q;
105500  const Constraint_System& p_constraints = p.constraints();
105501  for (Constraint_System::const_iterator i = p_constraints.begin(),
105502         p_constraints_end = p_constraints.end();
105503       i != p_constraints_end;
105504       ++i) {
105505    const Constraint& c = *i;
105506    if (c.is_equality()) {
105507      const Linear_Expression le(c.expression());
105508      linear_partition_aux(le <= 0, pset, r);
105509      linear_partition_aux(le >= 0, pset, r);
105510    }
105511    else {
105512      linear_partition_aux(c, pset, r);
105513    }
105514  }
105515  return std::make_pair(pset, r);
105516}
105517
105518} // namespace Parma_Polyhedra_Library
105519
105520/* Automatically generated from PPL source file ../src/Pointset_Powerset_defs.hh line 1455. */
105521
105522/* Automatically generated from PPL source file ../src/algorithms.hh line 29. */
105523#include <utility>
105524
105525namespace Parma_Polyhedra_Library {
105526
105527#ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
105528/*! \brief
105529  If the poly-hull of \p p and \p q is exact it is assigned
105530  to \p p and <CODE>true</CODE> is returned,
105531  otherwise <CODE>false</CODE> is returned.
105532
105533  \relates Polyhedron
105534*/
105535#endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
105536template <typename PH>
105537bool
105538poly_hull_assign_if_exact(PH& p, const PH& q);
105539
105540#ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
105541/*! \relates Polyhedron */
105542#endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
105543template <typename PH>
105544bool
105545poly_hull_assign_if_exact(PH& p, const PH& q) {
105546  PH poly_hull = p;
105547  NNC_Polyhedron nnc_p(p);
105548  poly_hull.poly_hull_assign(q);
105549  std::pair<PH, Pointset_Powerset<NNC_Polyhedron> >
105550    partition = linear_partition(q, poly_hull);
105551  const Pointset_Powerset<NNC_Polyhedron>& s = partition.second;
105552  typedef Pointset_Powerset<NNC_Polyhedron>::const_iterator iter;
105553  for (iter i = s.begin(), s_end = s.end(); i != s_end; ++i) {
105554    // The polyhedral hull is exact if and only if all the elements
105555    // of the partition of the polyhedral hull of `p' and `q' with
105556    // respect to `q' are included in `p'
105557    if (!nnc_p.contains(i->pointset())) {
105558      return false;
105559    }
105560  }
105561  p = poly_hull;
105562  return true;
105563}
105564
105565} // namespace Parma_Polyhedra_Library
105566
105567/* Automatically generated from PPL source file ../src/termination_defs.hh line 1. */
105568/* Utilities for termination analysis: declarations.
105569*/
105570
105571
105572/* Automatically generated from PPL source file ../src/termination_defs.hh line 28. */
105573
105574/* Automatically generated from PPL source file ../src/termination_defs.hh line 33. */
105575
105576namespace Parma_Polyhedra_Library {
105577
105578class Termination_Helpers {
105579public:
105580  static void
105581  all_affine_ranking_functions_PR(const Constraint_System& cs_before,
105582                                  const Constraint_System& cs_after,
105583                                  NNC_Polyhedron& mu_space);
105584  static bool
105585  one_affine_ranking_function_PR(const Constraint_System& cs_before,
105586                                 const Constraint_System& cs_after,
105587                                 Generator& mu);
105588  static bool
105589  one_affine_ranking_function_PR_original(const Constraint_System& cs,
105590                                          Generator& mu);
105591  static void
105592  all_affine_ranking_functions_PR_original(const Constraint_System& cs,
105593                                           NNC_Polyhedron& mu_space);
105594
105595  template <typename PSET>
105596  static void
105597  assign_all_inequalities_approximation(const PSET& pset_before,
105598                                        const PSET& pset_after,
105599                                        Constraint_System& cs);
105600}; // class Termination_Helpers
105601
105602//! \name Functions for the Synthesis of Linear Rankings
105603//@{
105604
105605/*! \ingroup PPL_CXX_interface \brief
105606  Termination test using an improvement of the method by Mesnard and
105607  Serebrenik \ref BMPZ10 "[BMPZ10]".
105608
105609  \tparam PSET
105610  Any pointset supported by the PPL that provides the
105611  <CODE>minimized_constraints()</CODE> method.
105612
105613  \param pset
105614  A pointset approximating the behavior of a loop whose termination
105615  is being analyzed.  The variables indices are allocated as follows:
105616  - \f$ x'_1, \ldots, x'_n \f$ go onto space dimensions
105617    \f$ 0, \ldots, n-1 \f$,
105618  - \f$ x_1, \ldots, x_n \f$ go onto space dimensions
105619    \f$ n, \ldots, 2n-1 \f$,
105620  .
105621  where unprimed variables represent the values of the loop-relevant
105622  program variables before the update performed in the loop body,
105623  and primed variables represent the values of those program variables
105624  after the update.
105625
105626  \return
105627  <CODE>true</CODE> if any loop approximated by \p pset definitely
105628  terminates; <CODE>false</CODE> if the test is inconclusive.
105629  However, if \p pset <EM>precisely</EM> characterizes the effect
105630  of the loop body onto the loop-relevant program variables,
105631  then <CODE>true</CODE> is returned <EM>if and only if</EM>
105632  the loop terminates.
105633*/
105634template <typename PSET>
105635bool
105636termination_test_MS(const PSET& pset);
105637
105638/*! \ingroup PPL_CXX_interface \brief
105639  Termination test using an improvement of the method by Mesnard and
105640  Serebrenik \ref BMPZ10 "[BMPZ10]".
105641
105642  \tparam PSET
105643  Any pointset supported by the PPL that provides the
105644  <CODE>minimized_constraints()</CODE> method.
105645
105646  \param pset_before
105647  A pointset approximating the values of loop-relevant variables
105648  <EM>before</EM> the update performed in the loop body that is being
105649  analyzed.  The variables indices are allocated as follows:
105650  - \f$ x_1, \ldots, x_n \f$ go onto space dimensions
105651    \f$ 0, \ldots, n-1 \f$.
105652
105653  \param pset_after
105654  A pointset approximating the values of loop-relevant variables
105655  <EM>after</EM> the update performed in the loop body that is being
105656  analyzed.  The variables indices are allocated as follows:
105657  - \f$ x'_1, \ldots, x'_n \f$ go onto space dimensions
105658    \f$ 0, \ldots, n-1 \f$,
105659  - \f$ x_1, \ldots, x_n \f$ go onto space dimensions
105660    \f$ n, \ldots, 2n-1 \f$,
105661
105662  Note that unprimed variables represent the values of the loop-relevant
105663  program variables before the update performed in the loop body,
105664  and primed variables represent the values of those program variables
105665  after the update.  Note also that unprimed variables are assigned
105666  to different space dimensions in \p pset_before and \p pset_after.
105667
105668  \return
105669  <CODE>true</CODE> if any loop approximated by \p pset definitely
105670  terminates; <CODE>false</CODE> if the test is inconclusive.
105671  However, if \p pset_before and \p pset_after <EM>precisely</EM>
105672  characterize the effect of the loop body onto the loop-relevant
105673  program variables, then <CODE>true</CODE> is returned
105674  <EM>if and only if</EM> the loop terminates.
105675*/
105676template <typename PSET>
105677bool
105678termination_test_MS_2(const PSET& pset_before, const PSET& pset_after);
105679
105680/*! \ingroup PPL_CXX_interface \brief
105681  Termination test with witness ranking function using an improvement
105682  of the method by Mesnard and Serebrenik \ref BMPZ10 "[BMPZ10]".
105683
105684  \tparam PSET
105685  Any pointset supported by the PPL that provides the
105686  <CODE>minimized_constraints()</CODE> method.
105687
105688  \param pset
105689  A pointset approximating the behavior of a loop whose termination
105690  is being analyzed.  The variables indices are allocated as follows:
105691  - \f$ x'_1, \ldots, x'_n \f$ go onto space dimensions
105692    \f$ 0, \ldots, n-1 \f$,
105693  - \f$ x_1, \ldots, x_n \f$ go onto space dimensions
105694    \f$ n, \ldots, 2n-1 \f$,
105695  .
105696  where unprimed variables represent the values of the loop-relevant
105697  program variables before the update performed in the loop body,
105698  and primed variables represent the values of those program variables
105699  after the update.
105700
105701  \param mu
105702  When <CODE>true</CODE> is returned, this is assigned a point
105703  of space dimension \f$ n+1 \f$ encoding one (not further specified)
105704  affine ranking function for the loop being analyzed.
105705  The ranking function is of the form \f$ \mu_0 + \sum_{i=1}^n \mu_i x_i \f$
105706  where \f$ \mu_0, \mu_1, \ldots, \mu_n \f$ are the coefficients
105707  of \p mu corresponding to the space dimensions \f$ n, 0, \ldots, n-1 \f$,
105708  respectively.
105709
105710  \return
105711  <CODE>true</CODE> if any loop approximated by \p pset definitely
105712  terminates; <CODE>false</CODE> if the test is inconclusive.
105713  However, if \p pset <EM>precisely</EM> characterizes the effect
105714  of the loop body onto the loop-relevant program variables,
105715  then <CODE>true</CODE> is returned <EM>if and only if</EM>
105716  the loop terminates.
105717*/
105718template <typename PSET>
105719bool
105720one_affine_ranking_function_MS(const PSET& pset, Generator& mu);
105721
105722/*! \ingroup PPL_CXX_interface \brief
105723  Termination test with witness ranking function using an improvement
105724  of the method by Mesnard and Serebrenik \ref BMPZ10 "[BMPZ10]".
105725
105726  \tparam PSET
105727  Any pointset supported by the PPL that provides the
105728  <CODE>minimized_constraints()</CODE> method.
105729
105730  \param pset_before
105731  A pointset approximating the values of loop-relevant variables
105732  <EM>before</EM> the update performed in the loop body that is being
105733  analyzed.  The variables indices are allocated as follows:
105734  - \f$ x_1, \ldots, x_n \f$ go onto space dimensions
105735    \f$ 0, \ldots, n-1 \f$.
105736
105737  \param pset_after
105738  A pointset approximating the values of loop-relevant variables
105739  <EM>after</EM> the update performed in the loop body that is being
105740  analyzed.  The variables indices are allocated as follows:
105741  - \f$ x'_1, \ldots, x'_n \f$ go onto space dimensions
105742    \f$ 0, \ldots, n-1 \f$,
105743  - \f$ x_1, \ldots, x_n \f$ go onto space dimensions
105744    \f$ n, \ldots, 2n-1 \f$,
105745
105746  Note that unprimed variables represent the values of the loop-relevant
105747  program variables before the update performed in the loop body,
105748  and primed variables represent the values of those program variables
105749  after the update.  Note also that unprimed variables are assigned
105750  to different space dimensions in \p pset_before and \p pset_after.
105751
105752  \param mu
105753  When <CODE>true</CODE> is returned, this is assigned a point
105754  of space dimension \f$ n+1 \f$ encoding one (not further specified)
105755  affine ranking function for the loop being analyzed.
105756  The ranking function is of the form \f$ \mu_0 + \sum_{i=1}^n \mu_i x_i \f$
105757  where \f$ \mu_0, \mu_1, \ldots, \mu_n \f$ are the coefficients
105758  of \p mu corresponding to the space dimensions \f$ n, 0, \ldots, n-1 \f$,
105759  respectively.
105760
105761  \return
105762  <CODE>true</CODE> if any loop approximated by \p pset definitely
105763  terminates; <CODE>false</CODE> if the test is inconclusive.
105764  However, if \p pset_before and \p pset_after <EM>precisely</EM>
105765  characterize the effect of the loop body onto the loop-relevant
105766  program variables, then <CODE>true</CODE> is returned
105767  <EM>if and only if</EM> the loop terminates.
105768*/
105769template <typename PSET>
105770bool
105771one_affine_ranking_function_MS_2(const PSET& pset_before,
105772                                 const PSET& pset_after,
105773                                 Generator& mu);
105774
105775/*! \ingroup PPL_CXX_interface \brief
105776  Termination test with ranking function space using an improvement
105777  of the method by Mesnard and Serebrenik \ref BMPZ10 "[BMPZ10]".
105778
105779  \tparam PSET
105780  Any pointset supported by the PPL that provides the
105781  <CODE>minimized_constraints()</CODE> method.
105782
105783  \param pset
105784  A pointset approximating the behavior of a loop whose termination
105785  is being analyzed.  The variables indices are allocated as follows:
105786  - \f$ x'_1, \ldots, x'_n \f$ go onto space dimensions
105787    \f$ 0, \ldots, n-1 \f$,
105788  - \f$ x_1, \ldots, x_n \f$ go onto space dimensions
105789    \f$ n, \ldots, 2n-1 \f$,
105790  .
105791  where unprimed variables represent the values of the loop-relevant
105792  program variables before the update performed in the loop body,
105793  and primed variables represent the values of those program variables
105794  after the update.
105795
105796  \param mu_space
105797  This is assigned a closed polyhedron of space dimension \f$ n+1 \f$
105798  representing the space of all the affine ranking functions for the loops
105799  that are precisely characterized by \p pset.
105800  These ranking functions are of the form
105801  \f$ \mu_0 + \sum_{i=1}^n \mu_i x_i \f$
105802  where \f$ \mu_0, \mu_1, \ldots, \mu_n \f$ identify any point of the
105803  \p mu_space polyhedron.
105804  The variables \f$ \mu_0, \mu_1, \ldots, \mu_n \f$
105805  correspond to the space dimensions of \p mu_space
105806  \f$ n, 0, \ldots, n-1 \f$, respectively.
105807  When \p mu_space is empty, it means that the test is inconclusive.
105808  However, if \p pset <EM>precisely</EM> characterizes the effect
105809  of the loop body onto the loop-relevant program variables,
105810  then \p mu_space is empty <EM>if and only if</EM>
105811  the loop does <EM>not</EM> terminate.
105812*/
105813template <typename PSET>
105814void
105815all_affine_ranking_functions_MS(const PSET& pset, C_Polyhedron& mu_space);
105816
105817/*! \ingroup PPL_CXX_interface \brief
105818  Termination test with ranking function space using an improvement
105819  of the method by Mesnard and Serebrenik \ref BMPZ10 "[BMPZ10]".
105820
105821  \tparam PSET
105822  Any pointset supported by the PPL that provides the
105823  <CODE>minimized_constraints()</CODE> method.
105824
105825  \param pset_before
105826  A pointset approximating the values of loop-relevant variables
105827  <EM>before</EM> the update performed in the loop body that is being
105828  analyzed.  The variables indices are allocated as follows:
105829  - \f$ x_1, \ldots, x_n \f$ go onto space dimensions
105830    \f$ 0, \ldots, n-1 \f$.
105831
105832  \param pset_after
105833  A pointset approximating the values of loop-relevant variables
105834  <EM>after</EM> the update performed in the loop body that is being
105835  analyzed.  The variables indices are allocated as follows:
105836  - \f$ x'_1, \ldots, x'_n \f$ go onto space dimensions
105837    \f$ 0, \ldots, n-1 \f$,
105838  - \f$ x_1, \ldots, x_n \f$ go onto space dimensions
105839    \f$ n, \ldots, 2n-1 \f$,
105840
105841  Note that unprimed variables represent the values of the loop-relevant
105842  program variables before the update performed in the loop body,
105843  and primed variables represent the values of those program variables
105844  after the update.  Note also that unprimed variables are assigned
105845  to different space dimensions in \p pset_before and \p pset_after.
105846
105847  \param mu_space
105848  This is assigned a closed polyhedron of space dimension \f$ n+1 \f$
105849  representing the space of all the affine ranking functions for the loops
105850  that are precisely characterized by \p pset.
105851  These ranking functions are of the form
105852  \f$ \mu_0 + \sum_{i=1}^n \mu_i x_i \f$
105853  where \f$ \mu_0, \mu_1, \ldots, \mu_n \f$ identify any point of the
105854  \p mu_space polyhedron.
105855  The variables \f$ \mu_0, \mu_1, \ldots, \mu_n \f$
105856  correspond to the space dimensions of \p mu_space
105857  \f$ n, 0, \ldots, n-1 \f$, respectively.
105858  When \p mu_space is empty, it means that the test is inconclusive.
105859  However, if \p pset_before and \p pset_after <EM>precisely</EM>
105860  characterize the effect of the loop body onto the loop-relevant
105861  program variables, then \p mu_space is empty <EM>if and only if</EM>
105862  the loop does <EM>not</EM> terminate.
105863*/
105864template <typename PSET>
105865void
105866all_affine_ranking_functions_MS_2(const PSET& pset_before,
105867                                  const PSET& pset_after,
105868                                  C_Polyhedron& mu_space);
105869
105870/*! \ingroup PPL_CXX_interface \brief
105871  Computes the spaces of affine \e quasi ranking functions
105872  using an improvement of the method by Mesnard and Serebrenik
105873  \ref BMPZ10 "[BMPZ10]".
105874
105875  \tparam PSET
105876  Any pointset supported by the PPL that provides the
105877  <CODE>minimized_constraints()</CODE> method.
105878
105879  \param pset
105880  A pointset approximating the behavior of a loop whose termination
105881  is being analyzed.  The variables indices are allocated as follows:
105882  - \f$ x'_1, \ldots, x'_n \f$ go onto space dimensions
105883    \f$ 0, \ldots, n-1 \f$,
105884  - \f$ x_1, \ldots, x_n \f$ go onto space dimensions
105885    \f$ n, \ldots, 2n-1 \f$,
105886  .
105887  where unprimed variables represent the values of the loop-relevant
105888  program variables before the update performed in the loop body,
105889  and primed variables represent the values of those program variables
105890  after the update.
105891
105892  \param decreasing_mu_space
105893  This is assigned a closed polyhedron of space dimension \f$ n+1 \f$
105894  representing the space of all the decreasing affine functions
105895  for the loops that are precisely characterized by \p pset.
105896
105897  \param bounded_mu_space
105898  This is assigned a closed polyhedron of space dimension \f$ n+1 \f$
105899  representing the space of all the lower bounded affine functions
105900  for the loops that are precisely characterized by \p pset.
105901
105902  These quasi-ranking functions are of the form
105903  \f$ \mu_0 + \sum_{i=1}^n \mu_i x_i \f$
105904  where \f$ \mu_0, \mu_1, \ldots, \mu_n \f$ identify any point of the
105905  \p decreasing_mu_space and \p bounded_mu_space polyhedrons.
105906  The variables \f$ \mu_0, \mu_1, \ldots, \mu_n \f$
105907  correspond to the space dimensions \f$ n, 0, \ldots, n-1 \f$, respectively.
105908  When \p decreasing_mu_space (resp., \p bounded_mu_space) is empty,
105909  it means that the test is inconclusive.
105910  However, if \p pset <EM>precisely</EM> characterizes the effect
105911  of the loop body onto the loop-relevant program variables,
105912  then \p decreasing_mu_space (resp., \p bounded_mu_space) will be empty
105913  <EM>if and only if</EM> there is no decreasing (resp., lower bounded)
105914  affine function, so that the loop does not terminate.
105915*/
105916template <typename PSET>
105917void
105918all_affine_quasi_ranking_functions_MS(const PSET& pset,
105919                                      C_Polyhedron& decreasing_mu_space,
105920                                      C_Polyhedron& bounded_mu_space);
105921
105922/*! \ingroup PPL_CXX_interface \brief
105923  Computes the spaces of affine \e quasi ranking functions
105924  using an improvement of the method by Mesnard and Serebrenik
105925  \ref BMPZ10 "[BMPZ10]".
105926
105927  \tparam PSET
105928  Any pointset supported by the PPL that provides the
105929  <CODE>minimized_constraints()</CODE> method.
105930
105931  \param pset_before
105932  A pointset approximating the values of loop-relevant variables
105933  <EM>before</EM> the update performed in the loop body that is being
105934  analyzed.  The variables indices are allocated as follows:
105935  - \f$ x_1, \ldots, x_n \f$ go onto space dimensions
105936    \f$ 0, \ldots, n-1 \f$.
105937
105938  \param pset_after
105939  A pointset approximating the values of loop-relevant variables
105940  <EM>after</EM> the update performed in the loop body that is being
105941  analyzed.  The variables indices are allocated as follows:
105942  - \f$ x'_1, \ldots, x'_n \f$ go onto space dimensions
105943    \f$ 0, \ldots, n-1 \f$,
105944  - \f$ x_1, \ldots, x_n \f$ go onto space dimensions
105945    \f$ n, \ldots, 2n-1 \f$,
105946
105947  Note that unprimed variables represent the values of the loop-relevant
105948  program variables before the update performed in the loop body,
105949  and primed variables represent the values of those program variables
105950  after the update.  Note also that unprimed variables are assigned
105951  to different space dimensions in \p pset_before and \p pset_after.
105952
105953  \param decreasing_mu_space
105954  This is assigned a closed polyhedron of space dimension \f$ n+1 \f$
105955  representing the space of all the decreasing affine functions
105956  for the loops that are precisely characterized by \p pset.
105957
105958  \param bounded_mu_space
105959  This is assigned a closed polyhedron of space dimension \f$ n+1 \f$
105960  representing the space of all the lower bounded affine functions
105961  for the loops that are precisely characterized by \p pset.
105962
105963  These ranking functions are of the form
105964  \f$ \mu_0 + \sum_{i=1}^n \mu_i x_i \f$
105965  where \f$ \mu_0, \mu_1, \ldots, \mu_n \f$ identify any point of the
105966  \p decreasing_mu_space and \p bounded_mu_space polyhedrons.
105967  The variables \f$ \mu_0, \mu_1, \ldots, \mu_n \f$
105968  correspond to the space dimensions \f$ n, 0, \ldots, n-1 \f$, respectively.
105969  When \p decreasing_mu_space (resp., \p bounded_mu_space) is empty,
105970  it means that the test is inconclusive.
105971  However, if \p pset_before and \p pset_after <EM>precisely</EM>
105972  characterize the effect of the loop body onto the loop-relevant
105973  program variables, then \p decreasing_mu_space (resp., \p bounded_mu_space)
105974  will be empty <EM>if and only if</EM> there is no decreasing
105975  (resp., lower bounded) affine function, so that the loop does not terminate.
105976*/
105977template <typename PSET>
105978void
105979all_affine_quasi_ranking_functions_MS_2(const PSET& pset_before,
105980                                        const PSET& pset_after,
105981                                        C_Polyhedron& decreasing_mu_space,
105982                                        C_Polyhedron& bounded_mu_space);
105983
105984/*! \ingroup PPL_CXX_interface \brief
105985  Like termination_test_MS() but using the method by Podelski and
105986  Rybalchenko \ref BMPZ10 "[BMPZ10]".
105987*/
105988template <typename PSET>
105989bool
105990termination_test_PR(const PSET& pset);
105991
105992/*! \ingroup PPL_CXX_interface \brief
105993  Like termination_test_MS_2() but using an alternative formalization
105994  of the method by Podelski and Rybalchenko \ref BMPZ10 "[BMPZ10]".
105995*/
105996template <typename PSET>
105997bool
105998termination_test_PR_2(const PSET& pset_before, const PSET& pset_after);
105999
106000/*! \ingroup PPL_CXX_interface \brief
106001  Like one_affine_ranking_function_MS() but using the method by Podelski
106002  and Rybalchenko \ref BMPZ10 "[BMPZ10]".
106003*/
106004template <typename PSET>
106005bool
106006one_affine_ranking_function_PR(const PSET& pset, Generator& mu);
106007
106008/*! \ingroup PPL_CXX_interface \brief
106009  Like one_affine_ranking_function_MS_2() but using an alternative
106010  formalization of the method by Podelski and Rybalchenko
106011  \ref BMPZ10 "[BMPZ10]".
106012*/
106013template <typename PSET>
106014bool
106015one_affine_ranking_function_PR_2(const PSET& pset_before,
106016                                 const PSET& pset_after,
106017                                 Generator& mu);
106018
106019/*! \ingroup PPL_CXX_interface \brief
106020  Like all_affine_ranking_functions_MS() but using the method by Podelski
106021  and Rybalchenko \ref BMPZ10 "[BMPZ10]".
106022*/
106023template <typename PSET>
106024void
106025all_affine_ranking_functions_PR(const PSET& pset, NNC_Polyhedron& mu_space);
106026
106027/*! \ingroup PPL_CXX_interface \brief
106028  Like all_affine_ranking_functions_MS_2() but using an alternative
106029  formalization of the method by Podelski and Rybalchenko
106030  \ref BMPZ10 "[BMPZ10]".
106031*/
106032template <typename PSET>
106033void
106034all_affine_ranking_functions_PR_2(const PSET& pset_before,
106035                                  const PSET& pset_after,
106036                                  NNC_Polyhedron& mu_space);
106037
106038//@} // Functions for the Synthesis of Linear Rankings
106039
106040} // namespace Parma_Polyhedra_Library
106041
106042/* Automatically generated from PPL source file ../src/termination_templates.hh line 1. */
106043/* Utilities for termination analysis: template functions.
106044*/
106045
106046
106047/* Automatically generated from PPL source file ../src/termination_templates.hh line 33. */
106048
106049#include <stdexcept>
106050
106051#define PRINT_DEBUG_INFO 0
106052
106053#if PRINT_DEBUG_INFO
106054#include <iostream>
106055#endif
106056
106057namespace Parma_Polyhedra_Library {
106058
106059namespace Implementation {
106060
106061namespace Termination {
106062
106063#if PRINT_DEBUG_INFO
106064static dimension_type output_function_MS_n;
106065static dimension_type output_function_MS_m;
106066
106067/* Encodes which object are we printing:
106068
106069   0 means input constraint system;
106070   1 means first output constraint system;
106071   2 means second output constraint system;
106072   3 means only output constraint system
106073     (i.e., when first and second are the same);
106074   4 means mu space.
106075*/
106076static int output_function_MS_which = -1;
106077
106078/*
106079  Debugging output function.  See the documentation of
106080  fill_constraint_systems_MS() for the allocation of variable indices.
106081*/
106082inline void
106083output_function_MS(std::ostream& s, const Variable v) {
106084  dimension_type id = v.id();
106085  switch (output_function_MS_which) {
106086  case 0:
106087    if (id < output_function_MS_n) {
106088      s << "x'" << id + 1;
106089    }
106090    else if (id < 2*output_function_MS_n) {
106091      s << "x" << id - output_function_MS_n + 1;
106092    }
106093    else {
106094      s << "WHAT?";
106095    }
106096    break;
106097  case 1:
106098    if (id < output_function_MS_n) {
106099      s << "mu" << id + 1;
106100    }
106101    else if (id == output_function_MS_n) {
106102      s << "WHAT?";
106103    }
106104    else if (id <= output_function_MS_n + output_function_MS_m) {
106105      s << "y" << id - output_function_MS_n;
106106    }
106107    else {
106108      s << "WHAT?";
106109    }
106110    break;
106111  case 2:
106112  case 4:
106113    if (id < output_function_MS_n) {
106114      s << "mu" << id + 1;
106115    }
106116    else if (id == output_function_MS_n) {
106117      s << "mu0";
106118    }
106119    else if (output_function_MS_which == 2
106120             && id <= output_function_MS_n + output_function_MS_m + 2) {
106121      s << "z" << id - output_function_MS_n;
106122    }
106123    else {
106124      s << "WHAT?";
106125    }
106126    break;
106127  case 3:
106128    if (id < output_function_MS_n) {
106129      s << "mu" << id + 1;
106130    }
106131    else if (id == output_function_MS_n) {
106132      s << "mu0";
106133    }
106134    else if (id <= output_function_MS_n + output_function_MS_m) {
106135      s << "y" << id - output_function_MS_n;
106136    }
106137    else if (id <= output_function_MS_n + 2*output_function_MS_m + 2) {
106138      s << "z" << id - (output_function_MS_n + output_function_MS_m);
106139    }
106140    else {
106141      s << "WHAT?";
106142    }
106143    break;
106144  default:
106145    abort();
106146    break;
106147  }
106148}
106149
106150static dimension_type output_function_PR_s;
106151static dimension_type output_function_PR_r;
106152
106153/*
106154  Debugging output function.  See the documentation of
106155  fill_constraint_system_PR() for the allocation of variable indices.
106156*/
106157inline void
106158output_function_PR(std::ostream& s, const Variable v) {
106159  dimension_type id = v.id();
106160  if (id < output_function_PR_s) {
106161    s << "u3_" << id + 1;
106162  }
106163  else if (id < output_function_PR_s + output_function_PR_r) {
106164    s << "u2_" << id - output_function_PR_s + 1;
106165  }
106166  else if (id < output_function_PR_s + 2*output_function_PR_r) {
106167    s << "u1_" << id - (output_function_PR_s + output_function_PR_r) + 1;
106168  }
106169  else {
106170    s << "WHAT?";
106171  }
106172}
106173#endif
106174
106175void
106176assign_all_inequalities_approximation(const Constraint_System& cs_in,
106177                                      Constraint_System& cs_out);
106178
106179template <typename PSET>
106180inline void
106181assign_all_inequalities_approximation(const PSET& pset,
106182                                      Constraint_System& cs) {
106183  assign_all_inequalities_approximation(pset.minimized_constraints(), cs);
106184}
106185
106186template <>
106187void
106188assign_all_inequalities_approximation(const C_Polyhedron& ph,
106189                                      Constraint_System& cs);
106190
106191bool
106192termination_test_MS(const Constraint_System& cs);
106193
106194bool
106195one_affine_ranking_function_MS(const Constraint_System& cs,
106196                               Generator& mu);
106197
106198void
106199all_affine_ranking_functions_MS(const Constraint_System& cs,
106200                                C_Polyhedron& mu_space);
106201
106202void
106203all_affine_quasi_ranking_functions_MS(const Constraint_System& cs,
106204                                      C_Polyhedron& decreasing_mu_space,
106205                                      C_Polyhedron& bounded_mu_space);
106206
106207bool
106208termination_test_PR(const Constraint_System& cs_before,
106209                    const Constraint_System& cs_after);
106210
106211bool
106212one_affine_ranking_function_PR(const Constraint_System& cs_before,
106213                               const Constraint_System& cs_after,
106214                               Generator& mu);
106215
106216void
106217all_affine_ranking_functions_PR(const Constraint_System& cs_before,
106218                                const Constraint_System& cs_after,
106219                                NNC_Polyhedron& mu_space);
106220
106221bool
106222termination_test_PR_original(const Constraint_System& cs);
106223
106224bool
106225one_affine_ranking_function_PR_original(const Constraint_System& cs,
106226                                        Generator& mu);
106227
106228void
106229all_affine_ranking_functions_PR_original(const Constraint_System& cs,
106230                                         NNC_Polyhedron& mu_space);
106231
106232} // namespace Termination
106233
106234} // namespace Implementation
106235
106236template <typename PSET>
106237void
106238Termination_Helpers
106239::assign_all_inequalities_approximation(const PSET& pset_before,
106240                                        const PSET& pset_after,
106241                                        Constraint_System& cs) {
106242  Implementation::Termination
106243    ::assign_all_inequalities_approximation(pset_before, cs);
106244  cs.shift_space_dimensions(Variable(0), cs.space_dimension());
106245  Constraint_System cs_after;
106246  Implementation::Termination
106247    ::assign_all_inequalities_approximation(pset_after, cs_after);
106248  // FIXME: provide an "append" for constraint systems.
106249  for (Constraint_System::const_iterator i = cs_after.begin(),
106250         cs_after_end = cs_after.end(); i != cs_after_end; ++i) {
106251    cs.insert(*i);
106252  }
106253}
106254
106255template <typename PSET>
106256bool
106257termination_test_MS(const PSET& pset) {
106258  const dimension_type space_dim = pset.space_dimension();
106259  if (space_dim % 2 != 0) {
106260    std::ostringstream s;
106261    s << "PPL::termination_test_MS(pset):\n"
106262         "pset.space_dimension() == " << space_dim
106263      << " is odd.";
106264    throw std::invalid_argument(s.str());
106265  }
106266
106267  using namespace Implementation::Termination;
106268  Constraint_System cs;
106269  assign_all_inequalities_approximation(pset, cs);
106270  return termination_test_MS(cs);
106271}
106272
106273template <typename PSET>
106274bool
106275termination_test_MS_2(const PSET& pset_before, const PSET& pset_after) {
106276  const dimension_type before_space_dim = pset_before.space_dimension();
106277  const dimension_type after_space_dim = pset_after.space_dimension();
106278  if (after_space_dim != 2*before_space_dim) {
106279    std::ostringstream s;
106280    s << "PPL::termination_test_MS_2(pset_before, pset_after):\n"
106281         "pset_before.space_dimension() == " << before_space_dim
106282      << ", pset_after.space_dimension() == " << after_space_dim
106283      << ";\nthe latter should be twice the former.";
106284    throw std::invalid_argument(s.str());
106285  }
106286
106287  using namespace Implementation::Termination;
106288  Constraint_System cs;
106289  Termination_Helpers
106290    ::assign_all_inequalities_approximation(pset_before, pset_after, cs);
106291  return termination_test_MS(cs);
106292}
106293
106294template <typename PSET>
106295bool
106296one_affine_ranking_function_MS(const PSET& pset, Generator& mu) {
106297  const dimension_type space_dim = pset.space_dimension();
106298  if (space_dim % 2 != 0) {
106299    std::ostringstream s;
106300    s << "PPL::one_affine_ranking_function_MS(pset, mu):\n"
106301         "pset.space_dimension() == " << space_dim
106302      << " is odd.";
106303    throw std::invalid_argument(s.str());
106304  }
106305
106306  using namespace Implementation::Termination;
106307  Constraint_System cs;
106308  assign_all_inequalities_approximation(pset, cs);
106309  return one_affine_ranking_function_MS(cs, mu);
106310}
106311
106312template <typename PSET>
106313bool
106314one_affine_ranking_function_MS_2(const PSET& pset_before,
106315                                 const PSET& pset_after,
106316                                 Generator& mu) {
106317  const dimension_type before_space_dim = pset_before.space_dimension();
106318  const dimension_type after_space_dim = pset_after.space_dimension();
106319  if (after_space_dim != 2*before_space_dim) {
106320    std::ostringstream s;
106321    s << "PPL::one_affine_ranking_function_MS_2(pset_before, pset_after, mu):\n"
106322         "pset_before.space_dimension() == " << before_space_dim
106323      << ", pset_after.space_dimension() == " << after_space_dim
106324      << ";\nthe latter should be twice the former.";
106325    throw std::invalid_argument(s.str());
106326  }
106327
106328  using namespace Implementation::Termination;
106329  Constraint_System cs;
106330  Termination_Helpers
106331    ::assign_all_inequalities_approximation(pset_before, pset_after, cs);
106332  return one_affine_ranking_function_MS(cs, mu);
106333}
106334
106335template <typename PSET>
106336void
106337all_affine_ranking_functions_MS(const PSET& pset, C_Polyhedron& mu_space) {
106338  const dimension_type space_dim = pset.space_dimension();
106339  if (space_dim % 2 != 0) {
106340    std::ostringstream s;
106341    s << "PPL::all_affine_ranking_functions_MS(pset, mu_space):\n"
106342         "pset.space_dimension() == " << space_dim
106343      << " is odd.";
106344    throw std::invalid_argument(s.str());
106345  }
106346
106347  if (pset.is_empty()) {
106348    mu_space = C_Polyhedron(1 + space_dim/2, UNIVERSE);
106349    return;
106350  }
106351
106352  using namespace Implementation::Termination;
106353  Constraint_System cs;
106354  assign_all_inequalities_approximation(pset, cs);
106355  all_affine_ranking_functions_MS(cs, mu_space);
106356}
106357
106358template <typename PSET>
106359void
106360all_affine_ranking_functions_MS_2(const PSET& pset_before,
106361                                  const PSET& pset_after,
106362                                  C_Polyhedron& mu_space) {
106363  const dimension_type before_space_dim = pset_before.space_dimension();
106364  const dimension_type after_space_dim = pset_after.space_dimension();
106365  if (after_space_dim != 2*before_space_dim) {
106366    std::ostringstream s;
106367    s << "PPL::all_affine_ranking_functions_MS_2"
106368      << "(pset_before, pset_after, mu_space):\n"
106369      << "pset_before.space_dimension() == " << before_space_dim
106370      << ", pset_after.space_dimension() == " << after_space_dim
106371      << ";\nthe latter should be twice the former.";
106372    throw std::invalid_argument(s.str());
106373  }
106374
106375  if (pset_before.is_empty()) {
106376    mu_space = C_Polyhedron(1 + before_space_dim, UNIVERSE);
106377    return;
106378  }
106379
106380  using namespace Implementation::Termination;
106381  Constraint_System cs;
106382  Termination_Helpers
106383    ::assign_all_inequalities_approximation(pset_before, pset_after, cs);
106384  all_affine_ranking_functions_MS(cs, mu_space);
106385}
106386
106387template <typename PSET>
106388void
106389all_affine_quasi_ranking_functions_MS(const PSET& pset,
106390                                      C_Polyhedron& decreasing_mu_space,
106391                                      C_Polyhedron& bounded_mu_space) {
106392  const dimension_type space_dim = pset.space_dimension();
106393  if (space_dim % 2 != 0) {
106394    std::ostringstream s;
106395    s << "PPL::all_affine_quasi_ranking_functions_MS"
106396      << "(pset, decr_space, bounded_space):\n"
106397      << "pset.space_dimension() == " << space_dim
106398      << " is odd.";
106399    throw std::invalid_argument(s.str());
106400  }
106401
106402  if (pset.is_empty()) {
106403    decreasing_mu_space = C_Polyhedron(1 + space_dim/2, UNIVERSE);
106404    bounded_mu_space = decreasing_mu_space;
106405    return;
106406  }
106407
106408  using namespace Implementation::Termination;
106409  Constraint_System cs;
106410  assign_all_inequalities_approximation(pset, cs);
106411  all_affine_quasi_ranking_functions_MS(cs,
106412                                        decreasing_mu_space,
106413                                        bounded_mu_space);
106414}
106415
106416template <typename PSET>
106417void
106418all_affine_quasi_ranking_functions_MS_2(const PSET& pset_before,
106419                                        const PSET& pset_after,
106420                                        C_Polyhedron& decreasing_mu_space,
106421                                        C_Polyhedron& bounded_mu_space) {
106422  const dimension_type before_space_dim = pset_before.space_dimension();
106423  const dimension_type after_space_dim = pset_after.space_dimension();
106424  if (after_space_dim != 2*before_space_dim) {
106425    std::ostringstream s;
106426    s << "PPL::all_affine_quasi_ranking_functions_MS_2"
106427      << "(pset_before, pset_after, decr_space, bounded_space):\n"
106428      << "pset_before.space_dimension() == " << before_space_dim
106429      << ", pset_after.space_dimension() == " << after_space_dim
106430      << ";\nthe latter should be twice the former.";
106431    throw std::invalid_argument(s.str());
106432  }
106433
106434  if (pset_before.is_empty()) {
106435    decreasing_mu_space = C_Polyhedron(1 + before_space_dim, UNIVERSE);
106436    bounded_mu_space = decreasing_mu_space;
106437    return;
106438  }
106439
106440  using namespace Implementation::Termination;
106441  Constraint_System cs;
106442  Termination_Helpers
106443    ::assign_all_inequalities_approximation(pset_before, pset_after, cs);
106444  all_affine_quasi_ranking_functions_MS(cs,
106445                                        decreasing_mu_space,
106446                                        bounded_mu_space);
106447}
106448
106449template <typename PSET>
106450bool
106451termination_test_PR_2(const PSET& pset_before, const PSET& pset_after) {
106452  const dimension_type before_space_dim = pset_before.space_dimension();
106453  const dimension_type after_space_dim = pset_after.space_dimension();
106454  if (after_space_dim != 2*before_space_dim) {
106455    std::ostringstream s;
106456    s << "PPL::termination_test_PR_2(pset_before, pset_after):\n"
106457      << "pset_before.space_dimension() == " << before_space_dim
106458      << ", pset_after.space_dimension() == " << after_space_dim
106459      << ";\nthe latter should be twice the former.";
106460    throw std::invalid_argument(s.str());
106461  }
106462
106463  using namespace Implementation::Termination;
106464  Constraint_System cs_before;
106465  Constraint_System cs_after;
106466  assign_all_inequalities_approximation(pset_before, cs_before);
106467  assign_all_inequalities_approximation(pset_after, cs_after);
106468  return termination_test_PR(cs_before, cs_after);
106469}
106470
106471template <typename PSET>
106472bool
106473termination_test_PR(const PSET& pset) {
106474  const dimension_type space_dim = pset.space_dimension();
106475  if (space_dim % 2 != 0) {
106476    std::ostringstream s;
106477    s << "PPL::termination_test_PR(pset):\n"
106478      << "pset.space_dimension() == " << space_dim
106479      << " is odd.";
106480    throw std::invalid_argument(s.str());
106481  }
106482
106483  using namespace Implementation::Termination;
106484  Constraint_System cs;
106485  assign_all_inequalities_approximation(pset, cs);
106486  return termination_test_PR_original(cs);
106487}
106488
106489template <typename PSET>
106490bool
106491one_affine_ranking_function_PR_2(const PSET& pset_before,
106492                                 const PSET& pset_after,
106493                                 Generator& mu) {
106494  const dimension_type before_space_dim = pset_before.space_dimension();
106495  const dimension_type after_space_dim = pset_after.space_dimension();
106496  if (after_space_dim != 2*before_space_dim) {
106497    std::ostringstream s;
106498    s << "PPL::one_affine_ranking_function_PR_2"
106499      << "(pset_before, pset_after, mu):\n"
106500      << "pset_before.space_dimension() == " << before_space_dim
106501      << ", pset_after.space_dimension() == " << after_space_dim
106502      << ";\nthe latter should be twice the former.";
106503    throw std::invalid_argument(s.str());
106504  }
106505
106506  using namespace Implementation::Termination;
106507  Constraint_System cs_before;
106508  Constraint_System cs_after;
106509  assign_all_inequalities_approximation(pset_before, cs_before);
106510  assign_all_inequalities_approximation(pset_after, cs_after);
106511  return one_affine_ranking_function_PR(cs_before, cs_after, mu);
106512}
106513
106514template <typename PSET>
106515bool
106516one_affine_ranking_function_PR(const PSET& pset, Generator& mu) {
106517  const dimension_type space_dim = pset.space_dimension();
106518  if (space_dim % 2 != 0) {
106519    std::ostringstream s;
106520    s << "PPL::one_affine_ranking_function_PR(pset, mu):\n"
106521      << "pset.space_dimension() == " << space_dim
106522      << " is odd.";
106523    throw std::invalid_argument(s.str());
106524  }
106525
106526  using namespace Implementation::Termination;
106527  Constraint_System cs;
106528  assign_all_inequalities_approximation(pset, cs);
106529  return one_affine_ranking_function_PR_original(cs, mu);
106530}
106531
106532template <typename PSET>
106533void
106534all_affine_ranking_functions_PR_2(const PSET& pset_before,
106535                                  const PSET& pset_after,
106536                                  NNC_Polyhedron& mu_space) {
106537  const dimension_type before_space_dim = pset_before.space_dimension();
106538  const dimension_type after_space_dim = pset_after.space_dimension();
106539  if (after_space_dim != 2*before_space_dim) {
106540    std::ostringstream s;
106541    s << "PPL::all_affine_ranking_functions_MS_2"
106542      << "(pset_before, pset_after, mu_space):\n"
106543      << "pset_before.space_dimension() == " << before_space_dim
106544      << ", pset_after.space_dimension() == " << after_space_dim
106545      << ";\nthe latter should be twice the former.";
106546    throw std::invalid_argument(s.str());
106547  }
106548
106549  if (pset_before.is_empty()) {
106550    mu_space = NNC_Polyhedron(1 + before_space_dim);
106551    return;
106552  }
106553
106554  using namespace Implementation::Termination;
106555  Constraint_System cs_before;
106556  Constraint_System cs_after;
106557  assign_all_inequalities_approximation(pset_before, cs_before);
106558  assign_all_inequalities_approximation(pset_after, cs_after);
106559  all_affine_ranking_functions_PR(cs_before, cs_after, mu_space);
106560}
106561
106562template <typename PSET>
106563void
106564all_affine_ranking_functions_PR(const PSET& pset,
106565                                NNC_Polyhedron& mu_space) {
106566  const dimension_type space_dim = pset.space_dimension();
106567  if (space_dim % 2 != 0) {
106568    std::ostringstream s;
106569    s << "PPL::all_affine_ranking_functions_PR(pset, mu_space):\n"
106570      << "pset.space_dimension() == " << space_dim
106571      << " is odd.";
106572    throw std::invalid_argument(s.str());
106573  }
106574
106575  if (pset.is_empty()) {
106576    mu_space = NNC_Polyhedron(1 + space_dim/2);
106577    return;
106578  }
106579
106580  using namespace Implementation::Termination;
106581  Constraint_System cs;
106582  assign_all_inequalities_approximation(pset, cs);
106583  all_affine_ranking_functions_PR_original(cs, mu_space);
106584}
106585
106586} // namespace Parma_Polyhedra_Library
106587
106588/* Automatically generated from PPL source file ../src/termination_defs.hh line 501. */
106589
106590/* Automatically generated from PPL source file ../src/wrap_string.hh line 1. */
106591/* Declaration of string wrapping function.
106592*/
106593
106594
106595/* Automatically generated from PPL source file ../src/wrap_string.hh line 28. */
106596
106597namespace Parma_Polyhedra_Library {
106598
106599namespace IO_Operators {
106600
106601//! Utility function for the wrapping of lines of text.
106602/*!
106603  \param src_string
106604  The source string holding the lines to wrap.
106605
106606  \param indent_depth
106607  The indentation depth.
106608
106609  \param preferred_first_line_length
106610  The preferred length for the first line of text.
106611
106612  \param preferred_line_length
106613  The preferred length for all the lines but the first one.
106614
106615  \return
106616  The wrapped string.
106617*/
106618std::string
106619wrap_string(const std::string& src_string,
106620            unsigned indent_depth,
106621            unsigned preferred_first_line_length,
106622            unsigned preferred_line_length);
106623
106624} // namespace IO_Operators
106625
106626} // namespace Parma_Polyhedra_Library
106627
106628/* Automatically generated from PPL source file ../src/Cast_Floating_Point_Expression_defs.hh line 1. */
106629/* Declarations for the Cast_Floating_Point_Expression class and
106630   its constituents.
106631*/
106632
106633
106634/* Automatically generated from PPL source file ../src/Cast_Floating_Point_Expression_types.hh line 1. */
106635
106636
106637namespace Parma_Polyhedra_Library {
106638
106639template <typename FP_Interval_Type, typename FP_Format>
106640class Cast_Floating_Point_Expression;
106641
106642} // namespace Parma_Polyhedra_Library
106643
106644/* Automatically generated from PPL source file ../src/Cast_Floating_Point_Expression_defs.hh line 31. */
106645#include <map>
106646
106647namespace Parma_Polyhedra_Library {
106648
106649//! Swaps \p x with \p y.
106650/*! \relates Cast_Floating_Point_Expression */
106651template<typename FP_Interval_Type, typename FP_Format>
106652void
106653swap(Cast_Floating_Point_Expression<FP_Interval_Type, FP_Format>& x,
106654     Cast_Floating_Point_Expression<FP_Interval_Type, FP_Format>& y);
106655
106656/*! \brief
106657  A generic Cast Floating Point Expression.
106658
106659  \ingroup PPL_CXX_interface
106660
106661  \par Template type parameters
106662
106663  - The class template type parameter \p FP_Interval_Type represents the type
106664  of the intervals used in the abstract domain.
106665  - The class template type parameter \p FP_Format represents the floating
106666  point format used in the concrete domain.
106667
106668  \par Linearization of floating-point cast expressions
106669
106670  Let \f$i + \sum_{v \in \cV}i_{v}v \f$ and
106671  \f$i' + \sum_{v \in \cV}i'_{v}v \f$
106672  be two linear forms and \f$\aslf\f$ a sound abstract operator on linear
106673  forms such that:
106674
106675  \f[
106676  \left(i + \sum_{v \in \cV}i_{v}v \right)
106677  \aslf
106678  \left(i' + \sum_{v \in \cV}i'_{v}v \right)
106679  =
106680  \left(i \asifp i'\right)
106681  + \sum_{v \in \cV}\left(i_{v} \asifp i'_{v} \right)v.
106682  \f]
106683
106684  Given a floating point expression \f$e\f$ and a composite abstract store
106685  \f$\left \llbracket \rho^{\#}, \rho^{\#}_l \right \rrbracket\f$,
106686  we construct the interval linear form
106687  \f$\linexprenv{cast(e)}{\rho^{\#}}{\rho^{\#}_l}\f$ as follows:
106688  \f[
106689  \linexprenv{cast(e)}{\rho^{\#}}{\rho^{\#}_l}
106690  =
106691  \linexprenv{e}{\rho^{\#}}{\rho^{\#}_l}
106692  \aslf
106693  \varepsilon_{\mathbf{f}}\left(\linexprenv{e}{\rho^{\#}}{\rho^{\#}_l}
106694  \right)
106695  \aslf
106696  mf_{\mathbf{f}}[-1, 1]
106697  \f]
106698  where \f$\varepsilon_{\mathbf{f}}(l)\f$ is the linear form computed by
106699  calling method <CODE>Floating_Point_Expression::relative_error</CODE>
106700  on \f$l\f$ and \f$mf_{\mathbf{f}}\f$ is a rounding error defined in
106701  <CODE>Floating_Point_Expression::absolute_error</CODE>.
106702*/
106703template <typename FP_Interval_Type, typename FP_Format>
106704class Cast_Floating_Point_Expression
106705  : public Floating_Point_Expression<FP_Interval_Type, FP_Format> {
106706
106707public:
106708
106709  /*! \brief
106710     Alias for the Linear_Form<FP_Interval_Type> from
106711     Floating_Point_Expression
106712  */
106713  typedef typename
106714  Floating_Point_Expression<FP_Interval_Type, FP_Format>::
106715  FP_Linear_Form FP_Linear_Form;
106716
106717  /*! \brief
106718     Alias for the Box<FP_Interval_Type> from
106719     Floating_Point_Expression.
106720  */
106721  typedef typename
106722  Floating_Point_Expression<FP_Interval_Type, FP_Format>::
106723  FP_Interval_Abstract_Store FP_Interval_Abstract_Store;
106724
106725  /*! \brief
106726     Alias for the std::map<dimension_type, FP_Linear_Form> from
106727     Floating_Point_Expression.
106728  */
106729  typedef typename
106730  Floating_Point_Expression<FP_Interval_Type, FP_Format>::
106731  FP_Linear_Form_Abstract_Store FP_Linear_Form_Abstract_Store;
106732
106733  //! \name Constructors and Destructor
106734  //@{
106735  /*! \brief
106736    Builds a cast floating point expression with the value
106737    expressed by \p expr.
106738  */
106739  Cast_Floating_Point_Expression(
106740    Floating_Point_Expression<FP_Interval_Type, FP_Format>* const expr);
106741
106742  //! Destructor.
106743  ~Cast_Floating_Point_Expression();
106744
106745  //@} // Constructors and Destructor
106746
106747  /*! \brief
106748    Linearizes the expression in a given astract store.
106749
106750    Makes \p result become the linearization of \p *this in the given
106751    composite abstract store.
106752
106753    \param int_store The interval abstract store.
106754    \param lf_store The linear form abstract store.
106755    \param result The modified linear form.
106756
106757    \return <CODE>true</CODE> if the linearization succeeded,
106758    <CODE>false</CODE> otherwise.
106759
106760    See the class description for an explanation of how \p result is computed.
106761  */
106762  bool linearize(const FP_Interval_Abstract_Store& int_store,
106763                 const FP_Linear_Form_Abstract_Store& lf_store,
106764                 FP_Linear_Form& result) const;
106765
106766  //! Swaps \p *this with \p y.
106767  void m_swap(Cast_Floating_Point_Expression& y);
106768
106769private:
106770
106771  //! Pointer to the casted expression.
106772  Floating_Point_Expression<FP_Interval_Type, FP_Format>* expr;
106773
106774  #ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
106775  /*! \brief
106776    Inhibited copy constructor.
106777  */
106778  #endif // PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
106779  Cast_Floating_Point_Expression(
106780                          const Cast_Floating_Point_Expression& y);
106781
106782  #ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
106783  /*! \brief
106784    Inhibited assignment operator.
106785  */
106786  #endif // PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAIL
106787  Cast_Floating_Point_Expression& operator=(
106788                          const Cast_Floating_Point_Expression& y);
106789
106790}; // class Cast_Floating_Point_Expression
106791
106792} // namespace Parma_Polyhedra_Library
106793
106794/* Automatically generated from PPL source file ../src/Cast_Floating_Point_Expression_inlines.hh line 1. */
106795/* Cast_Floating_Point_Expression class implementation: inline functions.
106796*/
106797
106798
106799/* Automatically generated from PPL source file ../src/Cast_Floating_Point_Expression_inlines.hh line 28. */
106800
106801namespace Parma_Polyhedra_Library {
106802
106803template <typename FP_Interval_Type, typename FP_Format>
106804inline
106805Cast_Floating_Point_Expression<FP_Interval_Type, FP_Format>::
106806Cast_Floating_Point_Expression(
106807Floating_Point_Expression<FP_Interval_Type, FP_Format>* const e)
106808  : expr(e) {
106809  assert(e != 0);
106810}
106811
106812template <typename FP_Interval_Type, typename FP_Format>
106813inline
106814Cast_Floating_Point_Expression<FP_Interval_Type, FP_Format>::
106815~Cast_Floating_Point_Expression() {
106816  delete expr;
106817}
106818
106819template <typename FP_Interval_Type, typename FP_Format>
106820inline void
106821Cast_Floating_Point_Expression<FP_Interval_Type, FP_Format>
106822::m_swap(Cast_Floating_Point_Expression& y) {
106823  swap(expr, y.expr);
106824}
106825
106826/*! \relates Cast_Floating_Point_Expression */
106827template <typename FP_Interval_Type, typename FP_Format>
106828inline void
106829swap(Cast_Floating_Point_Expression<FP_Interval_Type, FP_Format>& x,
106830     Cast_Floating_Point_Expression<FP_Interval_Type, FP_Format>& y) {
106831  x.m_swap(y);
106832}
106833
106834} // namespace Parma_Polyhedra_Library
106835
106836/* Automatically generated from PPL source file ../src/Cast_Floating_Point_Expression_defs.hh line 181. */
106837
106838/* Automatically generated from PPL source file ../src/Cast_Floating_Point_Expression_templates.hh line 1. */
106839/* Cast_Floating_Point_Expression class implementation:
106840   non-inline template functions.
106841*/
106842
106843
106844namespace Parma_Polyhedra_Library {
106845
106846template <typename FP_Interval_Type, typename FP_Format>
106847bool Cast_Floating_Point_Expression<FP_Interval_Type, FP_Format>
106848::linearize(const FP_Interval_Abstract_Store& int_store,
106849            const FP_Linear_Form_Abstract_Store& lf_store,
106850            FP_Linear_Form& result) const {
106851  if (!expr->linearize(int_store, lf_store, result)) {
106852    return false;
106853  }
106854  FP_Linear_Form rel_error;
106855  relative_error(result, rel_error);
106856  result += rel_error;
106857  result += this->absolute_error;
106858  return !this->overflows(result);
106859}
106860
106861} // namespace Parma_Polyhedra_Library
106862
106863/* Automatically generated from PPL source file ../src/Constant_Floating_Point_Expression_defs.hh line 1. */
106864/* Declarations for the Constant_Floating_Point_Expression class and
106865   its constituents.
106866*/
106867
106868
106869/* Automatically generated from PPL source file ../src/Constant_Floating_Point_Expression_types.hh line 1. */
106870
106871
106872namespace Parma_Polyhedra_Library {
106873
106874template <typename FP_Interval_Type, typename FP_Format>
106875class Constant_Floating_Point_Expression;
106876
106877} // namespace Parma_Polyhedra_Library
106878
106879/* Automatically generated from PPL source file ../src/Constant_Floating_Point_Expression_defs.hh line 31. */
106880#include <map>
106881
106882namespace Parma_Polyhedra_Library {
106883
106884//! Swaps \p x with \p y.
106885/*! \relates Constant_Floating_Point_Expression */
106886template<typename FP_Interval_Type, typename FP_Format>
106887void swap(Constant_Floating_Point_Expression<FP_Interval_Type, FP_Format>& x,
106888          Constant_Floating_Point_Expression<FP_Interval_Type, FP_Format>& y);
106889
106890/*! \brief
106891  A generic Constant Floating Point Expression.
106892
106893  \ingroup PPL_CXX_interface
106894
106895  \par Template type parameters
106896
106897  - The class template type parameter \p FP_Interval_Type represents the type
106898  of the intervals used in the abstract domain.
106899  - The class template type parameter \p FP_Format represents the floating
106900  point format used in the concrete domain.
106901
106902  \par Linearization of floating-point constant expressions
106903
106904  The linearization of a constant floating point expression results in a
106905  linear form consisting of only the inhomogeneous term
106906  \f$[l, u]\f$, where \f$l\f$ and \f$u\f$ are the lower
106907  and upper bounds of the constant value given to the class constructor.
106908*/
106909template <typename FP_Interval_Type, typename FP_Format>
106910class Constant_Floating_Point_Expression
106911  : public Floating_Point_Expression<FP_Interval_Type, FP_Format> {
106912
106913public:
106914
106915  /*! \brief
106916     Alias for the Linear_Form<FP_Interval_Type> from
106917     Floating_Point_Expression
106918  */
106919  typedef typename
106920  Floating_Point_Expression<FP_Interval_Type, FP_Format>::
106921  FP_Linear_Form FP_Linear_Form;
106922
106923  /*! \brief
106924     Alias for the Box<FP_Interval_Type> from
106925     Floating_Point_Expression.
106926  */
106927  typedef typename
106928  Floating_Point_Expression<FP_Interval_Type, FP_Format>::
106929  FP_Interval_Abstract_Store FP_Interval_Abstract_Store;
106930
106931  /*! \brief
106932     Alias for the std::map<dimension_type, FP_Linear_Form> from
106933     Floating_Point_Expression.
106934  */
106935  typedef typename
106936  Floating_Point_Expression<FP_Interval_Type, FP_Format>::
106937  FP_Linear_Form_Abstract_Store FP_Linear_Form_Abstract_Store;
106938
106939  /*! \brief
106940     Alias for the FP_Interval_Type::boundary_type from
106941     Floating_Point_Expression.
106942  */
106943  typedef typename
106944  Floating_Point_Expression<FP_Interval_Type, FP_Format>::boundary_type
106945  boundary_type;
106946
106947  /*! \brief
106948     Alias for the FP_Interval_Type::info_type from Floating_Point_Expression.
106949  */
106950  typedef typename
106951  Floating_Point_Expression<FP_Interval_Type, FP_Format>::info_type info_type;
106952
106953  //! \name Constructors and Destructor
106954  //@{
106955  /*! \brief
106956    Constructor with two parameters: builds the constant floating point
106957    expression from a \p lower_bound and an \p upper_bound of its
106958    value in the concrete domain.
106959  */
106960  Constant_Floating_Point_Expression(const boundary_type lower_bound,
106961                                     const boundary_type upper_bound);
106962
106963  /*! \brief
106964    Builds a constant floating point expression with the value
106965    expressed by the string \p str_value.
106966  */
106967  Constant_Floating_Point_Expression(const char* str_value);
106968
106969  //! Destructor.
106970  ~Constant_Floating_Point_Expression();
106971
106972  //@} // Constructors and Destructor
106973
106974  /*! \brief
106975    Linearizes the expression in a given astract store.
106976
106977    Makes \p result become the linearization of \p *this in the given
106978    composite abstract store.
106979
106980    \param int_store The interval abstract store.
106981    \param lf_store The linear form abstract store.
106982    \param result The modified linear form.
106983
106984    \return <CODE>true</CODE> if the linearization succeeded,
106985    <CODE>false</CODE> otherwise.
106986
106987    See the class description for an explanation of how \p result is computed.
106988  */
106989  bool linearize(const FP_Interval_Abstract_Store& int_store,
106990                 const FP_Linear_Form_Abstract_Store& lf_store,
106991                 FP_Linear_Form& result) const;
106992
106993  //! Swaps \p *this with \p y.
106994  void m_swap(Constant_Floating_Point_Expression& y);
106995
106996private:
106997
106998  FP_Interval_Type value;
106999
107000  #ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
107001  /*! \brief
107002    Inhibited copy constructor.
107003  */
107004  #endif // PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
107005  Constant_Floating_Point_Expression(
107006                          const Constant_Floating_Point_Expression& y);
107007
107008  #ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
107009  /*! \brief
107010    Inhibited assignment operator.
107011  */
107012  #endif // PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAIL
107013  Constant_Floating_Point_Expression& operator=(
107014                          const Constant_Floating_Point_Expression& y);
107015
107016}; // class Constant_Floating_Point_Expression
107017
107018} // namespace Parma_Polyhedra_Library
107019
107020/* Automatically generated from PPL source file ../src/Constant_Floating_Point_Expression_inlines.hh line 1. */
107021/* Constant_Floating_Point_Expression class implementation: inline functions.
107022*/
107023
107024
107025/* Automatically generated from PPL source file ../src/Constant_Floating_Point_Expression_inlines.hh line 28. */
107026
107027namespace Parma_Polyhedra_Library {
107028
107029template <typename FP_Interval_Type, typename FP_Format>
107030inline
107031Constant_Floating_Point_Expression<FP_Interval_Type, FP_Format>::
107032Constant_Floating_Point_Expression(const char* str_value)
107033  : value(str_value) {}
107034
107035template <typename FP_Interval_Type, typename FP_Format>
107036inline
107037Constant_Floating_Point_Expression<FP_Interval_Type, FP_Format>::
107038Constant_Floating_Point_Expression(const boundary_type lb,
107039                                   const boundary_type ub) {
107040  assert(lb <= ub);
107041  value.build(i_constraint(GREATER_OR_EQUAL, lb),
107042              i_constraint(LESS_OR_EQUAL, ub));
107043}
107044
107045template <typename FP_Interval_Type, typename FP_Format>
107046inline
107047Constant_Floating_Point_Expression<FP_Interval_Type, FP_Format>::
107048~Constant_Floating_Point_Expression() {}
107049
107050template <typename FP_Interval_Type, typename FP_Format>
107051inline void
107052Constant_Floating_Point_Expression<FP_Interval_Type, FP_Format>
107053::m_swap(Constant_Floating_Point_Expression& y) {
107054  using std::swap;
107055  swap(value, y.value);
107056}
107057
107058template <typename FP_Interval_Type, typename FP_Format>
107059inline bool
107060Constant_Floating_Point_Expression<FP_Interval_Type, FP_Format>
107061::linearize(const FP_Interval_Abstract_Store&,
107062            const FP_Linear_Form_Abstract_Store&,
107063            FP_Linear_Form& result) const {
107064  result = FP_Linear_Form(value);
107065  return true;
107066}
107067
107068/*! \relates Constant_Floating_Point_Expression */
107069template <typename FP_Interval_Type, typename FP_Format>
107070inline void
107071swap(Constant_Floating_Point_Expression<FP_Interval_Type, FP_Format>& x,
107072     Constant_Floating_Point_Expression<FP_Interval_Type, FP_Format>& y) {
107073  x.m_swap(y);
107074}
107075
107076} // namespace Parma_Polyhedra_Library
107077
107078/* Automatically generated from PPL source file ../src/Constant_Floating_Point_Expression_defs.hh line 172. */
107079
107080/* Automatically generated from PPL source file ../src/Variable_Floating_Point_Expression_defs.hh line 1. */
107081/* Declarations for the Variable_Floating_Point_Expression class and
107082   its constituents.
107083*/
107084
107085
107086/* Automatically generated from PPL source file ../src/Variable_Floating_Point_Expression_types.hh line 1. */
107087
107088
107089namespace Parma_Polyhedra_Library {
107090
107091template <typename FP_Interval_Type, typename FP_Format>
107092class Variable_Floating_Point_Expression;
107093
107094} // namespace Parma_Polyhedra_Library
107095
107096/* Automatically generated from PPL source file ../src/Variable_Floating_Point_Expression_defs.hh line 31. */
107097#include <map>
107098#include <utility>
107099
107100namespace Parma_Polyhedra_Library {
107101
107102//! Swaps \p x with \p y.
107103/*! \relates Variable_Floating_Point_Expression */
107104template<typename FP_Interval_Type, typename FP_Format>
107105void swap(Variable_Floating_Point_Expression<FP_Interval_Type, FP_Format>& x,
107106          Variable_Floating_Point_Expression<FP_Interval_Type, FP_Format>& y);
107107
107108/*! \brief
107109  A generic Variable Floating Point Expression.
107110
107111  \ingroup PPL_CXX_interface
107112
107113  \par Template type parameters
107114
107115  - The class template type parameter \p FP_Interval_Type represents the type
107116  of the intervals used in the abstract domain.
107117  - The class template type parameter \p FP_Format represents the floating
107118  point format used in the concrete domain.
107119
107120  \par Linearization of floating-point variable expressions
107121
107122  Given a variable expression \f$v\f$ and a composite
107123  abstract store \f$\left \llbracket \rho^{\#}, \rho^{\#}_l \right
107124  \rrbracket\f$, we construct the interval
107125  linear form \f$\linexprenv{v}{\rho^{\#}}{\rho^{\#}_l}\f$ as
107126  \f$\rho^{\#}_l(v)\f$ if it is defined; otherwise we construct it as
107127  \f$[-1, 1]v\f$.
107128*/
107129template <typename FP_Interval_Type, typename FP_Format>
107130class Variable_Floating_Point_Expression
107131: public Floating_Point_Expression<FP_Interval_Type, FP_Format> {
107132
107133public:
107134
107135  /*! \brief
107136     Alias for the Linear_Form<FP_Interval_Type> from
107137     Floating_Point_Expression
107138  */
107139  typedef typename
107140  Floating_Point_Expression<FP_Interval_Type, FP_Format>::
107141  FP_Linear_Form FP_Linear_Form;
107142
107143  /*! \brief
107144     Alias for the Box<FP_Interval_Type> from
107145     Floating_Point_Expression.
107146  */
107147  typedef typename
107148  Floating_Point_Expression<FP_Interval_Type, FP_Format>::
107149  FP_Interval_Abstract_Store FP_Interval_Abstract_Store;
107150
107151  /*! \brief
107152     Alias for the std::map<dimension_type, FP_Linear_Form> from
107153     Floating_Point_Expression.
107154  */
107155  typedef typename
107156  Floating_Point_Expression<FP_Interval_Type, FP_Format>::
107157  FP_Linear_Form_Abstract_Store FP_Linear_Form_Abstract_Store;
107158
107159  /*! \brief
107160     Alias for the FP_Interval_Type::boundary_type from
107161     Floating_Point_Expression.
107162  */
107163  typedef typename
107164  Floating_Point_Expression<FP_Interval_Type, FP_Format>::boundary_type
107165  boundary_type;
107166
107167  /*! \brief
107168     Alias for the FP_Interval_Type::info_type from Floating_Point_Expression.
107169  */
107170  typedef typename
107171  Floating_Point_Expression<FP_Interval_Type, FP_Format>::info_type info_type;
107172
107173  //! \name Constructors and Destructor
107174  //@{
107175  /*! \brief
107176    Constructor with a parameter: builds the variable floating point
107177    expression corresponding to the variable having \p v_index as its index.
107178  */
107179  explicit Variable_Floating_Point_Expression(const dimension_type v_index);
107180
107181  //! Destructor.
107182  ~Variable_Floating_Point_Expression();
107183
107184  //@} // Constructors and Destructor
107185
107186  /*! \brief
107187    Linearizes the expression in a given abstract store.
107188
107189    Makes \p result become the linearization of \p *this in the given
107190    composite abstract store.
107191
107192    \param int_store The interval abstract store.
107193    \param lf_store The linear form abstract store.
107194    \param result The modified linear form.
107195
107196    \return <CODE>true</CODE> if the linearization succeeded,
107197    <CODE>false</CODE> otherwise.
107198
107199    Note that the variable in the expression MUST have an associated value
107200    in \p int_store. If this precondition is not met, calling the method
107201    causes an undefined behavior.
107202
107203    See the class description for a detailed explanation of how \p result is
107204    computed.
107205  */
107206  bool linearize(const FP_Interval_Abstract_Store& int_store,
107207                 const FP_Linear_Form_Abstract_Store& lf_store,
107208                 FP_Linear_Form& result) const;
107209
107210  /*! \brief
107211    Assigns a linear form to the variable with the same index of
107212    \p *this in a given linear form abstract store.
107213
107214    \param lf The linear form assigned to the variable.
107215    \param lf_store The linear form abstract store.
107216
107217    Note that once \p lf is assigned to a variable, all the other entries
107218    of \p lf_store which contain that variable are discarded.
107219  */
107220  void linear_form_assign(const FP_Linear_Form& lf,
107221                                FP_Linear_Form_Abstract_Store& lf_store) const;
107222
107223  //! Swaps \p *this with \p y.
107224  void m_swap(Variable_Floating_Point_Expression& y);
107225
107226private:
107227
107228  #ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
107229  /*! \brief
107230    Inhibited copy constructor.
107231  */
107232  #endif // PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
107233  Variable_Floating_Point_Expression(
107234                          const Variable_Floating_Point_Expression& y);
107235
107236  #ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
107237  /*! \brief
107238    Inhibited assignment operator.
107239  */
107240  #endif // PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
107241  Variable_Floating_Point_Expression& operator=(
107242                          const Variable_Floating_Point_Expression& y);
107243
107244  //! The index of the variable.
107245  dimension_type variable_index;
107246
107247}; // class Variable_Floating_Point_Expression
107248
107249} // namespace Parma_Polyhedra_Library
107250
107251/* Automatically generated from PPL source file ../src/Variable_Floating_Point_Expression_inlines.hh line 1. */
107252/* Variable_Floating_Point_Expression class implementation: inline functions.
107253*/
107254
107255
107256/* Automatically generated from PPL source file ../src/Variable_Floating_Point_Expression_inlines.hh line 28. */
107257
107258namespace Parma_Polyhedra_Library {
107259
107260template <typename FP_Interval_Type, typename FP_Format>
107261inline
107262Variable_Floating_Point_Expression<FP_Interval_Type, FP_Format>::
107263Variable_Floating_Point_Expression(const dimension_type v_index)
107264  : variable_index(v_index) {}
107265
107266template <typename FP_Interval_Type, typename FP_Format>
107267inline
107268Variable_Floating_Point_Expression<FP_Interval_Type, FP_Format>::
107269~Variable_Floating_Point_Expression() {}
107270
107271template <typename FP_Interval_Type, typename FP_Format>
107272inline void
107273Variable_Floating_Point_Expression<FP_Interval_Type, FP_Format>
107274::m_swap(Variable_Floating_Point_Expression& y) {
107275  using std::swap;
107276  swap(variable_index, y.variable_index);
107277}
107278
107279template <typename FP_Interval_Type, typename FP_Format>
107280inline bool
107281Variable_Floating_Point_Expression<FP_Interval_Type, FP_Format>
107282::linearize(const FP_Interval_Abstract_Store&,
107283            const FP_Linear_Form_Abstract_Store& lf_store,
107284            FP_Linear_Form& result) const {
107285  typename FP_Linear_Form_Abstract_Store::const_iterator
107286           variable_value = lf_store.find(variable_index);
107287
107288  if (variable_value == lf_store.end()) {
107289    result = FP_Linear_Form(Variable(variable_index));
107290    return true;
107291  }
107292
107293  result = FP_Linear_Form(variable_value->second);
107294  return !this->overflows(result);
107295}
107296
107297template <typename FP_Interval_Type, typename FP_Format>
107298inline void
107299Variable_Floating_Point_Expression<FP_Interval_Type, FP_Format>
107300::linear_form_assign(const FP_Linear_Form& lf,
107301                           FP_Linear_Form_Abstract_Store& lf_store) const {
107302  for (typename FP_Linear_Form_Abstract_Store::iterator
107303         i = lf_store.begin(); i != lf_store.end(); ) {
107304    if ((i->second).coefficient(Variable(variable_index)) != 0) {
107305      i = lf_store.erase(i);
107306    }
107307    else {
107308      ++i;
107309    }
107310  }
107311  lf_store[variable_index] = lf;
107312  return;
107313}
107314
107315/*! \relates Variable_Floating_Point_Expression */
107316template <typename FP_Interval_Type, typename FP_Format>
107317inline void
107318swap(Variable_Floating_Point_Expression<FP_Interval_Type, FP_Format>& x,
107319     Variable_Floating_Point_Expression<FP_Interval_Type, FP_Format>& y) {
107320  x.m_swap(y);
107321}
107322
107323} // namespace Parma_Polyhedra_Library
107324
107325/* Automatically generated from PPL source file ../src/Variable_Floating_Point_Expression_defs.hh line 186. */
107326
107327/* Automatically generated from PPL source file ../src/Sum_Floating_Point_Expression_defs.hh line 1. */
107328/* Declarations for the Sum_Floating_Point_Expression class and
107329   its   constituents.
107330*/
107331
107332
107333/* Automatically generated from PPL source file ../src/Sum_Floating_Point_Expression_types.hh line 1. */
107334
107335
107336namespace Parma_Polyhedra_Library {
107337
107338template <typename FP_Interval_Type, typename FP_Format>
107339class Sum_Floating_Point_Expression;
107340
107341} // namespace Parma_Polyhedra_Library
107342
107343/* Automatically generated from PPL source file ../src/Sum_Floating_Point_Expression_defs.hh line 31. */
107344#include <map>
107345
107346namespace Parma_Polyhedra_Library {
107347
107348//! Swaps \p x with \p y.
107349/*! \relates Sum_Floating_Point_Expression */
107350template <typename FP_Interval_Type, typename FP_Format>
107351void swap(Sum_Floating_Point_Expression<FP_Interval_Type, FP_Format>& x,
107352          Sum_Floating_Point_Expression<FP_Interval_Type, FP_Format>& y);
107353
107354/*! \brief
107355  A generic Sum Floating Point Expression.
107356
107357  \ingroup PPL_CXX_interface
107358
107359  \par Template type parameters
107360
107361  - The class template type parameter \p FP_Interval_Type represents the type
107362  of the intervals used in the abstract domain.
107363  - The class template type parameter \p FP_Format represents the floating
107364  point format used in the concrete domain.
107365
107366  \par Linearization of sum floating-point expressions
107367
107368  Let \f$i + \sum_{v \in \cV}i_{v}v \f$ and
107369  \f$i' + \sum_{v \in \cV}i'_{v}v \f$
107370  be two linear forms and \f$\aslf\f$ a sound abstract operator on linear
107371  forms such that:
107372
107373  \f[
107374  \left(i + \sum_{v \in \cV}i_{v}v \right)
107375  \aslf
107376  \left(i' + \sum_{v \in \cV}i'_{v}v \right)
107377  =
107378  \left(i \asifp i'\right)
107379  + \sum_{v \in \cV}\left(i_{v} \asifp i'_{v} \right)v.
107380  \f]
107381
107382  Given an expression \f$e_{1} \oplus e_{2}\f$ and a composite
107383  abstract store \f$\left \llbracket \rho^{\#}, \rho^{\#}_l \right
107384  \rrbracket\f$, we construct the interval linear form
107385  \f$\linexprenv{e_{1} \oplus e_{2}}{\rho^{\#}}{\rho^{\#}_l}\f$
107386  as follows:
107387  \f[
107388  \linexprenv{e_{1} \oplus e_{2}}{\rho^{\#}}{\rho^{\#}_l}
107389  =
107390  \linexprenv{e_{1}}{\rho^{\#}}{\rho^{\#}_l}
107391  \aslf
107392  \linexprenv{e_{2}}{\rho^{\#}}{\rho^{\#}_l}
107393  \aslf
107394  \varepsilon_{\mathbf{f}}\left(\linexprenv{e_{1}}{\rho^{\#}}{\rho^{\#}_l}
107395  \right)
107396  \aslf
107397  \varepsilon_{\mathbf{f}}\left(\linexprenv{e_{2}}{\rho^{\#}}{\rho^{\#}_l}
107398  \right)
107399  \aslf
107400  mf_{\mathbf{f}}[-1, 1]
107401  \f]
107402  where \f$\varepsilon_{\mathbf{f}}(l)\f$ is the linear form computed by
107403  calling method <CODE>Floating_Point_Expression::relative_error</CODE>
107404  on \f$l\f$ and \f$mf_{\mathbf{f}}\f$ is a rounding error defined in
107405  <CODE>Floating_Point_Expression::absolute_error</CODE>.
107406*/
107407template <typename FP_Interval_Type, typename FP_Format>
107408class Sum_Floating_Point_Expression
107409  : public Floating_Point_Expression<FP_Interval_Type, FP_Format> {
107410
107411public:
107412
107413  /*! \brief
107414     Alias for the Linear_Form<FP_Interval_Type> from
107415     Floating_Point_Expression.
107416  */
107417  typedef typename
107418  Floating_Point_Expression<FP_Interval_Type, FP_Format>
107419  ::FP_Linear_Form FP_Linear_Form;
107420
107421  /*! \brief
107422     Alias for the Box<FP_Interval_Type> from
107423     Floating_Point_Expression.
107424  */
107425  typedef typename
107426  Floating_Point_Expression<FP_Interval_Type, FP_Format>
107427  ::FP_Interval_Abstract_Store FP_Interval_Abstract_Store;
107428
107429  /*! \brief
107430     Alias for the std::map<dimension_type, FP_Linear_Form> from
107431     Floating_Point_Expression.
107432  */
107433  typedef typename
107434  Floating_Point_Expression<FP_Interval_Type, FP_Format>::
107435  FP_Linear_Form_Abstract_Store FP_Linear_Form_Abstract_Store;
107436
107437  /*! \brief
107438     Alias for the FP_Interval_Type::boundary_type from
107439     Floating_Point_Expression.
107440  */
107441  typedef typename
107442  Floating_Point_Expression<FP_Interval_Type, FP_Format>::boundary_type
107443  boundary_type;
107444
107445  /*! \brief
107446     Alias for the FP_Interval_Type::info_type from Floating_Point_Expression.
107447  */
107448  typedef typename
107449  Floating_Point_Expression<FP_Interval_Type, FP_Format>::info_type info_type;
107450
107451  //! \name Constructors and Destructor
107452  //@{
107453  /*! \brief
107454    Constructor with two parameters: builds the sum floating point expression
107455    corresponding to \p x \f$\oplus\f$ \p y.
107456  */
107457  Sum_Floating_Point_Expression(
107458           Floating_Point_Expression<FP_Interval_Type, FP_Format>* const x,
107459           Floating_Point_Expression<FP_Interval_Type, FP_Format>* const y);
107460
107461  //! Destructor.
107462  ~Sum_Floating_Point_Expression();
107463
107464  //@} // Constructors and Destructor
107465
107466  /*! \brief
107467    Linearizes the expression in a given astract store.
107468
107469    Makes \p result become the linearization of \p *this in the given
107470    composite abstract store.
107471
107472    \param int_store The interval abstract store.
107473    \param lf_store The linear form abstract store.
107474    \param result The modified linear form.
107475
107476    \return <CODE>true</CODE> if the linearization succeeded,
107477    <CODE>false</CODE> otherwise.
107478
107479    Note that all variables occuring in the expressions represented
107480    by \p first_operand and \p second_operand MUST have an associated value in
107481    \p int_store. If this precondition is not met, calling the method
107482    causes an undefined behavior.
107483
107484    See the class description for a detailed explanation of how \p result
107485    is computed.
107486  */
107487  bool linearize(const FP_Interval_Abstract_Store& int_store,
107488                 const FP_Linear_Form_Abstract_Store& lf_store,
107489                 FP_Linear_Form& result) const;
107490
107491  //! Swaps \p *this with \p y.
107492  void m_swap(Sum_Floating_Point_Expression<FP_Interval_Type, FP_Format>& y);
107493
107494private:
107495
107496  //! Pointer to the first operand.
107497  Floating_Point_Expression<FP_Interval_Type, FP_Format>* first_operand;
107498  //! Pointer to the second operand.
107499  Floating_Point_Expression<FP_Interval_Type, FP_Format>* second_operand;
107500
107501  #ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
107502  /*! \brief
107503    Inhibited copy constructor.
107504  */
107505  #endif // PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
107506  Sum_Floating_Point_Expression(
107507         const Sum_Floating_Point_Expression<FP_Interval_Type, FP_Format>& e);
107508
107509  #ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
107510  /*! \brief
107511    Inhibited assignment operator.
107512  */
107513  #endif // PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
107514  Sum_Floating_Point_Expression<FP_Interval_Type, FP_Format>&
107515  operator=(const Sum_Floating_Point_Expression<FP_Interval_Type,
107516            FP_Format>& e);
107517
107518
107519}; // class Sum_Floating_Point_Expression
107520
107521} // namespace Parma_Polyhedra_Library
107522
107523/* Automatically generated from PPL source file ../src/Sum_Floating_Point_Expression_inlines.hh line 1. */
107524/* Sum_Floating_Point_Expression class implementation: inline
107525   functions.
107526*/
107527
107528
107529/* Automatically generated from PPL source file ../src/Sum_Floating_Point_Expression_inlines.hh line 29. */
107530
107531namespace Parma_Polyhedra_Library {
107532
107533template <typename FP_Interval_Type, typename FP_Format>
107534inline
107535Sum_Floating_Point_Expression<FP_Interval_Type, FP_Format>
107536::Sum_Floating_Point_Expression(
107537         Floating_Point_Expression<FP_Interval_Type, FP_Format>* const x,
107538         Floating_Point_Expression<FP_Interval_Type, FP_Format>* const y)
107539  : first_operand(x), second_operand(y) {
107540  assert(x != 0);
107541  assert(y != 0);
107542}
107543
107544template <typename FP_Interval_Type, typename FP_Format>
107545inline
107546Sum_Floating_Point_Expression<FP_Interval_Type, FP_Format>
107547::~Sum_Floating_Point_Expression() {
107548  delete first_operand;
107549  delete second_operand;
107550}
107551
107552template <typename FP_Interval_Type, typename FP_Format>
107553inline void
107554Sum_Floating_Point_Expression<FP_Interval_Type, FP_Format>
107555::m_swap(Sum_Floating_Point_Expression<FP_Interval_Type, FP_Format>& y) {
107556  using std::swap;
107557  swap(first_operand, y.first_operand);
107558  swap(second_operand, y.second_operand);
107559}
107560
107561/*! \relates Sum_Floating_Point_Expression */
107562template <typename FP_Interval_Type, typename FP_Format>
107563inline void
107564swap(Sum_Floating_Point_Expression<FP_Interval_Type, FP_Format>& x,
107565     Sum_Floating_Point_Expression<FP_Interval_Type, FP_Format>& y) {
107566  x.m_swap(y);
107567}
107568
107569} // namespace Parma_Polyhedra_Library
107570
107571/* Automatically generated from PPL source file ../src/Sum_Floating_Point_Expression_templates.hh line 1. */
107572/* Sum_Floating_Point_Expression class implementation:
107573   non-inline template functions.
107574*/
107575
107576
107577namespace Parma_Polyhedra_Library {
107578
107579template <typename FP_Interval_Type, typename FP_Format>
107580bool Sum_Floating_Point_Expression<FP_Interval_Type, FP_Format>
107581::linearize(const FP_Interval_Abstract_Store& int_store,
107582            const FP_Linear_Form_Abstract_Store& lf_store,
107583            FP_Linear_Form& result) const {
107584  if (!first_operand->linearize(int_store, lf_store, result)) {
107585    return false;
107586  }
107587  FP_Linear_Form rel_error;
107588  relative_error(result, rel_error);
107589  result += rel_error;
107590  FP_Linear_Form linearized_second_operand;
107591  if (!second_operand->linearize(int_store, lf_store,
107592                                linearized_second_operand)) {
107593    return false;
107594  }
107595  result += linearized_second_operand;
107596  relative_error(linearized_second_operand, rel_error);
107597  result += rel_error;
107598  result += this->absolute_error;
107599  return !this->overflows(result);
107600}
107601
107602} // namespace Parma_Polyhedra_Library
107603
107604/* Automatically generated from PPL source file ../src/Sum_Floating_Point_Expression_defs.hh line 212. */
107605
107606/* Automatically generated from PPL source file ../src/Difference_Floating_Point_Expression_defs.hh line 1. */
107607/* Declarations for the Difference_Floating_Point_Expression class and
107608   its constituents.
107609*/
107610
107611
107612/* Automatically generated from PPL source file ../src/Difference_Floating_Point_Expression_types.hh line 1. */
107613
107614
107615namespace Parma_Polyhedra_Library {
107616
107617template <typename FP_Interval_Type, typename FP_Format>
107618class Difference_Floating_Point_Expression;
107619
107620} // namespace Parma_Polyhedra_Library
107621
107622/* Automatically generated from PPL source file ../src/Difference_Floating_Point_Expression_defs.hh line 31. */
107623#include <map>
107624
107625namespace Parma_Polyhedra_Library {
107626
107627//! Swaps \p x with \p y.
107628/*! \relates Difference_Floating_Point_Expression */
107629template <typename FP_Interval_Type, typename FP_Format>
107630void
107631swap(Difference_Floating_Point_Expression<FP_Interval_Type, FP_Format>& x,
107632     Difference_Floating_Point_Expression<FP_Interval_Type, FP_Format>& y);
107633
107634/*! \brief
107635  A generic Difference Floating Point Expression.
107636  \ingroup PPL_CXX_interface
107637
107638  \par Template type parameters
107639
107640  - The class template type parameter \p FP_Interval_Type represents the type
107641  of the intervals used in the abstract domain.
107642  - The class template type parameter \p FP_Format represents the floating
107643  point format used in the concrete domain.
107644
107645  \par Linearization of difference floating-point expressions
107646
107647  Let \f$i + \sum_{v \in \cV}i_{v}v \f$ and
107648  \f$i' + \sum_{v \in \cV}i'_{v}v \f$
107649  be two linear forms, \f$\aslf\f$ and \f$\adlf\f$ two sound abstract
107650  operators on linear form such that:
107651  \f[
107652  \left(i + \sum_{v \in \cV}i_{v}v\right)
107653  \aslf
107654  \left(i' + \sum_{v \in \cV}i'_{v}v\right)
107655  =
107656  \left(i \asifp i'\right)
107657  + \sum_{v \in \cV}\left(i_{v} \asifp i'_{v}\right)v,
107658  \f]
107659  \f[
107660  \left(i + \sum_{v \in \cV}i_{v}v\right)
107661  \adlf
107662  \left(i' + \sum_{v \in \cV}i'_{v}v\right)
107663  =
107664  \left(i \adifp i'\right)
107665  + \sum_{v \in \cV}\left(i_{v} \adifp i'_{v}\right)v.
107666  \f]
107667  Given an expression \f$e_{1} \ominus e_{2}\f$ and a composite
107668  abstract store \f$\left \llbracket \rho^{\#}, \rho^{\#}_l \right
107669  \rrbracket\f$,  we construct the interval linear form
107670  \f$\linexprenv{e_{1} \ominus e_{2}}{\rho^{\#}}{\rho^{\#}_l}\f$
107671  on \f$\cV\f$ as follows:
107672  \f[
107673  \linexprenv{e_{1} \ominus e_{2}}{\rho^{\#}}{\rho^{\#}_l}
107674  =
107675  \linexprenv{e_{1}}{\rho^{\#}}{\rho^{\#}_l}
107676  \adlf
107677  \linexprenv{e_{2}}{\rho^{\#}}{\rho^{\#}_l}
107678  \aslf
107679  \varepsilon_{\mathbf{f}}\left(\linexprenv{e_{1}}{\rho^{\#}}{\rho^{\#}_l}
107680  \right)
107681  \aslf
107682  \varepsilon_{\mathbf{f}}\left(\linexprenv{e_{2}}{\rho^{\#}}{\rho^{\#}_l}
107683  \right)
107684  \aslf
107685  mf_{\mathbf{f}}[-1, 1]
107686  \f]
107687  where \f$\varepsilon_{\mathbf{f}}(l)\f$ is the linear form computed by
107688  calling method <CODE>Floating_Point_Expression::relative_error</CODE>
107689  on \f$l\f$ and \f$mf_{\mathbf{f}}\f$ is a rounding error defined in
107690  <CODE>Floating_Point_Expression::absolute_error</CODE>.
107691*/
107692template <typename FP_Interval_Type, typename FP_Format>
107693class Difference_Floating_Point_Expression
107694  : public Floating_Point_Expression<FP_Interval_Type, FP_Format> {
107695
107696public:
107697
107698  /*! \brief
107699     Alias for the Linear_Form<FP_Interval_Type> from
107700     Floating_Point_Expression
107701  */
107702  typedef typename
107703  Floating_Point_Expression<FP_Interval_Type, FP_Format>
107704  ::FP_Linear_Form FP_Linear_Form;
107705
107706  /*! \brief
107707     Alias for the Box<FP_Interval_Type> from
107708     Floating_Point_Expression.
107709  */
107710  typedef typename
107711  Floating_Point_Expression<FP_Interval_Type, FP_Format>
107712  ::FP_Interval_Abstract_Store FP_Interval_Abstract_Store;
107713
107714  /*! \brief
107715     Alias for the std::map<dimension_type, FP_Linear_Form> from
107716     Floating_Point_Expression.
107717  */
107718  typedef typename
107719  Floating_Point_Expression<FP_Interval_Type, FP_Format>
107720  ::FP_Linear_Form_Abstract_Store FP_Linear_Form_Abstract_Store;
107721
107722  /*! \brief
107723     Alias for the FP_Interval_Type::boundary_type from
107724     Floating_Point_Expression.
107725  */
107726  typedef typename
107727  Floating_Point_Expression<FP_Interval_Type, FP_Format>::boundary_type
107728  boundary_type;
107729
107730  /*! \brief
107731     Alias for the FP_Interval_Type::info_type from Floating_Point_Expression.
107732  */
107733  typedef typename
107734  Floating_Point_Expression<FP_Interval_Type, FP_Format>::info_type info_type;
107735
107736  //! \name Constructors and Destructor
107737  //@{
107738  /*! \brief
107739    Constructor with two parameters: builds the difference floating point
107740    expression corresponding to \p x \f$\ominus\f$ \p y.
107741  */
107742  Difference_Floating_Point_Expression(
107743           Floating_Point_Expression<FP_Interval_Type, FP_Format>* const x,
107744           Floating_Point_Expression<FP_Interval_Type, FP_Format>* const y);
107745
107746  //! Destructor.
107747  ~Difference_Floating_Point_Expression();
107748
107749  //@} // Constructors and Destructor
107750
107751  /*! \brief
107752    Linearizes the expression in a given astract store.
107753
107754    Makes \p result become the linearization of \p *this in the given
107755    composite abstract store.
107756
107757    \param int_store The interval abstract store.
107758    \param lf_store The linear form abstract store.
107759    \param result The modified linear form.
107760
107761    \return <CODE>true</CODE> if the linearization succeeded,
107762    <CODE>false</CODE> otherwise.
107763
107764    Note that all variables occuring in the expressions represented
107765    by \p first_operand and \p second_operand MUST have an associated value in
107766    \p int_store. If this precondition is not met, calling the method
107767    causes an undefined behavior.
107768
107769    See the class description for a detailed explanation of how \p result
107770    is computed.
107771  */
107772  bool linearize(const FP_Interval_Abstract_Store& int_store,
107773                 const FP_Linear_Form_Abstract_Store& lf_store,
107774                 FP_Linear_Form& result) const;
107775
107776  //! Swaps \p *this with \p y.
107777  void m_swap(Difference_Floating_Point_Expression<FP_Interval_Type,
107778                                                   FP_Format>& y);
107779
107780private:
107781
107782  //! Pointer to the first operand.
107783  Floating_Point_Expression<FP_Interval_Type, FP_Format>* first_operand;
107784  //! Pointer to the second operand.
107785  Floating_Point_Expression<FP_Interval_Type, FP_Format>* second_operand;
107786
107787  #ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
107788  /*! \brief
107789    Inhibited copy constructor.
107790  */
107791  #endif // PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
107792  Difference_Floating_Point_Expression(
107793         const Difference_Floating_Point_Expression<FP_Interval_Type,
107794                                                    FP_Format>& e);
107795
107796  #ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
107797  /*! \brief
107798    Inhibited asssignment operator.
107799  */
107800  #endif // PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
107801  Difference_Floating_Point_Expression<FP_Interval_Type, FP_Format>&
107802  operator=(const Difference_Floating_Point_Expression<FP_Interval_Type,
107803                                                       FP_Format>& e);
107804
107805
107806}; // class Difference_Floating_Point_Expression
107807
107808} // namespace Parma_Polyhedra_Library
107809
107810/* Automatically generated from PPL source file ../src/Difference_Floating_Point_Expression_inlines.hh line 1. */
107811/* Difference_Floating_Point_Expression class implementation: inline
107812   functions.
107813*/
107814
107815
107816/* Automatically generated from PPL source file ../src/Difference_Floating_Point_Expression_inlines.hh line 29. */
107817
107818namespace Parma_Polyhedra_Library {
107819
107820template <typename FP_Interval_Type, typename FP_Format>
107821inline
107822Difference_Floating_Point_Expression<FP_Interval_Type, FP_Format>
107823::Difference_Floating_Point_Expression(
107824         Floating_Point_Expression<FP_Interval_Type, FP_Format>* const x,
107825         Floating_Point_Expression<FP_Interval_Type, FP_Format>* const y)
107826  : first_operand(x), second_operand(y) {
107827  assert(x != 0);
107828  assert(y != 0);
107829}
107830
107831template <typename FP_Interval_Type, typename FP_Format>
107832inline
107833Difference_Floating_Point_Expression<FP_Interval_Type, FP_Format>
107834::~Difference_Floating_Point_Expression() {
107835  delete first_operand;
107836  delete second_operand;
107837}
107838
107839template <typename FP_Interval_Type, typename FP_Format>
107840inline void
107841Difference_Floating_Point_Expression<FP_Interval_Type, FP_Format>
107842::m_swap(Difference_Floating_Point_Expression<FP_Interval_Type, FP_Format>& y) {
107843  using std::swap;
107844  swap(first_operand, y.first_operand);
107845  swap(second_operand, y.second_operand);
107846}
107847
107848/*! \relates Difference_Floating_Point_Expression */
107849template <typename FP_Interval_Type, typename FP_Format>
107850inline void
107851swap(Difference_Floating_Point_Expression<FP_Interval_Type, FP_Format>& x,
107852     Difference_Floating_Point_Expression<FP_Interval_Type, FP_Format>& y) {
107853  x.m_swap(y);
107854}
107855
107856} // namespace Parma_Polyhedra_Library
107857
107858/* Automatically generated from PPL source file ../src/Difference_Floating_Point_Expression_templates.hh line 1. */
107859/* Difference_Floating_Point_Expression class implementation:
107860   non-inline template functions.
107861*/
107862
107863
107864namespace Parma_Polyhedra_Library {
107865
107866template <typename FP_Interval_Type, typename FP_Format>
107867bool Difference_Floating_Point_Expression<FP_Interval_Type, FP_Format>
107868::linearize(const FP_Interval_Abstract_Store& int_store,
107869            const FP_Linear_Form_Abstract_Store& lf_store,
107870            FP_Linear_Form& result) const {
107871  if (!first_operand->linearize(int_store, lf_store, result)) {
107872    return false;
107873  }
107874  FP_Linear_Form rel_error;
107875  relative_error(result, rel_error);
107876  result += rel_error;
107877  FP_Linear_Form linearized_second_operand;
107878  if (!second_operand->linearize(int_store, lf_store,
107879                      linearized_second_operand)) {
107880    return false;
107881  }
107882  result -= linearized_second_operand;
107883  relative_error(linearized_second_operand, rel_error);
107884  result += rel_error;
107885  result += this->absolute_error;
107886  return !this->overflows(result);
107887}
107888
107889} // namespace Parma_Polyhedra_Library
107890
107891/* Automatically generated from PPL source file ../src/Difference_Floating_Point_Expression_defs.hh line 220. */
107892
107893/* Automatically generated from PPL source file ../src/Multiplication_Floating_Point_Expression_defs.hh line 1. */
107894/* Declarations for the Multiplication_Floating_Point_Expression class and
107895   its constituents.
107896*/
107897
107898
107899/* Automatically generated from PPL source file ../src/Multiplication_Floating_Point_Expression_types.hh line 1. */
107900
107901
107902namespace Parma_Polyhedra_Library {
107903
107904template <typename FP_Interval_Type, typename FP_Format>
107905class Multiplication_Floating_Point_Expression;
107906
107907} // namespace Parma_Polyhedra_Library
107908
107909/* Automatically generated from PPL source file ../src/Multiplication_Floating_Point_Expression_defs.hh line 31. */
107910#include <map>
107911
107912namespace Parma_Polyhedra_Library {
107913
107914//! Swaps \p x with \p y.
107915/*! \relates Multiplication_Floating_Point_Expression */
107916template <typename FP_Interval_Type, typename FP_Format>
107917void
107918swap(Multiplication_Floating_Point_Expression<FP_Interval_Type, FP_Format>& x,
107919     Multiplication_Floating_Point_Expression<FP_Interval_Type, FP_Format>& y);
107920
107921/*! \brief
107922  A generic Multiplication Floating Point Expression.
107923
107924  \ingroup PPL_CXX_interface
107925
107926  \par Template type parameters
107927
107928  - The class template type parameter \p FP_Interval_Type represents the type
107929  of the intervals used in the abstract domain.
107930  - The class template type parameter \p FP_Format represents the floating
107931  point format used in the concrete domain.
107932
107933  \par Linearization of multiplication floating-point expressions
107934
107935  Let \f$i + \sum_{v \in \cV}i_{v}v \f$ and
107936  \f$i' + \sum_{v \in \cV}i'_{v}v \f$
107937  be two linear forms, \f$\aslf\f$ and \f$\amlf\f$ two sound abstract
107938  operators on linear forms such that:
107939  \f[
107940  \left(i + \sum_{v \in \cV}i_{v}v\right)
107941  \aslf
107942  \left(i' + \sum_{v \in \cV}i'_{v}v\right)
107943  =
107944  \left(i \asifp i'\right)
107945  + \sum_{v \in \cV}\left(i_{v} \asifp i'_{v}\right)v,
107946  \f]
107947  \f[
107948  i
107949  \amlf
107950  \left(i' + \sum_{v \in \cV}i'_{v}v\right)
107951  =
107952  \left(i \amifp i'\right)
107953  + \sum_{v \in \cV}\left(i \amifp i'_{v}\right)v.
107954  \f]
107955  Given an expression \f$[a, b] \otimes e_{2}\f$ and a composite
107956  abstract store \f$\left \llbracket \rho^{\#}, \rho^{\#}_l \right
107957  \rrbracket\f$, we construct the interval linear form
107958  \f$\linexprenv{[a, b] \otimes e_{2}}{\rho^{\#}}{\rho^{\#}_l}\f$
107959  as follows:
107960  \f[
107961  \linexprenv{[a, b] \otimes e_{2}}{\rho^{\#}}{\rho^{\#}_l}
107962  =
107963  \left([a, b]
107964  \amlf
107965  \linexprenv{e_{2}}{\rho^{\#}}{\rho^{\#}_l}\right)
107966  \aslf
107967  \left([a, b]
107968  \amlf
107969  \varepsilon_{\mathbf{f}}\left(\linexprenv{e_{2}}{\rho^{\#}}{\rho^{\#}_l}
107970  \right)\right)
107971  \aslf
107972  mf_{\mathbf{f}}[-1, 1].
107973  \f].
107974
107975  Given an expression \f$e_{1} \otimes [a, b]\f$ and a composite
107976  abstract store \f$\left \llbracket \rho^{\#}, \rho^{\#}_l \right
107977  \rrbracket\f$, we construct the interval linear form
107978  \f$\linexprenv{e_{1} \otimes [a, b]}{\rho^{\#}}{\rho^{\#}_l}\f$
107979  as follows:
107980  \f[
107981  \linexprenv{e_{1} \otimes [a, b]}{\rho^{\#}}{\rho^{\#}_l}
107982  =
107983  \linexprenv{[a, b] \otimes e_{1}}{\rho^{\#}}{\rho^{\#}_l}.
107984  \f]
107985
107986  Given an expression \f$e_{1} \otimes e_{2}\f$ and a composite
107987  abstract store \f$\left \llbracket \rho^{\#}, \rho^{\#}_l \right
107988  \rrbracket\f$, we construct the interval linear form
107989  \f$\linexprenv{e_{1} \otimes e_{2}}{\rho^{\#}}{\rho^{\#}_l}\f$
107990  as follows:
107991  \f[
107992  \linexprenv{e_{1} \otimes e_{2}}{\rho^{\#}}{\rho^{\#}_l}
107993  =
107994  \linexprenv{\iota\left(\linexprenv{e_{1}}{\rho^{\#}}{\rho^{\#}_l}
107995  \right)\rho^{\#}
107996  \otimes e_{2}}{\rho^{\#}}{\rho^{\#}_l},
107997  \f]
107998  where \f$\varepsilon_{\mathbf{f}}(l)\f$ is the linear form computed by
107999  calling method <CODE>Floating_Point_Expression::relative_error</CODE>
108000  on \f$l\f$, \f$\iota(l)\rho^{\#}\f$ is the linear form computed by calling
108001  method <CODE>Floating_Point_Expression::intervalize</CODE> on \f$l\f$
108002  and \f$\rho^{\#}\f$, and \f$mf_{\mathbf{f}}\f$ is a rounding error defined in
108003  <CODE>Floating_Point_Expression::absolute_error</CODE>.
108004
108005  Even though we intervalize the first operand in the above example, the
108006  actual implementation utilizes an heuristics for choosing which of the two
108007  operands must be intervalized in order to obtain the most precise result.
108008*/
108009template <typename FP_Interval_Type, typename FP_Format>
108010class Multiplication_Floating_Point_Expression
108011  : public Floating_Point_Expression<FP_Interval_Type, FP_Format> {
108012
108013public:
108014
108015  /*! \brief
108016     Alias for the Linear_Form<FP_Interval_Type> from
108017     Floating_Point_Expression
108018  */
108019  typedef typename
108020  Floating_Point_Expression<FP_Interval_Type, FP_Format>
108021  ::FP_Linear_Form FP_Linear_Form;
108022
108023  /*! \brief
108024     Alias for the Box<FP_Interval_Type> from
108025     Floating_Point_Expression.
108026  */
108027  typedef typename
108028  Floating_Point_Expression<FP_Interval_Type, FP_Format>
108029  ::FP_Interval_Abstract_Store FP_Interval_Abstract_Store;
108030
108031  /*! \brief
108032     Alias for the std::map<dimension_type, FP_Linear_Form> from
108033     Floating_Point_Expression.
108034  */
108035  typedef typename
108036  Floating_Point_Expression<FP_Interval_Type, FP_Format>::
108037  FP_Linear_Form_Abstract_Store FP_Linear_Form_Abstract_Store;
108038
108039  /*! \brief
108040     Alias for the FP_Interval_Type::boundary_type from
108041     Floating_Point_Expression.
108042  */
108043  typedef typename
108044  Floating_Point_Expression<FP_Interval_Type, FP_Format>::boundary_type
108045  boundary_type;
108046
108047  /*! \brief
108048     Alias for the FP_Interval_Type::info_type from Floating_Point_Expression.
108049  */
108050  typedef typename
108051  Floating_Point_Expression<FP_Interval_Type, FP_Format>::info_type info_type;
108052
108053  //! \name Constructors and Destructor
108054  //@{
108055  /*! \brief
108056    Constructor with two parameters: builds the multiplication floating point
108057    expression corresponding to \p x \f$\otimes\f$ \p y.
108058  */
108059  Multiplication_Floating_Point_Expression(
108060           Floating_Point_Expression<FP_Interval_Type, FP_Format>* const x,
108061           Floating_Point_Expression<FP_Interval_Type, FP_Format>* const y);
108062
108063  //! Destructor.
108064  ~Multiplication_Floating_Point_Expression();
108065
108066  //@} // Constructors and Destructor.
108067
108068  /*! \brief
108069    Linearizes the expression in a given astract store.
108070
108071    Makes \p result become the linearization of \p *this in the given
108072    composite abstract store.
108073
108074    \param int_store The interval abstract store.
108075    \param lf_store The linear form abstract store.
108076    \param result The modified linear form.
108077
108078    \return <CODE>true</CODE> if the linearization succeeded,
108079    <CODE>false</CODE> otherwise.
108080
108081    Note that all variables occuring in the expressions represented
108082    by \p first_operand and \p second_operand MUST have an associated value in
108083    \p int_store. If this precondition is not met, calling the method
108084    causes an undefined behavior.
108085
108086    See the class description for a detailed explanation of how \p result
108087    is computed.
108088  */
108089  bool linearize(const FP_Interval_Abstract_Store& int_store,
108090                         const FP_Linear_Form_Abstract_Store& lf_store,
108091                       FP_Linear_Form& result) const;
108092
108093  //! Swaps \p *this with \p y.
108094  void m_swap(Multiplication_Floating_Point_Expression<FP_Interval_Type,
108095                                                       FP_Format>& y);
108096
108097private:
108098
108099  //! Pointer to the first operand.
108100  Floating_Point_Expression<FP_Interval_Type, FP_Format>* first_operand;
108101  //! Pointer to the second operand.
108102  Floating_Point_Expression<FP_Interval_Type, FP_Format>* second_operand;
108103
108104  #ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
108105  /*! \brief
108106    Inhibited copy constructor.
108107  */
108108  #endif // PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
108109  Multiplication_Floating_Point_Expression(
108110         const Multiplication_Floating_Point_Expression<FP_Interval_Type,
108111                                                        FP_Format>& e);
108112
108113  #ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
108114  /*! \brief
108115    Inhibited assignment operator.
108116  */
108117  #endif // PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
108118  Multiplication_Floating_Point_Expression<FP_Interval_Type, FP_Format>&
108119  operator=(const Multiplication_Floating_Point_Expression<FP_Interval_Type,
108120            FP_Format>& e);
108121
108122
108123}; // class Multiplication_Floating_Point_Expression
108124
108125} // namespace Parma_Polyhedra_Library
108126
108127/* Automatically generated from PPL source file ../src/Multiplication_Floating_Point_Expression_inlines.hh line 1. */
108128/* Multiplication_Floating_Point_Expression class implementation: inline
108129   functions.
108130*/
108131
108132
108133/* Automatically generated from PPL source file ../src/Multiplication_Floating_Point_Expression_inlines.hh line 29. */
108134
108135namespace Parma_Polyhedra_Library {
108136
108137template <typename FP_Interval_Type, typename FP_Format>
108138inline
108139Multiplication_Floating_Point_Expression<FP_Interval_Type, FP_Format>
108140::Multiplication_Floating_Point_Expression(
108141         Floating_Point_Expression<FP_Interval_Type, FP_Format>* const x,
108142         Floating_Point_Expression<FP_Interval_Type, FP_Format>* const y)
108143  : first_operand(x), second_operand(y) {
108144  assert(x != 0);
108145  assert(y != 0);
108146}
108147
108148template <typename FP_Interval_Type, typename FP_Format>
108149inline
108150Multiplication_Floating_Point_Expression<FP_Interval_Type, FP_Format>
108151::~Multiplication_Floating_Point_Expression() {
108152  delete first_operand;
108153  delete second_operand;
108154}
108155
108156template <typename FP_Interval_Type, typename FP_Format>
108157inline void
108158Multiplication_Floating_Point_Expression<FP_Interval_Type, FP_Format>
108159::m_swap(Multiplication_Floating_Point_Expression<FP_Interval_Type,
108160                                                  FP_Format>& y) {
108161  using std::swap;
108162  swap(first_operand, y.first_operand);
108163  swap(second_operand, y.second_operand);
108164}
108165
108166/*! \relates Multiplication_Floating_Point_Expression */
108167template <typename FP_Interval_Type, typename FP_Format>
108168inline void
108169swap(Multiplication_Floating_Point_Expression<FP_Interval_Type, FP_Format>& x,
108170     Multiplication_Floating_Point_Expression<FP_Interval_Type, FP_Format>& y) {
108171  x.m_swap(y);
108172}
108173
108174} // namespace Parma_Polyhedra_Library
108175
108176/* Automatically generated from PPL source file ../src/Multiplication_Floating_Point_Expression_templates.hh line 1. */
108177/* Multiplication_Floating_Point_Expression class implementation:
108178   non-inline template functions.
108179*/
108180
108181
108182namespace Parma_Polyhedra_Library {
108183
108184template <typename FP_Interval_Type, typename FP_Format>
108185bool Multiplication_Floating_Point_Expression<FP_Interval_Type, FP_Format>
108186::linearize(const FP_Interval_Abstract_Store& int_store,
108187            const FP_Linear_Form_Abstract_Store& lf_store,
108188            FP_Linear_Form& result) const {
108189  /*
108190    FIXME: We currently adopt the "Interval-Size Local" strategy in order to
108191    decide which of the two linear forms must be intervalized, as described
108192    in Section 6.2.4 ("Multiplication Strategies") of Antoine Mine's Ph.D.
108193    thesis "Weakly Relational Numerical Abstract Domains".
108194    In this Section are also described other multiplication strategies, such
108195    as All-Cases, Relative-Size Local, Simplification-Driven Global and
108196    Homogeneity Global.
108197  */
108198
108199  // Here we choose which of the two linear forms must be intervalized.
108200
108201  // true if we intervalize the first form, false if we intervalize the second.
108202  bool intervalize_first;
108203  FP_Linear_Form linearized_first_operand;
108204  if (!first_operand->linearize(int_store, lf_store,
108205                               linearized_first_operand)) {
108206    return false;
108207  }
108208  FP_Interval_Type intervalized_first_operand;
108209  this->intervalize(linearized_first_operand, int_store,
108210                    intervalized_first_operand);
108211  FP_Linear_Form linearized_second_operand;
108212  if (!second_operand->linearize(int_store, lf_store,
108213                                linearized_second_operand)) {
108214    return false;
108215  }
108216  FP_Interval_Type intervalized_second_operand;
108217  this->intervalize(linearized_second_operand, int_store,
108218                    intervalized_second_operand);
108219
108220  // FIXME: we are not sure that what we do here is policy-proof.
108221  if (intervalized_first_operand.is_bounded()) {
108222    if (intervalized_second_operand.is_bounded()) {
108223      boundary_type first_interval_size
108224        = intervalized_first_operand.upper()
108225        - intervalized_first_operand.lower();
108226      boundary_type second_interval_size
108227        = intervalized_second_operand.upper()
108228        - intervalized_second_operand.lower();
108229      if (first_interval_size <= second_interval_size) {
108230        intervalize_first = true;
108231      }
108232      else {
108233        intervalize_first = false;
108234      }
108235    }
108236    else {
108237      intervalize_first = true;
108238    }
108239  }
108240  else {
108241    if (intervalized_second_operand.is_bounded()) {
108242      intervalize_first = false;
108243    }
108244    else {
108245      return false;
108246    }
108247  }
108248
108249  // Here we do the actual computation.
108250  // For optimizing, we store the relative error directly into result.
108251  if (intervalize_first) {
108252    relative_error(linearized_second_operand, result);
108253    linearized_second_operand *= intervalized_first_operand;
108254    result *= intervalized_first_operand;
108255    result += linearized_second_operand;
108256  }
108257  else {
108258    relative_error(linearized_first_operand, result);
108259    linearized_first_operand *= intervalized_second_operand;
108260    result *= intervalized_second_operand;
108261    result += linearized_first_operand;
108262  }
108263
108264  result += this->absolute_error;
108265  return !this->overflows(result);
108266}
108267
108268} // namespace Parma_Polyhedra_Library
108269
108270/* Automatically generated from PPL source file ../src/Multiplication_Floating_Point_Expression_defs.hh line 250. */
108271
108272/* Automatically generated from PPL source file ../src/Division_Floating_Point_Expression_defs.hh line 1. */
108273/* Declarations for the Division_Floating_Point_Expression class and its
108274   constituents.
108275*/
108276
108277
108278/* Automatically generated from PPL source file ../src/Division_Floating_Point_Expression_types.hh line 1. */
108279
108280
108281namespace Parma_Polyhedra_Library {
108282
108283template <typename FP_Interval_Type, typename FP_Format>
108284class Division_Floating_Point_Expression;
108285
108286} // namespace Parma_Polyhedra_Library
108287
108288/* Automatically generated from PPL source file ../src/Division_Floating_Point_Expression_defs.hh line 31. */
108289#include <map>
108290
108291namespace Parma_Polyhedra_Library {
108292
108293//! Swaps \p x with \p y.
108294/*! \relates Division_Floating_Point_Expression */
108295template <typename FP_Interval_Type, typename FP_Format>
108296void swap(Division_Floating_Point_Expression<FP_Interval_Type, FP_Format>& x,
108297          Division_Floating_Point_Expression<FP_Interval_Type, FP_Format>& y);
108298
108299/*! \brief
108300  A generic Division Floating Point Expression.
108301
108302  \ingroup PPL_CXX_interface
108303
108304  \par Template type parameters
108305
108306  - The class template type parameter \p FP_Interval_Type represents the type
108307  of the intervals used in the abstract domain.
108308  - The class template type parameter \p FP_Format represents the floating
108309  point format used in the concrete domain.
108310
108311  \par Linearizationd of division floating-point expressions
108312
108313  Let \f$i + \sum_{v \in \cV}i_{v}v \f$ and
108314  \f$i' + \sum_{v \in \cV}i'_{v}v \f$
108315  be two linear forms, \f$\aslf\f$ and \f$\adivlf\f$ two sound abstract
108316  operator on linear forms such that:
108317  \f[
108318  \left(i + \sum_{v \in \cV}i_{v}v\right)
108319  \aslf
108320  \left(i' + \sum_{v \in \cV}i'_{v}v\right)
108321  =
108322  \left(i \asifp i'\right)
108323  + \sum_{v \in \cV}\left(i_{v} \asifp i'_{v}\right)v,
108324  \f]
108325  \f[
108326  \left(i + \sum_{v \in \cV}i_{v}v\right)
108327  \adivlf
108328  i'
108329  =
108330  \left(i \adivifp i'\right)
108331  + \sum_{v \in \cV}\left(i_{v} \adivifp i'\right)v.
108332  \f]
108333  Given an expression \f$e_{1} \oslash [a, b]\f$ and a composite
108334  abstract store \f$\left \llbracket \rho^{\#}, \rho^{\#}_l \right
108335  \rrbracket\f$,
108336  we construct the interval linear form
108337  \f$
108338  \linexprenv{e_{1} \oslash [a, b]}{\rho^{\#}}{\rho^{\#}_l}
108339  \f$
108340  as follows:
108341  \f[
108342  \linexprenv{e_{1} \oslash [a, b]}{\rho^{\#}}{\rho^{\#}_l}
108343  =
108344  \left(\linexprenv{e_{1}}{\rho^{\#}}{\rho^{\#}_l}
108345  \adivlf
108346  [a, b]\right)
108347  \aslf
108348  \left(\varepsilon_{\mathbf{f}}\left(
108349  \linexprenv{e_{1}}{\rho^{\#}}{\rho^{\#}_l}
108350  \right)
108351  \adivlf
108352  [a, b]\right)
108353  \aslf
108354  mf_{\mathbf{f}}[-1, 1],
108355  \f]
108356  given an expression \f$e_{1} \oslash e_{2}\f$ and a composite
108357  abstract store \f$\left \llbracket \rho^{\#}, \rho^{\#}_l \right
108358  \rrbracket\f$, we construct the interval linear form
108359  \f$\linexprenv{e_{1} \oslash e_{2}}{\rho^{\#}}{\rho^{\#}_l}\f$
108360  as follows:
108361  \f[
108362  \linexprenv{e_{1} \oslash e_{2}}{\rho^{\#}}{\rho^{\#}_l}
108363  =
108364  \linexprenv{e_{1} \oslash \iota\left(
108365  \linexprenv{e_{2}}{\rho^{\#}}{\rho^{\#}_l}
108366  \right)\rho^{\#}}{\rho^{\#}}{\rho^{\#}_l},
108367  \f]
108368  where \f$\varepsilon_{\mathbf{f}}(l)\f$ is the linear form computed by
108369  calling method <CODE>Floating_Point_Expression::relative_error</CODE>
108370  on \f$l\f$, \f$\iota(l)\rho^{\#}\f$ is the linear form computed by calling
108371  method <CODE>Floating_Point_Expression::intervalize</CODE> on \f$l\f$
108372  and \f$\rho^{\#}\f$, and \f$mf_{\mathbf{f}}\f$ is a rounding error defined in
108373  <CODE>Floating_Point_Expression::absolute_error</CODE>.
108374*/
108375template <typename FP_Interval_Type, typename FP_Format>
108376class Division_Floating_Point_Expression
108377  : public Floating_Point_Expression<FP_Interval_Type, FP_Format> {
108378
108379public:
108380
108381  /*! \brief
108382     Alias for the Linear_Form<FP_Interval_Type> from
108383     Floating_Point_Expression
108384  */
108385  typedef typename
108386  Floating_Point_Expression<FP_Interval_Type, FP_Format>
108387  ::FP_Linear_Form FP_Linear_Form;
108388
108389  /*! \brief
108390     Alias for the Box<FP_Interval_Type> from
108391     Floating_Point_Expression.
108392  */
108393  typedef typename
108394  Floating_Point_Expression<FP_Interval_Type, FP_Format>
108395  ::FP_Interval_Abstract_Store FP_Interval_Abstract_Store;
108396
108397  /*! \brief
108398     Alias for the std::map<dimension_type, FP_Linear_Form> from
108399     Floating_Point_Expression.
108400  */
108401  typedef typename
108402  Floating_Point_Expression<FP_Interval_Type, FP_Format>::
108403  FP_Linear_Form_Abstract_Store FP_Linear_Form_Abstract_Store;
108404
108405  /*! \brief
108406     Alias for the FP_Interval_Type::boundary_type from
108407     Floating_Point_Expression.
108408  */
108409  typedef typename
108410  Floating_Point_Expression<FP_Interval_Type, FP_Format>::boundary_type
108411  boundary_type;
108412
108413  /*! \brief
108414     Alias for the FP_Interval_Type::info_type from Floating_Point_Expression.
108415  */
108416  typedef typename
108417  Floating_Point_Expression<FP_Interval_Type, FP_Format>::info_type info_type;
108418
108419  //! \name Constructors and Destructor
108420  //@{
108421  /*! \brief
108422    Constructor with two parameters: builds the division floating point
108423    expression corresponding to \p num \f$\oslash\f$ \p den.
108424  */
108425  Division_Floating_Point_Expression(
108426           Floating_Point_Expression<FP_Interval_Type, FP_Format>* const num,
108427           Floating_Point_Expression<FP_Interval_Type, FP_Format>* const den);
108428
108429  //! Destructor.
108430  ~Division_Floating_Point_Expression();
108431
108432  //@} // Constructors and Destructor
108433
108434  /*! \brief
108435    Linearizes the expression in a given astract store.
108436
108437    Makes \p result become the linearization of \p *this in the given
108438    composite abstract store.
108439
108440    \param int_store The interval abstract store.
108441    \param lf_store The linear form abstract store.
108442    \param result The modified linear form.
108443
108444    \return <CODE>true</CODE> if the linearization succeeded,
108445    <CODE>false</CODE> otherwise.
108446
108447    Note that all variables occuring in the expressions represented
108448    by \p first_operand and \p second_operand MUST have an associated value in
108449    \p int_store. If this precondition is not met, calling the method
108450    causes an undefined behavior.
108451
108452    See the class description for a detailed explanation of how \p result
108453    is computed.
108454  */
108455  bool linearize(const FP_Interval_Abstract_Store& int_store,
108456                 const FP_Linear_Form_Abstract_Store& lf_store,
108457                 FP_Linear_Form& result) const;
108458
108459  //! Swaps \p *this with \p y.
108460  void m_swap(Division_Floating_Point_Expression<FP_Interval_Type,
108461                                                 FP_Format>& y);
108462
108463private:
108464
108465  //! Pointer to the first operand.
108466  Floating_Point_Expression<FP_Interval_Type, FP_Format>* first_operand;
108467  //! Pointer to the second operand.
108468  Floating_Point_Expression<FP_Interval_Type, FP_Format>* second_operand;
108469
108470  #ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
108471  /*! \brief
108472    Copy constructor: temporary inhibited.
108473  */
108474  #endif // PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
108475  Division_Floating_Point_Expression(
108476         const Division_Floating_Point_Expression<FP_Interval_Type,
108477                                                  FP_Format>& e);
108478
108479  #ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
108480  /*! \brief
108481    Assignment operator: temporary inhibited.
108482  */
108483  #endif // PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
108484  Division_Floating_Point_Expression<FP_Interval_Type, FP_Format>&
108485  operator=(const Division_Floating_Point_Expression<FP_Interval_Type,
108486            FP_Format>& e);
108487
108488}; // class Division_Floating_Point_Expression
108489
108490} // namespace Parma_Polyhedra_Library
108491
108492/* Automatically generated from PPL source file ../src/Division_Floating_Point_Expression_inlines.hh line 1. */
108493/* Division_Floating_Point_Expression class implementation: inline functions.
108494*/
108495
108496
108497/* Automatically generated from PPL source file ../src/Division_Floating_Point_Expression_inlines.hh line 28. */
108498
108499namespace Parma_Polyhedra_Library {
108500
108501template <typename FP_Interval_Type, typename FP_Format>
108502inline
108503Division_Floating_Point_Expression<FP_Interval_Type, FP_Format>
108504::Division_Floating_Point_Expression(
108505         Floating_Point_Expression<FP_Interval_Type, FP_Format>* const num,
108506         Floating_Point_Expression<FP_Interval_Type, FP_Format>* const den)
108507  : first_operand(num), second_operand(den) {
108508  assert(num != 0);
108509  assert(den != 0);
108510}
108511
108512template <typename FP_Interval_Type, typename FP_Format>
108513inline
108514Division_Floating_Point_Expression<FP_Interval_Type, FP_Format>
108515::~Division_Floating_Point_Expression() {
108516  delete first_operand;
108517  delete second_operand;
108518}
108519
108520template <typename FP_Interval_Type, typename FP_Format>
108521inline void
108522Division_Floating_Point_Expression<FP_Interval_Type, FP_Format>
108523::m_swap(Division_Floating_Point_Expression<FP_Interval_Type, FP_Format>& y) {
108524  using std::swap;
108525  swap(first_operand, y.first_operand);
108526  swap(second_operand, y.second_operand);
108527}
108528
108529/*! \relates Division_Floating_Point_Expression */
108530template <typename FP_Interval_Type, typename FP_Format>
108531inline void
108532swap(Division_Floating_Point_Expression<FP_Interval_Type, FP_Format>& x,
108533     Division_Floating_Point_Expression<FP_Interval_Type, FP_Format>& y) {
108534  x.m_swap(y);
108535}
108536
108537} // namespace Parma_Polyhedra_Library
108538
108539/* Automatically generated from PPL source file ../src/Division_Floating_Point_Expression_templates.hh line 1. */
108540/* Division_Floating_Point_Expression class implementation:
108541   non-inline template functions.
108542*/
108543
108544
108545namespace Parma_Polyhedra_Library {
108546
108547template <typename FP_Interval_Type, typename FP_Format>
108548bool Division_Floating_Point_Expression<FP_Interval_Type, FP_Format>
108549::linearize(const FP_Interval_Abstract_Store& int_store,
108550            const FP_Linear_Form_Abstract_Store& lf_store,
108551            FP_Linear_Form& result) const {
108552  FP_Linear_Form linearized_second_operand;
108553  if (!second_operand->linearize(int_store, lf_store,
108554                                linearized_second_operand)) {
108555    return false;
108556  }
108557  FP_Interval_Type intervalized_second_operand;
108558  this->intervalize(linearized_second_operand, int_store,
108559                    intervalized_second_operand);
108560
108561  // Check if we may divide by zero.
108562  if (intervalized_second_operand.lower() <= 0
108563      && intervalized_second_operand.upper() >= 0) {
108564    return false;
108565  }
108566
108567  if (!first_operand->linearize(int_store, lf_store, result)) {
108568    return false;
108569  }
108570  FP_Linear_Form rel_error;
108571  relative_error(result, rel_error);
108572  result /= intervalized_second_operand;
108573  rel_error /= intervalized_second_operand;
108574  result += rel_error;
108575  result += this->absolute_error;
108576  return !this->overflows(result);
108577}
108578
108579} // namespace Parma_Polyhedra_Library
108580
108581/* Automatically generated from PPL source file ../src/Division_Floating_Point_Expression_defs.hh line 236. */
108582
108583/* Automatically generated from PPL source file ../src/Opposite_Floating_Point_Expression_defs.hh line 1. */
108584/* Declarations for the Opposite_Floating_Point_Expression class and
108585   its constituents.
108586*/
108587
108588
108589/* Automatically generated from PPL source file ../src/Opposite_Floating_Point_Expression_types.hh line 1. */
108590
108591
108592namespace Parma_Polyhedra_Library {
108593
108594template <typename FP_Interval_Type, typename FP_Format>
108595class Opposite_Floating_Point_Expression;
108596
108597} // namespace Parma_Polyhedra_Library
108598
108599/* Automatically generated from PPL source file ../src/Opposite_Floating_Point_Expression_defs.hh line 31. */
108600#include <map>
108601
108602namespace Parma_Polyhedra_Library {
108603
108604//! Swaps \p x with \p y.
108605/*! \relates Opposite_Floating_Point_Expression */
108606template<typename FP_Interval_Type, typename FP_Format>
108607void swap(Opposite_Floating_Point_Expression<FP_Interval_Type, FP_Format>& x,
108608          Opposite_Floating_Point_Expression<FP_Interval_Type, FP_Format>& y);
108609
108610/*! \brief
108611  A generic Opposite Floating Point Expression.
108612
108613  \ingroup PPL_CXX_interface
108614
108615  \par Template type parameters
108616
108617  - The class template type parameter \p FP_Interval_Type represents the type
108618  of the intervals used in the abstract domain.
108619  - The class template type parameter \p FP_Format represents the floating
108620  point format used in the concrete domain.
108621
108622  \par Linearization of opposite floating-point expressions
108623
108624  Let \f$i + \sum_{v \in \cV}i_{v}v \f$ be an interval linear form and
108625  let \f$\adlf\f$ be a sound unary operator on linear forms such that:
108626
108627  \f[
108628  \adlf
108629  \left(i + \sum_{v \in \cV}i_{v}v\right)
108630  =
108631  \left(\adifp i\right)
108632  + \sum_{v \in \cV}\left(\adifp i_{v} \right)v,
108633  \f]
108634
108635  Given a floating point expression \f$\ominus e\f$ and a composite
108636  abstract store \f$\left \llbracket \rho^{\#}, \rho^{\#}_l \right
108637  \rrbracket\f$, we construct the interval linear form
108638  \f$\linexprenv{\ominus e}{\rho^{\#}}{\rho^{\#}_l}\f$
108639  as follows:
108640  \f[
108641  \linexprenv{\ominus e}{\rho^{\#}}{\rho^{\#}_l}
108642  =
108643  \adlf
108644  \left(
108645  \linexprenv{e}{\rho^{\#}}{\rho^{\#}_l}
108646  \right).
108647  \f]
108648*/
108649template <typename FP_Interval_Type, typename FP_Format>
108650class Opposite_Floating_Point_Expression
108651  : public Floating_Point_Expression<FP_Interval_Type, FP_Format> {
108652
108653public:
108654
108655  /*! \brief
108656    Alias for the Linear_Form<FP_Interval_Type> from
108657    Floating_Point_Expression
108658  */
108659  typedef typename
108660  Floating_Point_Expression<FP_Interval_Type, FP_Format>::
108661  FP_Linear_Form FP_Linear_Form;
108662
108663  /*! \brief
108664    Alias for the std::map<dimension_type, FP_Interval_Type> from
108665    Floating_Point_Expression.
108666  */
108667  typedef typename
108668  Floating_Point_Expression<FP_Interval_Type, FP_Format>::
108669  FP_Interval_Abstract_Store FP_Interval_Abstract_Store;
108670
108671  /*! \brief
108672    Alias for the std::map<dimension_type, FP_Linear_Form> from
108673    Floating_Point_Expression.
108674  */
108675  typedef typename
108676  Floating_Point_Expression<FP_Interval_Type, FP_Format>::
108677  FP_Linear_Form_Abstract_Store FP_Linear_Form_Abstract_Store;
108678
108679  /*! \brief
108680    Alias for the FP_Interval_Type::boundary_type from
108681    Floating_Point_Expression.
108682  */
108683  typedef typename
108684  Floating_Point_Expression<FP_Interval_Type, FP_Format>::boundary_type
108685  boundary_type;
108686
108687  /*! \brief
108688    Alias for the FP_Interval_Type::info_type from Floating_Point_Expression.
108689  */
108690  typedef typename
108691  Floating_Point_Expression<FP_Interval_Type, FP_Format>::info_type info_type;
108692
108693  //! \name Constructors and Destructor
108694  //@{
108695  /*! \brief
108696    Constructor with one parameter: builds the opposite floating point
108697    expression \f$\ominus\f$ \p op.
108698  */
108699  explicit Opposite_Floating_Point_Expression(
108700           Floating_Point_Expression<FP_Interval_Type, FP_Format>* const op);
108701
108702  //! Destructor.
108703  ~Opposite_Floating_Point_Expression();
108704
108705  //@} // Constructors and Destructor
108706
108707  /*! \brief
108708    Linearizes the expression in a given astract store.
108709
108710    Makes \p result become the linearization of \p *this in the given
108711    composite abstract store.
108712
108713    \param int_store The interval abstract store.
108714    \param lf_store The linear form abstract store.
108715    \param result The modified linear form.
108716
108717    \return <CODE>true</CODE> if the linearization succeeded,
108718    <CODE>false</CODE> otherwise.
108719
108720    Note that all variables occuring in the expression represented
108721    by \p operand MUST have an associated value in \p int_store.
108722    If this precondition is not met, calling the method
108723    causes an undefined behavior.
108724
108725    See the class description for a detailed explanation of how \p result
108726    is computed.
108727  */
108728  bool linearize(const FP_Interval_Abstract_Store& int_store,
108729                 const FP_Linear_Form_Abstract_Store& lf_store,
108730                 FP_Linear_Form& result) const;
108731
108732  //! Swaps \p *this with \p y.
108733  void m_swap(Opposite_Floating_Point_Expression& y);
108734
108735private:
108736
108737  #ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
108738  /*! \brief
108739    Inhibited copy constructor.
108740  */
108741  #endif // PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
108742  Opposite_Floating_Point_Expression(
108743                          const Opposite_Floating_Point_Expression& y);
108744
108745  #ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
108746  /*! \brief
108747    Inhibited assignment operator.
108748  */
108749  #endif // PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
108750  Opposite_Floating_Point_Expression& operator=(
108751                          const Opposite_Floating_Point_Expression& y);
108752
108753  //! Pointer to the operand.
108754  Floating_Point_Expression<FP_Interval_Type, FP_Format>* operand;
108755
108756}; // class Opposite_Floating_Point_Expression
108757
108758} // namespace Parma_Polyhedra_Library
108759
108760/* Automatically generated from PPL source file ../src/Opposite_Floating_Point_Expression_inlines.hh line 1. */
108761/* Opposite_Floating_Point_Expression class implementation: inline functions.
108762*/
108763
108764
108765/* Automatically generated from PPL source file ../src/Opposite_Floating_Point_Expression_inlines.hh line 28. */
108766
108767namespace Parma_Polyhedra_Library {
108768
108769template <typename FP_Interval_Type, typename FP_Format>
108770inline
108771Opposite_Floating_Point_Expression<FP_Interval_Type, FP_Format>::
108772Opposite_Floating_Point_Expression(
108773         Floating_Point_Expression<FP_Interval_Type, FP_Format>* const op)
108774  : operand(op)
108775{
108776  assert(op != 0);
108777}
108778
108779template <typename FP_Interval_Type, typename FP_Format>
108780inline
108781Opposite_Floating_Point_Expression<FP_Interval_Type, FP_Format>::
108782~Opposite_Floating_Point_Expression() {
108783  delete operand;
108784}
108785
108786template <typename FP_Interval_Type, typename FP_Format>
108787inline void
108788Opposite_Floating_Point_Expression<FP_Interval_Type, FP_Format>
108789::m_swap(Opposite_Floating_Point_Expression& y) {
108790  using std::swap;
108791  swap(operand, y.operand);
108792}
108793
108794template <typename FP_Interval_Type, typename FP_Format>
108795inline bool
108796Opposite_Floating_Point_Expression<FP_Interval_Type, FP_Format>
108797::linearize(const FP_Interval_Abstract_Store& int_store,
108798            const FP_Linear_Form_Abstract_Store& lf_store,
108799            FP_Linear_Form& result) const {
108800  if (!operand->linearize(int_store, lf_store, result)) {
108801    return false;
108802  }
108803
108804  result.negate();
108805  return true;
108806}
108807
108808/*! \relates Opposite_Floating_Point_Expression */
108809template <typename FP_Interval_Type, typename FP_Format>
108810inline void
108811swap(Opposite_Floating_Point_Expression<FP_Interval_Type, FP_Format>& x,
108812     Opposite_Floating_Point_Expression<FP_Interval_Type, FP_Format>& y) {
108813  x.m_swap(y);
108814}
108815
108816} // namespace Parma_Polyhedra_Library
108817
108818/* Automatically generated from PPL source file ../src/Opposite_Floating_Point_Expression_defs.hh line 192. */
108819
108820/* Automatically generated from PPL source file ../src/Watchdog_defs.hh line 1. */
108821/* Watchdog and associated classes' declaration and inline functions.
108822*/
108823
108824
108825/* Automatically generated from PPL source file ../src/Watchdog_types.hh line 1. */
108826
108827
108828namespace Parma_Polyhedra_Library {
108829
108830class Watchdog;
108831
108832} // namespace Parma_Polyhedra_Library
108833
108834/* Automatically generated from PPL source file ../src/Time_defs.hh line 1. */
108835/* Time class declaration.
108836*/
108837
108838
108839/* Automatically generated from PPL source file ../src/Time_types.hh line 1. */
108840
108841
108842namespace Parma_Polyhedra_Library {
108843
108844namespace Implementation {
108845
108846namespace Watchdog {
108847
108848class Time;
108849
108850} // namespace Watchdog
108851
108852} // namespace Implementation
108853
108854} // namespace Parma_Polyhedra_Library
108855
108856/* Automatically generated from PPL source file ../src/Time_defs.hh line 28. */
108857
108858namespace Parma_Polyhedra_Library {
108859
108860namespace Implementation {
108861
108862namespace Watchdog {
108863
108864//! Returns <CODE>true</CODE> if and only if \p x and \p y are equal.
108865bool operator==(const Time& x, const Time& y);
108866
108867//! Returns <CODE>true</CODE> if and only if \p x and \p y are different.
108868bool operator!=(const Time& x, const Time& y);
108869
108870//! Returns <CODE>true</CODE> if and only if \p x is shorter than \p y.
108871bool operator<(const Time& x, const Time& y);
108872
108873/*! \brief
108874  Returns <CODE>true</CODE> if and only if \p x is shorter than
108875  or equal to \p y.
108876*/
108877bool operator<=(const Time& x, const Time& y);
108878
108879//! Returns <CODE>true</CODE> if and only if \p x is longer than \p y.
108880bool operator>(const Time& x, const Time& y);
108881
108882/*! \brief
108883  Returns <CODE>true</CODE> if and only if \p x is longer than
108884  or equal to \p y.
108885*/
108886bool operator>=(const Time& x, const Time& y);
108887
108888//! Returns the sum of \p x and \p y.
108889Time operator+(const Time& x, const Time& y);
108890
108891/*! \brief
108892  Returns the difference of \p x and \p y or the null interval,
108893  if \p x is shorter than \p y.
108894*/
108895Time operator-(const Time& x, const Time& y);
108896
108897} // namespace Watchdog
108898
108899} // namespace Implementation
108900
108901} // namespace Parma_Polyhedra_Library
108902
108903//! A class for representing and manipulating positive time intervals.
108904class Parma_Polyhedra_Library::Implementation::Watchdog::Time {
108905public:
108906  //! Zero seconds.
108907  Time();
108908
108909  //! Constructor taking a number of centiseconds.
108910  explicit Time(long centisecs);
108911
108912  //! Constructor with seconds and microseconds.
108913  Time(long s, long m);
108914
108915  /*! \brief
108916    Returns the number of whole seconds contained in the represented
108917    time interval.
108918  */
108919  long seconds() const;
108920
108921  /*! \brief
108922    Returns the number of microseconds that, when added to the number
108923    of seconds returned by seconds(), give the represent time interval.
108924  */
108925  long microseconds() const;
108926
108927  //! Adds \p y to \p *this.
108928  Time& operator+=(const Time& y);
108929
108930  /*! \brief
108931    Subtracts \p y from \p *this; if \p *this is shorter than \p y,
108932    \p *this is set to the null interval.
108933  */
108934  Time& operator-=(const Time& y);
108935
108936  //! Checks if all the invariants are satisfied.
108937  bool OK() const;
108938
108939private:
108940  //! Number of microseconds in a second.
108941  static const long USECS_PER_SEC = 1000000L;
108942
108943  //! Number of centiseconds in a second.
108944  static const long CSECS_PER_SEC = 100L;
108945
108946  //! Number of seconds.
108947  long secs;
108948
108949  //! Number of microseconds.
108950  long microsecs;
108951};
108952
108953/* Automatically generated from PPL source file ../src/Time_inlines.hh line 1. */
108954/* Time class implementation: inline functions.
108955*/
108956
108957
108958#include <cassert>
108959
108960namespace Parma_Polyhedra_Library {
108961
108962namespace Implementation {
108963
108964namespace Watchdog {
108965
108966inline
108967Time::Time()
108968  : secs(0), microsecs(0) {
108969  assert(OK());
108970}
108971
108972inline
108973Time::Time(long centisecs)
108974  : secs(centisecs / CSECS_PER_SEC),
108975    microsecs((centisecs % CSECS_PER_SEC) * (USECS_PER_SEC/CSECS_PER_SEC)) {
108976  assert(OK());
108977}
108978
108979inline
108980Time::Time(long s, long m)
108981  : secs(s),
108982    microsecs(m) {
108983  if (microsecs >= USECS_PER_SEC) {
108984    secs += microsecs / USECS_PER_SEC;
108985    microsecs %= USECS_PER_SEC;
108986  }
108987  assert(OK());
108988}
108989
108990inline long
108991Time::seconds() const {
108992  return secs;
108993}
108994
108995inline long
108996Time::microseconds() const {
108997  return microsecs;
108998}
108999
109000inline Time&
109001Time::operator+=(const Time& y) {
109002  long r_secs = secs + y.secs;
109003  long r_microsecs = microsecs + y.microsecs;
109004  if (r_microsecs >= USECS_PER_SEC) {
109005    ++r_secs;
109006    r_microsecs %= USECS_PER_SEC;
109007  }
109008  secs = r_secs;
109009  microsecs = r_microsecs;
109010  assert(OK());
109011  return *this;
109012}
109013
109014inline Time&
109015Time::operator-=(const Time& y) {
109016  long r_secs = secs - y.secs;
109017  long r_microsecs = microsecs - y.microsecs;
109018  if (r_microsecs < 0) {
109019    --r_secs;
109020    r_microsecs += USECS_PER_SEC;
109021  }
109022  if (r_secs < 0) {
109023    r_secs = 0;
109024    r_microsecs = 0;
109025  }
109026  secs = r_secs;
109027  microsecs = r_microsecs;
109028  assert(OK());
109029  return *this;
109030}
109031
109032inline Time
109033operator+(const Time& x, const Time& y) {
109034  Time z = x;
109035  z += y;
109036  return z;
109037}
109038
109039inline Time
109040operator-(const Time& x, const Time& y) {
109041  Time z = x;
109042  z -= y;
109043  return z;
109044}
109045
109046inline bool
109047operator==(const Time& x, const Time& y) {
109048  assert(x.OK() && y.OK());
109049  return x.seconds() == y.seconds() && y.microseconds() == y.microseconds();
109050}
109051
109052inline bool
109053operator!=(const Time& x, const Time& y) {
109054  assert(x.OK() && y.OK());
109055  return !(x == y);
109056}
109057
109058inline bool
109059operator<(const Time& x, const Time& y) {
109060  assert(x.OK() && y.OK());
109061  return x.seconds() < y.seconds()
109062    || (x.seconds() == y.seconds() && x.microseconds() < y.microseconds());
109063}
109064
109065inline bool
109066operator<=(const Time& x, const Time& y) {
109067  return x < y || x == y;
109068}
109069
109070inline bool
109071operator>(const Time& x, const Time& y) {
109072  return y < x;
109073}
109074
109075inline bool
109076operator>=(const Time& x, const Time& y) {
109077  return y <= x;
109078}
109079
109080} // namespace Watchdog
109081
109082} // namespace Implementation
109083
109084} // namespace Parma_Polyhedra_Library
109085
109086/* Automatically generated from PPL source file ../src/Time_defs.hh line 125. */
109087
109088/* Automatically generated from PPL source file ../src/Handler_types.hh line 1. */
109089
109090
109091namespace Parma_Polyhedra_Library {
109092
109093namespace Implementation {
109094
109095namespace Watchdog {
109096
109097class Handler;
109098
109099template <typename Flag_Base, typename Flag>
109100class Handler_Flag;
109101
109102class Handler_Function;
109103
109104} // namespace Watchdog
109105
109106} // namespace Implementation
109107
109108} // namespace Parma_Polyhedra_Library
109109
109110/* Automatically generated from PPL source file ../src/Pending_List_defs.hh line 1. */
109111/* Pending_List class declaration.
109112*/
109113
109114
109115/* Automatically generated from PPL source file ../src/Pending_List_types.hh line 1. */
109116
109117
109118namespace Parma_Polyhedra_Library {
109119
109120namespace Implementation {
109121
109122namespace Watchdog {
109123
109124template <typename Traits>
109125class Pending_List;
109126
109127} // namespace Watchdog
109128
109129} // namespace Implementation
109130
109131} // namespace Parma_Polyhedra_Library
109132
109133/* Automatically generated from PPL source file ../src/Pending_Element_defs.hh line 1. */
109134/* Pending_Element class declaration.
109135*/
109136
109137
109138/* Automatically generated from PPL source file ../src/Pending_Element_types.hh line 1. */
109139
109140
109141namespace Parma_Polyhedra_Library {
109142
109143namespace Implementation {
109144
109145namespace Watchdog {
109146
109147template <class Threshold>
109148class Pending_Element;
109149
109150} // namespace Watchdog
109151
109152} // namespace Implementation
109153
109154} // namespace Parma_Polyhedra_Library
109155
109156/* Automatically generated from PPL source file ../src/Doubly_Linked_Object_defs.hh line 1. */
109157/* Doubly_Linked_Object class declaration.
109158*/
109159
109160
109161/* Automatically generated from PPL source file ../src/Doubly_Linked_Object_types.hh line 1. */
109162
109163
109164namespace Parma_Polyhedra_Library {
109165
109166namespace Implementation {
109167
109168class Doubly_Linked_Object;
109169
109170} // namespace Implementation
109171
109172} // namespace Parma_Polyhedra_Library
109173
109174/* Automatically generated from PPL source file ../src/EList_types.hh line 1. */
109175
109176
109177namespace Parma_Polyhedra_Library {
109178
109179namespace Implementation {
109180
109181template <typename T>
109182class EList;
109183
109184} // namespace Implementation
109185
109186} // namespace Parma_Polyhedra_Library
109187
109188/* Automatically generated from PPL source file ../src/EList_Iterator_types.hh line 1. */
109189
109190
109191namespace Parma_Polyhedra_Library {
109192
109193namespace Implementation {
109194
109195template <typename T>
109196class EList_Iterator;
109197
109198} // namespace Implementation
109199
109200} // namespace Parma_Polyhedra_Library
109201
109202/* Automatically generated from PPL source file ../src/Doubly_Linked_Object_defs.hh line 30. */
109203
109204//! A (base) class for doubly linked objects.
109205class Parma_Polyhedra_Library::Implementation::Doubly_Linked_Object {
109206public:
109207  //! Default constructor.
109208  Doubly_Linked_Object();
109209
109210  //! Creates a chain element with forward link \p f and backward link \p b.
109211  Doubly_Linked_Object(Doubly_Linked_Object* f, Doubly_Linked_Object* b);
109212
109213  //! Inserts \p y before \p *this.
109214  void insert_before(Doubly_Linked_Object& y);
109215
109216  //! Inserts \p y after \p *this.
109217  void insert_after(Doubly_Linked_Object& y);
109218
109219  //! Erases \p *this from the chain and returns a pointer to the next element.
109220  Doubly_Linked_Object* erase();
109221
109222  //! Erases \p *this from the chain.
109223  ~Doubly_Linked_Object();
109224
109225private:
109226  //! Forward link.
109227  Doubly_Linked_Object* next;
109228
109229  //! Backward link.
109230  Doubly_Linked_Object* prev;
109231
109232  template <typename T> friend class EList;
109233  template <typename T> friend class EList_Iterator;
109234};
109235
109236/* Automatically generated from PPL source file ../src/Doubly_Linked_Object_inlines.hh line 1. */
109237/* Doubly_Linked_Object class implementation: inline functions.
109238*/
109239
109240
109241namespace Parma_Polyhedra_Library {
109242
109243namespace Implementation {
109244
109245inline
109246Doubly_Linked_Object::Doubly_Linked_Object() {
109247}
109248
109249inline
109250Doubly_Linked_Object::Doubly_Linked_Object(Doubly_Linked_Object* f,
109251                                           Doubly_Linked_Object* b)
109252  : next(f),
109253    prev(b) {
109254}
109255
109256inline void
109257Doubly_Linked_Object::insert_before(Doubly_Linked_Object& y) {
109258  y.next = this;
109259  y.prev = prev;
109260  prev->next = &y;
109261  prev = &y;
109262}
109263
109264inline void
109265Doubly_Linked_Object::insert_after(Doubly_Linked_Object& y) {
109266  y.next = next;
109267  y.prev = this;
109268  next->prev = &y;
109269  next = &y;
109270}
109271
109272inline Doubly_Linked_Object*
109273Doubly_Linked_Object::erase() {
109274  next->prev = prev;
109275  prev->next = next;
109276  return next;
109277}
109278
109279inline
109280Doubly_Linked_Object::~Doubly_Linked_Object() {
109281  erase();
109282}
109283
109284} // namespace Implementation
109285
109286} // namespace Parma_Polyhedra_Library
109287
109288/* Automatically generated from PPL source file ../src/Doubly_Linked_Object_defs.hh line 64. */
109289
109290/* Automatically generated from PPL source file ../src/Pending_Element_defs.hh line 30. */
109291
109292//! A class for pending watchdog events with embedded links.
109293/*!
109294  Each pending watchdog event is characterized by a deadline (a positive
109295  time interval), an associated handler that will be invoked upon event
109296  expiration, and a Boolean flag that indicates whether the event has already
109297  expired or not.
109298*/
109299template <typename Threshold>
109300class Parma_Polyhedra_Library::Implementation::Watchdog::Pending_Element
109301  : public Doubly_Linked_Object {
109302public:
109303  //! Constructs an element with the given attributes.
109304  Pending_Element(const Threshold& deadline,
109305                  const Handler& handler,
109306                  bool& expired_flag);
109307
109308  //! Modifies \p *this so that it has the given attributes.
109309  void assign(const Threshold& deadline,
109310              const Handler& handler,
109311              bool& expired_flag);
109312
109313  //! Returns the deadline of the event.
109314  const Threshold& deadline() const;
109315
109316  //! Returns the handler associated to the event.
109317  const Handler& handler() const;
109318
109319  //! Returns a reference to the "event-expired" flag.
109320  bool& expired_flag() const;
109321
109322  //! Checks if all the invariants are satisfied.
109323  bool OK() const;
109324
109325private:
109326  //! The deadline of the event.
109327  Threshold d;
109328
109329  //! A pointer to the handler associated to the event.
109330  const Handler* p_h;
109331
109332  //! A pointer to a flag saying whether the event has already expired or not.
109333  bool* p_f;
109334};
109335
109336/* Automatically generated from PPL source file ../src/Pending_Element_inlines.hh line 1. */
109337/* Pending_Element class implementation: inline functions.
109338*/
109339
109340
109341#include <cassert>
109342
109343namespace Parma_Polyhedra_Library {
109344
109345namespace Implementation {
109346
109347namespace Watchdog {
109348
109349template <typename Threshold>
109350inline bool
109351Pending_Element<Threshold>::OK() const {
109352  return true;
109353}
109354
109355template <typename Threshold>
109356inline
109357Pending_Element<Threshold>::Pending_Element(const Threshold& deadline,
109358                                            const Handler& handler,
109359                                            bool& expired_flag)
109360  : d(deadline), p_h(&handler), p_f(&expired_flag) {
109361  assert(OK());
109362}
109363
109364template <typename Threshold>
109365inline void
109366Pending_Element<Threshold>::assign(const Threshold& deadline,
109367                                   const Handler& handler,
109368                                   bool& expired_flag) {
109369  d = deadline;
109370  p_h = &handler;
109371  p_f = &expired_flag;
109372  assert(OK());
109373}
109374
109375template <typename Threshold>
109376inline const Threshold&
109377Pending_Element<Threshold>::deadline() const {
109378  return d;
109379}
109380
109381template <typename Threshold>
109382inline const Handler&
109383Pending_Element<Threshold>::handler() const {
109384  return *p_h;
109385}
109386
109387template <typename Threshold>
109388inline bool&
109389Pending_Element<Threshold>::expired_flag() const {
109390  return *p_f;
109391}
109392
109393} // namespace Watchdog
109394
109395} // namespace Implementation
109396
109397} // namespace Parma_Polyhedra_Library
109398
109399/* Automatically generated from PPL source file ../src/Pending_Element_defs.hh line 76. */
109400
109401/* Automatically generated from PPL source file ../src/EList_defs.hh line 1. */
109402/* EList class declaration.
109403*/
109404
109405
109406/* Automatically generated from PPL source file ../src/EList_Iterator_defs.hh line 1. */
109407/* EList_Iterator class declaration.
109408*/
109409
109410
109411/* Automatically generated from PPL source file ../src/EList_Iterator_defs.hh line 29. */
109412
109413namespace Parma_Polyhedra_Library {
109414
109415namespace Implementation {
109416
109417//! Returns <CODE>true</CODE> if and only if \p x and \p y are equal.
109418template <typename T>
109419bool operator==(const EList_Iterator<T>& x, const EList_Iterator<T>& y);
109420
109421//! Returns <CODE>true</CODE> if and only if \p x and \p y are different.
109422template <typename T>
109423bool operator!=(const EList_Iterator<T>& x, const EList_Iterator<T>& y);
109424
109425} // namespace Implementation
109426
109427} // namespace Parma_Polyhedra_Library
109428
109429//! A class providing iterators for embedded lists.
109430template <typename T>
109431class Parma_Polyhedra_Library::Implementation::EList_Iterator {
109432public:
109433  //! Constructs an iterator pointing to nothing.
109434  EList_Iterator();
109435
109436  //! Constructs an iterator pointing to \p p.
109437  explicit EList_Iterator(Doubly_Linked_Object* p);
109438
109439  //! Changes \p *this so that it points to \p p.
109440  EList_Iterator& operator=(Doubly_Linked_Object* p);
109441
109442  //! Indirect member selector.
109443  T* operator->();
109444
109445  //! Dereference operator.
109446  T& operator*();
109447
109448  //! Preincrement operator.
109449  EList_Iterator& operator++();
109450
109451  //! Postincrement operator.
109452  EList_Iterator operator++(int);
109453
109454  //! Predecrement operator.
109455  EList_Iterator& operator--();
109456
109457  //! Postdecrement operator.
109458  EList_Iterator operator--(int);
109459
109460private:
109461  //! Embedded pointer.
109462  Doubly_Linked_Object* ptr;
109463
109464  friend bool operator==<T>(const EList_Iterator& x, const EList_Iterator& y);
109465
109466  friend bool operator!=<T>(const EList_Iterator& x, const EList_Iterator& y);
109467};
109468
109469/* Automatically generated from PPL source file ../src/EList_Iterator_inlines.hh line 1. */
109470/* EList_Iterator class implementation: inline functions.
109471*/
109472
109473
109474/* Automatically generated from PPL source file ../src/EList_Iterator_inlines.hh line 28. */
109475
109476namespace Parma_Polyhedra_Library {
109477
109478namespace Implementation {
109479
109480template <typename T>
109481inline
109482EList_Iterator<T>::EList_Iterator() {
109483}
109484
109485template <typename T>
109486inline
109487EList_Iterator<T>::EList_Iterator(Doubly_Linked_Object* p)
109488  : ptr(p) {
109489}
109490
109491template <typename T>
109492inline EList_Iterator<T>&
109493EList_Iterator<T>::operator=(Doubly_Linked_Object* p) {
109494  ptr = p;
109495  return *this;
109496}
109497
109498template <typename T>
109499inline T*
109500EList_Iterator<T>::operator->() {
109501  return static_cast<T*>(ptr);
109502}
109503
109504template <typename T>
109505inline T&
109506EList_Iterator<T>::operator*() {
109507  return *operator->();
109508}
109509
109510template <typename T>
109511inline EList_Iterator<T>&
109512EList_Iterator<T>::operator++() {
109513  ptr = ptr->next;
109514  return *this;
109515}
109516
109517template <typename T>
109518inline EList_Iterator<T>
109519EList_Iterator<T>::operator++(int) {
109520  EList_Iterator tmp = *this;
109521  ++*this;
109522  return tmp;
109523}
109524
109525template <typename T>
109526inline EList_Iterator<T>&
109527EList_Iterator<T>::operator--() {
109528  ptr = ptr->prev;
109529  return *this;
109530}
109531
109532template <typename T>
109533inline EList_Iterator<T>
109534EList_Iterator<T>::operator--(int) {
109535  EList_Iterator tmp = *this;
109536  --*this;
109537  return tmp;
109538}
109539
109540template <typename T>
109541inline bool
109542operator==(const EList_Iterator<T>& x, const EList_Iterator<T>& y) {
109543  return x.ptr == y.ptr;
109544}
109545
109546template <typename T>
109547inline bool
109548operator!=(const EList_Iterator<T>& x, const EList_Iterator<T>& y) {
109549  return x.ptr != y.ptr;
109550}
109551
109552} // namespace Implementation
109553
109554} // namespace Parma_Polyhedra_Library
109555
109556/* Automatically generated from PPL source file ../src/EList_Iterator_defs.hh line 87. */
109557
109558/* Automatically generated from PPL source file ../src/EList_defs.hh line 30. */
109559
109560/*! \brief
109561  A simple kind of embedded list (i.e., a doubly linked objects
109562  where the links are embedded in the objects themselves).
109563*/
109564template <typename T>
109565class Parma_Polyhedra_Library::Implementation::EList
109566  : private Doubly_Linked_Object {
109567public:
109568  //! A const iterator to traverse the list.
109569  typedef EList_Iterator<const T> const_iterator;
109570
109571  //! A non-const iterator to traverse the list.
109572  typedef EList_Iterator<T> iterator;
109573
109574  //! Constructs an empty list.
109575  EList();
109576
109577  //! Destructs the list and all the elements in it.
109578  ~EList();
109579
109580  //! Pushes \p obj to the front of the list.
109581  void push_front(T& obj);
109582
109583  //! Pushes \p obj to the back of the list.
109584  void push_back(T& obj);
109585
109586  /*! \brief
109587    Inserts \p obj just before \p position and returns an iterator
109588    that points to the inserted object.
109589  */
109590  iterator insert(iterator position, T& obj);
109591
109592  /*! \brief
109593    Removes the element pointed to by \p position, returning
109594    an iterator pointing to the next element, if any, or end(), otherwise.
109595  */
109596  iterator erase(iterator position);
109597
109598  //! Returns <CODE>true</CODE> if and only if the list is empty.
109599  bool empty() const;
109600
109601  //! Returns an iterator pointing to the beginning of the list.
109602  iterator begin();
109603
109604  //! Returns an iterator pointing one past the last element in the list.
109605  iterator end();
109606
109607  //! Returns a const iterator pointing to the beginning of the list.
109608  const_iterator begin() const;
109609
109610  //! Returns a const iterator pointing one past the last element in the list.
109611  const_iterator end() const;
109612
109613  //! Checks if all the invariants are satisfied.
109614  bool OK() const;
109615};
109616
109617/* Automatically generated from PPL source file ../src/EList_inlines.hh line 1. */
109618/* EList class implementation: inline functions.
109619*/
109620
109621
109622#include <cassert>
109623
109624namespace Parma_Polyhedra_Library {
109625
109626namespace Implementation {
109627
109628template <typename T>
109629inline
109630EList<T>::EList()
109631  : Doubly_Linked_Object(this, this) {
109632}
109633
109634template <typename T>
109635inline void
109636EList<T>::push_front(T& obj) {
109637  next->insert_before(obj);
109638}
109639
109640template <typename T>
109641inline void
109642EList<T>::push_back(T& obj) {
109643  prev->insert_after(obj);
109644}
109645
109646template <typename T>
109647inline typename EList<T>::iterator
109648EList<T>::insert(iterator position, T& obj) {
109649  position->insert_before(obj);
109650  return iterator(&obj);
109651}
109652
109653template <typename T>
109654inline typename EList<T>::iterator
109655EList<T>::begin() {
109656  return iterator(next);
109657}
109658
109659template <typename T>
109660inline typename EList<T>::iterator
109661EList<T>::end() {
109662  return iterator(this);
109663}
109664
109665template <typename T>
109666inline typename EList<T>::const_iterator
109667EList<T>::begin() const {
109668  return const_iterator(next);
109669}
109670
109671template <typename T>
109672inline typename EList<T>::const_iterator
109673EList<T>::end() const {
109674  return const_iterator(const_cast<EList<T>*>(this));
109675}
109676
109677template <typename T>
109678inline bool
109679EList<T>::empty() const {
109680  return begin() == end();
109681}
109682
109683template <typename T>
109684inline typename EList<T>::iterator
109685EList<T>::erase(iterator position) {
109686  assert(!empty());
109687  return iterator(position->erase());
109688}
109689
109690template <typename T>
109691inline
109692EList<T>::~EList() {
109693  // Erase and deallocate all the elements.
109694  for (iterator i = begin(), lend = end(), next; i != lend; i = next) {
109695    next = erase(i);
109696    delete &*i;
109697  }
109698}
109699
109700template <typename T>
109701inline bool
109702EList<T>::OK() const {
109703  for (const_iterator i = begin(), lend = end(); i != lend; ++i) {
109704    if (!i->OK()) {
109705      return false;
109706    }
109707  }
109708
109709  return true;
109710}
109711
109712} // namespace Implementation
109713
109714} // namespace Parma_Polyhedra_Library
109715
109716/* Automatically generated from PPL source file ../src/EList_defs.hh line 89. */
109717
109718/* Automatically generated from PPL source file ../src/Pending_List_defs.hh line 31. */
109719
109720//! An ordered list for recording pending watchdog events.
109721template <typename Traits>
109722class Parma_Polyhedra_Library::Implementation::Watchdog::Pending_List {
109723public:
109724  //! A non-const iterator to traverse the list.
109725  typedef typename EList<Pending_Element<typename Traits::Threshold> >::iterator iterator;
109726
109727  //! A const iterator to traverse the list.
109728  typedef typename EList<Pending_Element<typename Traits::Threshold> >::const_iterator const_iterator;
109729
109730  //! Constructs an empty list.
109731  Pending_List();
109732
109733  //! Destructor.
109734  ~Pending_List();
109735
109736  //! Inserts a new Pending_Element object with the given attributes.
109737  iterator insert(const typename Traits::Threshold& deadline,
109738                  const Handler& handler,
109739                  bool& expired_flag);
109740
109741  /*! \brief
109742    Removes the element pointed to by \p position, returning
109743    an iterator pointing to the next element, if any, or end(), otherwise.
109744  */
109745  iterator erase(iterator position);
109746
109747  //! Returns <CODE>true</CODE> if and only if the list is empty.
109748  bool empty() const;
109749
109750  //! Returns an iterator pointing to the beginning of the list.
109751  iterator begin();
109752
109753  //! Returns an iterator pointing one past the last element in the list.
109754  iterator end();
109755
109756  //! Checks if all the invariants are satisfied.
109757  bool OK() const;
109758
109759private:
109760  EList<Pending_Element<typename Traits::Threshold> > active_list;
109761  EList<Pending_Element<typename Traits::Threshold> > free_list;
109762};
109763
109764/* Automatically generated from PPL source file ../src/Pending_List_inlines.hh line 1. */
109765/* Pending_List class implementation: inline functions.
109766*/
109767
109768
109769#include <cassert>
109770
109771namespace Parma_Polyhedra_Library {
109772
109773namespace Implementation {
109774
109775namespace Watchdog {
109776
109777template <typename Traits>
109778inline
109779Pending_List<Traits>::Pending_List()
109780  : active_list(),
109781    free_list() {
109782  assert(OK());
109783}
109784
109785template <typename Traits>
109786inline
109787Pending_List<Traits>::~Pending_List() {
109788}
109789
109790template <typename Traits>
109791inline typename Pending_List<Traits>::iterator
109792Pending_List<Traits>::begin() {
109793  return active_list.begin();
109794}
109795
109796template <typename Traits>
109797inline typename Pending_List<Traits>::iterator
109798Pending_List<Traits>::end() {
109799  return active_list.end();
109800}
109801
109802template <typename Traits>
109803inline bool
109804Pending_List<Traits>::empty() const {
109805  return active_list.empty();
109806}
109807
109808template <typename Traits>
109809inline typename Pending_List<Traits>::iterator
109810Pending_List<Traits>::erase(iterator position) {
109811  assert(!empty());
109812  iterator next = active_list.erase(position);
109813  free_list.push_back(*position);
109814  assert(OK());
109815  return next;
109816}
109817
109818} // namespace Watchdog
109819
109820} // namespace Implementation
109821
109822} // namespace Parma_Polyhedra_Library
109823
109824/* Automatically generated from PPL source file ../src/Pending_List_templates.hh line 1. */
109825/* Pending_List class implementation.
109826*/
109827
109828
109829#include <iostream>
109830
109831namespace Parma_Polyhedra_Library {
109832
109833namespace Implementation {
109834
109835namespace Watchdog {
109836
109837template <typename Traits>
109838typename Pending_List<Traits>::iterator
109839Pending_List<Traits>::insert(const typename Traits::Threshold& deadline,
109840                             const Handler& handler,
109841                             bool& expired_flag) {
109842  iterator position = active_list.begin();
109843  for (iterator active_list_end = active_list.end();
109844       position != active_list_end
109845         && Traits::less_than(position->deadline(), deadline);
109846       ++position) {
109847  }
109848  iterator pending_element_p;
109849  // Only allocate a new element if the free list is empty.
109850  if (free_list.empty()) {
109851    pending_element_p
109852      = new Pending_Element<typename Traits::Threshold>(deadline,
109853                                                        handler,
109854                                                        expired_flag);
109855  }
109856  else {
109857    pending_element_p = free_list.begin();
109858    free_list.erase(pending_element_p);
109859    pending_element_p->assign(deadline, handler, expired_flag);
109860  }
109861  iterator r = active_list.insert(position, *pending_element_p);
109862  assert(OK());
109863  return r;
109864}
109865
109866template <typename Traits>
109867bool
109868Pending_List<Traits>::OK() const {
109869  if (!active_list.OK()) {
109870    return false;
109871  }
109872  if (!free_list.OK()) {
109873    return false;
109874  }
109875
109876  const typename Traits::Threshold* old;
109877  const_iterator i = active_list.begin();
109878  old = &i->deadline();
109879  ++i;
109880  for (const_iterator active_list_end = active_list.end(); i != active_list_end; ++i) {
109881    const typename Traits::Threshold& t = i->deadline();
109882    if (Traits::less_than(t, *old)) {
109883#ifndef NDEBUG
109884      std::cerr << "The active list is not sorted!"
109885                << std::endl;
109886#endif
109887      return false;
109888    }
109889    old = &t;
109890  }
109891  return true;
109892}
109893
109894} // namespace Watchdog
109895
109896} // namespace Implementation
109897
109898} // namespace Parma_Polyhedra_Library
109899
109900/* Automatically generated from PPL source file ../src/Pending_List_defs.hh line 78. */
109901
109902/* Automatically generated from PPL source file ../src/Watchdog_defs.hh line 31. */
109903#include <cassert>
109904#include <functional>
109905
109906#ifdef PPL_HAVE_SYS_TIME_H
109907# include <sys/time.h>
109908#endif
109909
109910namespace Parma_Polyhedra_Library {
109911
109912// Set linkage now to declare it friend later.
109913extern "C" void PPL_handle_timeout(int signum);
109914
109915struct Watchdog_Traits {
109916  typedef Implementation::Watchdog::Time Threshold;
109917  static bool less_than(const Threshold& a, const Threshold& b) {
109918    return a < b;
109919  }
109920};
109921
109922//! A watchdog timer.
109923class Watchdog {
109924public:
109925  template <typename Flag_Base, typename Flag>
109926  Watchdog(long csecs, const Flag_Base* volatile& holder, Flag& flag);
109927
109928  /*! \brief
109929    Constructor: if not reset, the watchdog will trigger after \p csecs
109930    centiseconds, invoking handler \p function.
109931  */
109932  Watchdog(long csecs, void (* const function)());
109933
109934  //! Destructor.
109935  ~Watchdog();
109936
109937#if PPL_HAVE_DECL_SETITIMER && PPL_HAVE_DECL_SIGACTION
109938
109939  //! Static class initialization.
109940  static void initialize();
109941  //! Static class finalization.
109942  static void finalize();
109943
109944private:
109945  //! Whether or not this watchdog has expired.
109946  bool expired;
109947
109948  typedef Implementation::Watchdog::Pending_List<Watchdog_Traits>
109949  WD_Pending_List;
109950
109951  typedef Implementation::Watchdog::Handler
109952  WD_Handler;
109953
109954  const WD_Handler& handler;
109955  WD_Pending_List::iterator pending_position;
109956
109957  // Private and not implemented: copy construction is not allowed.
109958  Watchdog(const Watchdog&);
109959  // Private and not implemented: copy assignment is not allowed.
109960  Watchdog& operator=(const Watchdog&);
109961
109962  // Pass this to getitimer().
109963  static itimerval current_timer_status;
109964
109965  //! Reads the timer value into \p time.
109966  static void get_timer(Implementation::Watchdog::Time& time);
109967
109968  // Pass this to setitimer().
109969  static itimerval signal_once;
109970
109971  // Last time value we set the timer to.
109972  static Implementation::Watchdog::Time last_time_requested;
109973
109974  //! Sets the timer value to \p time.
109975  static void set_timer(const Implementation::Watchdog::Time& time);
109976
109977  //! Stops the timer.
109978  static void stop_timer();
109979
109980  //! Quick reschedule to avoid race conditions.
109981  static void reschedule();
109982
109983  // Used by the above.
109984  static Implementation::Watchdog::Time reschedule_time;
109985
109986  // Records the time elapsed since last fresh start.
109987  static Implementation::Watchdog::Time time_so_far;
109988
109989  //! The ordered queue of pending watchdog events.
109990  static WD_Pending_List pending;
109991
109992  //! The actual signal handler.
109993  static void handle_timeout(int);
109994
109995  //! Handles the addition of a new watchdog event.
109996  static WD_Pending_List::iterator
109997  new_watchdog_event(long csecs,
109998                     const WD_Handler& handler,
109999                     bool& expired_flag);
110000
110001  //! Handles the removal of the watchdog event referred by \p position.
110002  void remove_watchdog_event(WD_Pending_List::iterator position);
110003
110004  //! Whether the alarm clock is running.
110005  static volatile bool alarm_clock_running;
110006
110007  //! Whether we are changing data that is also changed by the signal handler.
110008  static volatile bool in_critical_section;
110009
110010  friend void PPL_handle_timeout(int signum);
110011
110012#endif // PPL_HAVE_DECL_SETITIMER && PPL_HAVE_DECL_SIGACTION
110013};
110014
110015} // namespace Parma_Polyhedra_Library
110016
110017/* Automatically generated from PPL source file ../src/Watchdog_inlines.hh line 1. */
110018/* Watchdog and associated classes' implementation: inline functions.
110019*/
110020
110021
110022/* Automatically generated from PPL source file ../src/Handler_defs.hh line 1. */
110023/* Handler and derived classes' declaration.
110024*/
110025
110026
110027/* Automatically generated from PPL source file ../src/Handler_defs.hh line 28. */
110028
110029//! Abstract base class for handlers of the watchdog events.
110030class Parma_Polyhedra_Library::Implementation::Watchdog::Handler {
110031public:
110032  //! Does the job.
110033  virtual void act() const = 0;
110034
110035  //! Virtual destructor.
110036  virtual ~Handler();
110037};
110038
110039//! A kind of Handler that installs a flag onto a flag-holder.
110040/*!
110041  The template class <CODE>Handler_Flag\<Flag_Base, Flag\></CODE>
110042  is an handler whose job is to install a flag onto an <EM>holder</EM>
110043  for the flag.
110044  The flag is of type \p Flag and the holder is a (volatile) pointer
110045  to \p Flag_Base.  Installing the flag onto the holder means making
110046  the holder point to the flag, so that it must be possible to assign
110047  a value of type <CODE>Flag*</CODE> to an entity of type
110048  <CODE>Flag_Base*</CODE>.
110049  The class \p Flag must provide the method
110050
110051  \code
110052    int priority() const
110053  \endcode
110054  returning an integer priority associated to the flag.
110055
110056  The handler will install its flag onto the holder only if the holder
110057  is empty, namely, it is the null pointer, or if the holder holds a
110058  flag of strictly lower priority.
110059 */
110060template <typename Flag_Base, typename Flag>
110061class Parma_Polyhedra_Library::Implementation::Watchdog::Handler_Flag
110062  : public Handler {
110063public:
110064  //! Constructor with a given function.
110065  Handler_Flag(const Flag_Base* volatile& holder, Flag& flag);
110066
110067  /*! \brief
110068    Does its job: installs the flag onto the holder, if a flag with
110069    an higher priority has not already been installed.
110070  */
110071  virtual void act() const;
110072
110073private:
110074  // Declare holder as reference to volatile pointer to const Flag_Base.
110075  const Flag_Base* volatile& h;
110076  Flag& f;
110077};
110078
110079//! A kind of Handler calling a given function.
110080class Parma_Polyhedra_Library::Implementation::Watchdog::Handler_Function
110081  : public Handler {
110082public:
110083  //! Constructor with a given function.
110084  Handler_Function(void (* const function)());
110085
110086  //! Does its job: calls the embedded function.
110087  virtual void act() const;
110088
110089private:
110090  //! Pointer to the embedded function.
110091  void (* const f)();
110092};
110093
110094/* Automatically generated from PPL source file ../src/Handler_inlines.hh line 1. */
110095/* Handler and derived classes' implementation: inline functions.
110096*/
110097
110098
110099namespace Parma_Polyhedra_Library {
110100
110101namespace Implementation {
110102
110103namespace Watchdog {
110104
110105template <typename Flag_Base, typename Flag>
110106Handler_Flag<Flag_Base, Flag>::Handler_Flag(const Flag_Base* volatile& holder,
110107                                            Flag& flag)
110108  : h(holder), f(flag) {
110109}
110110
110111template <typename Flag_Base, typename Flag>
110112void
110113Handler_Flag<Flag_Base, Flag>::act() const {
110114  if (h == 0 || static_cast<const Flag&>(*h).priority() < f.priority()) {
110115    h = &f;
110116  }
110117}
110118
110119inline
110120Handler_Function::Handler_Function(void (* const function)())
110121  : f(function) {
110122}
110123
110124} // namespace Watchdog
110125
110126} // namespace Implementation
110127
110128} // namespace Parma_Polyhedra_Library
110129
110130/* Automatically generated from PPL source file ../src/Handler_defs.hh line 95. */
110131
110132/* Automatically generated from PPL source file ../src/Watchdog_inlines.hh line 28. */
110133#include <stdexcept>
110134
110135namespace Parma_Polyhedra_Library {
110136
110137#if PPL_HAVE_DECL_SETITIMER && PPL_HAVE_DECL_SIGACTION
110138
110139template <typename Flag_Base, typename Flag>
110140Watchdog::Watchdog(long csecs,
110141                   const Flag_Base* volatile& holder,
110142                   Flag& flag)
110143  : expired(false),
110144    handler(*new
110145            Implementation::Watchdog::Handler_Flag<Flag_Base, Flag>(holder,
110146                                                                    flag)) {
110147  if (csecs == 0) {
110148    throw std::invalid_argument("Watchdog constructor called with a"
110149                                " non-positive number of centiseconds");
110150  }
110151  in_critical_section = true;
110152  pending_position = new_watchdog_event(csecs, handler, expired);
110153  in_critical_section = false;
110154}
110155
110156inline
110157Watchdog::Watchdog(long csecs, void (* const function)())
110158  : expired(false),
110159    handler(*new Implementation::Watchdog::Handler_Function(function)) {
110160  if (csecs == 0) {
110161    throw std::invalid_argument("Watchdog constructor called with a"
110162                                " non-positive number of centiseconds");
110163  }
110164  in_critical_section = true;
110165  pending_position = new_watchdog_event(csecs, handler, expired);
110166  in_critical_section = false;
110167}
110168
110169inline
110170Watchdog::~Watchdog() {
110171  if (!expired) {
110172    in_critical_section = true;
110173    remove_watchdog_event(pending_position);
110174    in_critical_section = false;
110175  }
110176  delete &handler;
110177}
110178
110179inline void
110180Watchdog::reschedule() {
110181  set_timer(reschedule_time);
110182}
110183
110184#else // !PPL_HAVE_DECL_SETITIMER !! !PPL_HAVE_DECL_SIGACTION
110185
110186template <typename Flag_Base, typename Flag>
110187Watchdog::Watchdog(long /* csecs */,
110188                   const Flag_Base* volatile& /* holder */,
110189                   Flag& /* flag */) {
110190  throw std::logic_error("PPL::Watchdog::Watchdog objects not supported:"
110191                         " system does not provide setitimer()");
110192}
110193
110194inline
110195Watchdog::Watchdog(long /* csecs */, void (* /* function */)()) {
110196  throw std::logic_error("PPL::Watchdog::Watchdog objects not supported:"
110197                         " system does not provide setitimer()");
110198}
110199
110200inline
110201Watchdog::~Watchdog() {
110202}
110203
110204#endif // !PPL_HAVE_DECL_SETITIMER !! !PPL_HAVE_DECL_SIGACTION
110205
110206} // namespace Parma_Polyhedra_Library
110207
110208/* Automatically generated from PPL source file ../src/Watchdog_defs.hh line 146. */
110209
110210
110211/* Automatically generated from PPL source file ../src/Threshold_Watcher_defs.hh line 1. */
110212/* Threshold_Watcher and associated classes' declaration and inline functions.
110213*/
110214
110215
110216/* Automatically generated from PPL source file ../src/Threshold_Watcher_types.hh line 1. */
110217
110218
110219namespace Parma_Polyhedra_Library {
110220
110221template <typename Traits>
110222class Threshold_Watcher;
110223
110224} // namespace Parma_Polyhedra_Library
110225
110226/* Automatically generated from PPL source file ../src/Threshold_Watcher_defs.hh line 30. */
110227#include <cassert>
110228
110229/*! \brief
110230  A class of watchdogs controlling the exceeding of a threshold.
110231
110232  \tparam Traits
110233  A class to set data types and functions for the threshold handling.
110234  See \c Parma_Polyhedra_Library::Weightwatch_Traits for an example.
110235*/
110236template <typename Traits>
110237class Parma_Polyhedra_Library::Threshold_Watcher {
110238public:
110239  template <typename Flag_Base, typename Flag>
110240  Threshold_Watcher(const typename Traits::Delta& delta,
110241                    const Flag_Base* volatile& holder,
110242                    Flag& flag);
110243
110244  Threshold_Watcher(const typename Traits::Delta& delta,
110245                    void (*function)());
110246
110247  ~Threshold_Watcher();
110248
110249private:
110250  typedef Implementation::Watchdog::Pending_List<Traits> TW_Pending_List;
110251  typedef Implementation::Watchdog::Handler TW_Handler;
110252
110253  bool expired;
110254  const TW_Handler& handler;
110255  typename TW_Pending_List::iterator pending_position;
110256
110257  // Just to prevent their use.
110258  Threshold_Watcher(const Threshold_Watcher&);
110259  Threshold_Watcher& operator=(const Threshold_Watcher&);
110260
110261  struct Initialize {
110262    //! The ordered queue of pending thresholds.
110263    TW_Pending_List pending;
110264  };
110265  static Initialize init;
110266
110267  // Handle the addition of a new threshold.
110268  static typename TW_Pending_List::iterator
110269  add_threshold(typename Traits::Threshold threshold,
110270                const TW_Handler& handler,
110271                bool& expired_flag);
110272
110273  // Handle the removal of a threshold.
110274  static typename TW_Pending_List::iterator
110275  remove_threshold(typename TW_Pending_List::iterator position);
110276
110277  //! Check threshold reaching.
110278  static void check();
110279
110280}; // class Parma_Polyhedra_Library::Threshold_Watcher
110281
110282
110283// Templatic initialization of static data member.
110284template <typename Traits>
110285typename
110286Parma_Polyhedra_Library::Threshold_Watcher<Traits>::Initialize
110287Parma_Polyhedra_Library::Threshold_Watcher<Traits>::init;
110288
110289/* Automatically generated from PPL source file ../src/Threshold_Watcher_inlines.hh line 1. */
110290/* Threshold_Watcher and associated classes' implementation: inline functions.
110291*/
110292
110293
110294/* Automatically generated from PPL source file ../src/Threshold_Watcher_inlines.hh line 28. */
110295#include <stdexcept>
110296
110297namespace Parma_Polyhedra_Library {
110298
110299template <typename Traits>
110300template <typename Flag_Base, typename Flag>
110301Threshold_Watcher<Traits>
110302::Threshold_Watcher(const typename Traits::Delta& delta,
110303                    const Flag_Base* volatile& holder,
110304                    Flag& flag)
110305  : expired(false),
110306    handler(*new
110307            Implementation::Watchdog::Handler_Flag<Flag_Base, Flag>(holder,
110308                                                                    flag)) {
110309  typename Traits::Threshold threshold;
110310  Traits::from_delta(threshold, delta);
110311  if (!Traits::less_than(Traits::get(), threshold)) {
110312    throw std::invalid_argument("Threshold_Watcher constructor called with a"
110313                                " threshold already reached");
110314  }
110315  pending_position = add_threshold(threshold, handler, expired);
110316}
110317
110318template <typename Traits>
110319inline
110320Threshold_Watcher<Traits>
110321::Threshold_Watcher(const typename Traits::Delta& delta, void (*function)())
110322  : expired(false),
110323    handler(*new Implementation::Watchdog::Handler_Function(function)) {
110324  typename Traits::Threshold threshold;
110325  Traits::from_delta(threshold, delta);
110326  if (!Traits::less_than(Traits::get(), threshold)) {
110327    throw std::invalid_argument("Threshold_Watcher constructor called with a"
110328                                " threshold already reached");
110329  }
110330  pending_position = add_threshold(threshold, handler, expired);
110331}
110332
110333} // namespace Parma_Polyhedra_Library
110334
110335/* Automatically generated from PPL source file ../src/Threshold_Watcher_templates.hh line 1. */
110336/* Threshold_Watcher and associated classes'.
110337*/
110338
110339
110340namespace Parma_Polyhedra_Library {
110341
110342template <typename Traits>
110343typename Threshold_Watcher<Traits>::TW_Pending_List::iterator
110344Threshold_Watcher<Traits>::add_threshold(typename Traits::Threshold threshold,
110345                                         const TW_Handler& handler,
110346                                         bool& expired_flag) {
110347  Traits::check_function = Threshold_Watcher::check;
110348  return init.pending.insert(threshold, handler, expired_flag);
110349}
110350
110351template <typename Traits>
110352typename Threshold_Watcher<Traits>::TW_Pending_List::iterator
110353Threshold_Watcher<Traits>
110354::remove_threshold(typename TW_Pending_List::iterator position) {
110355  typename TW_Pending_List::iterator i = init.pending.erase(position);
110356  if (init.pending.empty()) {
110357    Traits::check_function = 0;
110358  }
110359  return i;
110360}
110361
110362template <typename Traits>
110363Threshold_Watcher<Traits>::~Threshold_Watcher() {
110364  if (!expired) {
110365    remove_threshold(pending_position);
110366  }
110367  delete &handler;
110368}
110369
110370template <typename Traits>
110371void
110372Threshold_Watcher<Traits>::check() {
110373  typename TW_Pending_List::iterator i = init.pending.begin();
110374  assert(i != init.pending.end());
110375  const typename Traits::Threshold& current = Traits::get();
110376  while (!Traits::less_than(current, i->deadline())) {
110377    i->handler().act();
110378    i->expired_flag() = true;
110379    i = remove_threshold(i);
110380    if (i == init.pending.end()) {
110381      break;
110382    }
110383  }
110384}
110385
110386} // namespace Parma_Polyhedra_Library
110387
110388/* Automatically generated from PPL source file ../src/Threshold_Watcher_defs.hh line 94. */
110389
110390
110391
110392//! Defined to 1 if PPL::Watchdog objects are supported, to 0 otherwise.
110393#define PPL_WATCHDOG_OBJECTS_ARE_SUPPORTED \
110394  (PPL_HAVE_DECL_SETITIMER && PPL_HAVE_DECL_SIGACTION)
110395
110396#undef PPL_SPECIALIZE_ABS
110397#undef PPL_SPECIALIZE_ADD
110398#undef PPL_SPECIALIZE_ADD_MUL
110399#undef PPL_SPECIALIZE_ASSIGN
110400#undef PPL_SPECIALIZE_ASSIGN_SPECIAL
110401#undef PPL_SPECIALIZE_CEIL
110402#undef PPL_SPECIALIZE_CLASSIFY
110403#undef PPL_SPECIALIZE_CMP
110404#undef PPL_SPECIALIZE_CONSTRUCT
110405#undef PPL_SPECIALIZE_CONSTRUCT_SPECIAL
110406#undef PPL_SPECIALIZE_COPY
110407#undef PPL_SPECIALIZE_DIV
110408#undef PPL_SPECIALIZE_DIV2EXP
110409#undef PPL_SPECIALIZE_FLOOR
110410#undef PPL_SPECIALIZE_FUN1_0_0
110411#undef PPL_SPECIALIZE_FUN1_0_1
110412#undef PPL_SPECIALIZE_FUN1_0_2
110413#undef PPL_SPECIALIZE_FUN1_0_3
110414#undef PPL_SPECIALIZE_FUN1_1_1
110415#undef PPL_SPECIALIZE_FUN1_1_2
110416#undef PPL_SPECIALIZE_FUN1_2_2
110417#undef PPL_SPECIALIZE_FUN2_0_0
110418#undef PPL_SPECIALIZE_FUN2_0_1
110419#undef PPL_SPECIALIZE_FUN2_0_2
110420#undef PPL_SPECIALIZE_FUN3_0_1
110421#undef PPL_SPECIALIZE_FUN5_0_1
110422#undef PPL_SPECIALIZE_GCD
110423#undef PPL_SPECIALIZE_GCDEXT
110424#undef PPL_SPECIALIZE_IDIV
110425#undef PPL_SPECIALIZE_INPUT
110426#undef PPL_SPECIALIZE_IS_INT
110427#undef PPL_SPECIALIZE_IS_MINF
110428#undef PPL_SPECIALIZE_IS_NAN
110429#undef PPL_SPECIALIZE_IS_PINF
110430#undef PPL_SPECIALIZE_LCM
110431#undef PPL_SPECIALIZE_MUL
110432#undef PPL_SPECIALIZE_MUL2EXP
110433#undef PPL_SPECIALIZE_NEG
110434#undef PPL_SPECIALIZE_OUTPUT
110435#undef PPL_SPECIALIZE_REM
110436#undef PPL_SPECIALIZE_SGN
110437#undef PPL_SPECIALIZE_SQRT
110438#undef PPL_SPECIALIZE_SUB
110439#undef PPL_SPECIALIZE_SUB_MUL
110440#undef PPL_SPECIALIZE_TRUNC
110441
110442#undef PPL_COMPILE_TIME_CHECK
110443#undef PPL_COMPILE_TIME_CHECK_AUX
110444#undef PPL_COMPILE_TIME_CHECK_NAME
110445
110446#ifdef __STDC_LIMIT_MACROS
110447# undef __STDC_LIMIT_MACROS
110448#endif
110449#ifdef PPL_SAVE_STDC_LIMIT_MACROS
110450# define __STDC_LIMIT_MACROS PPL_SAVE_STDC_LIMIT_MACROS
110451# undef PPL_SAVE_STDC_LIMIT_MACROS
110452#endif
110453
110454#ifdef PPL_SAVE_NDEBUG
110455# ifndef NDEBUG
110456#  define NDEBUG PPL_SAVE_NDEBUG
110457# endif
110458# undef PPL_SAVE_NDEBUG
110459#else
110460# ifdef NDEBUG
110461#  undef NDEBUG
110462# endif
110463#endif
110464// Must include <cassert> again in order to make the latest changes to
110465// NDEBUG effective.
110466#include <cassert>
110467
110468#ifdef PPL_NO_AUTOMATIC_INITIALIZATION
110469 #undef PPL_NO_AUTOMATIC_INITIALIZATION
110470#endif
110471
110472#endif // !defined(PPL_ppl_hh)
110473