source: Sophya/trunk/SophyaLib/TArray/basarr.cc@ 944

Last change on this file since 944 was 926, checked in by ansari, 25 years ago

documentation cmv 13/4/00

File size: 18.3 KB
Line 
1// Base class for numerical arrays
2// R. Ansari, C.Magneville 03/2000
3
4#include "machdefs.h"
5#include <stdio.h>
6#include <stdlib.h>
7#include "pexceptions.h"
8#include "basarr.h"
9
10/*!
11 \class SOPHYA::BaseArray
12 \ingroup TArray
13 Base class for template arrays
14 No data are connected to this class.
15
16 Define base methods, enum and defaults for TArray , TMatrix and TVector.
17*/
18
19// Variables statiques globales
20char * BaseArray::ck_op_msg_[6] =
21 {"???", "Size(int )", "IsPacked(int )"
22 ,"Stride(int )", "ElemCheckBound()", "operator()" };
23uint_4 BaseArray::max_nprt_ = 50;
24uint_4 BaseArray::prt_lev_ = 0;
25short BaseArray::default_memory_mapping = CMemoryMapping;
26short BaseArray::default_vector_type = ColumnVector;
27uint_8 BaseArray::openmp_size_threshold = 200000;
28
29// ------ Methodes statiques globales --------
30
31//! Set maximum number of printed elements and print level
32/*!
33 \param nprt : maximum number of print
34 \param lev : print level
35*/
36void BaseArray::SetMaxPrint(uint_4 nprt, uint_4 lev)
37{
38 max_nprt_ = nprt;
39 prt_lev_ = (lev < 3) ? lev : 3;
40}
41
42//! Set Size threshold for parallel routine call
43/*!
44 \param thr : thresold value
45*/
46void BaseArray::SetOpenMPSizeThreshold(uint_8 thr)
47{
48 openmp_size_threshold = thr;
49}
50
51
52//! Compute totale size
53/*!
54 \param ndim : number of dimensions
55 \param siz : array of size along the \b ndim dimensions
56 \param step[ndim] : step value
57 \param offset : offset value
58 \return Total size of the array
59*/
60uint_8 BaseArray::ComputeTotalSize(uint_4 ndim, const uint_4 * siz, uint_4 step, uint_8 offset)
61{
62 uint_8 rs = step;
63 for(int k=0; k<ndim; k++) rs *= siz[k];
64 return(rs+offset);
65}
66
67//! Set Default Memory Mapping
68/*!
69 \param mm : Memory Mapping type
70 \verbatim
71 mm == CMemoryMapping : C like memory mapping
72 mm == FortranMemoryMapping : Fortran like memory mapping
73 \endverbatim
74 \verbatim
75 # ===== For Matrices
76 *** MATHEMATICS: m(row,column) with indexes running [1,n])
77 | 11 12 13 |
78 matrix Math = Mmath= | 21 22 23 |
79 | 31 32 33 |
80 *** IDL, \b FORTRAN: indexes data in \b row-major format:
81 indexes arrays in (column,row) order.
82 index IDL running [0,n[ ; index FORTRAN running [1,n]
83 M in memory: [ 11 12 13 : 21 22 23 : 31 32 33 : ... ]
84 line 1 : line 2 : line 3 : ...
85 ex: Midl(0,2) = Mfor(1,3) = Mmath(3,1) = 31
86 Midl(2,0) = Mfor(3,1) = Mmath(1,3) = 13
87 *** C: indexes data in \b column-major format:
88 indexes arrays in [row][column] order.
89 index C running [0,n[
90 M in memory: [ 11 21 31 : 12 22 32 : 13 23 33 : ... ]
91 column 1 : column 2 : column 3 : ...
92 ex: Mc[2][0] = Mmath(3,1) = 31
93 Mc[0][2] = Mmath(1,3) = 13
94 *** RESUME diff Idl/Fortan/C/Math:
95 Midl(col-1,row-1) = Mfor(col,row) = Mc[row-1][col-1] = Mmath(row,col)
96 TRANSPOSE(column-major array) --> row-major array
97 \endverbatim
98 \return default memory mapping value
99 */
100short BaseArray::SetDefaultMemoryMapping(short mm)
101{
102 default_memory_mapping = (mm != CMemoryMapping) ? FortranMemoryMapping : CMemoryMapping;
103 return default_memory_mapping;
104}
105
106//! Set Default Vector Type
107/*!
108 \param vt : vector type (ColumnVector,RowVector)
109 \return default vector type value
110 */
111short BaseArray::SetDefaultVectorType(short vt)
112{
113 default_vector_type = (vt != ColumnVector) ? RowVector : ColumnVector ;
114 return default_vector_type;
115}
116
117//! Select Memory Mapping
118/*!
119 Do essentially nothing.
120 \param mm : type of Memory Mapping (CMemoryMapping,FortranMemoryMapping)
121 \return return \b mm if it makes sense or default memory mapping value
122 \sa SetDefaultMemoryMapping
123 */
124short BaseArray::SelectMemoryMapping(short mm)
125{
126 if ( (mm == CMemoryMapping) || (mm == FortranMemoryMapping) ) return (mm) ;
127 else return (default_memory_mapping);
128}
129
130//! Select Vector type
131/*!
132 Do essentially nothing.
133 \param vt : vector type (ColumnVector,RowVector)
134 \return return \b vt if it makes sense or default vector type
135 \sa SetDefaultVectorType
136 */
137short BaseArray::SelectVectorType(short vt)
138{
139 if ((vt == ColumnVector) || (vt == RowVector)) return(vt);
140 else return(default_vector_type);
141}
142
143//! Update Memory Mapping
144/*!
145 Update variables marowi_ macoli_ veceli_
146 \param mm : type of Memory Mapping (CMemoryMapping,FortranMemoryMapping)
147 \sa SetDefaultMemoryMapping
148 */
149void BaseArray::UpdateMemoryMapping(short mm)
150{
151 short vt = default_vector_type;
152 if ( (mm != CMemoryMapping) && (mm != FortranMemoryMapping) ) mm = default_memory_mapping;
153 if (mm == CMemoryMapping) {
154 marowi_ = 1; macoli_ = 0;
155 }
156 else {
157 marowi_ = 0; macoli_ = 1;
158 }
159
160 if ( (ndim_ == 2) && ((size_[0] == 1) || (size_[1] == 1)) ) {
161 // Choix automatique Vecteur ligne ou colonne
162 if ( size_[macoli_] == 1) veceli_ = marowi_;
163 else veceli_ = macoli_;
164 }
165 else veceli_ = (vt == ColumnVector ) ? marowi_ : macoli_;
166 ck_memo_vt_ = true; // Check MemMapping and VectorType for CompareSize
167}
168
169//! Update Memory Mapping
170/*!
171 \param a : Array to be compared with
172 \param mm : type of Memory Mapping or memory mapping transfert
173 (SameMemoryMapping,AutoMemoryMapping,CMemoryMapping,FortranMemoryMapping)
174 \sa SetDefaultMemoryMapping
175 */
176void BaseArray::UpdateMemoryMapping(BaseArray const & a, short mm)
177{
178 short vt = default_vector_type;
179 if (mm == SameMemoryMapping) {
180 mm = ((a.marowi_ == 1) ? CMemoryMapping : FortranMemoryMapping);
181 vt = (a.marowi_ == a.veceli_) ? ColumnVector : RowVector;
182 }
183 else if (mm == AutoMemoryMapping) mm = default_memory_mapping;
184
185 if ( (mm != CMemoryMapping) && (mm != FortranMemoryMapping) ) mm = default_memory_mapping;
186 if (mm == CMemoryMapping) {
187 marowi_ = 1; macoli_ = 0;
188 }
189 else {
190 marowi_ = 0; macoli_ = 1;
191 }
192 if ( (ndim_ == 2) && ((size_[0] == 1) || (size_[1] == 1)) ) {
193 // Choix automatique Vecteur ligne ou colonne
194 if ( size_[macoli_] == 1) veceli_ = marowi_;
195 else veceli_ = marowi_;
196 }
197 else veceli_ = (vt == ColumnVector ) ? marowi_ : macoli_;
198 ck_memo_vt_ = true; // Check MemMapping and VectorType for CompareSize
199}
200
201//! Set Memory Mapping type
202/*!
203 Compute values for variables marowi_ macoli_ veceli_
204 \param mm : Memory Mapping type (SameMemoryMapping,AutoMemoryMapping
205 ,CMemoryMapping,FortranMemoryMapping)
206 \sa SetDefaultMemoryMapping
207 */
208void BaseArray::SetMemoryMapping(short mm)
209{
210 if (mm == SameMemoryMapping) return;
211 if (mm == AutoMemoryMapping) mm = default_memory_mapping;
212 if ( (mm != CMemoryMapping) && (mm != FortranMemoryMapping) ) return;
213 short vt = (marowi_ == veceli_) ? ColumnVector : RowVector;
214 if (mm == CMemoryMapping) {
215 marowi_ = 1; macoli_ = 0;
216 }
217 else {
218 marowi_ = 0; macoli_ = 1;
219 }
220 if ( (ndim_ == 2) && ((size_[0] == 1) || (size_[1] == 1)) ) {
221 // Choix automatique Vecteur ligne ou colonne
222 if ( size_[macoli_] == 1) veceli_ = marowi_;
223 else veceli_ = macoli_;
224 }
225 else veceli_ = (vt == ColumnVector ) ? marowi_ : macoli_;
226 ck_memo_vt_ = true; // Check MemMapping and VectorType for CompareSize
227}
228
229//! Set Vector Type
230/*!
231 Compute values for variable veceli_
232 \param vt : vector type ()
233 \sa SetDefaultVectorType
234 */
235void BaseArray::SetVectorType(short vt)
236{
237 if (vt == SameVectorType) return;
238 if (vt == AutoVectorType) vt = default_vector_type;
239 if ( (ndim_ == 2) && ((size_[0] == 1) || (size_[1] == 1)) ) {
240 // Choix automatique Vecteur ligne ou colonne
241 if ( size_[macoli_] == 1) veceli_ = marowi_;
242 else veceli_ = macoli_;
243 }
244 else veceli_ = (vt == ColumnVector ) ? marowi_ : macoli_;
245 ck_memo_vt_ = true; // Check MemMapping and VectorType for CompareSize
246}
247
248// -------------------------------------------------------
249// Methodes de la classe
250// -------------------------------------------------------
251
252//! Default constructor
253BaseArray::BaseArray()
254 : mInfo(NULL)
255{
256 ndim_ = 0;
257 for(int k=0; k<BASEARRAY_MAXNDIMS; k++) step_[k] = size_[k] = 0;
258 totsize_ = 0;
259 minstep_ = 0;
260 moystep_ = 0;
261 offset_ = 0;
262 // Default for matrices : Memory organisation and Vector type
263 if (default_memory_mapping == CMemoryMapping) {
264 marowi_ = 1; macoli_ = 0;
265 }
266 else {
267 marowi_ = 0; macoli_ = 1;
268 }
269 veceli_ = (default_vector_type == ColumnVector ) ? marowi_ : macoli_;
270 ck_memo_vt_ = false; // Default : Don't Check MemMapping and VectorType for CompareSize
271}
272
273//! Destructor
274BaseArray::~BaseArray()
275{
276}
277
278
279//! Returns true if dimension and sizes are equal
280/*!
281 \param a : array to be compared
282 \return true if ndim and sizes[ndim] are equal, false if not
283*/
284bool BaseArray::CompareSizes(const BaseArray& a)
285{
286 if (ndim_ != a.ndim_) return(false);
287 for(int k=0; k<ndim_; k++)
288 if (size_[k] != a.size_[k]) return(false);
289 // $CHECK$ Reza doit-on verifier ca
290 if (ck_memo_vt_ && a.ck_memo_vt_)
291 if ( (macoli_ != a.macoli_) || (marowi_ != a.marowi_) ||
292 (veceli_ != a.veceli_) ) return(false);
293 return(true);
294}
295
296//! Change dimension if some size == 1
297void BaseArray::CompactAllDim()
298{
299 if (ndim_ < 2) return;
300 uint_4 ndim = 0;
301 uint_4 size[BASEARRAY_MAXNDIMS];
302 uint_4 step[BASEARRAY_MAXNDIMS];
303 for(int k=0; k<ndim_; k++) {
304 if (size_[k] < 2) continue;
305 size[ndim] = size_[k];
306 step[ndim] = step_[k];
307 ndim++;
308 }
309 if (ndim == 0) {
310 size[0] = size_[0];
311 step[0] = step_[0];
312 ndim = 1;
313 }
314 string exmsg = "BaseArray::CompactAllDim() ";
315 if (!UpdateSizes(ndim, size, step, offset_, exmsg)) throw( ParmError(exmsg) );
316 return;
317}
318
319//! Change dimension if some trailed size == 1
320void BaseArray::CompactTrailingDim()
321{
322 if (ndim_ < 2) return;
323 uint_4 ndim = 0;
324 uint_4 size[BASEARRAY_MAXNDIMS];
325 uint_4 step[BASEARRAY_MAXNDIMS];
326 for(int k=0; k<ndim_; k++) {
327 size[ndim] = size_[k];
328 step[ndim] = step_[k];
329 if (size_[k] > 1) ndim=k;
330 }
331 if (ndim == 0) ndim = 1;
332 string exmsg = "BaseArray::CompactTrailingDim() ";
333 if (!UpdateSizes(ndim, size, step, offset_, exmsg)) throw( ParmError(exmsg) );
334 return;
335}
336
337//! return minimum value for step[ndim]
338uint_4 BaseArray::MinStepKA() const
339{
340 for(int ka=0; ka<ndim_; ka++)
341 if (step_[ka] == minstep_) return(ka);
342 return(0);
343}
344
345//! return maximum value for step[ndim]
346uint_4 BaseArray::MaxSizeKA() const
347{
348 uint_4 ka = 0;
349 uint_4 mx = size_[0];
350 for(int k=0; k<ndim_; k++)
351 if (size_[k] > mx) { ka = k; mx = size_[k]; }
352 return(ka);
353}
354
355
356// Acces lineaire aux elements .... Calcul d'offset
357// --------------------------------------------------
358// Position de l'element 0 du vecteur i selon l'axe ka
359// --------------------------------------------------
360//! return position of first element for vector \b i alond \b ka th axe.
361uint_8 BaseArray::Offset(uint_4 ka, uint_8 i) const
362{
363
364 if ( (ndim_ < 1) || (i == 0) ) return(offset_);
365 //#ifdef SO_BOUNDCHECKING
366 if (ka >= ndim_)
367 throw RangeCheckError("BaseArray::Offset(uint_4 ka, uint_8 i) Axe KA Error");
368 if ( i*size_[ka] >= totsize_ )
369 throw RangeCheckError("BaseArray::Offset(uint_4 ka, uint_8 i) Index Error");
370 //#endif
371 uint_4 idx[BASEARRAY_MAXNDIMS];
372 int k;
373 uint_8 rest = i;
374 idx[ka] = 0;
375 for(k=0; k<ndim_; k++) {
376 if (k == ka) continue;
377 idx[k] = rest%size_[k]; rest /= size_[k];
378 }
379 uint_8 off = offset_;
380 for(k=0; k<ndim_; k++) off += idx[k]*step_[k];
381 return (off);
382}
383
384//! return position of element \b ip.
385uint_8 BaseArray::Offset(uint_8 ip) const
386{
387 if ( (ndim_ < 1) || (ip == 0) ) return(offset_);
388 //#ifdef SO_BOUNDCHECKING
389 if (ip >= totsize_)
390 throw RangeCheckError("BaseArray::Offset(uint_8 ip) Out of range index ip");
391 //#endif
392
393 uint_4 idx[BASEARRAY_MAXNDIMS];
394 int k;
395 uint_8 rest = ip;
396 for(k=0; k<ndim_; k++) {
397 idx[k] = rest%size_[k]; rest /= size_[k];
398 }
399 //#ifdef SO_BOUNDCHECKING
400 if (rest != 0)
401 throw PError("BaseArray::Offset(uint_8 ip) GUG !!! rest != 0");
402 //#endif
403// if (rest != 0) cerr << " BUG ---- BaseArray::Offset( " << ip << " )" << rest << endl;
404// cerr << " DBG-Offset( " << ip << ")" ;
405// for(k=0; k<ndim_; k++) cerr << idx[k] << "," ;
406// cerr << " ZZZZ " << endl;
407 uint_8 off = offset_;
408 for(k=0; k<ndim_; k++) off += idx[k]*step_[k];
409 return (off);
410}
411
412
413// ----------------------------------------------------
414// Impression, etc ...
415// ----------------------------------------------------
416
417//! Show infos on stream \b os (\b si to display DvList)
418void BaseArray::Show(ostream& os, bool si) const
419{
420 if (ndim_ < 1) {
421 os << "\n--- " << BaseArray::InfoString() << " Unallocated Array ! " << endl;
422 return;
423 }
424 os << "\n--- " << InfoString() ;
425 os << " ND=" << ndim_ << " SizeX*Y*...= " ;
426 for(int k=0; k<ndim_; k++) {
427 os << size_[k];
428 if (k<ndim_-1) os << "x";
429 }
430 os << " ---" << endl;
431 if (prt_lev_ > 0) {
432 os << " TotSize= " << totsize_ << " Step(X Y ...)=" ;
433 for(int k=0; k<ndim_; k++) os << step_[k] << " " ;
434 os << " Offset= " << offset_ << endl;
435 }
436 if (prt_lev_ > 1) {
437 os << " MemoryMapping=" << GetMemoryMapping() << " VecType= " << GetVectorType()
438 << " RowsKA= " << RowsKA() << " ColsKA= " << ColsKA()
439 << " VectKA=" << VectKA() << endl;
440 }
441 if (!si && (prt_lev_ < 2)) return;
442 if (mInfo != NULL) os << (*mInfo) << endl;
443
444}
445
446//! Return BaseArray Type
447string BaseArray::InfoString() const
448{
449 string rs = "BaseArray Type= ";
450 rs += typeid(*this).name() ;
451 return rs;
452}
453
454//! Return attached DVList
455DVList& BaseArray::Info()
456{
457if (mInfo == NULL) mInfo = new DVList;
458return(*mInfo);
459}
460
461//! Update sizes and information for array
462/*!
463 \param ndim : dimension
464 \param siz[ndim] : sizes
465 \param step : step (must be the same on all dimensions)
466 \param offset : offset of the first element
467 \return true if all OK, false if problems appear
468 \return string \b exmsg for explanation in case of problems
469 */
470bool BaseArray::UpdateSizes(uint_4 ndim, const uint_4 * siz, uint_4 step, uint_8 offset, string & exmsg)
471{
472 if (ndim >= BASEARRAY_MAXNDIMS) {
473 exmsg += " NDim Error"; return false;
474 }
475 if (step < 1) {
476 exmsg += " Step(=0) Error"; return false;
477 }
478
479 minstep_ = moystep_ = step;
480
481 // Flagging bad updates ...
482 ndim_ = 0;
483
484 totsize_ = 1;
485 int k;
486 for(k=0; k<BASEARRAY_MAXNDIMS; k++) {
487 size_[k] = 1;
488 step_[k] = 0;
489 }
490 for(k=0; k<ndim; k++) {
491 size_[k] = siz[k] ;
492 step_[k] = totsize_*step;
493 totsize_ *= size_[k];
494 }
495 if (totsize_ < 1) {
496 exmsg += " Size Error"; return false;
497 }
498 offset_ = offset;
499 // Default for matrices : Memory organisation and Vector type
500 if (default_memory_mapping == CMemoryMapping) {
501 marowi_ = 1; macoli_ = 0;
502 }
503 else {
504 marowi_ = 0; macoli_ = 1;
505 }
506 veceli_ = (default_vector_type == ColumnVector ) ? marowi_ : macoli_;
507 ck_memo_vt_ = false; // Default : Don't Check MemMapping and VectorType for CompareSize
508 // Update OK
509 ndim_ = ndim;
510 return true;
511}
512
513//! Update sizes and information for array
514/*!
515 \param ndim : dimension
516 \param siz[ndim] : sizes
517 \param step[ndim] : steps
518 \param offset : offset of the first element
519 \return true if all OK, false if problems appear
520 \return string \b exmsg for explanation in case of problems
521 */
522bool BaseArray::UpdateSizes(uint_4 ndim, const uint_4 * siz, const uint_4 * step, uint_8 offset, string & exmsg)
523{
524 if (ndim >= BASEARRAY_MAXNDIMS) {
525 exmsg += " NDim Error"; return false;
526 }
527
528 // Flagging bad updates ...
529 ndim_ = 0;
530
531 totsize_ = 1;
532 int k;
533 for(k=0; k<BASEARRAY_MAXNDIMS; k++) {
534 size_[k] = 1;
535 step_[k] = 0;
536 }
537 uint_4 minstep = step[0];
538 for(k=0; k<ndim; k++) {
539 size_[k] = siz[k] ;
540 step_[k] = step[k];
541 totsize_ *= size_[k];
542 if (step_[k] < minstep) minstep = step_[k];
543 }
544 if (minstep < 1) {
545 exmsg += " Step(=0) Error"; return false;
546 }
547 if (totsize_ < 1) {
548 exmsg += " Size Error"; return false;
549 }
550 uint_8 plast = 0;
551 for(k=0; k<ndim; k++) plast += (siz[k]-1)*step[k];
552 if (plast == minstep*totsize_ ) moystep_ = minstep;
553 else moystep_ = 0;
554 minstep_ = minstep;
555 offset_ = offset;
556 // Default for matrices : Memory organisation and Vector type
557 if (default_memory_mapping == CMemoryMapping) {
558 marowi_ = 1; macoli_ = 0;
559 }
560 else {
561 marowi_ = 0; macoli_ = 1;
562 }
563 veceli_ = (default_vector_type == ColumnVector ) ? marowi_ : macoli_;
564 ck_memo_vt_ = false; // Default : Don't Check MemMapping and VectorType for CompareSize
565 // Update OK
566 ndim_ = ndim;
567 return true;
568}
569
570//! Update sizes and information relative to array \b a
571/*!
572 \param a : array to be compare with
573 \return true if all OK, false if problems appear
574 \return string \b exmsg for explanation in case of problems
575 */
576bool BaseArray::UpdateSizes(const BaseArray& a, string & exmsg)
577{
578 if (a.ndim_ >= BASEARRAY_MAXNDIMS) {
579 exmsg += " NDim Error"; return false;
580 }
581
582 // Flagging bad updates ...
583 ndim_ = 0;
584
585 totsize_ = 1;
586 int k;
587 for(k=0; k<BASEARRAY_MAXNDIMS; k++) {
588 size_[k] = 1;
589 step_[k] = 0;
590 }
591 uint_4 minstep = a.step_[0];
592 for(k=0; k<a.ndim_; k++) {
593 size_[k] = a.size_[k] ;
594 step_[k] = a.step_[k];
595 totsize_ *= size_[k];
596 if (step_[k] < minstep) minstep = step_[k];
597 }
598 if (minstep < 1) {
599 exmsg += " Step(=0) Error"; return false;
600 }
601 if (totsize_ < 1) {
602 exmsg += " Size Error"; return false;
603 }
604
605 minstep_ = a.minstep_;
606 moystep_ = a.moystep_;
607 offset_ = a.offset_;
608 macoli_ = a.macoli_;
609 marowi_ = a.marowi_;
610 veceli_ = a.veceli_;
611 ck_memo_vt_ = a.ck_memo_vt_;
612 // Update OK
613 ndim_ = a.ndim_;
614 return true;
615}
616
617
618//! Update sizes and information relative to array \b a
619/*!
620 \param a : array to be compare with
621 \param ndim : could be change (but should be less than the ndim of the current class)
622 \param siz[ndim],pos[ndim],step[ndim] : could be changed but must be
623 compatible within the memory size with those of the current class.
624 \return true if all OK, false if problems appear
625 \return string \b exmsg for explanation in case of problems
626 */
627void BaseArray::UpdateSubArraySizes(BaseArray & ra, uint_4 ndim, uint_4 * siz, uint_4 * pos, uint_4 * step) const
628{
629 if ( (ndim > ndim_) || (ndim < 1) )
630 throw(SzMismatchError("BaseArray::UpdateSubArraySizes( ... ) NDim Error") );
631 int k;
632 for(k=0; k<ndim; k++)
633 if ( (siz[k]*step[k]+pos[k]) > size_[k] )
634 throw(SzMismatchError("BaseArray::UpdateSubArraySizes( ... ) Size/Pos Error") );
635 uint_8 offset = offset_;
636 for(k=0; k<ndim_; k++) {
637 offset += pos[k]*step_[k];
638 step[k] *= step_[k];
639 }
640 string exm = "BaseArray::UpdateSubArraySizes() ";
641 if (!ra.UpdateSizes(ndim, siz, step, offset, exm))
642 throw( ParmError(exm) );
643 return;
644}
645
646
Note: See TracBrowser for help on using the repository browser.