STK++ 0.9.13
STK_MemSAllocator1D.h
Go to the documentation of this file.
1/*--------------------------------------------------------------------*/
2/* Copyright (C) 2004-2018 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/* Project: stkpp::Arrays
26 * created on: Apr 13, 2018
27 * Author: iovleff, S..._Dot_I..._At_stkpp_Dot_org (see copyright for ...)
28 **/
29
36#ifndef STK_MEMSALLOCATOR1D_H
37#define STK_MEMSALLOCATOR1D_H
38
39#include "../STK_Array1D.h"
40
41namespace STK
42{
43// forward declaration
44template< typename Type_, int NzMax_=UnknownSize> class MemSAllocator1D;
45
52template< typename Type_, int NzMax_>
54{
55 public:
56 enum
57 {
59 };
60 typedef Type_ Type;
62
69
72
88 MemSAllocator1D( MemSAllocator1D const& A, bool ref =false);
92 template< int OtherNzMax_>
98 template<int OtherNzMax_>
100 , AllocatorRange const& I, bool ref = true);
103
104 // getters
106 inline AllocatorRange const& range() const { return range_;}
108 inline int begin() const { return range_.begin();}
110 inline int end() const { return range_.end();}
112 inline int size() const { return range_.size();}
113
115 inline int beginIdx() const { return p_idx_->begin();}
117 inline int endIdx() const { return p_idx_->end();}
119 inline int sizeIdx() const { return p_idx_->size();}
120
122 inline Indexes const& idx() const { return *p_idx_;}
124 inline Values const& val() const { return *p_val_;}
125
126 // manipulator
131 TypeConst elt(int pos) const;
135 void setValue(int pos, Type const& value);
139 void setZero(int pos);
140
145 template<int OtherSize>
157 template<int OtherSize>
160 void free();
166 template<int OtherSize_, int RangeSize_>
171 void memmove(int pos, Range const& range);
172
188 template<int OtherSize_>
190
204 MemSAllocator1D& shift(int first);
205
206 protected:
211
212 private:
216 const Type zero_;
218 mutable int idx1_, idx2_;
219
225 void writeValue( int pos, Type_ const& value);
231 void setValue1( int pos, TypeConst value);
232
236 inline void findIdx1(int pos) const
237 { for ( idx1_ = beginIdx(); p_idx_->elt(idx1_+1) <= pos; ++idx1_) {} }
241 inline void findIdx1Next(int pos) const
242 { if (p_idx_->elt(idx1_) == Arithmetic<int>::max()) return;
243 for ( ; p_idx_->elt(idx1_+1) <= pos; ++idx1_) {}
244 }
248 inline void findIdx1Prev(int pos) const
249 { for ( ; p_idx_->elt(idx1_) >= pos; --idx1_) {}}
250
254 inline void findIdx2(int pos) const
255 { for ( idx2_ = beginIdx(); p_idx_->elt(idx2_+1) <= pos; ++idx2_) {} }
259 inline void findIdx2Next(int pos) const
260 { if (p_idx_->elt(idx2_) == Arithmetic<int>::max()) return;
261 for ( ; p_idx_->elt(idx2_+1) <= pos; ++idx2_) {}
262 }
266 inline void findIdx2Prev(int pos) const
267 { for ( ; p_idx_->elt(idx2_) >= pos; --idx2_) {}}
268
272 void setZero1(int pos);
276 void setValue1(int pos);
280 void setValue2(int pos);
281};
282
283/* default constructor */
284template< typename Type_, int NzMax_>
286 , p_idx_(new Indexes(2))
287 , p_val_(new Values(2))
288 , range_()
289 , zero_(0)
290{
291 p_idx_->setValue(Arithmetic<int>::max());
292 p_idx_->front() = -Arithmetic<int>::max();
293 p_val_->setValue(Arithmetic<Type>::NA());
294}
295
296/* constructor with specified dimension
297 * @param I range of the rows
298 **/
299template< typename Type_, int NzMax_>
302 , p_idx_(new Indexes(2))
303 , p_val_(new Values(2))
304 , range_(I)
305 , zero_(0)
306{
307 p_idx_->setValue(Arithmetic<int>::max());
308 p_idx_->front() = -Arithmetic<int>::max();
309 p_val_->setValue(Arithmetic<Type>::NA());
310}
311
312/* constructor with specified dimensions
313 * @param I range of the rows
314 * @param nzmax maximal number of data
315 **/
316template< typename Type_, int NzMax_>
319 , p_idx_( new Indexes(2) )
320 , p_val_( new Values(2) )
321 , range_(I)
322 , zero_(0)
323{
324 p_idx_->reserve(nzmax);
325 p_val_->reserve(nzmax);
326 p_idx_->setValue(Arithmetic<int>::max());
327 p_idx_->front() = -Arithmetic<int>::max();
328 p_val_->setValue(Arithmetic<Type>::NA());
329}
330
331/* copy constructor
332 * @param A allocator to copy
333 * @param ref @c true if this copy is just a reference, @c false otherwise
334 **/
335template< typename Type_, int NzMax_>
337 : IContainerRef(ref)
338 , p_idx_(ref ? A.p_idx_ : new Indexes(A.idx()))
339 , p_val_(ref ? A.p_val_ : new Values(A.val()))
340 , range_(A.range_)
341 , zero_(A.zero_)
342{}
343/* Copy constructor.
344 * @param A allocator to copy
345 **/
346template< typename Type_, int NzMax_>
347template< int OtherNzMax_>
350 , p_idx_(new Indexes(A.idx()))
351 , p_val_(new Values(A.val()))
352 , range_(A.range_)
353 , zero_(A.zero_)
354{}
355/* Copy constructor. Map a range of A.
356 * @param A,I the allocator and range to reference
357 * @param ref is this a wrapper of A ? (true by default)
358 **/
359template< typename Type_, int NzMax_>
360template<int OtherNzMax_>
362 , AllocatorRange const& I
363 , bool ref
364 )
365 : IContainerRef(ref)
366 , p_idx_(ref ? A.p_idx_ : new Indexes(A.idx()))
367 , p_val_(ref ? A.p_val_ : new Values(A.val()))
368 , range_(I)
369 , zero_(A.zero_)
370{}
371
372/* destructor. */
373template<typename Type_, int NzMax_>
375{
376 if (!isRef())
377 {
378 delete p_idx_;
379 delete p_val_;
380 }
381}
382
383/* This method allows to get the element (p_idx, s_idx)
384 * @param p_idx the index of the row (or column)
385 * @param s_idx the index of the column (or row)
386 * @return 0 if the element is not stored, the value of the element otherwise
387 **/
388template< typename Type_, int NzMax_>
391{
392#ifdef STK_BOUNDS_CHECK
393 if (pos < begin())
395 if (pos >= end())
397#endif
398 findIdx1(pos);
399 return (p_idx_->elt(idx1_) == pos) ? p_val_->elt(idx1_) : zero_;
400}
401
402/* This method allows to overwrite or insert an element to the position (p_idx, s_idx)
403 * @param p_idx index of the row (respectively column)
404 * @param s_idx index of the column (respectively row)
405 * @param value value to set
406 **/
407template< typename Type_, int NzMax_>
409{
410#ifdef STK_BOUNDS_CHECK
411 if (pos < begin())
413 if (pos >= end())
415#endif
416 if (value == zero_) { setZero(pos);}
417 else { writeValue(pos, value);}
418}
419
420template< typename Type_, int NzMax_>
422{
423#ifdef STK_BOUNDS_CHECK
424 if (pos < begin())
426 if (pos >= end())
428#endif
429 findIdx1(pos);
430 if (p_idx_->elt(idx1_) == pos)
431 {
432 p_idx_->erase(idx1_);
433 p_val_->erase(idx1_);
434 }
435}
436
437/* @brief main method for memory allocation.
438 * @note do nothing for sparse arrays.
439 * @param I range of the data allocated
440 **/
441template<typename Type_, int NzMax_>
442template<int OtherSize>
444{
445 // there is no necessity to allocate if range_ is the same
446 if (range_ == I) return *this;
448 p_idx_->resize( Range(I.begin(),2) );
449 p_val_->resize( Range(I.begin(),2) );
450 p_idx_->setValue(Arithmetic<int>::max());
451 p_idx_->front() = -Arithmetic<int>::max();
452 p_val_->setValue(Arithmetic<Type>::NA());
453 range_ = I;
454 return *this;
455}
456/* @brief function for main ptr memory reallocation.
457 *
458 * If the size requested is greater than the allocated size,
459 * the Type stored are saved and copied using the operator=. the Type
460 * class have to provide this operator.
461 *
462 * If the size requested is lesser than the allocated size, only
463 * the first elements fitting in the container are copied.
464 * @param I range of the data to reserve
465 **/
466template<typename Type_, int NzMax_>
467template<int OtherSize>
469{
470 // there is no necessity to allocate if range_ is the same
471 if (range_ == I) return *this;
473 p_idx_->resize(I);
474 p_val_->resize(I);
475 range_ = I;
476 return this;
477}
478/* function releasing all stored values. */
479template<typename Type_, int NzMax_>
481{
482 p_idx_->clear();
483 p_val_->clear();
484 range_ = AllocatorRange();
485 return;
486}
487
488/* function copying a part of allocator T in this.
489 * @param pos position where will be copied data
490 * @param T,range the array of data and the range of data to copy
491 * @note only which are not zero are copied
492 **/
493template<typename Type_, int NzMax_>
494template<int OtherSize_, int RangeSize_>
496{
497 if (range.size() <= 0) return *this;
498#ifdef STK_BOUNDS_CHECK
499 if (pos < begin()) { STKOUT_OF_RANGE_1ARG(MemSAllocator1D::memcpy,pos,begin() > pos);}
500 if (pos >= end()) { STKOUT_OF_RANGE_1ARG(MemSAllocator1D::memcpy,pos,end() <= pos);}
501 if (!T.range().isContaining(range))
502 { STKOUT_OF_RANGE_1ARG(MemSAllocator::memcopy,range,range not in T.range());}
503#endif
504 for (int k=range.begin(); k<range.end(); ++k, ++pos)
505 { setValue(pos, T.elt(k));}
506 return *this;
507}
508
509/* function moving a part of the allocator.
510 * @param pos,range position and range in form [begin,end) to move
511 **/
512template<typename Type_, int NzMax_>
514{
515 if ((range.size() <= 0)||(range.begin() == pos)) return;
516#ifdef STK_BOUNDS_CHECK
517 if (pos < begin())
519 if (pos >= end())
521 if (!range_.isContaining(range))
523#endif
524 if (pos < range.begin()) // ==> idx1 < idx2
525 {
526 // initialize idx1_ and idx2_
527 findIdx1(pos);
528 findIdx2(range.begin());
529 // start loop over range
530 for (int k= range.begin(); k<range.end(); ++k, ++pos)
531 {
532 // update idx1_ and idx2 (do nothing at the beginning)
533 findIdx1Next(pos);
534 findIdx2Next(k);
535 if (p_idx_->elt(idx2_) != k) { setZero1(pos);}
536 else { setValue1(pos);}
537 }
538 }
539 else // ==> idx2 < idx1
540 {
541 // initialize idx1_ and idx2_
542 findIdx2(range.lastIdx());
543 pos += range.size();
544 findIdx1(pos);
545 for (int k= range.lastIdx(); k>=range.begin(); --k, --pos)
546 {
547 // update idx1_ and idx2 (do nothing at the beginning)
548 findIdx1Prev(pos);
549 findIdx2Prev(k);
550 if (p_idx_->elt(idx2_) != k) { setZero1(pos);}
551 else { setValue2(pos);}
552 }
553 }
554}
555
556/* exchange this with T.
557 * @param T the container to exchange with T
558 **/
559template<typename Type_, int NzMax_>
561{
562 std::swap(p_idx_, T.p_idx_);
563 std::swap(p_val_, T.p_val_);
564 std::swap(range_, T.range_);
566 return *this;
567}
568
569/* @brief copy the Allocator T by value.
570 * The memory is free and the Allocator T is physically copied in this.
571 * @param T the allocator to copy by value
572 * @return a copy of T
573 **/
574template<typename Type_, int NzMax_>
577{
578 *p_idx_ = T.idx();
579 *p_val_ = T.val();
580 range_ = T.range();
581 return *this;
582}
583/* @brief set a value.*/
584template<typename Type, int NzMax_>
585template<int OtherSize_>
588{
589 // reserve first if not zero_ using upper-bound current size + range size
590 findIdx1(I.begin());
591 if (value!=zero_)
592 {
593 p_idx_->reserve(I.size()+p_idx_->size());
594 p_val_->reserve(I.size()+p_val_->size());
595 for (int pos= I.begin(); pos < I.end(); ++pos)
596 {
597 findIdx1Next(pos);
598 setValue1(pos, value);
599 }
600 }
601 else
602 {
603 for (int pos= I.begin(); pos < I.end(); ++pos)
604 {
605 findIdx1Next(pos);
606 setZero1(pos);
607 }
608 }
609 return *this;
610}
611
612/* @brief move the Allocator T to this.
613 * The memory of this is freed and T becomes a reference of this. This
614 * method allow to move the data of T to this without using physical copy.
615 *
616 * @param T the allocator to move to this
617 * @return this object.
618 * @note the data member ref_ is mutable so that T can be passed as a
619 * constant reference.
620 **/
621template<typename Type_, int NzMax_>
623{
624 p_idx_->move(T.p_idx_);
625 p_val_->move(T.p_val_);
626 range_ = T.range_;
627 setRef(T.ref());
628 return *this;
629}
630
631/* shift the first index of the data to first.
632 * @param first the index of the first data to set
633 **/
634template<typename Type_, int NzMax_>
636{
637 int inc = first - begin();
638 for (int t=p_idx_->begin()+1; p_idx_->elt(t) != Arithmetic<int>::max(); ++t)
639 { p_idx_->elt(t) += inc;}
640 range_.shift(first);
641 return *this;
642}
643
644/* write a value at the given position. If p_idx_->elt(pos) != idx
645 * value is inserted at this position, otherwise exiting value is
646 * overwritten.
647 * @param pos position in p_idx_
648 * @param value value to write
649 **/
650template<typename Type_, int NzMax_>
651void STK::MemSAllocator1D<Type_, NzMax_>::writeValue( int pos, Type_ const& value)
652{
653 findIdx1(pos);
654 setValue1(pos, value);
655}
656/* write a value at the given position. If p_idx_->elt(pos) != idx
657 * value is inserted at this position, otherwise exiting value is
658 * overwritten.
659 * @param pos position in p_idx_
660 * @param value value to write
661 **/
662template<typename Type_, int NzMax_>
664{
665 // there is an existing stored value for this entry
666 if (p_idx_->elt(idx1_) == pos) { p_val_->elt(idx1_) =value;}
667 else // value is not yet an entry, so add it
668 {
669 // Otherwise insert it
670 p_idx_->insert(idx1_+1, pos);
671 p_val_->insert(idx1_+1, value);
672 }
673}
674
675
676template< typename Type_, int NzMax_>
678{
679 // there is an existing stored value for this entry
680 if (p_idx_->elt(idx1_) == pos)
681 {
682 p_idx_->erase(idx1_);
683 p_val_->erase(idx1_);
684 }
685}
686
687/* write a value at the given position. If p_idx_->elt(pos) != idx
688 * value is inserted at this position, otherwise exiting value is
689 * overwritten.
690 * @param pos position in p_idx_
691 **/
692template<typename Type_, int NzMax_>
694{
695 // there is an existing stored value for this entry
696 if (p_idx_->elt(idx1_) == pos)
697 { p_val_->elt(idx1_) = p_val_->elt(idx2_);}
698 else // value is not yet an entry, so add it
699 {
700 idx1_++;
701 p_idx_->insert(idx1_, pos);
702 p_val_->insertElt(idx1_, 1);
703 p_val_->elt(idx1_) = p_val_->elt(idx2_+1); // take care that elt1 and elt2 are shifted
704 }
705}
706/* write a value at the given position. If p_idx_->elt(pos) != idx
707 * value is inserted at this position, otherwise exiting value is
708 * overwritten.
709 * @param pos position in p_idx_
710 **/
711template<typename Type_, int NzMax_>
713{
714 // there is an existing stored value for this entry
715 if (p_idx_->elt(idx1_) == pos)
716 { p_val_->elt(idx1_) = p_val_->elt(idx2_);}
717 else // value is not yet an entry, so add it
718 {
719 idx1_++;
720 p_idx_->insert(idx1_, pos);
721 p_val_->insertElt(idx1_, 1);
722 p_val_->elt(idx1_) = p_val_->elt(idx2_);
723
724 }
725}
726
727
728} // namespace STK
729
730
731#endif /* STK_MEMSALLOCATOR1D_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
memory allocator for sparse vectors classes.
Array1D< int, nzmax_ > Indexes
Type of the array storing indexes.
TRange< UnknownSize > AllocatorRange
Type of the range of the data.
void free()
function releasing all stored values.
TypeConst elt(int pos) const
This method allows to get the jth value.
void writeValue(int pos, Type_ const &value)
Write a value at the given position.
Values * p_val_
array of values
MemSAllocator1D & malloc(TRange< OtherSize > const &I)
main method for memory allocation.
void setZero1(int pos)
Set zero at position idx1_.
void memmove(int pos, Range const &range)
function moving a part of the allocator.
MemSAllocator1D()
default constructor
MemSAllocator1D & assign(TRange< OtherSize_ > const &I, Type const &value)
assign a value to allocator.
Indexes * p_idx_
array of indexes
const Type zero_
zero value
MemSAllocator1D & shift(int first)
shift the first index of the data to first.
Array1D< Type, nzmax_ > Values
Type of the array storing data.
void findIdx1(int pos) const
find first position in p_idx_ less or equal to pos
AllocatorRange range_
Range of the data.
AllocatorRange const & range() const
void findIdx1Prev(int pos) const
find idx1_ previous position in p_idx_ greater than pos
void findIdx2Next(int pos) const
find idx2_ next position in p_idx_ less or equal to pos
void findIdx2Prev(int pos) const
find idx2_ previous position in p_idx_ greater than pos
hidden::RemoveConst< Type_ >::Type const & TypeConst
MemSAllocator1D & exchange(MemSAllocator1D &T)
exchange this with T.
void findIdx2(int pos) const
find first position in p_idx_ less or equal to pos
MemSAllocator1D & assign(MemSAllocator1D const &T)
copy the Allocator T by value.
int idx1_
Current indexes used for internal lookup.
void setValue1(int pos, TypeConst value)
Write a value at position idx1_.
MemSAllocator1D & realloc(TRange< OtherSize > const &I)
function for main ptr memory reallocation.
Values const & val() const
void setZero(int pos)
This method allows to write zero to the given position.
Indexes const & idx() const
void setValue2(int pos)
Set value idx2_ at position idx1_ when idx1 > idx2.
void findIdx1Next(int pos) const
find first position in p_idx_ less or equal to pos
MemSAllocator1D & memcpy(int pos, MemSAllocator1D< Type, OtherSize_ > const &T, TRange< RangeSize_ > const &range)
function copying a part of allocator T in this.
void setValue(int pos, Type const &value)
This method allows to overwrite or insert an element to the given position.
MemSAllocator1D & move(MemSAllocator1D const &T)
move the Allocator T to this.
The MultidimRegression class allows to regress a multidimensional output variable among a multivariat...
int begin() const
get the first index of the TRange.
Definition STK_Range.h:93
Index sub-vector region: Specialization when the size is unknown.
Definition STK_Range.h:265
int lastIdx() const
get the last index of the TRange.
Definition STK_Range.h:313
int end() const
get the ending index of the TRange.
Definition STK_Range.h:299
int size() const
get the size of the TRange (the number of elements).
Definition STK_Range.h:303
@ zero_
0 value
Definition STK_Binary.h:49
const int UnknownSize
This value means that an integer is not known at compile-time, and that instead the value is stored i...
The namespace STK is the main domain space of the Statistical ToolKit project.
TRange< UnknownSize > Range
Definition STK_Range.h:59
Arithmetic properties of STK fundamental types.
void setRef(bool ref) const
Modify the container : can become a reference or the owner of the data.
void exchange(TRef const &T)
swap this with the container T.
bool isRef() const