STK++ 0.9.13
STK_IArray2DModifiers.h
Go to the documentation of this file.
1/*--------------------------------------------------------------------*/
2/* Copyright (C) 2004-2016 Serge Iovleff, Université Lille 1, Inria
3
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU Lesser General Public License as
6 published by the Free Software Foundation; either version 2 of the
7 License, or (at your option) any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU Lesser General Public License for more details.
13
14 You should have received a copy of the GNU Lesser General Public
15 License along with this program; if not, write to the
16 Free Software Foundation, Inc.,
17 59 Temple Place,
18 Suite 330,
19 Boston, MA 02111-1307
20 USA
21
22 Contact : S..._Dot_I..._At_stkpp_Dot_org (see copyright for ...)
23*/
24
25/*
26 * Project: stkpp::Arrays
27 * Purpose: Define the Interface for the Array classes.
28 * Author: Serge Iovleff, S..._Dot_I..._At_stkpp_Dot_org (see copyright for ...)
29 *
30 **/
31
36#ifndef STK_IARRAY2DMODIFIERS_H
37#define STK_IARRAY2DMODIFIERS_H
38
39namespace STK
40{
41
42/*@brief function for reserving memory in all the columns
43 * @param sizeRows,sizeCols the size to reserve for the rows and columns
44 **/
45template < class Derived >
46void IArray2D< Derived>::reserve(int sizeRows, int sizeCols)
47{
48 reserveCols(sizeCols);
49 reserveRows(sizeRows);
50}
51/*@brief function for reserving memory in all the columns
52 * @param size the size to reserve
53 **/
54template < class Derived >
56{ reserveRowsCols(cols(), size);}
57/*Reserve a certain amount of columns
58 * @param sizeCols the size to reserve.
59 **/
60template< class Derived>
62{
63 if (availableCols() >= sizeCols) return;
64 // is this structure just a pointer?
65 if (isRef())
67 // try to allocate memory
68 try
69 {
70 Range J(this->beginCols(), sizeCols);
71 allocator_.realloc(J);
72 rangeCols_.reserve(J.size());
73 }
74 catch (Exception const& error) // if an error occur
75 {
77 }
78}
79
80/*@brief Internal method for reserving memory in a range of columns.
81 * @param J range of the columns to initialize
82 * @param size the size to reserve
83 **/
84template < class Derived >
86{
87 for (int j=J.begin(); j<J.end(); j++)
88 { reserveRowCol(j, size);}
89}
90/*@brief Internal method for reserving rows to a specified column.
91 * reserve @c size memory place to the column @c col of the array
92 * @param col,size index of the column and size to reserve
93 **/
94template < class Derived >
95void IArray2D< Derived>::reserveRowCol( int col, int size)
96{
97 if (this->capacityCol(col) >= size) return;
98 allocator_.elt(col)->reserve(size);
99}
100
101
102// shift
103/*@brief Set new beginning indexes to the array.
104 * @param rbeg, cbeg the indexes of the first row and first column to set
105 **/
106template < class Derived >
108{
109 shiftCols(cbeg);
110 shiftRows(rbeg);
111}
112/*New first index for the object.
113 * @param beg the index of the first element to set
114 **/
115template < class Derived >
117{ this->asDerived().shift1D(beg);}
118/*New first index for the rows of the array.
119 * @param beg the index of the first row to set
120 **/
121template < class Derived >
123{
124 // compute increment
125 int inc = beg - beginRows();
126 if (inc == 0) return;
127 // is this structure just a pointer?
129
130 // translate rows
131 Base2D::shiftRows(beg);
132 // if there is rows, for all cols shift
133 for (int j=beginCols(); j<endCols(); j++)
134 { shiftRowCol(j, rangeCols_[j].begin()+inc);}
135}
136/*New beginning index for the columns of the object.
137 * @param cbeg the index of the first column to set
138 **/
139template < class Derived >
141{
142 // if there is something to do
143 if (cbeg == this->beginCols()) return;
144 // is this structure just a pointer?
145 if (isRef())
147 // shift beginCols()
148 allocator_.shift(cbeg); // translate data
149 rangeCols_.shift(cbeg); // translate rangeCols_
150 Base2D::shiftCols(cbeg); // adjust dimensions
151}
152/*@brief internal method for translating a column.
153 *
154 * Method for the the allocation of memory of the column
155 * pos with the given range.
156 * @param col,beg index of the column and new begin of the column
157 **/
158template < class Derived >
160{
161 if (allocator_.elt(col)) { allocator_.elt(col)->shift(beg);}
162 rangeCols_[col].shift(beg);
163}
164/*resize the array.
165 * @note The implicit assumption made by this method is that it is easiest
166 * and faster to add column than add rows to the 2D array.
167 *
168 * @param I the new range for the rows of the array
169 * @param J the new range for the columns of the array
170 **/
171template < class Derived >
172Derived& IArray2D< Derived>::resize( Range const& I, Range const& J)
173{
174 // check if there is something to do
175 if ((this->rows() == I) && (this->cols() == J)) return this->asDerived();
176 if (isRef())
178 // translate and check again if there is something to do
179 shift(I.begin(), J.begin());
180 if ((this->rows() == I) && (this->cols() == J)) return this->asDerived();
181 // just clear empty container
182 if (I.size()<=0 || J.size() <= 0)
183 { clear(); return this->asDerived();}
184
185 // number of rows and columns to delete or add
186 int rinc = I.end() - endRows();
187 int cinc = J.end() - endCols();
188
189 // work first on rows as we add columns
190 if ((cinc >=0))
191 {
192 if (rinc < 0) { popBackRows(-rinc);} // less rows
193 else { pushBackRows(rinc);} // more rows
194 pushBackCols(cinc); // add columns
195 }
196 else // work first on columns as we remove column
197 {
198 popBackCols(-cinc); // remove columns
199 if (rinc < 0) { popBackRows(-rinc);} // less rows
200 else { pushBackRows(rinc);} // more rows
201 }
202 return this->asDerived();
203}
204/*@return the resized row/column/square array
205 * @param I the new range for the vector/point
206 **/
207template < class Derived >
209{ return this->asDerived().resize1D(I);}
210
211// rows
212/*Insert n rows in front of the array.
213 * @param n number of elements to insert (default is 1)
214 **/
215template < class Derived >
217{
218 if (n <= 0) return;
219 if (isRef())
221
222 insertRows(beginRows(), n);
223}
224/*Add n rows to the array.
225 * @param n number of rows to add (default is 1)
226 **/
227template < class Derived >
229{
230 if (n <= 0) return;
231 if (isRef())
233
234 insertRows(endRows(), n);
235}
236/*Delete n first rows of the array.
237 * @param n number of rows to delete (default is 1)
238 **/
239template < class Derived >
241{
242 if (n <= 0) return;
243 if (isRef())
245#ifdef STK_BOUNDS_CHECK
246 if (sizeRows() < n)
247 { STKOUT_OF_RANGE_1ARG(IArray2D::popFrontRows,n,sizeRows() < n);}
248#endif
249 eraseRows(endRows()-n, n);
250}
251/*Delete n latest rows of the array.
252 * @param n number of rows to delete (default is 1)
253 **/
254template < class Derived >
256{
257 if (n <= 0) return;
258 if (isRef())
260#ifdef STK_BOUNDS_CHECK
261 if (sizeRows() < n)
262 { STKOUT_OF_RANGE_1ARG(IArray2D::popBackRows,n,sizeRows() < n);}
263#endif
264 eraseRows(endRows()-n, n);
265}
266/*set other at the beginning of this (concatenate). Perform a copy of the
267 * values stored in other to this.
268 * @param other the array to add
269 * @note the size and the type have to match
270 **/
271template < class Derived >
272template<class Other>
274{
275 // check if the array is empty
276 if (empty())
277 {
278 this->asDerived() = other.asDerived();
279 return this->asDerived();
280 }
281 // not empty
282 if (other.cols() != this->cols())
284 // add nbRow to existing rows
285 int nbRow = other.sizeRows();
286 pushFrontRows(nbRow);
287 for (int j=beginCols(); j< endCols(); ++j)
288 {
289 for (int i=beginRows(), iOther= other.beginRows(); iOther<other.endRows(); ++i, ++iOther)
290 { setValue(i,j, other.elt(iOther,j));}
291 }
292 // return this
293 return this->asDerived();
294}
295/*set other at the end of this (concatenate). Perform a copy of the
296 * values stored in other to this.
297 * @param other the array to add back
298 * @note the size and the type have to match
299 **/
300template < class Derived >
301template<class Other>
303{
304 // check if the array is empty
305 if (empty())
306 {
307 this->asDerived() = other.asDerived();
308 return this->asDerived();
309 }
310 // not empty
311 if (other.cols() != this->cols())
313 // add nbRow to existing rows
314 int nbRow = other.sizeRows();
315 pushBackRows(nbRow);
316 for (int j=beginCols(); j< endCols(); ++j)
317 {
318 // start from the end in order to avoid
319 for (int i=this->lastIdxRows(), iOther= other.lastIdxRows(); iOther>=other.beginRows(); --i, --iOther)
320 { elt(i,j) = other.elt(iOther,j);}
321 }
322 // return this
323 return this->asDerived();
324}
325
326// columns
327/*Insert n columns at the beginning of the array.
328 * @param n the number of column to insert (default is 1)
329 **/
330template < class Derived >
332{
333 if (n <= 0) return;
334 if (isRef())
336
337 insertCols(beginCols(), n );
338}
339/*Add n columns at the end of the array.
340 * @param n the number of Columns to add (default is 1)
341 **/
342template < class Derived >
344{
345 if (n <= 0) return;
346 if (isRef())
348
349 insertCols(endCols(), n );
350}
351/*Delete first columns of the array
352 * @param n the number of Columns to delete (default is 1)
353 **/
354template < class Derived >
356{
357 if (n<=0) return;
358 if (isRef())
360#ifdef STK_BOUNDS_CHECK
361 if (sizeCols() < n)
363#endif
364
365 eraseCols(beginCols(), n);
366}
367/*Delete last columns of the array
368 * @param n the number of Columns to delete (default is 1)
369 **/
370template < class Derived >
372{
373 if (n<=0) return;
374 if (isRef())
376#ifdef STK_BOUNDS_CHECK
377 if (sizeCols() < n)
379#endif
380
381 eraseCols(endCols()-n, n);
382}
383/*merge (by value) the array other with this.
384 * @param other the array to merge to this
385 **/
386template < class Derived >
387template<class Other>
389{
390 // if the array is empty use operator=
391 if (empty())
392 {
393 this->asDerived() = other.asDerived();
394 return this->asDerived();
396 // this is not empty
397 if (other.rows() != this->rows())
399 // if the array is not empty we add the column and copy other inside
400 this->asDerived().insertCols(beginCols(), other.sizeCols());
401 for (int j= beginCols(), j1= other.beginCols(); j < endCols(); ++j, ++j1)
402 {
403 *allocator_.elt(j) = other.col(j1);
405 // return this
406 return this->asDerived();
407}
408/*Specialization for Array1D. merge (by value) the array other with this
409 * @param other the column to add to this
410 **/
411template < class Derived >
412template<class Other>
414{
415 // check if the array is empty
416 if (empty())
418 resize(other.rows(),1);
419 for (int i=other.begin(); i<other.end(); i++)
420 (*this)(i, lastIdxCols()) = other[i];
421 return this->asDerived();
423 // not empty
424 if (other.rows() != this->rows())
426 int last = endCols();
427 pushBackCols();
428 for (int i=other.begin(); i<other.end(); i++)
429 (*this)(i, last) = other[i];
430 // return this
431 return this->asDerived();
432}
433
434 // columns
435 /*Insert n columns at the index pos to the array.
436 * @param pos position to insert columns
437 * @param n the number of column to insert (default is 1)
438 **/
439template < class Derived >
441 {
442 if (n <= 0) return;
443
444 if (isRef())
446#ifdef STK_BOUNDS_CHECK
447 if (beginCols() > pos)
448 { STKOUT_OF_RANGE_2ARG(IArray2D::insertCols,pos,n,beginCols() > pos);}
449 if (endCols() < pos)
450 { STKOUT_OF_RANGE_2ARG(IArray2D::insertCols,pos,n,endCols() < pos);}
451#endif
452 // compute column range of the array after insertion
453 Range OldRange(cols()), NewRange(cols());
454 NewRange.incLast(n);
455 reallocCols(NewRange);
456 // translate and copy last Columns from Taux to this
457 for (int k=OldRange.lastIdx(); k>=pos; k--)
458 { transferCol(k+n, k);}
459 // initialize the rows in the range pos:pos+n-1
460 nullCols( Range(pos, n) );
461 initializeCols( Range(pos, n) );
462 }
463 /*Delete n columns at the specified position of the array.
464 * @param pos the position of the deleted Columns
465 * @param n the number of column to delete (default is 1)
466 **/
467template < class Derived >
468 void IArray2D< Derived>::eraseCols(int pos, int n)
469 {
470 if (n<=0) return;
471 if (isRef())
473#ifdef STK_BOUNDS_CHECK
474 if (beginCols() > pos)
475 { STKOUT_OF_RANGE_2ARG(IArray2D::eraseCols,pos,n,beginCols() > pos);}
476 if (endCols() <= pos)
477 { STKOUT_OF_RANGE_2ARG(IArray2D::eraseCols,pos,n,endCols() <= pos);}
478 if (endCols() < pos+n)
479 { STKOUT_OF_RANGE_2ARG(IArray2D::eraseCols,pos,n,endCols() < pos+n);}
480#endif
481 // delete each col
482 freeCols(Range(pos, n));
483 // update cols_, rangeCols_
484 this->decLastIdxCols(n);
485 rangeCols_.erase(pos, n);
486 allocator_.memmove(pos, Range(pos+n, endCols()-pos));
487 // liberate memory if there is no more columns (don't use clear(), as we want to preserve rows_)
488 if (sizeCols() == 0) { freeMem();}
490
491 // rows
492 /*Insert n rows at position pos in the array
493 * If pos is outside the range of a column, then the method do nothing
494 * (useful for triangular/diagonal/... arrays).
495 * @param pos index where to insert rows
496 * @param n number of elements to insert (default is 1)
497 **/
498template < class Derived >
500 {
501 if (n <= 0) return;
502 if (isRef())
504#ifdef STK_BOUNDS_CHECK
505 if (beginRows() > pos)
506 { STKOUT_OF_RANGE_2ARG(IArray2D::insertRows,pos,n,beginRows() > pos);}
507 if (endRows() < pos)
509#endif
510
511 this->incLastIdxRows(n);
512 for (int j=beginCols(); j<endCols(); j++)
513 {
514 if (!allocator_.elt(j))
515 { initializeCol(j, this->rangeRowsInCol(j));}
516 else
517 {
518 if ( (pos >= rangeCols_[j].begin()) && (pos <= rangeCols_[j].end()))
519 { insertRowsCol(j, pos, n);}
520 }
521 }
522 }
523 /*Delete n rows at the position pos
524 * @param pos index where to delete elements
525 * @param n number of rows to delete (default is 1)
526 **/
527template < class Derived >
528 void IArray2D< Derived>::eraseRows(int pos, int n)
529 {
530 if (n<=0) return;
531 // is this structure just a pointer?
532 if (isRef())
534#ifdef STK_BOUNDS_CHECK
535 if (beginRows() > pos)
536 { STKOUT_OF_RANGE_2ARG(IArray2D::eraseRows,pos,n,beginRows() > pos);}
537 if (endRows() <= pos)
538 { STKOUT_OF_RANGE_2ARG(IArray2D::eraseRows,pos,n,endRows() <= pos);}
539 if (endRows() < pos+n)
540 { STKOUT_OF_RANGE_2ARG(IArray2D::eraseRows,pos,n,endRows() < pos+n);}
541#endif
542
543 for (int j=beginCols(); j<endCols(); j++) { eraseRowsCol(j, pos, n);}
544 this->decLastIdxRows(n);
545 }
546
547// STL compatibility: for one dimension containers
548/*STL compatibility: push front an element.
549 * @param v value to push front
550 **/
551template < class Derived >
553{ // push_front defined for vector, point and diagonal arrays
555 insert(Range(this->begin(), 1), v);
556}
557/*STL compatibility: append an element v.
558 * @param v value to append back
559 **/
560template < class Derived >
562{ // push_back defined for vector, point and diagonal arrays
564 this->asDerived().pushBack();
565 this->back() = v;
566}
567/*STL compatibility: insert element @c v in the range @c I of the Array.
568 * @param v,I value and range of indexes
569 **/
570template < class Derived >
572{ // insert defined for vector, point and diagonal arrays
574 this->asDerived().insertElt(I.begin(), I.size());
575 for (int i=I.begin(); i<I.end(); i++) { elt(i) = v;}
576}
577
578/* STL compatibility:Delete n elements at the @c pos index from the container.
579 * @param pos index where to delete elements
580 * @param n number of elements to delete (default 1)
581 **/
582template < class Derived >
583void IArray2D< Derived>::erase(int pos, int n)
584{
586 if (structure_ == Arrays::vector_) { eraseRows(pos, n); }
587 else { eraseCols(pos, n); }
588
589}
590
591
592/*@brief Internal method for resizing a column with a specified range.
593 *
594 * This method resize the column @c col to the desired range using:
595 * - @c shiftRowCol
596 * - either @c popBackRowsToCol or @c pushBackRowsToCol if needed.
597 * @param col index of the column
598 * @param I range to set to the column
599**/
600template < class Derived >
602{
603 if (rangeCols_[col] == I) return;
604 shiftRowCol(col, I.begin());
605 int inc = rangeCols_[col].size() - I.size();
606 if (inc == 0) return;
607 if (inc < 0)
608 {
609 allocator_.elt(col)->pushBack(-inc);
610 rangeCols_[col].incLast(-inc);
611 }
612 else
613 {
614 rangeCols_[col].decLast(inc);
615 if (rangeCols_[col].size()==0) freeCol(col);
616 }
617}
618/*@brief Internal method for inserting rows to a specified column.
619 *
620 * Insert n rows at the position pos to the column column of the
621 * array. No check is done about the index.
622 * @param col,pos,n column position, row position and number of rows to insert
623 **/
624template < class Derived >
625void IArray2D< Derived>::insertRowsCol( int col, int pos, int n)
626{
627 allocator_.elt(col)->insertElt(pos, n);
628 rangeCols_[col].incLast(n);
629}
630/*@brief Internal method for deleting rows from a specified column.
631 * Delete n rows at the position @c pos to the column @c col of the array.
632 *
633 * @note It is possible to remove data outside the range of the column (but not
634 * outside the range of the array). In this case it is assumed
635 * that the data are zero and are not stored by the array
636 * (like for triangular or diagonal matrices).
637 *
638 * @warning No check is done about indexes.
639 *
640 * @param col,pos,n index of the column, row position and number of elements to delete
641**/
642template < class Derived >
643void IArray2D< Derived>::eraseRowsCol( int col, int pos, int n)
644{
645 // check trivial cases
646 if (rangeCols_[col].lastIdx() < pos) return;
647 if (rangeCols_[col].begin()> pos+n-1)
648 { shiftRowCol( col, rangeCols_[col].begin() - n); return;}
649
650 // find the existing rows to delete
651 Range newRange(pos, n);
652 newRange.inf(rangeCols_[col]);
653 if (newRange == rangeCols_[col]) { freeCol(col); return;}
654
655 // copy remaining rows
656 allocator_.elt(col)->memmove(newRange.begin(), newRange.end(), rangeCols_[col].end() - newRange.end());
657 rangeCols_[col].decLast(newRange.size());
658
659 // shift if necessary [if pos<newRange.begin() there is a "padding" to take into account]
660 if (pos < newRange.begin())
661 { shiftRowCol( col, rangeCols_[col].begin() - (n-newRange.size()));}
662}
663
664
665} // namespace STK
666
667
668
669#endif
670// STK_IARRAY2DMODIFIERS_H
#define STKOUT_OF_RANGE_1ARG(Where, Arg, Error)
Definition STK_Macros.h:93
#define STKRUNTIME_ERROR_1ARG(Where, Arg, Error)
Definition STK_Macros.h:129
#define STKOUT_OF_RANGE_2ARG(Where, Arg1, Arg2, Error)
Definition STK_Macros.h:102
#define STKRUNTIME_ERROR_NO_ARG(Where, Error)
Definition STK_Macros.h:138
#define STKRUNTIME_ERROR_2ARG(Where, Arg1, Arg2, Error)
Definition STK_Macros.h:120
#define STK_STATIC_ASSERT_ONE_DIMENSION_ONLY(EXPR)
Sdk class for all library Exceptions.
void shiftRowCol(int col, int beg)
internal method for translating a column.
void reserveRowsCols(Range const &J, int size)
Internal method for reserving memory in a range of columns.
void insertRowsCol(int col, int pos, int n)
Internal method for inserting rows to a specified column.
void reserveRows(int size)
Reserve a certain amount of rows in all columns.
void erase(int pos, int n=1)
STL compatibility:Delete n elements at the pos index from the container.
void pushFrontCols(int n=1)
Insert n columns at the beginning of the array.
void insertCols(int pos, int n=1)
Insert n columns at the index pos to the array.
Derived & resize(Range const &I, Range const &J)
resize the array.
void pushBackCols(int n=1)
Add n columns at the end of the array.
void resizeRowCol(int col, Range const &I)
Internal method for resizing a column with a specified range.
void reserve(int sizeRows, int sizeCols)
function for reserving memory in all the columns
void popBackCols(int n=1)
Delete last columns of the array.
void insert(Range const &I, Type const &v)
STL compatibility: insert element v in the range I of the Array.
void popFrontCols(int n=1)
Delete first columns of the array.
void pushBackRows(int n=1)
Add n rows to the array.
void reserveRowCol(int col, int size)
Internal method for reserving rows to a specified column.
void push_back(Type const &v)
STL compatibility: append an element v.
void shiftCols(int cbeg)
New first index for the columns of the object.
void eraseRows(int pos, int n=1)
Delete n rows at the position pos.
void popBackRows(int n=1)
Delete n latest rows of the array.
void pushFrontRows(int n=1)
Insert n rows in front of the array.
void reserveCols(int sizeCols)
Reserve a certain amount of columns.
void shift(int rbeg, int cbeg)
Set new beginning indexes to the array.
void shiftRows(int beg)
New first index for the rows of the array.
void eraseRowsCol(int col, int pos, int n)
Internal method for deleting rows from a specified column.
void push_front(Type const &v)
STL compatibility: push front an element.
void popFrontRows(int n=1)
Delete n first rows of the array.
void insertRows(int pos, int n=1)
Insert n rows at position pos in the array If pos is outside the range of a column,...
hidden::Traits< Derived >::Type Type
void eraseCols(int pos, int n=1)
Delete n columns at the specified position of the array.
String const & error() const
get the last error message.
Definition STK_IRunner.h:82
The MultidimRegression class allows to regress a multidimensional output variable among a multivariat...
Index sub-vector region: Specialization when the size is unknown.
Definition STK_Range.h:265
@ vector_
column oriented vector/array/expression
The namespace STK is the main domain space of the Statistical ToolKit project.
TRange< UnknownSize > Range
Definition STK_Range.h:59