KADATH
magma_interface.hpp
1 /*
2  Copyright 2020 sauliac
3 
4  This file is part of Kadath.
5 
6  Kadath is free software: you can redistribute it and/or modify
7  it under the terms of the GNU General Public License as published by
8  the Free Software Foundation, either version 3 of the License, or
9  (at your option) any later version.
10 
11  Kadath is distributed in the hope that it will be useful,
12  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  GNU General Public License for more details.
15 
16  You should have received a copy of the GNU General Public License
17  along with Kadath. If not, see <http://www.gnu.org/licenses/>.
18 */
19 #ifndef __MAGMA_INTERFACE_HPP_
20 #define __MAGMA_INTERFACE_HPP_
21 
22 #include <vector>
23 #include <memory>
24 #include "config.h"
25 #include "array.hpp"
26 
27 #ifdef ENABLE_GPU_USE
28 #include "magma_v2.h"
29 #include "magma_lapack.h"
30 #endif
31 
32 
33 #define TESTING_CHECK( err ) \
34  do { \
35  magma_int_t err_ = (err); \
36  if ( err_ != 0 ) { \
37  fprintf( stderr, "Error: %s\nfailed at %s:%d: error %lld: %s\n", \
38  #err, __FILE__, __LINE__, \
39  (long long) err_, magma_strerror(err_) ); \
40  exit(1); \
41  } \
42  } while( 0 )
43 
44 
45 namespace Kadath {
46 
47 
48 #ifdef ENABLE_GPU_USE
50  template<typename T> struct Magma_allocator //: public std::allocator_traits<std::allocator<double>>
51  {
53  using value_type = T;
54  using pointer = value_type *;
55  using const_pointer = value_type const *;
56  using void_pointer = void*;
57  using const_void_pointer = void const *;
58  using size_type = std::size_t;
60  Magma_allocator() = default;
61  template<class U> constexpr Magma_allocator(Magma_allocator<U> const &) noexcept {};
62 
63  pointer allocate(std::size_t n);
64 
65  void deallocate(pointer data,std::size_t) noexcept {
66  magma_free_cpu(data);
67  }
68  };
69 
70  template<> double * Magma_allocator<double>::allocate(std::size_t n)
71  {
72  double * data{nullptr};
73  magma_int_t err{magma_dmalloc_cpu(&data,static_cast<magma_int_t>(n))};
74  if(err!= 0) throw std::bad_alloc{};
75  return data;
76  }
77  template<> magma_int_t * Magma_allocator<magma_int_t>::allocate(std::size_t n)
78  {
79  magma_int_t * data{nullptr};
80  magma_int_t err{magma_imalloc_cpu(&data,static_cast<magma_int_t>(n))};
81  if(err!= 0) throw std::bad_alloc{};
82  return data;
83  }
84 
85  //for the moment, no rebind only magma double allocators
86  template<typename A,typename B> inline constexpr bool operator==(Magma_allocator<A> const &,Magma_allocator<B> const &)
87  {return std::is_same<A,B>::value;}
88  template<typename A,typename B> inline constexpr bool operator!=(Magma_allocator<A> const &,Magma_allocator<B> const &)
89  {return !std::is_same<A,B>::value;}
90 
91 
92  class Magma_array : public std::vector<double,Magma_allocator<double>>
93  {
94  protected:
95  using Base = std::vector<double,Magma_allocator<double>>;
96  magma_int_t dim;
97  public:
98  Magma_array(std::size_t _dim) : Base(_dim),dim{static_cast<magma_int_t>(_dim)} {}
99  Magma_array(Array<double> const & source) ;
100  magma_int_t get_dim() const {return dim;}
102  Magma_array & operator=(Array<double> const &source);
103  };
108  class Magma_matrix : public Magma_array
109  {
110  public:
111  using PPivot = std::unique_ptr<std::vector<magma_int_t,Magma_allocator<magma_int_t>>>;
112  private:
114  magma_int_t order;
116  magma_int_t lda;
118  PPivot pivot;
119 
120  public:
122  Magma_matrix(std::size_t _order,std::size_t _lda=0) :
123  Magma_array{_lda==0 ? _order*_order : _order*_lda},
124  order{static_cast<magma_int_t>(_order)},
125  lda{static_cast<magma_int_t>(_lda==0 ? _order : _lda)}, pivot{nullptr}
126  {assert(lda >= std::max(1,order));}
128  Magma_matrix(Array<double> const & source,std::size_t n) : Magma_array{source},
129  order{static_cast<magma_int_t>(n)},
130  lda{static_cast<magma_int_t>(n)}, pivot{nullptr} {}
131 
132  bool is_factorized() const {return pivot != nullptr;}
133  double operator()(std::size_t i,std::size_t j) const
134  {
135  assert(0<=i && i<dim && 0<=j && j<lda);
136  return (*this)[i+lda*j];
137  }
139  double & operator()(std::size_t i,std::size_t j)
140  {
141  assert(0<=i && i<dim && 0<=j && j<lda);
142  return (*this)[i+lda*j];
143  }
144 
145  Magma_matrix & set_column(std::size_t col,Array<double> const & source)
146  {
147  assert(source.get_nbr() == order);
148  for(std::size_t i{0};i<source.get_nbr();i++)
149  {
150  (*this)(i,col) = source.get_data()[i];
151  }
152  return *this;
153  }
154 
155  magma_int_t get_order() const {return order;}
156  magma_int_t get_lda() const {return lda;}
157 
158  Magma_array & solve(Magma_array & second_member);
159  using Magma_array::operator=;
160  };
161 
162 #endif
163 
164 }
165 #endif //__MAGMA_INTERFACE_HPP_