1 /* Init class implementation (non-inline functions and static variables).
2 Copyright (C) 2001-2010 Roberto Bagnara <bagnara@cs.unipr.it>
3 Copyright (C) 2010-2016 BUGSENG srl (http://bugseng.com)
4
5 This file is part of the Parma Polyhedra Library (PPL).
6
7 The PPL is free software; you can redistribute it and/or modify it
8 under the terms of the GNU General Public License as published by the
9 Free Software Foundation; either version 3 of the License, or (at your
10 option) any later version.
11
12 The PPL is distributed in the hope that it will be useful, but WITHOUT
13 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15 for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software Foundation,
19 Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1307, USA.
20
21 For the most up-to-date information see the Parma Polyhedra Library
22 site: http://bugseng.com/products/ppl/ . */
23
24 #include "ppl-config.h"
25 #include "Init_defs.hh"
26 #include "Variable_defs.hh"
27 #include "fpu_defs.hh"
28 #include "Rounding_Dir_defs.hh"
29 #include "checked_defs.hh"
30 #include "Coefficient_defs.hh"
31 #include "Linear_Expression_defs.hh"
32 #include "Constraint_defs.hh"
33 #include "Generator_defs.hh"
34 #include "Congruence_defs.hh"
35 #include "Grid_Generator_defs.hh"
36 #include "Constraint_System_defs.hh"
37 #include "Generator_System_defs.hh"
38 #include "Congruence_System_defs.hh"
39 #include "Grid_Generator_System_defs.hh"
40 #include "Polyhedron_defs.hh"
41 #include "Watchdog_defs.hh"
42 #include <stdexcept>
43
44 namespace PPL = Parma_Polyhedra_Library;
45
46 unsigned int PPL::Init::count = 0;
47
48 PPL::fpu_rounding_direction_type PPL::Init::old_rounding_direction;
49
50 extern "C" void
51 ppl_set_GMP_memory_allocation_functions(void);
52
53 #if PPL_CAN_CONTROL_FPU \
54 && defined(PPL_ARM_CAN_CONTROL_FPU) && PPL_ARM_CAN_CONTROL_FPU
55
56 namespace {
57
58 float nf1 = -3, pf1 = 3, f2 = 5;
59 double nd1 = -7, pd1 = 7, d2 = 11;
60 long double nl1 = -13, pl1 = 13, l2 = 17;
61
62 float nf[2], pf[2];
63 double nd[2], pd[2];
64 long double nl[2], pl[2];
65
66 int
ppl_check_function()67 ppl_check_function() {
68 int r = 0;
69 if (nf[0] == nf[1] || pf[0] == pf[1] || -nf[0] != pf[1] || -nf[1] != pf[0]) {
70 r |= 1;
71 }
72 if (nd[0] == nd[1] || pd[0] == pd[1] || -nd[0] != pd[1] || -nd[1] != pd[0]) {
73 r |= 2;
74 }
75 if (nl[0] == nl[1] || pl[0] == pl[1] || -nl[0] != pl[1] || -nl[1] != pl[0]) {
76 r |= 4;
77 }
78 return r;
79 }
80
81 int
ppl_setround_function(int rounding_mode)82 ppl_setround_function(int rounding_mode) {
83 return fesetround(rounding_mode);
84 }
85
86 } // namespace
87
88 namespace Parma_Polyhedra_Library {
89
90 namespace Implementation {
91
92 int (* volatile ppl_check_function_p)() = ppl_check_function;
93 int (* volatile ppl_setround_function_p)(int) = ppl_setround_function;
94
95 } // namespace Implementation
96
97 } // namespace Parma_Polyhedra_Library
98
99 namespace {
100
101 int
ppl_test_rounding()102 ppl_test_rounding() {
103 if ((*ppl_setround_function_p)(FE_DOWNWARD) != 0) {
104 return 255;
105 }
106
107 nf[0] = nf1 / f2;
108 nd[0] = nd1 / d2;
109 nl[0] = nl1 / l2;
110 pf[0] = pf1 / f2;
111 pd[0] = pd1 / d2;
112 pl[0] = pl1 / l2;
113
114 if ((*ppl_setround_function_p)(FE_UPWARD) != 0) {
115 return 255;
116 }
117
118 nf[1] = nf1 / f2;
119 nd[1] = nd1 / d2;
120 nl[1] = nl1 / l2;
121 pf[1] = pf1 / f2;
122 pd[1] = pd1 / d2;
123 pl[1] = pl1 / l2;
124
125 return (*ppl_check_function_p)();
126 }
127
128 } // namespace
129
130 #endif // PPL_CAN_CONTROL_FPU
131 // && defined(PPL_ARM_CAN_CONTROL_FPU) && PPL_ARM_CAN_CONTROL_FPU
132
Init()133 PPL::Init::Init() {
134 // Only when the first Init object is constructed...
135 if (count++ == 0) {
136 // ... the GMP memory allocation functions are set, ...
137 ppl_set_GMP_memory_allocation_functions();
138 // ... the default output function for Variable objects is set, ...
139 Variable::set_output_function(&Variable::default_output_function);
140 // ... the Coefficient constants are initialized, ...
141 Coefficient_constants_initialize();
142 // ... the Linear_Expression class is initialized, ...
143 Linear_Expression::initialize();
144 // ... the Constraint, Generator, Congruence, Grid_Generator,
145 // Constraint_System, Generator_System, Congruence_System,
146 // Grid_Generator_System and Polyhedron classes are initialized, ...
147 Constraint::initialize();
148 Generator::initialize();
149 Congruence::initialize();
150 Grid_Generator::initialize();
151 Constraint_System::initialize();
152 Generator_System::initialize();
153 Congruence_System::initialize();
154 Grid_Generator_System::initialize();
155 Polyhedron::initialize();
156
157 #if PPL_HAVE_DECL_SETITIMER && PPL_HAVE_DECL_SIGACTION
158 // ... the Watchdog subsystem is initialized, ...
159 Watchdog::Watchdog::initialize();
160 #endif // PPL_HAVE_DECL_SETITIMER && PPL_HAVE_DECL_SIGACTION
161
162 #if PPL_CAN_CONTROL_FPU
163
164 // ... and the FPU rounding direction is set.
165 fpu_initialize_control_functions();
166 old_rounding_direction = fpu_get_rounding_direction();
167 fpu_set_rounding_direction(round_fpu_dir(ROUND_DIRECT));
168
169 #if defined(PPL_ARM_CAN_CONTROL_FPU) && PPL_ARM_CAN_CONTROL_FPU
170 if (ppl_test_rounding() != 0) {
171 throw std::logic_error("PPL configuration error:"
172 " PPL_ARM_CAN_CONTROL_FPU evaluates to true,"
173 " but rounding does not work.");
174 }
175 #endif // defined(PPL_ARM_CAN_CONTROL_FPU) && PPL_ARM_CAN_CONTROL_FPU
176
177 #endif // PPL_CAN_CONTROL_FPU
178
179 // The default is chosen to have a precision greater than most
180 // precise IEC 559 floating point (112 bits of mantissa).
181 set_irrational_precision(DEFAULT_IRRATIONAL_PRECISION);
182 }
183 }
184
~Init()185 PPL::Init::~Init() {
186 // Only when the last Init object is destroyed...
187 if (--count == 0) {
188 #if PPL_CAN_CONTROL_FPU
189 // ... the FPU rounding direction is restored, ...
190 fpu_set_rounding_direction(old_rounding_direction);
191 #endif
192
193 #if PPL_HAVE_DECL_SETITIMER && PPL_HAVE_DECL_SIGACTION
194 // ... the Watchdog subsystem is finalized, ...
195 Watchdog::Watchdog::finalize();
196 #endif // PPL_HAVE_DECL_SETITIMER && PPL_HAVE_DECL_SIGACTION
197
198 // ... the Polyhedron, Grid_Generator_System, Congruence_System,
199 // Generator_System, Constraint_System, Grid_Generator,
200 // Congruence, Generator and Constraint classes are finalized
201 // IN THAT ORDER, ...
202 Polyhedron::finalize();
203 Grid_Generator_System::finalize();
204 Congruence_System::finalize();
205 Generator_System::finalize();
206 Constraint_System::finalize();
207 Grid_Generator::finalize();
208 Congruence::finalize();
209 Generator::finalize();
210 Constraint::finalize();
211 // ... the Linear_Expression class is finalized, ...
212 Linear_Expression::finalize();
213 // ... and the Coefficient constants are finalized.
214 Coefficient_constants_finalize();
215 }
216 }
217
218 namespace Parma_Polyhedra_Library {
219
220 namespace Implementation {
221
222 namespace {
223
224 static Parma_Polyhedra_Library::Init* Parma_Polyhedra_Library_initializer_p;
225
226 } // namespace
227
228 void
initialize_aux()229 initialize_aux() {
230 if (Parma_Polyhedra_Library_initializer_p == 0) {
231 Parma_Polyhedra_Library_initializer_p = new Init();
232 }
233 }
234
235 void
finalize_aux()236 finalize_aux() {
237 PPL_ASSERT(Parma_Polyhedra_Library_initializer_p != 0);
238 delete Parma_Polyhedra_Library_initializer_p;
239 Parma_Polyhedra_Library_initializer_p = 0;
240 }
241
242 } // namespace Implementation
243
244 } // namespace Parma_Polyhedra_Library
245