1 
2 
3 
4 
5 #ifndef NTL_tools__H
6 #define NTL_tools__H
7 
8 //#define NTL_TEST_EXCEPTIONS
9 
10 #include <NTL/ctools.h>
11 #include <NTL/new.h>
12 
13 #include <utility>
14 #include <iostream>
15 #include <new>
16 #include <stdexcept>
17 #include <streambuf>
18 
19 #include <cstdlib>
20 #include <cmath>
21 #include <cstring>
22 
23 #ifdef NTL_SAFE_VECTORS
24 
25 #include <type_traits>
26 
27 #endif
28 
29 
30 #if (defined(NTL_THREADS) && defined(NTL_TLS_HACK))
31 #include <pthread.h>
32 #endif
33 
34 
35 
36 
37 #define NTL_SNS std ::
38 #define NTL_USE_SNS using namespace std;
39 
40 #define NTL_IMPORT_FROM_STD \
41    using NTL_SNS abs; \
42    using NTL_SNS ceil; \
43    using NTL_SNS exp; \
44    using NTL_SNS fabs; \
45    using NTL_SNS floor; \
46    using NTL_SNS ldexp; \
47    using NTL_SNS log; \
48    using NTL_SNS sqrt; \
49    using NTL_SNS ostream;  \
50    using NTL_SNS istream;  \
51    using NTL_SNS cerr;  \
52    using NTL_SNS ifstream;  \
53    using NTL_SNS ofstream;
54 
55 
56 
57 #ifndef NTL_LEGACY_NO_NAMESPACE
58 
59 // This wraps NTL in the NTL namespace.
60 // This is the current default.
61 
62 #define NTL_NAMESPACE NTL
63 #define NTL_OPEN_NNS namespace NTL_NAMESPACE {
64 #define NTL_CLOSE_NNS  }
65 #define NTL_USE_NNS using namespace NTL_NAMESPACE;
66 #define NTL_NNS NTL_NAMESPACE ::
67 
68 // To make things work, we have to apply using declarations of all std
69 // functions that are both overloaded by NTL and are used in
70 // the implementation of NTL.
71 
72 #define NTL_START_IMPL NTL_OPEN_NNS NTL_IMPORT_FROM_STD
73 
74 
75 #define NTL_END_IMPL NTL_CLOSE_NNS
76 
77 #else
78 
79 // This puts NTL in the global namespace.
80 // Provided only for backward compatibility.
81 
82 #define NTL_NAMESPACE
83 #define NTL_OPEN_NNS
84 #define NTL_CLOSE_NNS
85 #define NTL_USE_NNS
86 #define NTL_NNS
87 
88 #define NTL_START_IMPL NTL_IMPORT_FROM_STD
89 #define NTL_END_IMPL
90 
91 #endif
92 
93 #define NTL_CLIENT NTL_USE_SNS NTL_USE_NNS
94 
95 
96 
97 double _ntl_GetTime();
98 unsigned long _ntl_GetPID();
99 
100 typedef unsigned long _ntl_ulong;
101 typedef _ntl_ulong *_ntl_ulong_ptr;
102 // I made these have "obscure" names to avoid conflict with
103 // (non-standard but common) definitions in standard headers.
104 // Putting u_long inside namespace NTL only tends to creates ambiguities,
105 // for no good reason.
106 
107 
108 
109 
110 NTL_OPEN_NNS
111 
112 #ifndef NTL_LEGACY_INPUT_ERROR
113 
114 // this newer version is more in line with wider C++
115 // practice, setting the "fail bit" of an input stream
116 // when an error is encounted.  This is now the default in NTL
117 
118 #define NTL_INPUT_ERROR(s, msg) \
119    do {\
120       s.setstate(NTL_SNS ios::failbit);\
121       return s;\
122    } while (0)\
123 
124 
125 #else
126 
127 // this version provides full backward compatibility,
128 // raising an error on ill-formed or missing input
129 
130 #define NTL_INPUT_ERROR(s, msg) \
131    do {\
132       InputError(msg);\
133    } while (0)\
134 
135 
136 #endif
137 
138 
139 #define NTL_INPUT_CHECK_ERR(stmt) \
140    do {\
141       if (!(stmt)) InputError("bad input\n");\
142    } while (0)\
143 
144 
145 
146 #define NTL_INPUT_CHECK_RET(s, stmt) \
147    do {\
148       if (!(stmt)) { s.setstate(NTL_SNS ios::failbit); return s; }\
149    } while (0)\
150 
151 
152 
153 
154 
155 #define NTL_FILE_THRESH (1e12)
156 // threshold in KB for switching to external storage of certain tables
157 
158 
159 
160 
161 struct INIT_SIZE_STRUCT { };
162 const INIT_SIZE_STRUCT INIT_SIZE = INIT_SIZE_STRUCT();
163 typedef const INIT_SIZE_STRUCT& INIT_SIZE_TYPE;
164 
165 struct INIT_VAL_STRUCT { };
166 const INIT_VAL_STRUCT INIT_VAL = INIT_VAL_STRUCT();
167 typedef const INIT_VAL_STRUCT& INIT_VAL_TYPE;
168 
169 struct INIT_TRANS_STRUCT { };
170 const INIT_TRANS_STRUCT INIT_TRANS = INIT_TRANS_STRUCT();
171 typedef const INIT_TRANS_STRUCT& INIT_TRANS_TYPE;
172 
173 
174 struct INIT_LOOP_HOLE_STRUCT { };
175 const INIT_LOOP_HOLE_STRUCT INIT_LOOP_HOLE = INIT_LOOP_HOLE_STRUCT();
176 typedef const INIT_LOOP_HOLE_STRUCT& INIT_LOOP_HOLE_TYPE;
177 
178 struct INIT_FFT_STRUCT { };
179 const INIT_FFT_STRUCT INIT_FFT = INIT_FFT_STRUCT();
180 typedef const INIT_FFT_STRUCT& INIT_FFT_TYPE;
181 
182 struct INIT_USER_FFT_STRUCT { };
183 const INIT_USER_FFT_STRUCT INIT_USER_FFT = INIT_USER_FFT_STRUCT();
184 typedef const INIT_USER_FFT_STRUCT& INIT_USER_FFT_TYPE;
185 
186 struct INIT_NO_ALLOC_STRUCT { };
187 const INIT_NO_ALLOC_STRUCT INIT_NO_ALLOC = INIT_NO_ALLOC_STRUCT();
188 typedef const INIT_NO_ALLOC_STRUCT& INIT_NO_ALLOC_TYPE;
189 
190 struct INIT_ALLOC_STRUCT { };
191 const INIT_ALLOC_STRUCT INIT_ALLOC = INIT_ALLOC_STRUCT();
192 typedef const INIT_ALLOC_STRUCT& INIT_ALLOC_TYPE;
193 
194 struct INIT_MONO_STRUCT { };
195 const INIT_MONO_STRUCT INIT_MONO = INIT_MONO_STRUCT();
196 typedef const INIT_MONO_STRUCT& INIT_MONO_TYPE;
197 
198 
199 
200 #ifdef NTL_NO_INIT_TRANS
201 #define NTL_OPT_RETURN(t, x) return x
202 #else
203 #define NTL_OPT_RETURN(t, x) return t(x, INIT_TRANS)
204 #endif
205 
206 
207 #ifndef NTL_NO_MIN_MAX
208 
min(int a,int b)209 inline int min(int a, int b) { return (a < b) ?  a : b; }
max(int a,int b)210 inline int max(int a, int b) { return (a < b) ? b : a; }
211 
min(long a,long b)212 inline long min(long a, long b) { return (a < b) ?  a : b; }
max(long a,long b)213 inline long max(long a, long b) { return (a < b) ? b : a; }
214 
min(int a,long b)215 inline long min(int a, long b) { return (a < b) ?  long(a) : b; }
max(int a,long b)216 inline long max(int a, long b) { return (a < b) ? b : long(a); }
217 
min(long a,int b)218 inline long min(long a, int b) { return (a < b) ?  a : long(b); }
max(long a,int b)219 inline long max(long a, int b) { return (a < b) ? long(b) : a; }
220 
min(unsigned int a,unsigned int b)221 inline unsigned int min(unsigned int a, unsigned int b)
222 { return (a < b) ?  a : b; }
max(unsigned int a,unsigned int b)223 inline unsigned int max(unsigned int a, unsigned int b)
224 { return (a < b) ? b : a; }
225 
min(unsigned long a,unsigned long b)226 inline unsigned long min(unsigned long a, unsigned long b)
227 { return (a < b) ?  a : b; }
max(unsigned long a,unsigned long b)228 inline unsigned long max(unsigned long a, unsigned long b)
229 { return (a < b) ? b : a; }
230 
min(unsigned int a,unsigned long b)231 inline unsigned long min(unsigned int a, unsigned long b)
232 { return (a < b) ?  (unsigned long)(a) : b; }
max(unsigned int a,unsigned long b)233 inline unsigned long max(unsigned int a, unsigned long b)
234 { return (a < b) ? b : (unsigned long)(a); }
235 
min(unsigned long a,unsigned int b)236 inline unsigned long min(unsigned long a, unsigned int b)
237 { return (a < b) ?  a : (unsigned long)(b); }
max(unsigned long a,unsigned int b)238 inline unsigned long max(unsigned long a, unsigned int b)
239 { return (a < b) ? (unsigned long)(b) : a; }
240 
241 #endif
242 
243 
244 // NOTE: these are here for historical reasons, so I'll leave them
245 // Since it is likely to lead to ambiguities with std::swap,
246 // I am not defining any more of these.
swap(long & a,long & b)247 inline void swap(long& a, long& b)  {  long t;  t = a; a = b; b = t; }
swap(int & a,int & b)248 inline void swap(int& a, int& b)  {  int t;  t = a; a = b; b = t; }
249 
250 
251 // some convenience casting routines:
252 
cast_unsigned(long a)253 inline unsigned long cast_unsigned(long a) { return (unsigned long) a; }
cast_unsigned(int a)254 inline unsigned int cast_unsigned(int a) { return (unsigned int) a; }
255 
256 
257 // these routines respect the NTL_CLEAN_INT flag: if set,
258 // they use code that is guaranteed to work, under the
259 // assumption that signed integers are two's complement.
260 // A good compiler should optimize it all away and generate
261 // the same code in either case (tested on gcc, clang, icc, msvc++).
262 // This is really an academic exercise...
263 
264 #ifdef NTL_CLEAN_INT
265 
cast_signed(unsigned long a)266 inline long cast_signed(unsigned long a)
267 { return NTL_ULONG_TO_LONG(a); }
268 
cast_signed(unsigned int a)269 inline int cast_signed(unsigned int a)
270 { return NTL_UINT_TO_INT(a); }
271 
272 #else
273 
cast_signed(unsigned long a)274 inline long cast_signed(unsigned long a) { return long(a); }
cast_signed(unsigned int a)275 inline int cast_signed(unsigned int a) { return int(a); }
276 
277 #endif
278 
279 
conv(int & x,int a)280 inline void conv(int& x, int a) { x = a; }
conv(int & x,long a)281 inline void conv(int& x, long a)
282    { unsigned y = (unsigned) a;  x = cast_signed(y); }
conv(int & x,float a)283 inline void conv(int& x, float a) { x = int(NTL_SNS floor(double(a))); }
conv(int & x,double a)284 inline void conv(int& x, double a) { x = int(NTL_SNS floor(a)); }
285 
conv(int & x,unsigned a)286 inline void conv(int& x, unsigned a)
287    { x = cast_signed(a); }
288 
conv(int & x,unsigned long a)289 inline void conv(int& x, unsigned long a)
290    { unsigned y = (unsigned) a;  x = cast_signed(y); }
291 
to_int(int a)292 inline int to_int(int a) { return a; }
to_int(long a)293 inline int to_int(long a)
294    { unsigned y = (unsigned) a;  return cast_signed(y); }
to_int(float a)295 inline int to_int(float a) { return int(NTL_SNS floor(double(a))); }
to_int(double a)296 inline int to_int(double a) { return int(NTL_SNS floor(a)); }
297 
to_int(unsigned a)298 inline int to_int(unsigned a)
299    { return cast_signed(a); }
300 
to_int(unsigned long a)301 inline int to_int(unsigned long a)
302    { unsigned y = (unsigned) a;  return cast_signed(y); }
303 
304 
conv(long & x,int a)305 inline void conv(long& x, int a) { x = a; }
conv(long & x,long a)306 inline void conv(long& x, long a) { x = a; }
conv(long & x,float a)307 inline void conv(long& x, float a) { x = long(NTL_SNS floor(double(a))); }
conv(long & x,double a)308 inline void conv(long& x, double a) { x = long(NTL_SNS floor(a)); }
309 
conv(long & x,unsigned a)310 inline void conv(long& x, unsigned a)
311    { unsigned long y = a;  x = cast_signed(y); }
312 
conv(long & x,unsigned long a)313 inline void conv(long& x, unsigned long a)
314    { x = cast_signed(a); }
315 
to_long(int a)316 inline long to_long(int a) { return a; }
to_long(long a)317 inline long to_long(long a) { return a; }
to_long(float a)318 inline long to_long(float a) { return long(NTL_SNS floor(double(a))); }
to_long(double a)319 inline long to_long(double a) { return long(NTL_SNS floor(a)); }
320 
to_long(unsigned a)321 inline long to_long(unsigned a)
322    { unsigned long y = a;  return cast_signed(y); }
323 
to_long(unsigned long a)324 inline long to_long(unsigned long a)
325    { return cast_signed(a); }
326 
conv(float & x,int a)327 inline void conv(float& x, int a) { x = float(a); }
conv(float & x,long a)328 inline void conv(float& x, long a) { x = float(a); }
conv(float & x,unsigned a)329 inline void conv(float& x, unsigned a) { x = float(a); }
conv(float & x,unsigned long a)330 inline void conv(float& x, unsigned long a) { x = float(a); }
conv(float & x,float a)331 inline void conv(float& x, float a) { x = a; }
conv(float & x,double a)332 inline void conv(float& x, double a) { x = float(a); }
333 
to_float(int a)334 inline float to_float(int a) { return float(a); }
to_float(long a)335 inline float to_float(long a) { return float(a); }
to_float(unsigned a)336 inline float to_float(unsigned a) { return float(a); }
to_float(unsigned long a)337 inline float to_float(unsigned long a) { return float(a); }
to_float(float a)338 inline float to_float(float a) { return a; }
to_float(double a)339 inline float to_float(double a) { return float(a); }
340 
conv(double & x,int a)341 inline void conv(double& x, int a) { x = double(a); }
conv(double & x,long a)342 inline void conv(double& x, long a) { x = double(a); }
conv(double & x,unsigned a)343 inline void conv(double& x, unsigned a) { x = double(a); }
conv(double & x,unsigned long a)344 inline void conv(double& x, unsigned long a) { x = double(a); }
conv(double & x,float a)345 inline void conv(double& x, float a) { x = double(a); }
conv(double & x,double a)346 inline void conv(double& x, double a) { x = a; }
347 
to_double(int a)348 inline double to_double(int a) { return double(a); }
to_double(long a)349 inline double to_double(long a) { return double(a); }
to_double(unsigned a)350 inline double to_double(unsigned a) { return double(a); }
to_double(unsigned long a)351 inline double to_double(unsigned long a) { return double(a); }
to_double(float a)352 inline double to_double(float a) { return double(a); }
to_double(double a)353 inline double to_double(double a) { return a; }
354 
355 
356 
357 /* additional legacy conversions for v6 conversion regime */
358 
359 
conv(unsigned int & x,int a)360 inline void conv(unsigned int& x, int a) { x = ((unsigned int)(a)); }
conv(unsigned int & x,long a)361 inline void conv(unsigned int& x, long a) { x = ((unsigned int)(a)); }
conv(unsigned int & x,unsigned a)362 inline void conv(unsigned int& x, unsigned a) { x = a; }
conv(unsigned int & x,unsigned long a)363 inline void conv(unsigned int& x, unsigned long a) { x = ((unsigned int)(a)); }
conv(unsigned int & x,float a)364 inline void conv(unsigned int& x, float a) { x = ((unsigned int) to_long(a)); }
conv(unsigned int & x,double a)365 inline void conv(unsigned int& x, double a) { x = ((unsigned int) to_long(a)); }
366 
conv(unsigned long & x,int a)367 inline void conv(unsigned long& x, int a) { x = ((unsigned long)(a)); }
conv(unsigned long & x,long a)368 inline void conv(unsigned long& x, long a) { x = ((unsigned long)(a)); }
conv(unsigned long & x,unsigned a)369 inline void conv(unsigned long& x, unsigned a) { x = ((unsigned long)(a)); }
conv(unsigned long & x,unsigned long a)370 inline void conv(unsigned long& x, unsigned long a) { x = a; }
conv(unsigned long & x,float a)371 inline void conv(unsigned long& x, float a) { x = ((unsigned int) to_long(a)); }
conv(unsigned long & x,double a)372 inline void conv(unsigned long& x, double a) { x = ((unsigned int) to_long(a)); }
373 
374 
375 
376 
377 
378 
379 
380 
381 
382 
383 
384 
385 
386 
387 
388 long SkipWhiteSpace(NTL_SNS istream& s);
389 long IsWhiteSpace(long c);
390 long IsEOFChar(long c);
391 
392 long CharToIntVal(long c);
393 char IntValToChar(long a);
394 
395 
396 
397 
398 
GetTime()399 inline double GetTime() { return _ntl_GetTime(); }
GetPID()400 inline unsigned long GetPID() { return _ntl_GetPID(); }
401 
GetWallTime()402 inline double GetWallTime() { return _ntl_GetWallTime(); }
403 
IsFinite(double * p)404 inline long IsFinite(double *p) { return _ntl_IsFinite(p); }
405 
406 
407 #if (NTL_EXT_DOUBLE)
408 
ForceToMem(double * p)409 inline void ForceToMem(double *p) { _ntl_ForceToMem(p); }
410 
411 #else
412 
ForceToMem(double * p)413 inline void ForceToMem(double *p) { }
414 
415 #endif
416 
417 
TrueDouble(double x)418 inline double TrueDouble(double x)
419 {
420    ForceToMem(&x);
421    return x;
422 }
423 
424 
425 
426 
427 void PrintTime(NTL_SNS ostream& s, double t);
428 
429 
430 
431 #if (defined(__GNUC__) && (__GNUC__ >= 4))
432 
433 // on relative modern versions of gcc, we can
434 // decalare "restricted" pointers in C++
435 
436 // we also can use __attribute__((always_inline))
437 
438 
439 #define NTL_RESTRICT __restrict
440 #define NTL_ALWAYS_INLINE __attribute__((always_inline))
441 
442 #else
443 
444 #define NTL_RESTRICT
445 #define NTL_ALWAYS_INLINE
446 
447 #endif
448 
449 
450 
451 
452 
453 // A very lightly wrapped pointer than does nothing more than provide
454 // auto cleanup in a destructor.  Use the UniquePtr class (in SmartPtr.h)
455 // for a class with more safety and convenience features.
456 // This class is easiest to use to retrofit older code with RAII
457 // semantics.
458 
459 // A call to Deleter::apply should free the pointed-to storage
460 
461 template<class T, class Deleter>
462 class WrappedPtr {
463 private:
464    WrappedPtr(const WrappedPtr&); // disable
465    void operator=(const WrappedPtr&); // disable
466 public:
467    typedef T * raw_ptr;
468 
469    raw_ptr rep;
470 
WrappedPtr()471    WrappedPtr() : rep(0) { }
472    void operator=(const raw_ptr& _rep)  { rep = _rep; }
473 
~WrappedPtr()474    ~WrappedPtr() { if (rep) Deleter::apply(rep); }
475 
476    operator const raw_ptr& () const { return rep; }
477    operator raw_ptr& () { return rep; }
478 
479    const raw_ptr* operator&() const { return &rep; }
480    raw_ptr* operator&() { return &rep; }
481 
kill()482    void kill() { if (rep) { Deleter::apply(rep); rep = 0; } }
483 
swap(WrappedPtr & other)484    void swap(WrappedPtr& other) { _ntl_swap(rep, other.rep); }
485 
move(WrappedPtr & other)486    void move(WrappedPtr& other)
487    {
488       WrappedPtr tmp;
489       tmp.swap(other);
490       tmp.swap(*this);
491    }
492 
493 };
494 
495 template<class T, class Deleter>
swap(WrappedPtr<T,Deleter> & x,WrappedPtr<T,Deleter> & y)496 void swap(WrappedPtr<T,Deleter>& x, WrappedPtr<T,Deleter>& y)
497 {
498    x.swap(y);
499 }
500 
501 
502 
503 // Error Handling
504 
505 
506 
507 class ErrorObject : public NTL_SNS runtime_error {
508 public:
ErrorObject(const char * msg)509    ErrorObject(const char *msg) : runtime_error(msg) { }
510 };
511 
512 class LogicErrorObject : public ErrorObject {
513 public:
LogicErrorObject(const char * msg)514    LogicErrorObject(const char *msg) : ErrorObject(msg) { }
515 };
516 
517 class ArithmeticErrorObject : public ErrorObject {
518 public:
ArithmeticErrorObject(const char * msg)519    ArithmeticErrorObject(const char *msg) : ErrorObject(msg) { }
520 };
521 
522 class ResourceErrorObject : public ErrorObject {
523 public:
ResourceErrorObject(const char * msg)524    ResourceErrorObject(const char *msg) : ErrorObject(msg) { }
525 };
526 
527 class FileErrorObject : public ErrorObject {
528 public:
FileErrorObject(const char * msg)529    FileErrorObject(const char *msg) : ErrorObject(msg) { }
530 };
531 
532 class InputErrorObject : public ErrorObject {
533 public:
InputErrorObject(const char * msg)534    InputErrorObject(const char *msg) : ErrorObject(msg) { }
535 };
536 
537 
538 
539 extern NTL_CHEAP_THREAD_LOCAL void (*ErrorCallback)();
540 
541 extern NTL_CHEAP_THREAD_LOCAL void (*ErrorMsgCallback)(const char *);
542 
543 
544 void TerminalError(const char *s);
545 
546 #ifdef NTL_EXCEPTIONS
547 
MemoryError()548 inline void MemoryError() { throw NTL_SNS bad_alloc(); }
Error(const char * msg)549 inline void Error(const char *msg) { throw ErrorObject(msg); }
LogicError(const char * msg)550 inline void LogicError(const char *msg) { throw LogicErrorObject(msg); }
ArithmeticError(const char * msg)551 inline void ArithmeticError(const char *msg) { throw ArithmeticErrorObject(msg); }
InvModError(const char * msg)552 inline void InvModError(const char *msg) { throw ArithmeticErrorObject(msg); }
ResourceError(const char * msg)553 inline void ResourceError(const char *msg) { throw ResourceErrorObject(msg); }
FileError(const char * msg)554 inline void FileError(const char *msg) { throw FileErrorObject(msg); }
InputError(const char * msg)555 inline void InputError(const char *msg) { throw InputErrorObject(msg); }
556 
557 #else
558 
MemoryError()559 inline void MemoryError() { TerminalError("out of memory"); }
Error(const char * msg)560 inline void Error(const char *msg) { TerminalError(msg); }
LogicError(const char * msg)561 inline void LogicError(const char *msg) { TerminalError(msg); }
ArithmeticError(const char * msg)562 inline void ArithmeticError(const char *msg) { TerminalError(msg); }
InvModError(const char * msg)563 inline void InvModError(const char *msg) { TerminalError(msg); }
ResourceError(const char * msg)564 inline void ResourceError(const char *msg) { TerminalError(msg); }
FileError(const char * msg)565 inline void FileError(const char *msg) { TerminalError(msg); }
InputError(const char * msg)566 inline void InputError(const char *msg) { TerminalError(msg); }
567 
568 #endif
569 
570 
571 
572 
573 
574 
575 #ifdef NTL_EXCEPTIONS
576 
577 
578 template < typename F  >
579 class scope_guard
580 {
581     typename std::remove_reference<F>::type f;
582     bool active;
583     const char *info;
584 
585 public:
scope_guard(F && _f,const char * _info)586     scope_guard(F&& _f, const char *_info) :
587        f(std::forward<F>(_f)), active(true), info(_info) { }
588 
~scope_guard()589     ~scope_guard() {
590         if (active) {
591 #ifdef NTL_TEST_EXCEPTIONS
592             NTL_SNS cerr << "*** ACTIVE SCOPE GUARD TRIGGERED: "
593                          <<  info << "\n";
594 #endif
595             f();
596         }
597     }
598 
relax()599     void relax() { active = false; }
600 };
601 
602 
603 struct scope_guard_builder {
604    const char *info;
scope_guard_builderscope_guard_builder605    explicit scope_guard_builder(const char *_info) : info(_info) { }
606 };
607 
608 template < typename F >
609 scope_guard<F>
610 operator+(scope_guard_builder b, F&& f)
611 {
612     return scope_guard<F>(std::forward<F>(f), b.info);
613 }
614 
615 
616 #define NTL_SCOPE(var) auto var =  \
617    scope_guard_builder(__FILE__ ":" NTL_STRINGIFY(__LINE__)) + [&]
618 
619 
620 #else
621 
622 
623 class DummyScopeGuard {
624   bool active;
625 public:
DummyScopeGuard()626    DummyScopeGuard() : active(true) { }
~DummyScopeGuard()627    ~DummyScopeGuard() { if (active) TerminalError("unexpected exception"); }
628 
relax()629    void relax() { active = false; }
630 };
631 
632 #define NTL_SCOPE(var) DummyScopeGuard var; if (false)
633 
634 
635 
636 
637 #endif
638 
639 
640 
641 #define NTL_DETAILS_PTHREAD NTL_NNS details_pthread
642 
643 
644 #if (defined(NTL_THREADS) && defined(NTL_TLS_HACK))
645 
646 // NOTE: All of this TLS code is replicated in CheckThreads.cpp.
647 
648 
649 namespace details_pthread {
650 
651 
652 struct Node {
653    Node *next;
654 
NodeNode655    Node() : next(0) { }
~NodeNode656    virtual ~Node() { }
657 };
658 
659 template<class T>
660 struct DerivedNode : Node {
661    T t;
662 
663    template<class... Args>
DerivedNodeDerivedNode664    DerivedNode(Args&&... args) : t(std::forward<Args>(args)...) { }
665 };
666 
667 inline void
delete_node(Node * p)668 delete_node(Node *p) noexcept { delete p;  }
669 // an exception here would likely lead to a complete mess...
670 // the noexcept specification should force an immediate termination
671 
672 inline void
delete_list(void * vp)673 delete_list(void *vp)
674 {
675    Node *p = (Node *) vp;
676    while (p) {
677       Node *tmp = p;
678       p = p->next;
679       delete_node(tmp);
680    }
681 }
682 
683 
684 using namespace std;
685 // I'm not sure if pthread stuff might be placed in namespace std
686 
687 struct key_wrapper {
688    pthread_key_t key;
689 
key_wrapperkey_wrapper690    key_wrapper(void (*destructor)(void*))
691    {
692       if (pthread_key_create(&key, destructor))
693          ResourceError("pthread_key_create failed");
694    }
695 };
696 
697 
698 inline void
push_node(Node * p)699 push_node(Node *p)
700 // this pushes a new node to the front to the list
701 // of objects that need to be deleted
702 {
703    if (!p) MemoryError();
704 
705    static key_wrapper wkey(delete_list);
706    // This relies on C++11 thread-safe static initialization.
707    // It also relies on the guarantee that there is just one
708    // global key (this requirement is only needed to
709    // limit the number of keys, not for correctness).
710 
711 
712    p->next = (Node *) pthread_getspecific(wkey.key);
713 
714    if (pthread_setspecific(wkey.key, p)) {
715       delete_node(p);
716       ResourceError("pthread_setspecific failed");
717    }
718 }
719 
720 }
721 
722 
723 #define NTL_TLS_LOCAL_INIT(type, var, init)  \
724    static NTL_CHEAP_THREAD_LOCAL NTL_DETAILS_PTHREAD::DerivedNode<type> *_ntl_hidden_variable_tls_local_ptr_ ## var = 0;  \
725    NTL_DETAILS_PTHREAD::DerivedNode<type> *_ntl_hidden_variable_tls_local_ptr1_ ## var = _ntl_hidden_variable_tls_local_ptr_ ## var;  \
726    if (!_ntl_hidden_variable_tls_local_ptr1_ ## var) {  \
727       NTL_DETAILS_PTHREAD::DerivedNode<type> *_ntl_hidden_variable_tls_local_ptr2_ ## var = NTL_NEW_OP NTL_DETAILS_PTHREAD::DerivedNode<type> init;  \
728       NTL_DETAILS_PTHREAD::push_node(_ntl_hidden_variable_tls_local_ptr2_ ## var); \
729       _ntl_hidden_variable_tls_local_ptr1_ ## var = _ntl_hidden_variable_tls_local_ptr2_ ## var;  \
730       _ntl_hidden_variable_tls_local_ptr_ ## var = _ntl_hidden_variable_tls_local_ptr1_ ## var;  \
731    }  \
732    type &var = _ntl_hidden_variable_tls_local_ptr1_ ## var->t  \
733 
734 
735 
736 #else
737 
738 
739 // NOTE: this definition of NTL_TLS_LOCAL_INIT ensures that var names
740 // a local reference, regardless of the implementation
741 #define NTL_TLS_LOCAL_INIT(type,var,init) \
742     static NTL_THREAD_LOCAL type _ntl_hidden_variable_tls_local ## var init; \
743     type &var = _ntl_hidden_variable_tls_local ## var
744 
745 
746 
747 
748 #endif
749 
750 #define NTL_EMPTY_ARG
751 #define NTL_TLS_LOCAL(type,var) NTL_TLS_LOCAL_INIT(type,var,NTL_EMPTY_ARG)
752 
753 #define NTL_TLS_GLOBAL_DECL_INIT(type,var,init)  \
754    typedef type _ntl_hidden_typedef_tls_access_ ## var;  \
755    static inline  \
756    type& _ntl_hidden_function_tls_access_ ## var() {  \
757       NTL_TLS_LOCAL_INIT(type,var,init);  \
758       return var;  \
759    }  \
760 
761 
762 #define NTL_TLS_GLOBAL_DECL(type,var) NTL_TLS_GLOBAL_DECL_INIT(type,var,NTL_EMPTY_ARG)
763 
764 #define NTL_TLS_GLOBAL_ACCESS(var) \
765 _ntl_hidden_typedef_tls_access_ ## var & var = _ntl_hidden_function_tls_access_ ## var()
766 
767 
768 // **************************************************************
769 // Following is code for "long long" arithmetic that can
770 // be implemented using NTL_ULL_TYPE or using assembly.
771 // I have found that the assembly can be a bit faster.
772 // For now, this code is only available if NTL_HAVE_LL_TYPE
773 // is defined.  This could change.  In any case, this provides
774 // a cleaner interface and might eventually allow for
775 // implementation on systems that don't provide a long long type.
776 // **************************************************************
777 
778 #ifdef NTL_HAVE_LL_TYPE
779 
780 
781 #if (!defined(NTL_DISABLE_LL_ASM) \
782      && defined(__GNUC__) && (__GNUC__ >= 4) && !defined(__INTEL_COMPILER)  && !defined(__clang__) \
783      && defined (__x86_64__)  && NTL_BITS_PER_LONG == 64)
784 
785 // NOTE: clang's and icc's inline asm code gen is pretty bad, so
786 // we don't even try.
787 
788 // FIXME: probably, this should all be properly tested for speed (and correctness)
789 // using the Wizard.
790 
791 
792 struct ll_type {
793    unsigned long hi, lo;
794 };
795 
796 
797 inline void
ll_mul_add(ll_type & x,unsigned long a,unsigned long b)798 ll_mul_add(ll_type& x, unsigned long a, unsigned long b)
799 {
800   unsigned long hi, lo;
801    __asm__ (
802    "mulq %[b] \n\t"
803    "addq %[lo],%[xlo] \n\t"
804    "adcq %[hi],%[xhi]" :
805    [lo] "=a" (lo), [hi] "=d" (hi), [xhi] "+r" (x.hi), [xlo] "+r" (x.lo) :
806    [a] "%[lo]" (a), [b] "rm" (b) :
807    "cc"
808    );
809 }
810 
811 inline void
ll_imul_add(ll_type & x,unsigned long a,unsigned long b)812 ll_imul_add(ll_type& x, unsigned long a, unsigned long b)
813 {
814   unsigned long hi, lo;
815    __asm__ (
816    "imulq %[b] \n\t"
817    "addq %[lo],%[xlo] \n\t"
818    "adcq %[hi],%[xhi]" :
819    [lo] "=a" (lo), [hi] "=d" (hi), [xhi] "+r" (x.hi), [xlo] "+r" (x.lo) :
820    [a] "%[lo]" (a), [b] "rm" (b) :
821    "cc"
822    );
823 }
824 
825 inline void
ll_mul(ll_type & x,unsigned long a,unsigned long b)826 ll_mul(ll_type& x, unsigned long a, unsigned long b)
827 {
828    __asm__ (
829    "mulq %[b]" :
830    [lo] "=a" (x.lo), [hi] "=d" (x.hi) :
831    [a] "%[lo]" (a), [b] "rm" (b) :
832    "cc"
833    );
834 }
835 
836 inline void
ll_imul(ll_type & x,unsigned long a,unsigned long b)837 ll_imul(ll_type& x, unsigned long a, unsigned long b)
838 {
839    __asm__ (
840    "imulq %[b]" :
841    [lo] "=a" (x.lo), [hi] "=d" (x.hi) :
842    [a] "%[lo]" (a), [b] "rm" (b) :
843    "cc"
844    );
845 }
846 
847 inline void
ll_add(ll_type & x,unsigned long a)848 ll_add(ll_type& x, unsigned long a)
849 {
850    __asm__ (
851    "addq %[a],%[xlo] \n\t"
852    "adcq %[z],%[xhi]" :
853    [xhi] "+r" (x.hi), [xlo] "+r" (x.lo) :
854    [a] "rm" (a), [z] "i" (0) :
855    "cc"
856    );
857 }
858 
859 inline void
ll_add(ll_type & x,const ll_type & a)860 ll_add(ll_type& x, const ll_type& a)
861 {
862    __asm__ (
863    "addq %[alo],%[xlo] \n\t"
864    "adcq %[ahi],%[xhi]" :
865    [xhi] "+r" (x.hi), [xlo] "+r" (x.lo) :
866    [ahi] "rm" (a.hi), [alo] "rm" (a.lo) :
867    "cc"
868    );
869 }
870 
871 
872 
873 
874 // NOTE: an optimizing compiler will remove the conditional.
875 // The alternative would be to make a specialization for shamt=0.
876 // Unfortunately, this is impossible to do across a wide range
877 // of compilers and still maintain internal linkage --- it is not
878 // allowed to include static spec in the specialization (new compilers
879 // will complain) and without it, some older compilers will generate
880 // an external symbol.  In fact, NTL currently never calls
881 // this with shamt=0, so it is all rather academic...but I want to
882 // keep this general for future use.
883 
884 // NOTE: this implementation assumes that shamt is in the range
885 // 0..NTL_BITS_PER_LONG-1
886 
887 #if 1
888 
889 // The shrd instruction can be very slow on some
890 // machines.  Two shifts is usually just as good.
891 
892 template<long shamt>
893 unsigned long
ll_rshift_get_lo(ll_type x)894 ll_rshift_get_lo(ll_type x)
895 {
896    unsigned long res;
897    if (shamt)
898       res = (x.lo >> shamt) | (x.hi << (NTL_BITS_PER_LONG-shamt));
899    else
900       res = x.lo;
901 
902    return res;
903 }
904 
905 #else
906 
907 
908 template<long shamt>
909 unsigned long
ll_rshift_get_lo(ll_type x)910 ll_rshift_get_lo(ll_type x)
911 {
912    if (shamt) {
913       __asm__ (
914       "shrdq %[shamt],%[hi],%[lo]" :
915       [lo] "+r" (x.lo) :
916       [shamt] "i" (shamt), [hi] "r" (x.hi) :
917       "cc"
918       );
919    }
920    return x.lo;
921 }
922 
923 #endif
924 
925 
926 inline unsigned long
ll_get_lo(const ll_type & x)927 ll_get_lo(const ll_type& x)
928 {
929    return x.lo;
930 }
931 
932 inline unsigned long
ll_get_hi(const ll_type & x)933 ll_get_hi(const ll_type& x)
934 {
935    return x.hi;
936 }
937 
938 
939 inline void
ll_init(ll_type & x,unsigned long a)940 ll_init(ll_type& x, unsigned long a)
941 {
942    x.lo = a;
943    x.hi = 0;
944 }
945 
946 #else
947 
948 
949 typedef NTL_ULL_TYPE ll_type;
950 
951 // NOTE: the following functions definitions should serve as
952 // documentation, as well.
953 
954 inline void
ll_mul_add(ll_type & x,unsigned long a,unsigned long b)955 ll_mul_add(ll_type& x, unsigned long a, unsigned long b)
956 {
957    x += ((ll_type) a)*((ll_type) b);
958 }
959 
960 // a and b should be representable as positive long's,
961 // to allow for the most flexible implementation
962 inline void
ll_imul_add(ll_type & x,unsigned long a,unsigned long b)963 ll_imul_add(ll_type& x, unsigned long a, unsigned long b)
964 {
965    x += ((ll_type) long(a))*((ll_type) long(b));
966 }
967 inline void
ll_mul(ll_type & x,unsigned long a,unsigned long b)968 ll_mul(ll_type& x, unsigned long a, unsigned long b)
969 {
970    x = ((ll_type) a)*((ll_type) b);
971 }
972 
973 // a and b should be representable as positive long's,
974 // to allow for the most flexible implementation
975 inline void
ll_imul(ll_type & x,unsigned long a,unsigned long b)976 ll_imul(ll_type& x, unsigned long a, unsigned long b)
977 {
978    x = ((ll_type) long(a))*((ll_type) long(b));
979 }
980 
981 inline void
ll_add(ll_type & x,unsigned long a)982 ll_add(ll_type& x, unsigned long a)
983 {
984    x += a;
985 }
986 
987 inline void
ll_add(ll_type & x,const ll_type & a)988 ll_add(ll_type& x, const ll_type& a)
989 {
990    x += a;
991 }
992 
993 
994 // NOTE: shamt must be in the range 0..NTL_BITS_PER_LONG-1
995 template<long shamt>
996 unsigned long
ll_rshift_get_lo(const ll_type & x)997 ll_rshift_get_lo(const ll_type& x)
998 {
999    return ((unsigned long) (x >> shamt));
1000 }
1001 
1002 inline unsigned long
ll_get_lo(const ll_type & x)1003 ll_get_lo(const ll_type& x)
1004 {
1005    return ((unsigned long) x);
1006 }
1007 
1008 inline unsigned long
ll_get_hi(const ll_type & x)1009 ll_get_hi(const ll_type& x)
1010 {
1011    return ((unsigned long) (x >> NTL_BITS_PER_LONG));
1012 }
1013 
1014 
1015 inline void
ll_init(ll_type & x,unsigned long a)1016 ll_init(ll_type& x, unsigned long a)
1017 {
1018    x = a;
1019 }
1020 
1021 
1022 #endif
1023 
1024 
1025 inline unsigned long
ll_mul_hi(unsigned long a,unsigned long b)1026 ll_mul_hi(unsigned long a, unsigned long b)
1027 {
1028    ll_type x;
1029    ll_mul(x, a, b);
1030    return ll_get_hi(x);
1031 }
1032 
1033 
1034 #endif
1035 
1036 
1037 
1038 
1039 
1040 #ifdef NTL_SAFE_VECTORS
1041 
1042 
1043 #define NTL_RELOC_TAG (relocatable)
1044 
1045 #define NTL_DECLARE_RELOCATABLE_WHEN(x) \
1046 constexpr bool DeclareRelocatableType x
1047 
1048 #if (defined(NTL_HAVE_COPY_TRAITS1) || defined(NTL_WINPACK))
1049 
1050 
1051 // This strategy is used on compilers that fully support C++11 type traits.
1052 // For some reason, is_trivially_copyable says "true" even if the class
1053 // has deleted it's copy constructor.  Which means it is not copyable at all.
1054 // So I added an explicit test for is_copy_constructible.
1055 // Just to be on the safe side, I check for a trivial destructor.
1056 
1057 // This strategy is checked in the CheckCOPY_TRAITS1.cpp program.
1058 
1059 // We also use this strategy for the WINPACK distribution.
1060 // It should work on Windows with any compiler that properly supports C++11
1061 
1062 
1063 template<class T>
Relocate_aux_has_trivial_copy(T *)1064 constexpr bool Relocate_aux_has_trivial_copy(T*)
1065 {
1066    return  std::is_trivially_copyable<T>::value &&
1067            std::is_trivially_destructible<T>::value &&
1068            std::is_copy_constructible<T>::value;
1069 }
1070 
1071 template<class T>
Relocate_aux_has_any_copy(T *)1072 constexpr bool Relocate_aux_has_any_copy(T*)
1073 {
1074    return std::is_copy_constructible<T>::value;
1075 }
1076 
1077 #elif (defined(NTL_HAVE_COPY_TRAITS2))
1078 
1079 // This strategy is needed on GCC before v5.0, as the required type
1080 // traits are not impplemented.  Note that on a class with it's copy
1081 // constructors deleted, __has_trivial_copy is false on GCC before 4.9
1082 // and true startig with 4.9.  So I had to make use of SFINAE techniques
1083 // to make sure there actually is a non-deleted copy constructor.
1084 // Just to be on the safe side, I check for a trivial destructor.
1085 
1086 // This strategy is checked in the CheckCOPY_TRAITS2.cpp program.
1087 
1088 template <bool statement, typename out>
1089 struct Relocate_aux_Failable
1090 {
1091      typedef out Type;
1092 };
1093 
1094 struct Relocate_aux_TwoChars { char d[2]; };
1095 
1096 template <typename T>
1097 struct Relocate_aux_has_copy
1098 {
1099 
1100      static const T *MakeT();
1101 
1102      template <typename U> // U and T are the same type
1103      static typename Relocate_aux_Failable<(bool(sizeof U(*MakeT()))), char>::Type copy(int);
1104 
1105      template <typename U>
1106      static typename Relocate_aux_Failable<true, Relocate_aux_TwoChars>::Type copy(...);
1107 
1108      enum { value =  sizeof( copy<T>(0) )  == 1 };
1109 };
1110 
1111 
1112 template<class T>
Relocate_aux_has_trivial_copy(T *)1113 constexpr bool Relocate_aux_has_trivial_copy(T*)
1114 {
1115    return  __has_trivial_copy(T) &&
1116            __has_trivial_destructor(T) &&
1117            Relocate_aux_has_copy<T>::value;
1118 }
1119 
1120 template<class T>
Relocate_aux_has_any_copy(T *)1121 constexpr bool Relocate_aux_has_any_copy(T*)
1122 {
1123    return Relocate_aux_has_copy<T>::value;
1124 }
1125 
1126 
1127 #else
1128 
1129 #error "lacking compiler support for NTL_SAFE_VECTORS"
1130 
1131 #endif
1132 
1133 
1134 // NOTE: I've checked the correctness of the above strategies using
1135 // Godbolt's compiler explorer across a range of complilers
1136 // (clang, gcc, icc, MS).
1137 
1138 
1139 template<class T>
DeclareRelocatableType(T *)1140 constexpr bool DeclareRelocatableType(T*)
1141 {
1142    return Relocate_aux_has_trivial_copy((T*)0);
1143 }
1144 
1145 
1146 #else
1147 
1148 #define NTL_RELOC_TAG (true)
1149 
1150 #define NTL_DECLARE_RELOCATABLE_WHEN(x) \
1151 inline bool DeclareRelocatableType x
1152 
1153 
1154 template<class T>
DeclareRelocatableType(T *)1155 inline bool DeclareRelocatableType(T*)
1156 {
1157    return true;
1158 }
1159 
1160 #endif
1161 
1162 
1163 #define NTL_DECLARE_RELOCATABLE(x) NTL_DECLARE_RELOCATABLE_WHEN(x) \
1164    { return true; }
1165 
1166 
1167 // Examples:
1168 //   NTL_DECLARE_RELOCATABLE((int*))
1169 //   NTL_DECLARE_RELOCATABLE((Foo<int>*))
1170 //   template <class X, class Y> NTL_DECLARE_RELOCATABLE((Foo<X,Y>*))
1171 
1172 
1173 #if (NTL_CXX_STANDARD >= 2011)
1174 
1175 #define NTL_DEFAULT =default;
1176 
1177 #else
1178 
1179 #define NTL_DEFAULT {}
1180 
1181 #endif
1182 
1183 
1184 // The following idea for deriving from streambuf comes from:
1185 // https://stackoverflow.com/questions/1448467/initializing-a-c-stdistringstream-from-an-in-memory-buffer/1449527#1449527
1186 
1187 struct plain_c_string_streambuf : public std::streambuf
1188 {
plain_c_string_streambufplain_c_string_streambuf1189    plain_c_string_streambuf(const char* ss)
1190    {
1191       char *s = const_cast<char*>(ss);
1192       // casting away constant should be safe here,
1193       // based of my reading of the functionality
1194       // of streambuf from the documentation at cplusplus.com.
1195 
1196       setg(s, s, s + std::strlen(s));
1197    }
1198 };
1199 
1200 // Generic conversion from char* or const char*.  We use SFINAE
1201 // to prevent conversions from 0.
1202 
1203 
1204 template<class S, class T>
1205 typename _ntl_enable_if<_ntl_is_char_pointer<T>::value,void>::type
conv(S & x,T y)1206 conv(S& x, T y)
1207 {
1208    if (!y) InputError("bad conversion from char*");
1209    plain_c_string_streambuf buf(y);
1210    std::istream istr(&buf);
1211    if (!(istr >> x)) InputError("bad conversion from char*");
1212 }
1213 
1214 
1215 
1216 // new style converson function
1217 //   example: ZZ x = conv<ZZ>(1);
1218 //   note: modern C++ compilers should implemented
1219 //     "named return value optimization", so the
1220 //     result statement should not create a temporary
1221 
1222 template<class T, class S>
conv(const S & a)1223 T conv(const S& a)
1224 {
1225    T x;
1226    conv(x, a);
1227    return x;
1228 }
1229 
1230 
1231 
1232 NTL_CLOSE_NNS
1233 
1234 
1235 #endif
1236 
1237