SparseLibrary  Version 1.6.0
HTS.hpp
1 /*
2  * Copyright (c) 2007-2014, A. N. Yzelman, Utrecht University 2007-2011;
3  * KU Leuven 2011-2014.
4  * R. H. Bisseling, Utrecht University 2007-2014.
5  *
6  * This file is part of the Sparse Library.
7  *
8  * This library was developed under supervision of Prof. dr. Rob H. Bisseling at
9  * Utrecht University, from 2007 until 2011. From 2011-2014, development continued
10  * at KU Leuven, where Prof. dr. Dirk Roose contributed significantly to the ideas
11  * behind the newer parts of the library code.
12  *
13  * The Sparse Library is free software: you can redistribute it and/or modify
14  * it under the terms of the GNU General Public License as published by the
15  * Free Software Foundation, either version 3 of the License, or (at your
16  * option) any later version.
17  *
18  * The Sparse Library is distributed in the hope that it will be useful, but
19  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
20  * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
21  * for more details.
22  *
23  * You should have received a copy of the GNU General Public License along
24  * with the Sparse Library. If not, see <http://www.gnu.org/licenses/>.
25  */
26 
27 
28 /*
29  * File created by:
30  * A. N. Yzelman, Dept. of Mathematics, Utrecht University, 2007.
31  */
32 
33 
34 #include <vector>
35 #include <algorithm>
36 #include "SparseMatrix.hpp"
37 #include "HilbertTriplet.hpp"
38 #include "HilbertTripletCompare.hpp"
39 #include "Triplet.hpp"
40 
41 #ifdef _DEBUG
42  #include <iostream>
43 #endif
44 
45 #ifndef _H_HTS
46 #define _H_HTS
47 
50 template< typename T >
51 class HTS: public SparseMatrix< T, ULI > {
52 
53  private:
54 
55  protected:
56 
58  ULI minexp;
59 
61  std::vector< HilbertTriplet< T > > ds;
62 
65 
66  if( left.i() == right.i() && left.j() == right.j() ) return true;
67 
68  const std::vector< unsigned long int > h_one = left.getHilbert();
69  const std::vector< unsigned long int > h_two = right.getHilbert();
70 
71  unsigned long int max = h_one.size();
72  bool max_is_one = true;
73  if ( h_two.size() < max ) { max = h_two.size(); max_is_one = false; }
74  for( unsigned long int i=0; i<max; i++ )
75  if( h_one[ i ] != h_two[ i ] )
76  return h_one[ i ] < h_two[ i ];
77 #ifdef _DEBUG
78  std::cout << "expand, ";
79 #endif
80  if ( max_is_one )
81  left.morePrecision( this->nor, this->noc );
82  else
83  right.morePrecision( this->nor, this->noc );
84 
85  return cmp( left, right );
86  }
87 
95  unsigned long int find( HilbertTriplet< T > &x, ULI &left, ULI &right ) {
96 #ifdef _DEBUG
97  std::cout << "left: " << left << ", right: " << right << std::endl;
98 #endif
99  if( ds[left].getHilbert().size() < ds[minexp].getHilbert().size() ) minexp = left;
100  if( ds[right].getHilbert().size() < ds[minexp].getHilbert().size() ) minexp = right;
101 
102  if ( left == right ) return left;
103  if ( left+1 == right ) return right;
104  if ( cmp( x, ds[ left ] ) ) return left;
105  if ( cmp( ds[ right ], x ) ) return right+1;
106 
107  ULI mid = static_cast< unsigned long int >( ( left + right ) / 2 );
108 #ifdef _DEBUG
109  std::cout << "mid: " << mid << std::endl;
110 #endif
111  if ( cmp( x, ds[ mid ] ) )
112  return find( x, left, mid );
113  else
114  return find( x, mid, right );
115  }
116 
117  public:
118 
120  HTS() {}
121 
126  HTS( std::string file, T zero = 0 ) {
127  this->loadFromFile( file, zero );
128  }
129 
138  HTS( std::vector< Triplet< T > >& input, ULI m, ULI n, T zero ) {
139  load( input, m, n, zero );
140  }
141 
143  virtual void load( std::vector< Triplet< T > >& input, const ULI m, const ULI n, const T zero ) {
144  this->zero_element = 0;
145  this->nor = m;
146  this->noc = n;
147  this->nnz = input.size();
148  for( ULI i=0; i<this->nnz; i++ ) {
149  ds.push_back( HilbertTriplet< T >( input[ i ].i(), input[ i ].j(), input[ i ].value ) );
150  ds[ i ].calculateHilbertCoordinate();
151  }
153  std::sort( ds.begin(), ds.end(), compare );
154 #ifdef _DEBUG
155  for( ULI i=0; i<this->nnz; i++ )
156  std::cout << ds[i].getMostSignificantHilbertBits() << " " << ds[i].getLeastSignificantHilbertBits() << std::endl;
157 #endif
158  }
159 
161  virtual void getFirstIndexPair( ULI &row, ULI &col ) {
162  row = ds[ 0 ].i();
163  col = ds[ 0 ].j();
164  }
165 
173  virtual void zxa( const T* x, T* z ) {
174  for( ULI i=0; i<this->nnz; i++ )
175  z[ ds[i].j() ] += ds[i].value * x[ ds[i].i() ];
176  }
177 
185  virtual void zax( const T* x, T* z ) {
186  for( ULI i=0; i<this->nnz; i++ )
187  z[ ds[i].i() ] += ds[i].value * x[ ds[i].j() ];
188  }
189 
190  virtual size_t bytesUsed() {
191  return sizeof( ULI ) * 2 * this->nnz + sizeof( T ) * this->nnz;
192  }
193 
198  void saveBinary( const std::string fn ) {
199  HilbertTriplet< T >::save( fn, ds, this->nor, this->noc );
200  }
201 
203  void loadBinary( const std::string fn ) {
204  std::cerr << "Warning: assuming binary file was saved by HTS scheme, i.e., that it is pre-ordered using Hilbert coordinates." << std::endl;
205  ds = Triplet< T >::load( fn, this->nor, this->noc );
206  }
207 
208 };
209 
210 #endif
211 
ULI nnz
Number of non-zeros.
Definition: SparseMatrix.hpp:58
static std::vector< Triplet< T > > load(const std::string fn, ULI &m, ULI &n)
Loads an array of triplets from a binary file.
Definition: Triplet.hpp:123
std::vector< HilbertTriplet< T > > ds
Vector storing the non-zeros and their locations.
Definition: HTS.hpp:61
unsigned long int find(HilbertTriplet< T > &x, ULI &left, ULI &right)
Binary search for finding a given triplet in a given range.
Definition: HTS.hpp:95
bool cmp(HilbertTriplet< T > &left, HilbertTriplet< T > &right)
HilbertCoordinate comparison function.
Definition: HTS.hpp:64
Hilbert-coordinate-aware triplet.
Definition: HilbertTriplet.hpp:46
virtual size_t bytesUsed()
Function to query the amount of storage required by this sparse matrix.
Definition: HTS.hpp:190
void saveBinary(const std::string fn)
Saves the current HTS.
Definition: HTS.hpp:198
virtual unsigned long int m()
Queries the number of rows this matrix contains.
Definition: SparseMatrix.hpp:107
Class-comparator of HilbertTriplet.
Definition: HilbertTripletCompare.hpp:41
static void save(std::string fn, HilbertTriplet< T > *toWrite, const unsigned long int m, const unsigned long int n, const size_t s)
Saves an array of Hilbert triplets to a file, in binary format.
Definition: HilbertTriplet.hpp:121
void loadFromFile(const std::string file, const T zero=0)
Function which loads a matrix from a matrix market file.
Definition: SparseMatrix.hpp:89
Interface common to all sparse matrix storage schemes.
Definition: SparseMatrix.hpp:46
ULI noc
Number of columns.
Definition: SparseMatrix.hpp:55
void loadBinary(const std::string fn)
Loads from binary triplets, assumes Hilbert ordering already done.
Definition: HTS.hpp:203
ULI nor
Number of rows.
Definition: SparseMatrix.hpp:52
T zero_element
The element considered to be zero.
Definition: SparseMatrix.hpp:63
unsigned long int i() const
Definition: HilbertTriplet.hpp:65
ULI minexp
Minimum number of expansions.
Definition: HTS.hpp:58
The Hilbert triplet scheme.
Definition: HTS.hpp:51
virtual void getFirstIndexPair(ULI &row, ULI &col)
Returns the first nonzero index, per reference.
Definition: HTS.hpp:161
HTS(std::string file, T zero=0)
Base constructor.
Definition: HTS.hpp:126
HTS(std::vector< Triplet< T > > &input, ULI m, ULI n, T zero)
Base constructor.
Definition: HTS.hpp:138
virtual void load(std::vector< Triplet< T > > &input, const ULI m, const ULI n, const T zero)
Definition: HTS.hpp:143
virtual unsigned long int n()
Queries the number of columns this matrix contains.
Definition: SparseMatrix.hpp:115
A single triplet value.
Definition: Triplet.hpp:52
HTS()
Base constructor.
Definition: HTS.hpp:120
virtual void zax(const T *x, T *z)
Calculates z=Ax.
Definition: HTS.hpp:185
unsigned long int j() const
Definition: HilbertTriplet.hpp:68
virtual void zxa(const T *x, T *z)
Calculates z=xA.
Definition: HTS.hpp:173