multiDimArray_tpl.h 8.16 KB
Newer Older
phw's avatar
phw committed
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
/***************************************************************************
 *   Copyright (C) 2005 by Pierre-Henri WUILLEMIN et Christophe GONZALES   *
 *   {prenom.nom}_at_lip6.fr                                               *
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 *   This program is distributed in the hope that it will be useful,       *
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
 *   GNU General Public License for more details.                          *
 *                                                                         *
 *   You should have received a copy of the GNU General Public License     *
 *   along with this program; if not, write to the                         *
 *   Free Software Foundation, Inc.,                                       *
 *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
 ***************************************************************************/
20 21 22 23 24 25
/**
 * @file
 * @brief Implementation of the MultiDimArray class.
 *
 * @author Pierre-Henri WUILLEMIN et Christophe GONZALES
 */
phw's avatar
phw committed
26

27 28
#include <agrum/multidim/implementations/multiDimArray.h>
#include <agrum/multidim/implementations/multiDimWithOffset.h>
phw's avatar
phw committed
29 30

namespace gum {
31

32
  // Default constructor: creates an empty null dimensional matrix
33 34 35
  template < typename GUM_SCALAR >
  MultiDimArray< GUM_SCALAR >::MultiDimArray()
      : MultiDimWithOffset< GUM_SCALAR >() {
phw's avatar
phw committed
36
    // for debugging purposes
37
    GUM_CONSTRUCTOR(MultiDimArray);
phw's avatar
phw committed
38
  }
phw's avatar
phw committed
39

40
  // copy constructor
41 42 43 44 45
  template < typename GUM_SCALAR >
  MultiDimArray< GUM_SCALAR >::MultiDimArray(
    const MultiDimArray< GUM_SCALAR >& src)
      : MultiDimWithOffset< GUM_SCALAR >(src)
      , _values(src._values) {
phw's avatar
phw committed
46
    // for debugging purposes
47
    GUM_CONS_CPY(MultiDimArray);
phw's avatar
phw committed
48
  }
phw's avatar
phw committed
49

50
  // destructor
51 52
  template < typename GUM_SCALAR >
  MultiDimArray< GUM_SCALAR >::~MultiDimArray() {
phw's avatar
phw committed
53
    // for debugging purposes
54
    GUM_DESTRUCTOR(MultiDimArray);
phw's avatar
phw committed
55
    // no need to unregister all slaves as it will be done by MultiDimWithOffset
phw's avatar
phw committed
56
  }
phw's avatar
phw committed
57

58 59 60 61
  template < typename GUM_SCALAR >
  void MultiDimArray< GUM_SCALAR >::copyFrom(
    const MultiDimContainer< GUM_SCALAR >& src) const {
    auto mda = dynamic_cast< const MultiDimArray< GUM_SCALAR >* >(&src);
62

63 64
    if (mda == nullptr) {
      MultiDimContainer< GUM_SCALAR >::copyFrom(src);
65 66 67 68
    } else {
      _values = mda->_values;
    }
  }
69

70 71 72 73
  template < typename GUM_SCALAR >
  void MultiDimArray< GUM_SCALAR >::apply(
    std::function< GUM_SCALAR(GUM_SCALAR) > f) const {
    std::transform(_values.begin(), _values.end(), _values.begin(), f);
74 75
  }

76 77 78 79
  template < typename GUM_SCALAR >
  GUM_SCALAR MultiDimArray< GUM_SCALAR >::reduce(
    std::function< GUM_SCALAR(GUM_SCALAR, GUM_SCALAR) > f, GUM_SCALAR base) const {
    return std::accumulate(_values.begin(), _values.end(), base, f);
80 81
  }

82

83
  // data access operator
84
  template < typename GUM_SCALAR >
85
  INLINE GUM_SCALAR&
86 87
  MultiDimArray< GUM_SCALAR >::_get(const Instantiation& i) const {
    if (i.isMaster(this)) {
phw's avatar
phw committed
88
      return _values[this->_offsets[&i]];
phw's avatar
phw committed
89
    } else {
90
      return _values[this->_getOffs(i)];
phw's avatar
phw committed
91
    }
phw's avatar
phw committed
92
  }
phw's avatar
phw committed
93

94
  // add a new dimension, needed for updating the _offsets & _gaps
95 96 97 98
  template < typename GUM_SCALAR >
  INLINE void MultiDimArray< GUM_SCALAR >::add(const DiscreteVariable& v) {
    Size lg = MultiDimWithOffset< GUM_SCALAR >::domainSize();
    MultiDimWithOffset< GUM_SCALAR >::add(v);
99

100 101
    if (!this->_isInMultipleChangeMethod()) {
      _values.resize(lg * v.domainSize());
phw's avatar
phw committed
102
    }
phw's avatar
phw committed
103
  }
phw's avatar
phw committed
104

105
  // removes a dimension, needed for updating the _offsets & _gaps
106 107 108 109
  template < typename GUM_SCALAR >
  INLINE void MultiDimArray< GUM_SCALAR >::erase(const DiscreteVariable& v) {
    Sequence< const DiscreteVariable* > variables = this->variablesSequence();
    Idx pos = variables.pos(&v);  // throw a NotFound if necessary
110

111 112
    if (variables.size() == 1) {
      if (!this->_isInMultipleChangeMethod()) _values.clear();
phw's avatar
phw committed
113
    } else {
phw's avatar
phw committed
114
      Size v_size = v.domainSize();
115
      Size size = this->domainSize();
phw's avatar
phw committed
116 117 118 119 120 121 122 123
      // here, the variable does belong to the array.
      // => if pos = variables.size() - 1 then we just have to extract the
      // beginning of the array (actually the first gap of variable v)
      // if pos = 0, then copy every element whose index is a multiple of |v|
      // Assume now that pos != 0 and pos != variables.size() - 1, then
      // let w be the next variable in the set of variables of the array.
      // Then we must copy |gap(v)| elements every |gap(w)| elements

124 125
      if (!this->_isInMultipleChangeMethod()) {
        if (pos != variables.size() - 1) {
126 127
          Size gap_v = this->_gaps[variables[pos]];
          Size gap_w = this->_gaps[variables[pos + 1]];
phw's avatar
phw committed
128

129
          for (Idx i = 0, j = 0; i < size; i += gap_w) {
phw's avatar
phw committed
130 131
            Idx last = i + gap_v;

132
            for (Idx k = i; k < last; ++k, ++j)
phw's avatar
phw committed
133 134
              _values[j] = _values[k];
          }
phw's avatar
phw committed
135
        }
phw's avatar
phw committed
136 137

        // shrink _values
138
        _values.resize(size / v_size);
phw's avatar
phw committed
139
      }
phw's avatar
phw committed
140 141
    }

142
    MultiDimWithOffset< GUM_SCALAR >::erase(v);
phw's avatar
phw committed
143
  }
144

145
  template < typename GUM_SCALAR >
146
  INLINE Size MultiDimArray< GUM_SCALAR >::realSize() const {
phw's avatar
phw committed
147
    return this->domainSize();
phw's avatar
phw committed
148
  }
phw's avatar
phw committed
149

150
  // synchronise content after MultipleChanges
151
  template < typename GUM_SCALAR >
152
  INLINE void MultiDimArray< GUM_SCALAR >::_commitMultipleChanges() {
153 154
    if (MultiDimWithOffset< GUM_SCALAR >::domainSize() != _values.size()) {
      _values.resize(MultiDimWithOffset< GUM_SCALAR >::domainSize());
phw's avatar
phw committed
155
    }
phw's avatar
phw committed
156 157
  }

158
  // synchronise content after MultipleChanges
159
  template < typename GUM_SCALAR >
160
  INLINE void
161 162 163
  MultiDimArray< GUM_SCALAR >::_commitMultipleChanges(const GUM_SCALAR& x) {
    if (MultiDimWithOffset< GUM_SCALAR >::domainSize() != _values.size()) {
      _values.resize(MultiDimWithOffset< GUM_SCALAR >::domainSize(), x);
164
    }
phw's avatar
phw committed
165
  }
166

167
  // fill the array with the arg
168 169 170
  template < typename GUM_SCALAR >
  INLINE void MultiDimArray< GUM_SCALAR >::fill(const GUM_SCALAR& d) const {
    if (!this->empty()) std::fill(_values.begin(), _values.end(), d);
phw's avatar
phw committed
171
  }
phw's avatar
phw committed
172

173
  // virtual constructor
174 175 176 177
  template < typename GUM_SCALAR >
  INLINE MultiDimContainer< GUM_SCALAR >*
         MultiDimArray< GUM_SCALAR >::newFactory() const {
    return new MultiDimArray< GUM_SCALAR >;
phw's avatar
phw committed
178
  }
dubus's avatar
dubus committed
179

180
  // returns the element stored in the multidimArray at a given offset
181
  template < typename GUM_SCALAR >
182
  INLINE const GUM_SCALAR&
183
  MultiDimArray< GUM_SCALAR >::unsafeGet(Idx offset) const {
184
    return _values[offset];
phw's avatar
phw committed
185
  }
186

187 188 189
  template < typename GUM_SCALAR >
  INLINE void MultiDimArray< GUM_SCALAR >::unsafeSet(Idx               offset,
                                                     const GUM_SCALAR& data) {
190
    _values[offset] = data;
phw's avatar
phw committed
191
  }
192

193
  // returns the element stored in the multidimArray at a given offset
194
  template < typename GUM_SCALAR >
195
  INLINE const GUM_SCALAR&
196 197 198
  MultiDimArray< GUM_SCALAR >::getByOffset(Idx offset) const {
    if (offset >= _values.size()) {
      GUM_ERROR(OutOfBounds, "offset too large");
phw's avatar
phw committed
199
    }
200

201
    return _values[offset];
phw's avatar
phw committed
202
  }
203

204 205 206 207 208
  template < typename GUM_SCALAR >
  INLINE void MultiDimArray< GUM_SCALAR >::setByOffset(Idx               offset,
                                                       const GUM_SCALAR& data) {
    if (offset >= _values.size()) {
      GUM_ERROR(OutOfBounds, "offset too large");
phw's avatar
phw committed
209
    }
210

211
    _values[offset] = data;
phw's avatar
phw committed
212
  }
213

214
  // returns the name of the implementation
215 216
  template < typename GUM_SCALAR >
  INLINE const std::string& MultiDimArray< GUM_SCALAR >::name() const {
217 218
    static const std::string str = "MultiDimArray";
    return str;
phw's avatar
phw committed
219
  }
220

221
  template < typename GUM_SCALAR >
222
  INLINE void MultiDimArray< GUM_SCALAR >::_replace(const DiscreteVariable* x,
223
                                                 const DiscreteVariable* y) {
224
    MultiDimImplementation< GUM_SCALAR >::_replace(x, y);
phw's avatar
phw committed
225
  }
phw's avatar
phw committed
226
} /* namespace gum */