Ginkgo  Generated from tags/v1.0.0^0 branch based on master. Ginkgo version 1.0.0
A numerical linear algebra library targeting many-core architectures
lin_op.hpp
1 /*******************************<GINKGO LICENSE>******************************
2 Copyright (c) 2017-2019, the Ginkgo authors
3 All rights reserved.
4 
5 Redistribution and use in source and binary forms, with or without
6 modification, are permitted provided that the following conditions
7 are met:
8 
9 1. Redistributions of source code must retain the above copyright
10 notice, this list of conditions and the following disclaimer.
11 
12 2. Redistributions in binary form must reproduce the above copyright
13 notice, this list of conditions and the following disclaimer in the
14 documentation and/or other materials provided with the distribution.
15 
16 3. Neither the name of the copyright holder nor the names of its
17 contributors may be used to endorse or promote products derived from
18 this software without specific prior written permission.
19 
20 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
21 IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
22 TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
23 PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24 HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25 SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26 LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 ******************************<GINKGO LICENSE>*******************************/
32 
33 #ifndef GKO_CORE_BASE_LIN_OP_HPP_
34 #define GKO_CORE_BASE_LIN_OP_HPP_
35 
36 #include <ginkgo/core/base/abstract_factory.hpp>
37 #include <ginkgo/core/base/dim.hpp>
38 #include <ginkgo/core/base/exception_helpers.hpp>
39 #include <ginkgo/core/base/matrix_data.hpp>
40 #include <ginkgo/core/base/polymorphic_object.hpp>
41 #include <ginkgo/core/base/std_extensions.hpp>
42 #include <ginkgo/core/base/types.hpp>
43 #include <ginkgo/core/base/utils.hpp>
44 #include <ginkgo/core/log/logger.hpp>
45 
46 
47 #include <memory>
48 #include <utility>
49 
50 
51 namespace gko {
52 
53 
134 class LinOp : public EnableAbstractPolymorphicObject<LinOp> {
135 public:
146  LinOp *apply(const LinOp *b, LinOp *x)
147  {
148  this->template log<log::Logger::linop_apply_started>(this, b, x);
149  this->validate_application_parameters(b, x);
150  auto exec = this->get_executor();
151  this->apply_impl(make_temporary_clone(exec, b).get(),
152  make_temporary_clone(exec, x).get());
153  this->template log<log::Logger::linop_apply_completed>(this, b, x);
154  return this;
155  }
156 
160  const LinOp *apply(const LinOp *b, LinOp *x) const
161  {
162  this->template log<log::Logger::linop_apply_started>(this, b, x);
163  this->validate_application_parameters(b, x);
164  auto exec = this->get_executor();
165  this->apply_impl(make_temporary_clone(exec, b).get(),
166  make_temporary_clone(exec, x).get());
167  this->template log<log::Logger::linop_apply_completed>(this, b, x);
168  return this;
169  }
170 
181  LinOp *apply(const LinOp *alpha, const LinOp *b, const LinOp *beta,
182  LinOp *x)
183  {
184  this->template log<log::Logger::linop_advanced_apply_started>(
185  this, alpha, b, beta, x);
186  this->validate_application_parameters(alpha, b, beta, x);
187  auto exec = this->get_executor();
188  this->apply_impl(make_temporary_clone(exec, alpha).get(),
189  make_temporary_clone(exec, b).get(),
190  make_temporary_clone(exec, beta).get(),
191  make_temporary_clone(exec, x).get());
192  this->template log<log::Logger::linop_advanced_apply_completed>(
193  this, alpha, b, beta, x);
194  return this;
195  }
196 
200  const LinOp *apply(const LinOp *alpha, const LinOp *b, const LinOp *beta,
201  LinOp *x) const
202  {
203  this->template log<log::Logger::linop_advanced_apply_started>(
204  this, alpha, b, beta, x);
205  this->validate_application_parameters(alpha, b, beta, x);
206  auto exec = this->get_executor();
207  this->apply_impl(make_temporary_clone(exec, alpha).get(),
208  make_temporary_clone(exec, b).get(),
209  make_temporary_clone(exec, beta).get(),
210  make_temporary_clone(exec, x).get());
211  this->template log<log::Logger::linop_advanced_apply_completed>(
212  this, alpha, b, beta, x);
213  return this;
214  }
215 
221  const dim<2> &get_size() const noexcept { return size_; }
222 
223 protected:
230  explicit LinOp(std::shared_ptr<const Executor> exec,
231  const dim<2> &size = dim<2>{})
232  : EnableAbstractPolymorphicObject<LinOp>(exec), size_{size}
233  {}
234 
240  void set_size(const dim<2> &value) noexcept { size_ = value; }
241 
251  virtual void apply_impl(const LinOp *b, LinOp *x) const = 0;
252 
262  virtual void apply_impl(const LinOp *alpha, const LinOp *b,
263  const LinOp *beta, LinOp *x) const = 0;
264 
272  void validate_application_parameters(const LinOp *b, const LinOp *x) const
273  {
274  GKO_ASSERT_CONFORMANT(this, b);
275  GKO_ASSERT_EQUAL_ROWS(this, x);
276  GKO_ASSERT_EQUAL_COLS(b, x);
277  }
278 
288  void validate_application_parameters(const LinOp *alpha, const LinOp *b,
289  const LinOp *beta,
290  const LinOp *x) const
291  {
292  this->validate_application_parameters(b, x);
293  GKO_ASSERT_EQUAL_DIMENSIONS(alpha, dim<2>(1, 1));
294  GKO_ASSERT_EQUAL_DIMENSIONS(beta, dim<2>(1, 1));
295  }
296 
297 private:
298  dim<2> size_{};
299 };
300 
301 
358 public:
360 
361  std::unique_ptr<LinOp> generate(std::shared_ptr<const LinOp> input) const
362  {
363  this->template log<log::Logger::linop_factory_generate_started>(
364  this, input.get());
365  auto generated = AbstractFactory::generate(input);
366  this->template log<log::Logger::linop_factory_generate_completed>(
367  this, input.get(), generated.get());
368  return generated;
369  }
370 };
371 
372 
399 public:
400  virtual ~Transposable() = default;
401 
407  virtual std::unique_ptr<LinOp> transpose() const = 0;
408 
415  virtual std::unique_ptr<LinOp> conj_transpose() const = 0;
416 };
417 
418 
425 template <typename ValueType, typename IndexType>
427 public:
428  virtual ~ReadableFromMatrixData() = default;
429 
435  virtual void read(const matrix_data<ValueType, IndexType> &data) = 0;
436 };
437 
438 
445 template <typename ValueType, typename IndexType>
447 public:
448  virtual ~WritableToMatrixData() = default;
449 
455  virtual void write(matrix_data<ValueType, IndexType> &data) const = 0;
456 };
457 
458 
466 public:
467  virtual ~Preconditionable() = default;
468 
474  virtual std::shared_ptr<const LinOp> get_preconditioner() const = 0;
475 };
476 
477 
508 template <typename ConcreteLinOp, typename PolymorphicBase = LinOp>
512 public:
513  using EnablePolymorphicObject<ConcreteLinOp,
514  PolymorphicBase>::EnablePolymorphicObject;
515 
516  const ConcreteLinOp *apply(const LinOp *b, LinOp *x) const
517  {
518  this->template log<log::Logger::linop_apply_started>(this, b, x);
519  this->validate_application_parameters(b, x);
520  auto exec = this->get_executor();
521  this->apply_impl(make_temporary_clone(exec, b).get(),
522  make_temporary_clone(exec, x).get());
523  this->template log<log::Logger::linop_apply_completed>(this, b, x);
524  return self();
525  }
526 
527  ConcreteLinOp *apply(const LinOp *b, LinOp *x)
528  {
529  this->template log<log::Logger::linop_apply_started>(this, b, x);
530  this->validate_application_parameters(b, x);
531  auto exec = this->get_executor();
532  this->apply_impl(make_temporary_clone(exec, b).get(),
533  make_temporary_clone(exec, x).get());
534  this->template log<log::Logger::linop_apply_completed>(this, b, x);
535  return self();
536  }
537 
538  const ConcreteLinOp *apply(const LinOp *alpha, const LinOp *b,
539  const LinOp *beta, LinOp *x) const
540  {
541  this->template log<log::Logger::linop_advanced_apply_started>(
542  this, alpha, b, beta, x);
543  this->validate_application_parameters(alpha, b, beta, x);
544  auto exec = this->get_executor();
545  this->apply_impl(make_temporary_clone(exec, alpha).get(),
546  make_temporary_clone(exec, b).get(),
547  make_temporary_clone(exec, beta).get(),
548  make_temporary_clone(exec, x).get());
549  this->template log<log::Logger::linop_advanced_apply_completed>(
550  this, alpha, b, beta, x);
551  return self();
552  }
553 
554  ConcreteLinOp *apply(const LinOp *alpha, const LinOp *b, const LinOp *beta,
555  LinOp *x)
556  {
557  this->template log<log::Logger::linop_advanced_apply_started>(
558  this, alpha, b, beta, x);
559  this->validate_application_parameters(alpha, b, beta, x);
560  auto exec = this->get_executor();
561  this->apply_impl(make_temporary_clone(exec, alpha).get(),
562  make_temporary_clone(exec, b).get(),
563  make_temporary_clone(exec, beta).get(),
564  make_temporary_clone(exec, x).get());
565  this->template log<log::Logger::linop_advanced_apply_completed>(
566  this, alpha, b, beta, x);
567  return self();
568  }
569 
570 protected:
571  GKO_ENABLE_SELF(ConcreteLinOp);
572 };
573 
574 
592 template <typename ConcreteFactory, typename ConcreteLinOp,
593  typename ParametersType, typename PolymorphicBase = LinOpFactory>
595  EnableDefaultFactory<ConcreteFactory, ConcreteLinOp, ParametersType,
596  PolymorphicBase>;
597 
611 #define GKO_CREATE_FACTORY_PARAMETERS(_parameters_name, _factory_name) \
612 public: \
613  class _factory_name; \
614  struct _parameters_name##_type \
615  : ::gko::enable_parameters_type<_parameters_name##_type, \
616  _factory_name>
617 
618 
691 #define GKO_ENABLE_LIN_OP_FACTORY(_lin_op, _parameters_name, _factory_name) \
692 public: \
693  const _parameters_name##_type &get_##_parameters_name() const \
694  { \
695  return _parameters_name##_; \
696  } \
697  \
698  class _factory_name \
699  : public ::gko::EnableDefaultLinOpFactory<_factory_name, _lin_op, \
700  _parameters_name##_type> { \
701  friend class ::gko::EnablePolymorphicObject<_factory_name, \
702  ::gko::LinOpFactory>; \
703  friend class ::gko::enable_parameters_type<_parameters_name##_type, \
704  _factory_name>; \
705  using ::gko::EnableDefaultLinOpFactory< \
706  _factory_name, _lin_op, \
707  _parameters_name##_type>::EnableDefaultLinOpFactory; \
708  }; \
709  friend ::gko::EnableDefaultLinOpFactory<_factory_name, _lin_op, \
710  _parameters_name##_type>; \
711  \
712  \
713 private: \
714  _parameters_name##_type _parameters_name##_; \
715  \
716 public: \
717  static_assert(true, \
718  "This assert is used to counter the false positive extra " \
719  "semi-colon warnings")
720 
721 
730 #define GKO_ENABLE_BUILD_METHOD(_factory_name) \
731  static auto build()->decltype(_factory_name::create()) \
732  { \
733  return _factory_name::create(); \
734  } \
735  static_assert(true, \
736  "This assert is used to counter the false positive extra " \
737  "semi-colon warnings")
738 
739 
740 #ifndef __CUDACC__
741 
751 #define GKO_FACTORY_PARAMETER(_name, ...) \
752  mutable _name{__VA_ARGS__}; \
753  \
754  template <typename... Args> \
755  auto with_##_name(Args &&... _value) \
756  const->const ::gko::xstd::decay_t<decltype(*this)> & \
757  { \
758  using type = decltype(this->_name); \
759  this->_name = type{std::forward<Args>(_value)...}; \
760  return *this; \
761  } \
762  static_assert(true, \
763  "This assert is used to counter the false positive extra " \
764  "semi-colon warnings")
765 #else // __CUDACC__
766 // A workaround for the NVCC compiler - parameter pack expansion does not work
767 // properly. You won't be able to use factories in code compiled with NVCC, but
768 // at least this won't trigger a compiler error as soon as a header using it is
769 // included.
770 #define GKO_FACTORY_PARAMETER(_name, ...) \
771  mutable _name{__VA_ARGS__}; \
772  \
773  template <typename... Args> \
774  auto with_##_name(Args &&... _value) \
775  const->const ::gko::xstd::decay_t<decltype(*this)> &
776 #endif // __CUDACC__
777 
778 
779 } // namespace gko
780 
781 
782 #endif // GKO_CORE_BASE_LIN_OP_HPP_
This mixin inherits from (a subclass of) PolymorphicObject and provides a base implementation of a ne...
Definition: polymorphic_object.hpp:285
const LinOp * apply(const LinOp *b, LinOp *x) const
Applies a linear operator to a vector (or a sequence of vectors).
Definition: lin_op.hpp:160
std::unique_ptr< AbstractProductType > generate(Args &&... args) const
Creates a new product from the given components.
Definition: abstract_factory.hpp:92
void write(StreamType &&os, MatrixType *matrix, layout_type layout=layout_type::array)
Reads a matrix stored in matrix market format from an input stream.
Definition: mtx_io.hpp:134
A LinOpFactory represents a higher order mapping which transforms one linear operator into another...
Definition: lin_op.hpp:356
const LinOp * apply(const LinOp *alpha, const LinOp *b, const LinOp *beta, LinOp *x) const
Performs the operation x = alpha * op(b) + beta * x.
Definition: lin_op.hpp:200
The Ginkgo namespace.
Definition: abstract_factory.hpp:45
This mixin provides a default implementation of a concrete factory.
Definition: abstract_factory.hpp:148
Definition: lin_op.hpp:134
The EnableLinOp mixin can be used to provide sensible default implementations of the majority of the ...
Definition: lin_op.hpp:509
std::unique_ptr< MatrixType > read(StreamType &&is, MatrixArgs &&... args)
Reads a matrix stored in matrix market format from an input stream.
Definition: mtx_io.hpp:113
const dim< 2 > & get_size() const noexcept
Returns the size of the operator.
Definition: lin_op.hpp:221
The AbstractFactory is a generic interface template that enables easy implementation of the abstract ...
Definition: abstract_factory.hpp:70
A LinOp implementing this interface can be preconditioned.
Definition: lin_op.hpp:465
LinOp * apply(const LinOp *b, LinOp *x)
Applies a linear operator to a vector (or a sequence of vectors).
Definition: lin_op.hpp:146
std::shared_ptr< const Executor > get_executor() const noexcept
Returns the Executor of the object.
Definition: polymorphic_object.hpp:201
A LinOp implementing this interface can write its data to a matrix_data structure.
Definition: lin_op.hpp:446
Linear operators which support transposition should implement the Transposable interface.
Definition: lin_op.hpp:398
This structure is used as an intermediate data type to store a sparse matrix.
Definition: matrix_data.hpp:102
A LinOp implementing this interface can read its data from a matrix_data structure.
Definition: lin_op.hpp:426
constexpr dim< 2, DimensionType > transpose(const dim< 2, DimensionType > &dimensions) noexcept
Returns a dim<2> object with its dimensions swapped.
Definition: dim.hpp:234
temporary_clone< T > make_temporary_clone(std::shared_ptr< const Executor > exec, T *ptr)
Creates a temporary_clone.
Definition: utils.hpp:474
LinOp * apply(const LinOp *alpha, const LinOp *b, const LinOp *beta, LinOp *x)
Performs the operation x = alpha * op(b) + beta * x.
Definition: lin_op.hpp:181