STK++ 0.9.13
STK_IArray1D.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 * Author: Serge Iovleff, S..._Dot_I..._At_stkpp_Dot_org (see copyright for ...)
28 **/
29
39#ifndef STK_IARRAY1D_H
40#define STK_IARRAY1D_H
41
42#include <STKernel.h>
43#include "STK_IContainerRef.h"
44#include "STK_ArraysTraits.h"
45#include "STK_Arrays_Util.h"
46#include "STK_ITContainer1D.h"
50
51namespace STK
52{
53
54namespace Arrays
55{
60inline int evalSizeCapacity(int m)
61{
62 int n = 0;
63 for (int k=1; k <= m; k <<= 1) {n++;}
64 return(m+n);
65}
66
71template<int Size_>
77template<>
79{
80 int n = 0;
81 for (int k=1; k <= I.size(); k <<= 1){ n++;}
82 return Range(I.begin(),I.size() + n);
83}
84
85} // namespace Arrays
86
93template<class Derived>
94class IArray1D: public ITContainer1D<Derived>
95{
96 public:
97
100
101 enum
102 {
110 };
111
114
117
122
123 using Base::range;
124 using Base::begin;
125 using Base::end;
126 using Base::size;
127 using Base::lastIdx;
128
129 using Base::decLast;
130 using Base::incLast;
131 using Base::incRange;
132 using Base::setRange;
133
134 using Base::elt;
135
136 protected:
142 IArray1D( Range const& I);
147 IArray1D( Range const& I, Type const& v);
152 IArray1D( IArray1D const& T, bool ref);
157 template<class OtherDerived>
158 IArray1D( IArray1D<OtherDerived> const& T, bool ref);
163 template<class OtherDerived>
164 IArray1D( IArray1D<OtherDerived> const& T, RowRange const& I, bool ref);
169 IArray1D( Allocator const& A, Range const& I, bool ref);
172
173 public:
175 inline bool isRef() const { return allocator_.isRef();}
181 inline void setRef(bool ref) const { allocator_.setRef(ref);}
182
184 Allocator const& allocator() const { return allocator_;}
185
187 inline RowRange const& rows() const { return range();}
189 inline int beginRows() const { return begin();}
191 inline int endRows() const { return end();}
193 inline int sizeRows() const { return size();}
194
196 inline ColRange cols() const { return ColRange(1);}
198 inline int beginCols() const { return baseIdx;}
200 inline int endCols() const { return baseIdx+1;}
202 inline int sizeCols() const { return 1;};
203
205 inline int lastIdxRows() const { return this->lastIdx();}
207 inline int lastIdxCols() const { return baseIdx;}
208
210 inline int capacity() const { return allocator_.size();}
211
216 inline Type& elt1Impl(int pos) { return allocator_.elt(pos);}
221 inline TypeConst elt1Impl(int pos) const { return allocator_.elt(pos);}
222
226 Derived& setValue(Type const& value);
231 inline void setValue(int pos, TypeConst value)
232 { allocator_.setValue(pos, value);}
233
237 void shiftImpl(int beg = baseIdx);
244 Derived& resizeImpl(Range const& I);
248 void reserve(int size);
252 void clear();
257 void move(Derived const& T);
261 Derived& pushBack( int n=1);
265 Derived& popBack(int n = 1);
270 Derived& erase(int pos, int n=1);
274 Derived& insertElt( int pos, int n =1);
279 Derived& insert( int pos, Type const& v);
284 Derived& insert( Range const& I, Type const& v);
288 Derived& push_front(Type const& v);
292 Derived& push_back(Type const& v);
296 void swap(int pos1, int pos2);
306 Derived& assign( IArray1D const& src);
307
312 void memmove(int pos1, int pos2, int n);
313
314 protected:
317
322 void initialize(RowRange const& I);
328 void allocate(RowRange const& I);
332 void freeMem();
333
334 private:
336};
337
338template<class Derived>
339IArray1D<Derived>::IArray1D(): Base(), allocator_(Arrays::evalRangeCapacity(range())) {}
340
341template<class Derived>
343 : Base(I), allocator_(Arrays::evalRangeCapacity(I)) {}
344
345template<class Derived>
347 : Base(I)
348 , allocator_(Arrays::evalRangeCapacity(I))
349{ allocator_.assign(I,v);}
350
351/* Copy constructor
352 * @param T the container to copy
353 * @param ref
354 **/
355template<class Derived>
357 : Base(T.range())
358 , allocator_(T.allocator(), ref)
359{}
360/* Copy constructor
361 * @param T the container to copy
362 * @param ref
363 **/
364template<class Derived>
365template<class OtherDerived>
367 : Base(T.range())
368 , allocator_(T.allocator(), ref)
369{}
370
371/* copy constructor.
372 * @param T,I the container and the range of data to wrap
373 * @param ref @c true if T is wrapped
374 **/
375template<class Derived>
376template<class OtherDerived>
378 : Base(I)
379 , allocator_(T.allocator(), I, ref)
380{}
381
382/* Wrapper constructor
383 * @param A,I range and allocator to wrap
384 * @param ref @c true if A is wrapped
385 **/
386template<class Derived>
388 : Base(I)
389 , allocator_(A, I, ref)
390{}
391/* destructor: allocated memory is liberated by MemAllocator class.*/
392template<class Derived>
394
395/* implement shift */
396template<class Derived>
398{
399 // compute increment
400 int inc = beg - begin();
401 if (inc == 0) return;
402 if (isRef()) // is this structure just a pointer ?
404 // translate range and data
405 incRange(inc);
406 allocator_.shift(beg);
407}
408
409template<class Derived>
411{
412 // check if there is something to do
413 if ( range() == I) return this->asDerived();
415 // translate
416 shiftImpl(I.begin());
417 // compute number of elements to delete or add
418 const int inc = I.end() - end();
419 // adjust size of the container
420 if (inc > 0) pushBack(inc); // more elements
421 else popBack(-inc); // less elements
422 return this->asDerived();
423}
424
425template<class Derived>
427{
428 // nothing to do
429 if (size < this->capacity() || isFixedSize_) return;
430 // is this structure a ptr ?
432 allocator_.realloc(Range(begin(), size));
433}
434
435template<class Derived>
437{
438 if (isRef()) return; // Nothing to do for ref
439 freeMem(); // Free Mem
440}
441
442template<class Derived>
443void IArray1D<Derived>::move(Derived const& T)
444{
445 if (this->asPtrDerived() == &T) return; // avoid move on itself
446 if (!isRef()) { freeMem();}
447 allocator_.move(T.allocator_); // move Allocator part
448 setRange(T.range()); // Set ITContainer1D part
449}
450
451template<class Derived>
453{
454#ifdef STK_ARRAYS_VERY_VERBOSE
455 stk_cout << _T("Entering IArray1D<Derived>::pushBack(") << n << _T(")\n");
456#endif
457 // checks
458 if (n <= 0) return this->asDerived();
460 // If container is empty : create it, otherwise add element from end() position
461 if (this->empty()) { initialize(RowRange(begin(), n));}
462 else { insertElt(end(), n);}
463 return this->asDerived();
464}
465
466template<class Derived>
468{
469 // checks
470 if (n <= 0 || isFixedSize_) return this->asDerived();
471 if (isRef())
473 decLast(n);
474 if (size() <= 0) this->freeMem(); // release mem if there's no more elts
475 return this->asDerived();
476}
477
478template<class Derived>
479Derived& IArray1D<Derived>::erase(int pos, int n)
480{
481#ifdef STK_DEBUG_ARRAY2D
482 stk_cout << _T("Entering IArray1D::erase\n");
483 stk_cout << _T("Deleting pos=") << pos <<_T(", n=") << n <<_T("\n");
484#endif
485
486// STK_STATIC_ASSERT_DENSE_ONLY(Derived)
487 // checks
488 if (n<=0) return this->asDerived();
489 if (isRef())
491#ifdef STK_BOUNDS_CHECK
492 if (begin() > pos)
493 { STKOUT_OF_RANGE_2ARG(IArray1D::erase,pos, n,begin() > pos);}
494 if (end() <= pos)
495 { STKOUT_OF_RANGE_2ARG(IArray1D::erase,pos, n,end() <= pos);}
496 if (end() < pos+n)
497 { STKOUT_OF_RANGE_2ARG(IArray1D::erase,pos, n,end() < pos+n);}
498#endif
499
500 // translate remaining elements and update dimensions
501 allocator_.memmove(pos, _R(pos+n, end()-1));
502
503 decLast(n);
504 if (size() <= 0) this->freeMem(); // if empty release allocated memory
505 return this->asDerived();
506}
507
508template<class Derived>
509Derived& IArray1D<Derived>::insertElt( int pos, int n)
510{
511 // checks
512 if (n <= 0 ) return this->asDerived();
514#ifdef STK_BOUNDS_CHECK
515 if (begin() > pos)
516 { STKOUT_OF_RANGE_2ARG(IArray1D::insertElt,pos, n,begin() > pos);}
517 if (end() < pos)
518 { STKOUT_OF_RANGE_2ARG(IArray1D::insertElt,pos, n,end() < pos);}
519#endif
520
521 // allocate, if necessary, memory for the elements
522 if ( (capacity() < size()+n) && !isFixedSize_ )
523 {
524 // temporary container
526 exchange(Taux);
527 // compute range of the container after insertion
528 RowRange range(Taux.range());
529 range.incLast(n);
530 // allocate
531 try { allocate(range);}
532 catch (Exception const& error) // if an error occur
533 {
534 exchange(Taux); // restore this
535 throw error; // and send again the Exception
536 }
537 // set range
538 setRange(Taux.range());
539 // copy original elements
540 allocator_.memcpy(Taux.begin(), Taux.allocator_, Range(Taux.begin(), pos - begin()) );
541 allocator_.memcpy(pos+n, Taux.allocator_, Range(pos, end()-pos) );
542 }
543 else // enough space -> shift the last elements
544 {
545 if (!isFixedSize_)
546 { allocator_.memmove(pos+n, Range(pos, end() - pos));}
547 else
548 { allocator_.memmove(pos+n, Range(pos, end() - pos - n));}
549 }
550 incLast(n);
551 return this->asDerived();
552}
553
554/* STL compatibility: Insert element @c v at position @c pos of the Array.
555 * @param pos position to insert elements
556 * @param v value to insert
557 **/
558template<class Derived>
559Derived& IArray1D<Derived>::insert( int pos, Type const& v)
560{
561 insertElt(pos, 1);
562 allocator_.setValue(pos,v);
563 return this->asDerived();
564}
565
566template<class Derived>
567Derived& IArray1D<Derived>::insert( Range const& I, Type const& v)
568{
569 insertElt(I.begin(), I.size());
570 for (int i=I.begin(); i<I.end(); i++) allocator_.setValue(i,v);
571 return this->asDerived();
572}
573
574template<class Derived>
576{
577 insert(Range(begin(), 1), v);
578 return this->asDerived();
579}
580
581template<class Derived>
583{
584 pushBack();
585 allocator_.setValue(this->lastIdx(),v);
586 return this->asDerived();
587}
588
589template<class Derived>
591{
592#ifdef STK_BOUNDS_CHECK
593 if (begin() > pos1) { STKOUT_OF_RANGE_2ARG(IArray1D::swap,pos1,pos2,begin()>pos1);}
594 if (end() <= pos1) { STKOUT_OF_RANGE_2ARG(IArray1D::swap,pos1,pos2,end()<=pos1);}
595 if (begin() > pos2) { STKOUT_OF_RANGE_2ARG(IArray1D::swap,pos1,pos2,begin()>pos2);}
596 if (end() <= pos2) { STKOUT_OF_RANGE_2ARG(IArray1D::swap,pos1,pos2,end()<=pos2);}
597#endif
598 std::swap(elt(pos1), elt(pos2));
599}
600
601template<class Derived>
603{
604 allocator_.exchange(T.allocator_);
605 Base::exchange(T);
606}
607
608template<class Derived>
610{
611 // cannot assign same data
612 if (&allocator_ == &(src.allocator())) { return this->asDerived();}
613 // Resize if necessary.
614 if ( size() != src.size() ) { this->resize(src.range());}
615 allocator_.memcpy(begin(), src.allocator_, src.range());
616 return this->asDerived();
617}
618
619/* Copy n elements from pos2 to pos1, guaranteeing correct behavior for overlapping.
620 * @param pos1,pos2 positions of the elements to move
621 * @param n number of elements to move
622 **/
623template<class Derived>
625{
626#ifdef STK_BOUNDS_CHECK
627 if (begin() > pos1) { STKOUT_OF_RANGE_2ARG(IArray1D::memmove,pos1,pos2,begin()>pos1);}
628 if (end() <= pos1) { STKOUT_OF_RANGE_2ARG(IArray1D::memmove,pos1,pos2,end()<=pos1);}
629 if (begin() > pos2) { STKOUT_OF_RANGE_2ARG(IArray1D::memmove,pos1,pos2,begin()>pos2);}
630 if (end() < pos2+n) { STKOUT_OF_RANGE_2ARG(IArray1D::memmove,pos1,pos2,end()<pos2+n);}
631#endif
632 allocator_.memmove(pos1, Range(pos2, n));
633}
634
635
636/* set a value to this container.
637 * @param value the value to set
638 **/
639template<class Derived>
640Derived& IArray1D<Derived>::setValue(Type const& value)
641{
642 allocator_.assign(range(), value);
643 return this->asDerived();
644}
645
646template<class Derived>
648{
649 allocate(I);
650 allocator_.setRef(false);
651 setRange(I);
652}
653
654template<class Derived>
656{
657 try
658 {
659 allocator_.malloc(Arrays::evalRangeCapacity(I));
660 }
661 catch (Exception const& error)
662 {
663 setRange(); // if an error occur set default range
664 throw error;
665 }
666}
667
668template<class Derived>
670{
671 if (isRef()) return; // Nothing to do for ref
672 allocator_.free();
673 setRange(RowRange(begin(),0)); // set range to default (Base)
674}
675
676} // namespace STK
677
678#endif // STK_IARRAY1D_H
In this file we define the main traits class we use for the STK++ Containers.
In this file we define utilities functions and enum for the Array classes.
In this file we implement the BiDirectionalIterator class.
In this file we define and implement the DenseRandomIterator and ConstDenseRandomIterator classes.
This is an internal header file, included by other Containers library headers.
in this file we define the interface class ITContainer1D.
#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_2ARG(Where, Arg1, Arg2, Error)
Definition STK_Macros.h:120
In this file we define the class MemAllocator.
#define _R(first, last)
Utility macro that can be used in a similar way that first:last.
Definition STK_Range.h:53
#define stk_cout
Standard stk output stream.
#define _T(x)
Let x unmodified.
This file include all the header files of the project STKernel.
Sdk class for all library Exceptions.
template one dimensional Array.
Derived & popBack(int n=1)
Delete last elts of the container.
Derived & setValue(Type const &value)
set a value to this container.
void setValue(int pos, TypeConst value)
Write a value at a given position.
Derived & assign(IArray1D const &src)
overwrite this with src.
Allocator allocator_
Derived & insert(Range const &I, Type const &v)
STL compatibility: Insert element v in the range I of the Array.
int capacity() const
Derived & erase(int pos, int n=1)
Delete n elements at the pos index to the container.
hidden::Traits< Derived >::Iterator Iterator
hidden::Traits< Derived >::ConstReverseIterator ConstReverseIterator
hidden::Traits< Derived >::ColRange ColRange
RowRange const & rows() const
Type & elt1Impl(int pos)
access to an element
int lastIdxRows() const
bool isRef() const
void memmove(int pos1, int pos2, int n)
Copy n elements from pos2 to pos1, guaranteeing correct behavior for overlapping.
IArray1D(Range const &I)
constructor with a specified Range.
IArray1D(Range const &I, Type const &v)
Misc constructor with first and last, initialization with a constant.
Allocator & allocator()
void swap(int pos1, int pos2)
Swapping the pos1 elt and the pos2 elt.
void exchange(IArray1D &T)
exchange this Container with T.
int endRows() const
ITContainer1D< Derived > Base
IArray1D(Allocator const &A, Range const &I, bool ref)
Wrapper constructor.
TypeConst elt1Impl(int pos) const
access to a constant element
IArray1D(IArray1D< OtherDerived > const &T, bool ref)
Copy constructor.
void setRef(bool ref) const
Modify the state of the container: this become a reference (if ref is true) or the owner of the data ...
void allocate(RowRange const &I)
function for memory allocation.
Derived & pushBack(int n=1)
Add n Elements to the end of the container.
void freeMem()
Method for memory deallocation.
int beginCols() const
hidden::Traits< Derived >::ReverseIterator ReverseIterator
Derived & resizeImpl(Range const &I)
Resize the container.
int sizeRows() const
void reserve(int size)
reserve internal memory for at least size elements.
int endCols() const
void clear()
Clear the object.
hidden::Traits< Derived >::Type Type
hidden::Traits< Derived >::Allocator Allocator
hidden::Traits< Derived >::TypeConst TypeConst
void initialize(RowRange const &I)
function for memory allocation and initialization.
int beginRows() const
Derived & push_back(Type const &v)
STL compatibility: append an element v.
void shiftImpl(int beg=baseIdx)
New beginning index for the object.
int lastIdxCols() const
hidden::Traits< Derived >::RowRange RowRange
~IArray1D()
destructor: allocated memory is liberated by MemAllocator class.
Derived & insert(int pos, Type const &v)
STL compatibility: Insert element v at position pos of the Array.
Derived & insertElt(int pos, int n=1)
Insert n elements at the position pos of the container.
IArray1D(IArray1D const &T, bool ref)
Copy constructor.
int lastIdx() const
Derived & push_front(Type const &v)
STL compatibility: push front an element.
IArray1D(IArray1D< OtherDerived > const &T, RowRange const &I, bool ref)
copy constructor.
RowRange const & range() const
hidden::Traits< Derived >::ConstIterator ConstIterator
IArray1D()
Default constructor.
void move(Derived const &T)
move T to this.
int sizeCols() const
Allocator const & allocator() const
ColRange cols() const
String const & error() const
get the last error message.
Definition STK_IRunner.h:82
Interface base class for homogeneous 1D containers.
void incRange(int n=1)
increment the range of the container (can be negative).
void setRange(RowRange const &I=RowRange())
Set range of the rows of the container.
void incLast(int n=1)
increment the end of the container (can be negative).
RowRange const & range() const
void decLast(int n=1)
decrement the end of the container.
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
int evalSizeCapacity(int m)
TRange< Size_ > evalRangeCapacity(TRange< Size_ > const &I)
Range incLast(TRange< SizeI_ > const &I)
if I=a:b, return a:b+1
Definition STK_Range.h:491
Range decLast(TRange< SizeI_ > const &I)
if I=a:b, return a:b-1
Definition STK_Range.h:505
const int UnknownSize
This value means that an integer is not known at compile-time, and that instead the value is stored i...
const int baseIdx
base index of the containers created in STK++.
The namespace STK is the main domain space of the Statistical ToolKit project.
TRange< UnknownSize > Range
Definition STK_Range.h:59