~ubuntu-branches/ubuntu/hardy/libterralib/hardy

« back to all changes in this revision

Viewing changes to src/terralib/kernel/TeSparseMatrix.h

  • Committer: Bazaar Package Importer
  • Author(s): Daniel T Chen
  • Date: 2005-11-25 22:32:59 UTC
  • Revision ID: james.westby@ubuntu.com-20051125223259-3zubal8ux4ki4fjg
Tags: upstream-3.0.3b2
ImportĀ upstreamĀ versionĀ 3.0.3b2

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
// k9/a4/sparmat.h, templates for sparse matrices
 
2
#ifndef SPARSEMATRIX_H
 
3
#define SPARSEMATRIX_H SPARSEMATRIX_H
 
4
 
 
5
// selection of implementation
 
6
#ifdef STL_map            // defined in main()
 
7
#include<map>
 
8
#include<cassert>
 
9
#else
 
10
#include<hmap.h>
 
11
 
 
12
/* If at this point the HMap container is chosen, a function for
 
13
   calculating the hash table addresses is needed. As opposed to the
 
14
   hash functions described up to now, not only one value, but two are
 
15
   used for the calculation. Therefore, the function operator of the
 
16
   PairHashFun class takes a pair as argument. The address calculation
 
17
   itself is simple, but sufficient for our purposes. */
 
18
 
 
19
using namespace std;
 
20
 
 
21
template<class IndexType>  // int, long or unsigned
 
22
class PairHashFun
 
23
{
 
24
  public:
 
25
    PairHashFun(long prime=65537) // another prime number is possible
 
26
        // e.g. 2111 for smaller Matrizes
 
27
    : tabSize(prime)
 
28
    {}
 
29
 
 
30
    // Address calculation with two values
 
31
    long operator()(const pair<IndexType, IndexType>& p) const
 
32
    {
 
33
       return (p.first + p.second) % tabSize;
 
34
    }
 
35
 
 
36
    long tableSize() const
 
37
    { 
 
38
       return tabSize;
 
39
    }
 
40
 
 
41
  private:
 
42
    long tabSize;
 
43
};
 
44
#endif          //  STL_map
 
45
 
 
46
#ifdef _MSC_VER
 
47
#include <utility>
 
48
using namespace std;
 
49
#endif
 
50
 
 
51
template<class ValueType, class IndexType, class ContainerType>
 
52
class MatrixElement
 
53
{
 
54
  private:
 
55
    ContainerType& C;
 
56
    typename ContainerType::iterator I;
 
57
    IndexType row, column;
 
58
 
 
59
  public:
 
60
    typedef pair<IndexType, IndexType> IndexPair;
 
61
    typedef MatrixElement<ValueType, IndexType,
 
62
                          ContainerType>&  Reference;
 
63
 
 
64
    MatrixElement(ContainerType& Cont, IndexType r, IndexType c)
 
65
    : C(Cont), I(C.find(IndexPair(r,c))),
 
66
      row(r), column(c)
 
67
    {}
 
68
 
 
69
    /* The constructor initializes the private variables with all
 
70
       information that is needed. The container itself is located in
 
71
       the sparseMatrix class; here, the reference to it is entered.
 
72
       If the passed indices for row and column belong to an element
 
73
       not yet stored in the container, the iterator has the value
 
74
       C.end(). */
 
75
 
 
76
    ValueType asValue() const
 
77
    {
 
78
       if(I == C.end())
 
79
           return ValueType(0);
 
80
       else
 
81
           return (*I).second;
 
82
    }
 
83
 
 
84
    operator ValueType () const  // type conversion operator
 
85
    {
 
86
       return asValue();
 
87
    }
 
88
 
 
89
    /* According to the definition of the sparse matrix, 0 is returned
 
90
       if the element is not present in the container. Otherwise, the
 
91
       result is the second part of the object of type value_type
 
92
       stored in the container. */
 
93
 
 
94
    Reference operator=(const ValueType& x)
 
95
    {
 
96
       if(x != ValueType(0))        // not equal 0?
 
97
       {
 
98
         /* If the element does not yet exist, it is put, together
 
99
            with the indices, into an object of type value_type and
 
100
            inserted with insert(): */
 
101
 
 
102
          if(I == C.end())
 
103
          {
 
104
             assert(C.size() < C.max_size());
 
105
             I = (C.insert(
 
106
#ifndef _MSC_VER
 
107
                         typename
 
108
#endif
 
109
                         ContainerType::value_type(
 
110
                        IndexPair(row,column), x))
 
111
                 ).first;
 
112
          }
 
113
          else (*I).second = x;
 
114
       }
 
115
 
 
116
       /* insert() returns a pair whose first part is an iterator
 
117
          pointing to the inserted object. The second part is of type
 
118
          bool and indicates whether the insertion took place because
 
119
          no element with this key existed. This is, however, not
 
120
          evaluated here because, due to the precondition (I ==
 
121
          C.end()), the second part must always have the value true.
 
122
          If, instead, the element already exists, the value is
 
123
          entered into the second part of the value_type object. If
 
124
          the value is equal 0, in order to save space the element is
 
125
          deleted if it existed. */
 
126
 
 
127
       else                    // x = 0
 
128
          if(I != C.end())
 
129
          {
 
130
              C.erase(I);
 
131
              I = C.end();
 
132
          }
 
133
       return *this;
 
134
    }
 
135
 
 
136
    /* An assignment operator is required which in turn requires a
 
137
       reference to an object of type MatrixElement. When both the
 
138
       left- and right-hand side are identical, nothing has to happen.
 
139
       Otherwise, as above, it has to be checked whether the value of
 
140
       the right-hand element is 0 or not. The resulting behavior is
 
141
       described together with the above assignment operator, so that
 
142
       here it is simply called: */
 
143
 
 
144
    Reference operator=(const Reference rhs)
 
145
    {
 
146
       if(this != &rhs)      // not identical?
 
147
       {
 
148
           return operator=(rhs.asValue());  // see above
 
149
       }
 
150
       return *this;
 
151
    }
 
152
 
 
153
};  // class MatrixElement
 
