1 /***************************************************************************
2                           typedefs.hpp  -  basic typedefs
3                              -------------------
4     begin                : July 22 2002
5     copyright            : (C) 2002 by Marc Schellens
6     email                : m_schellens@users.sf.net
7 ***************************************************************************/
8 
9 /***************************************************************************
10  *                                                                         *
11  *   This program is free software; you can redistribute it and/or modify  *
12  *   it under the terms of the GNU General Public License as published by  *
13  *   the Free Software Foundation; either version 2 of the License, or     *
14  *   (at your option) any later version.                                   *
15  *                                                                         *
16  ***************************************************************************/
17 
18 #ifndef TYPEDEFS_HPP_
19 #define TYPEDEFS_HPP_
20 
21 // check for needed libraries here as this file is included by most sources
22 // (via dimension.hpp via basegdl.hpp)
23 #ifdef HAVE_CONFIG_H
24 
25 #include <config.h>
26 
27 #ifndef HAVE_LIBGSL
28 #error "GNU Scientific Library not installed. Please see README file."
29 #endif
30 
31 #ifndef HAVE_LIBGSLCBLAS
32 #error "CBLAS (part of GNU Scientific Library) not installed. Please see README file."
33 #endif
34 
35 #ifndef HAVE_LIBPLPLOTCXXD
36 #error "plplot not installed. Please see README file."
37 #endif
38 
39 #endif // HAVE_CONFIG_H
40 
41 // Python.h must be included before everything else
42 #if defined(USE_PYTHON) || defined(PYTHON_MODULE)
43 #undef _POSIX_C_SOURCE // get rid of warning
44 #undef _XOPEN_SOURCE // get rid of warning
45 #undef HAVE_PROTOTYPES // get rid of warning
46 
47 //libreadline must be deactivated after Python.h if we do not use libreadline
48 #ifndef HAVE_LIBREADLINE
49 #define GDL_NOT_HAVE_READLINE
50 #endif
51 
52 #include <Python.h>
53 
54 #ifdef GDL_NOT_HAVE_READLINE
55 #undef HAVE_LIBREADLINE
56 #endif
57 #undef GDL_NOT_HAVE_READLINE
58 
59 //#ifndef _POSIX_C_SOURCE
60 //#warning "_POSIX_C_SOURCE not defined in Python.h (remove #undef)"
61 //#endif
62 //#ifndef _XOPEN_SOURCE
63 //#warning "_XOPEN_SOURCE not defined in Python.h (remove #undef)"
64 //#endif
65 //#ifndef HAVE_PROTOTYPES
66 //#warning "HAVE_PROTOTYPES not defined in Python.h (remove #undef)"
67 //#endif
68 #endif
69 
70 #include <set>
71 #include <string>
72 // #include <string.h> // memcopy
73 #include <cstring> // memcopy
74 // #include <deque>
75 #include <complex>
76 #include <vector>
77 #include <valarray>
78 #include <cassert>
79 #include <iostream>
80 
81 #undef USE_MPFR
82 
83 #ifdef USE_MPFR
84 #include "mpreal.h"
85 #endif
86 
87 // // undef for releases (should not give diagnostics)
88 // // define for the CVS (where the default sizes can easily be adjusted)
89 // #define GDL_CVS_VERSION
90 // //#undef GDL_CVS_VERSION
91 // // ?
92 // #ifdef GDL_CVS_VERSION
93 // #include <iostream>
94 // #endif
95 
96 //#define TRACE_OMP_CALLS
97 #undef TRACE_OMP_CALLS
98 
99 #if defined(_OPENMP) && defined(TRACE_OMP_CALLS)
100 #define TRACEOMP( file, line)   std::cout << "TRACEOMP\t" << file << "\t" << line << std::endl;
101 #else
102 #define TRACEOMP( file, line)
103 #endif
104 
105 // SA: fixing bug no. 3296360
106 typedef unsigned long long int      SizeT;
107 typedef long long int RangeT;
108 typedef long long int OMPInt;
109 
110 const SizeT MAXRANK=8;         // arrays are limited to 8 dimensions
111 const std::string MAXRANK_STR("8");  // for use in strings (error messages)
112 const std::string INTERNAL_LIBRARY_STR("<INTERNAL_LIBRARY>");
113 
114 //// SA: the version introduced by Joel in 2006:
115 ////#if defined(HAVE_64BIT_OS)
116 ////  typedef unsigned long long int      SizeT;
117 ////  typedef long long int RangeT;
118 ////#else
119 ////  typedef unsigned int        	    SizeT;
120 ////  typedef int                            RangeT;
121 ////#endif
122 
123 // SA: the original version from 2005:
124 //typedef size_t              SizeT;
125 
126 
127 typedef unsigned int        UInt;
128 typedef unsigned long       ULong;
129 
130 
131 // convenient naming
132 typedef unsigned char          DByte;
133 // typedef int                    DInt;
134 // typedef unsigned int           DUInt;
135 // typedef long int               DLong;
136 // typedef unsigned long int      DULong;
137 
138 #ifdef _MSC_VER
139 typedef __int64               DLong64;
140 typedef unsigned __int64      DULong64;
141 
142 #else
143 //typedef long int               DLong64;
144 //typedef unsigned long int      DULong64;
145 typedef long long int          DLong64;
146 typedef unsigned long long int DULong64;
147 #endif
148 
149 #ifdef USE_MPFR
150 
151 typedef __int128               DLong128;
152 typedef unsigned __int128      DULong128;
153 
154 typedef long double            DLDouble;
155 typedef std::complex<DLDouble> DComplexLDbl;
156 
157 
158 typedef mpfr::mpreal           DArbitrary;
159 #endif
160 
161 
162 typedef short                  DInt;
163 typedef unsigned short         DUInt;
164 typedef int                    DLong;
165 typedef unsigned int           DULong;
166 typedef float                  DFloat;
167 typedef double                 DDouble;
168 typedef std::string            DString;
169 typedef SizeT                  DPtr; // ptr to heap
170 typedef DPtr                   DObj; // ptr to object heap
171 typedef std::complex<DFloat>   DComplex;
172 typedef std::complex<DDouble>  DComplexDbl;
173 
174 // list of identifiers (used in several places)
175 typedef std::vector<std::string>       IDList;
176 typedef std::vector<std::string>       StrArr;
177 
178 // for dpro
179 typedef std::vector<std::string> KeyVarListT;
180 
181 // used by file.cpp and in other places
182 typedef std::vector<DString>           FileListT;
183 
184 //typedef std::valarray<SizeT>          AllIxT;
185 
186 typedef std::set< DPtr>               DPtrListT;
187 
188 //class ArrayIndexT;
189 //typedef std::vector<ArrayIndexT*> ArrayIndexVectorT;
190 
191 // // for GUI (but also used in GDLEventHandler()
192 // typedef DLong WidgetIDT;
193 
194 // to resolve include conflict (declared in gdlexception.hpp)
195 void ThrowGDLException( const std::string& str);
196 
197 // for OpenMP (defined in objects.cpp - must be declared here)
198 extern DLong CpuHW_NCPU;
199 extern DLong CpuTPOOL_NTHREADS;
200 extern DLong64 CpuTPOOL_MIN_ELTS;
201 extern DLong64 CpuTPOOL_MAX_ELTS;
202 
203 // convert something to string
204 template <typename T>
i2s(T i,SizeT w)205 inline std::string i2s( T i, SizeT w)// = 0)
206 {
207   std::ostringstream os;
208   os.width(w);
209   os << i;
210   return os.str();
211 }
212 template <typename T>
i2s(T i)213 inline std::string i2s( T i)
214 {
215   std::ostringstream os;
216   assert( os.width() == 0);
217   os << i;
218   return os.str();
219 }
220 
221 // debug
222 //#include <iostream>
223 
224 // searches IDList idL for std::string s, returns its position, -1 if not found
FindInIDList(IDList & idL,const std::string & s)225 inline int FindInIDList(IDList& idL,const std::string& s)
226 {
227 //   int ix=0;
228   for(IDList::iterator i=idL.begin(); i != idL.end(); ++i)//, ++ix)
229     if( *i==s)
230       {
231 	return i - idL.begin();
232       }
233 
234   return -1;
235 }
236 // TODO: make a template
FindInKeyVarListT(KeyVarListT & idL,const std::string & s)237 inline int FindInKeyVarListT(KeyVarListT& idL,const std::string& s)
238 {
239 //   int ix=0;
240   for(KeyVarListT::iterator i=idL.begin(); i != idL.end(); ++i)//, ++ix)
241     if( *i==s)
242       {
243 	return i - idL.begin();
244       }
245 
246   return -1;
247 }
248 
249 // as auto_ptr is obsoleted Guard offers an alternative
250 template <class T>
251 class Guard
252 {
253 private:
254   T*      guarded;
255 
operator =(Guard & r)256   Guard& operator=( Guard& r)
257   {
258     if( &r == this) return *this;
259     delete guarded;
260     guarded = r.guarded;
261     r.guarded = NULL;
262     return *this;
263   }
264 
265 
266 public:
Guard()267   Guard(): guarded( NULL)
268   {}
Guard(T * c)269   Guard( T* c): guarded( c)
270   {}
271 
Init(T * iniGuarded)272   void Init( T* iniGuarded) // saves a call to delete
273   {
274     assert( guarded == NULL);
275     guarded = iniGuarded;
276   }
Reset(T * newGuarded)277   void Reset( T* newGuarded)
278   {
279     delete guarded;
280     guarded = newGuarded;
281   }
282   // for compatibiltiy with replaced auto_ptr
reset(T * newGuarded)283   void reset( T* newGuarded)
284   {
285     delete guarded;
286     guarded = newGuarded;
287   }
Release()288   void Release()
289   {
290     guarded = NULL;
291   }
release()292   T* release()
293   {
294     T* g = guarded;
295     guarded = NULL;
296     return g;
297   }
Get() const298   T* Get() const
299   {
300     return guarded;
301   }
302   // for compatibiltiy with replaced auto_ptr
get() const303   T* get() const
304   {
305     return guarded;
306   }
307   // for compatibiltiy with replaced auto_ptr
operator ->() const308   T* operator->() const
309   {
310     return guarded;
311   }
IsNull() const312   bool IsNull() const
313   {
314     return guarded == NULL;
315   }
316 
~Guard()317   ~Guard()
318   {
319     delete guarded;
320   }
321 };
322 
323 
324 
325 
326 // like auto_ptr but for arrays (delete[] is used upon destruction)
327 template <class T>
328 class ArrayGuard
329 {
330 private:
331   T*      guarded;
332 
333 public:
ArrayGuard()334   ArrayGuard(): guarded( NULL)
335   {}
ArrayGuard(T * c)336   ArrayGuard( T* c): guarded( c)
337   {}
338 
Reset(T * newGuarded)339   void Reset( T* newGuarded)
340   {
341     delete[] guarded;
342     guarded = newGuarded;
343   }
Release()344   void Release()
345   {
346     guarded = NULL;
347   }
348 
~ArrayGuard()349   ~ArrayGuard()
350   {
351     delete[] guarded;
352   }
353 };
354 
355 // maintains size of stack, needed for exceptions
356 template <class T>
357 class StackGuard
358 {
359 private:
360   T& container;
361   typename T::size_type cSize;
362 
363 public:
StackGuard(T & c)364   StackGuard( T& c): container( c)
365   {
366     cSize=container.size();
367   }
368 
~StackGuard()369   ~StackGuard()
370   {
371     for( typename T::size_type s=container.size(); s > cSize; s--)
372       {
373 	delete container.back();
374 	container.pop_back();
375       }
376   }
377 };
378 
379 // needed for exceptions
380 // does not delete elements
381 template <class T>
382 class StackSizeGuard
383 {
384 private:
385   T&     container;
386   SizeT  cSize;
387 
388 public:
StackSizeGuard(T & c)389   StackSizeGuard( T& c): container( c)
390   {
391     cSize=container.size();
392   }
393 
~StackSizeGuard()394   ~StackSizeGuard()
395   {
396     for( SizeT s=container.size(); s > cSize; s--)
397       { // no deleting here
398 	container.pop_back();
399       }
400   }
401 };
402 
403 // needed for exception savety (assures that after destruction the value
404 // will be the same as on instantiation)
405 template <class T>
406 class ValueGuard
407 {
408 private:
409   T&     val;
410   T      oldVal;
411 
412 public:
ValueGuard(T & v)413   ValueGuard( T& v): val( v), oldVal( v)
414   {}
415 
~ValueGuard()416   ~ValueGuard()
417   {
418     val = oldVal;
419   }
420 };
421 
422 // like stackguard, but allows releasing
423 template <class T>
424 class PtrGuard
425 {
426 private:
427   T*     container;
428   SizeT  cSize;
429 
430 public:
PtrGuard(T * c)431   PtrGuard( T* c): container( c)
432   {
433     cSize=container->size();
434   }
435 
~PtrGuard()436   ~PtrGuard()
437   {
438     if( container != NULL)
439       for( SizeT s=container->size(); s > cSize; s--)
440 	{
441 	  delete container->back();
442 	  container->pop_back();
443 	}
444   }
445 
Release()446   T* Release() { T* r=container; container=NULL; return r;}
447 };
448 
449 
450 // this data structure is optimized for list sizes < ExprListDefaultLength
451 // ExprListDefaultLength should be set such that it will probably never exceed
452 // note: it will work for larger lists as well, but then copy operations are performed
453 // The effect for indexed access was significant (>40%).
454 template< typename T, SizeT defaultLength> class PreAllocPListT
455 {
456 public:
457 typedef T* iterator;
458 
459 private:
460 T* eArr;
461 T buf[defaultLength];
462 SizeT sz;
463 SizeT actLen;
464 
465 public:
PreAllocPListT()466 PreAllocPListT(): eArr(buf), sz(0) {}
~PreAllocPListT()467 ~PreAllocPListT()
468 {
469 	T* pEnd = &eArr[sz];
470 	for( T* p = &eArr[0]; p!=pEnd;++p)
471 		delete *p;
472 	if( eArr != buf)
473 		delete[] eArr;
474 }
push_back(T p)475 void push_back( T p)
476 {
477 	if( sz < defaultLength)
478 	{
479 		eArr[ sz++] = p;
480 		return;
481 	}
482 	if( sz == defaultLength)
483 		actLen =defaultLength; // only init here
484 	if( sz == actLen)
485 	{
486 // /* #ifdef CVS_VERSION
487 //  		only for CVS version
488 //   		std::cerr << "PreAllocPListT: Resize triggered ("+i2s(sz)+"). All Ok! But please report at: https://github.com/gnudatalanguage/gdl/issues" << std::endl;
489 // #endif*/
490 		actLen *= 2;
491 		T* newArr = new T[ actLen];
492 		for( SizeT i=0; i<sz; ++i)
493 			newArr[i] = eArr[i];
494 		if( eArr != buf)
495 			delete[] eArr;
496 		eArr = newArr;
497 	}
498 	eArr[ sz++] = p;
499 }
operator [](SizeT i) const500 T operator[]( SizeT i) const { assert( i<sz);  return eArr[i];}
operator [](SizeT i)501 T& operator[]( SizeT i) { assert( i<sz);  return eArr[i];}
size() const502 SizeT size() const { return sz;}
begin()503 iterator begin()  { return &eArr[0];}
end()504 iterator end()  { return &eArr[sz];}
505 
empty() const506 bool empty() const { return sz == 0;}
front()507 T& front() { return eArr[0];}
front() const508 const T& front() const { return eArr[0];}
back()509 T& back() { return eArr[sz-1];}
back() const510 const T& back() const { return eArr[sz-1];}
511 };
512 
513 class BaseGDL;
514 const int ExprListDefaultLength = 64;
515 typedef PreAllocPListT<BaseGDL*, ExprListDefaultLength> ExprListT;
516 typedef ExprListT::iterator ExprListIterT;
517 
518 // exception save usage of GSL types
519 // you need to pass the gsl-object to guard and the gsl-clenaup (free) function
520 // example usage (for gsl_matrix):
521 //
522 // gsl_matrix *matrix = gsl_matrix_alloc(p0->Dim(0), p0->Dim(0));
523 //
524 // GDLGuard< gsl_matrix> gsl_matrix_guard( matrix, gsl_matrix_free);
525 // (of course no explicit call to the gsl-cleanup function must be done anymore)
526 template< typename GSLType, typename cleanupReturnType=void, typename cleanupArgType=GSLType>
527 class GDLGuard
528 {
529   GSLType* gslObject;
530 
531   // note: cleanupArgType must be GSLType,
532   // except for free( void*) with GSLType==void*
533   // where it must be void
534   cleanupReturnType (*gslDestructor)(cleanupArgType*);
535 
GDLGuard()536   GDLGuard() {}
537 
538 public:
GDLGuard(void (* d)(GSLType *))539   GDLGuard( void (*d)(GSLType*)): gslObject( NULL), gslDestructor(d) {}
GDLGuard(GSLType * o,cleanupReturnType (* d)(cleanupArgType *))540   GDLGuard( GSLType* o, cleanupReturnType (*d)(cleanupArgType*)): gslObject( o), gslDestructor(d) {}
~GDLGuard()541   ~GDLGuard()
542   {
543     (*gslDestructor)( (cleanupArgType*)gslObject);
544   }
Init(GSLType * o)545   void Init( GSLType* o)
546   {
547     assert( gslObject == NULL);
548     gslObject = o;
549   }
550 };
551 
552 // int fclose(...);
553 typedef GDLGuard< FILE, int> FILEGuard;
554 
555 // class FILEGuard
556 // {
557 //   FILE* fp;
558 //
559 //   FILEGuard() {}
560 //
561 // public:
562 //   FILEGuard( FILE* f): fp( f) {}
563 //   ~FILEGuard()
564 //   {
565 //     fclose( fp);
566 //   }
567 // };
568 
569 
570 class FreeListT
571 {
572   typedef void* PType;
573   PType* freeList;
574   SizeT sz;
575   SizeT endIx;
576 
577 public:
FreeListT()578   FreeListT(): freeList(NULL), sz(0), endIx(0) {}
579 
size() const580   SizeT size() const { return endIx;}
resize(SizeT s)581   void resize( SizeT s) { endIx = s;}
pop_back()582   PType pop_back() { assert(endIx > 0); return freeList[endIx--];}
583 //   PType back() const { assert(endIx > 0); assert( freeList != NULL); return freeList[endIx];}
push_back(PType p)584   void push_back( PType p) { assert( endIx < (sz-1));  assert( freeList != NULL); freeList[++endIx] = p;}
585 
Init(SizeT s,char * res,SizeT sizeOfType)586   char* Init( SizeT s, char* res, SizeT sizeOfType)
587   {
588     endIx = s;
589 
590     //freeList[0] = res; // the ptr to free (not implemented)
591     for( size_t i=1; i<=endIx; ++i)
592     {
593       freeList[ i] = res;
594       res += sizeOfType;
595     }
596     return res;
597   }
598 //   PType& operator[]( SizeT i)
599 //   {
600 //     return freeList[ i];
601 //   }
602 //   PType operator[]( SizeT i) const
603 //   {
604 //     return freeList[ i+1];
605 //   }
606 
reserve(SizeT s)607   void reserve( SizeT s)
608   {
609     assert( endIx == 0);
610 
611     // alloc one more
612     if( ++s == sz)
613       return;
614 
615     free( freeList);
616     freeList = (PType*) malloc( s * sizeof(PType));
617     if( freeList == NULL) // error
618     {
619       freeList = (PType*) malloc( sz * sizeof(PType));
620       if( freeList == NULL)
621       {
622 	std::cerr << "% Error allocating free list. Probably already too late. Sorry.\n"
623 	  "Try to save what to save and immediately exit GDL session."<<std::endl;
624       }
625       else
626       {
627 	std::cerr << "% Error allocating free list. Segmentation fault pending.\n"
628 	  "Try to save what to save and immediately exit GDL session."<<std::endl;
629       }
630       return;
631     }
632     sz = s;
633   }
634 
635 };
636 
637 //typedef std::vector< void*> FreeListT;
638 
639 #endif
640