154
 
 
155
template<class ValueType, class IndexType>
 
156
class TeSparseMatrix
 
157
{
 
158
   public:
 
159
     typedef pair<IndexType, IndexType> IndexPair;
 
160
 
 
161
     // The switch STL_map controls the compilation:
 
162
 
 
163
#ifdef STL_map
 
164
     typedef map<IndexPair, ValueType,
 
165
                  less<IndexPair> >       ContainerType;
 
166
#else
 
167
     typedef HMap<IndexPair, ValueType,
 
168
                  PairHashFun<IndexType> > ContainerType;
 
169
#endif
 
170
 
 
171
     typedef MatrixElement<ValueType, IndexType,
 
172
                           ContainerType> MatrixElement;
 
173
 
 
174
  public:
 
175
    typedef IndexType size_type;
 
176
 
 
177
    /* The constructor only initializes the row and column
 
178
       information. The container is created by its standard
 
179
       constructor, where in the case of hash implementation, the size
 
180
       of the container is given by the hash function object of type
 
181
       PairHashFun (see typedef above). */
 
182
 
 
183
  private:
 
184
    size_type rows, columns;
 
185
    ContainerType C;
 
186
 
 
187
  public:
 
188
    sparseMatrix(size_type r, size_type c)
 
189
    : rows(r), columns(c)
 
190
    {}
 
191
 
 
192
   size_type Rows()  const { return rows;}
 
193
   size_type Columns() const { return columns;}
 
194
 
 
195
   // usual container type definitions
 
196
   typedef typename ContainerType::iterator iterator;
 
197
   typedef typename ContainerType::const_iterator const_iterator;
 
198
 
 
199
   // usual container functions
 
200
   size_type size()       const { return C.size();}
 
201
   size_type max_size()   const { return C.max_size();}
 
202
 
 
203
   iterator begin()             { return C.begin();}
 
204
   iterator end()               { return C.end();}
 
205
 
 
206
   const_iterator begin() const { return C.begin();}
 
207
   const_iterator end()   const { return C.end();}
 
208
 
 
209
   void clear()
 
210
   {
 
211
       C.clear();
 
212
 
 
213
   }
 
214
 
 
215
   class Aux  // for index operator below
 
216
   {
 
217
     public:
 
218
       Aux(size_type r, size_type maxs, ContainerType& Cont)
 
219
       : Row(r), maxColumns(maxs), C(Cont)
 
220
       {}
 
221
 
 
222
       /* After checking the number of columns, the index operator of
 
223
          Aux returns a matrix element which is equipped with all
 
224
          necessary information to carry out a successful assignment.
 
225
        */
 
226
 
 
227
       MatrixElement operator[](size_type c)
 
228
       {
 
229
           assert(c >= 0 && c < maxColumns);
 
230
           return MatrixElement(C, Row, c);
 
231
       }
 
232
 
 
233
     private:
 
234
       size_type Row, maxColumns;
 
235
       ContainerType& C;
 
236
   };
 
237
 
 
238
   /* The index operator of the sparseMatrix class returns the
 
239
       auxiliary object, whose class is defined as nested inside
 
240
       sparseMatrix. */
 
241
   Aux operator[](size_type r)
 
242
   {
 
243
      assert(r >= 0 && r < rows);
 
244
      return Aux(r, columns, C);
 
245
   }
 
246
 
 
247
    /* Up to this point, from a functionality point of view, the
 
248
       sparseMatrix class is sufficiently equipped. In order, however,
 
249
       to avoid writing such horrible things as `(*I).first.first' for
 
250
       accessing the elements, some auxiliary functions follow which
 
251
       determine the indices and associated values of an iterator in a
 
252
       more readable way. */
 
253
 
 
254
   size_type Index1(iterator& I) const
 
255
   {
 
256
      return (*I).first.first;
 
257
   }
 
258
 
 
259
   size_type Index2(iterator& I) const
 
260
   {
 
261
      return (*I).first.second;
 
262
   }
 
263
 
 
264
   ValueType Value(iterator& I) const
 
265
   {
 
266
      return (*I).second;
 
267
   }
 
268
};       // class sparseMatrix
 
269
 
 
270
#endif   // file sparmat.h
 
271
 
 
272