Program Listing for File core.hpp

Return to documentation for file (/tmp/ws/src/proxsuite/include/proxsuite/linalg/sparse/core.hpp)

//
// Copyright (c) 2022 INRIA
//
#ifndef PROXSUITE_LINALG_SPARSE_LDLT_CORE_HPP
#define PROXSUITE_LINALG_SPARSE_LDLT_CORE_HPP

#include <proxsuite/linalg/veg/slice.hpp>
#include <proxsuite/linalg/veg/memory/dynamic_stack.hpp>
#include <type_traits>
#include <Eigen/SparseCore>

#define SPARSE_LDLT_CONCEPT(...)                                               \
  VEG_CONCEPT_MACRO(::proxsuite::linalg::sparse::concepts, __VA_ARGS__)
#define SPARSE_LDLT_CHECK_CONCEPT(...)                                         \
  VEG_CONCEPT_MACRO(::proxsuite::linalg::sparse::concepts, __VA_ARGS__)

namespace proxsuite {
namespace linalg {
namespace sparse {
using proxsuite::linalg::veg::dynstack::DynStackMut;
using namespace proxsuite::linalg::veg::literals;

using proxsuite::linalg::veg::isize;
using proxsuite::linalg::veg::usize;

using proxsuite::linalg::veg::Slice;
using proxsuite::linalg::veg::SliceMut;

using proxsuite::linalg::veg::mut;
using proxsuite::linalg::veg::Ref;
using proxsuite::linalg::veg::ref;
using proxsuite::linalg::veg::RefMut;

inline namespace tags {
using proxsuite::linalg::veg::Unsafe;
using proxsuite::linalg::veg::unsafe;

using proxsuite::linalg::veg::from_raw_parts;
using proxsuite::linalg::veg::FromRawParts;
VEG_TAG(from_eigen, FromEigen);
} // namespace tags

namespace concepts {
} // namespace concepts

namespace _detail {
template<typename I, bool = sizeof(I) < sizeof(int)>
struct WrappingPlusType;

template<typename I>
struct WrappingPlusType<I, true>
{
  using Promoted = unsigned;
};
template<typename I>
struct WrappingPlusType<I, false>
{
  using Promoted = typename std::make_unsigned<I>::type;
};
} // namespace _detail
namespace util {
namespace nb {
struct wrapping_plus
{
  template<typename I>
  auto operator()(I a, I b) const noexcept -> I
  {
    using U = typename _detail::WrappingPlusType<I>::Promoted;
    return I(U(a) + U(b));
  }
};
struct checked_non_negative_plus
{
  template<typename I>
  auto operator()(I a, I b) const noexcept -> I
  {
    return (VEG_ASSERT(wrapping_plus{}(a, b) >= a), //
            wrapping_plus{}(a, b));
  }
};

struct wrapping_inc
{
  template<typename I>
  auto operator()(RefMut<I> a) const noexcept -> I
  {
    return a.get() = wrapping_plus{}(a.get(), I(1));
  }
};
struct wrapping_dec
{
  template<typename I>
  auto operator()(RefMut<I> a) const noexcept -> I
  {
    return a.get() = wrapping_plus{}(a.get(), I(-1));
  }
};
struct sign_extend
{
  template<typename I>
  auto operator()(I a) const noexcept -> usize
  {
    return usize(isize(typename std::make_signed<I>::type(a)));
  }
};
struct zero_extend
{
  template<typename I>
  auto operator()(I a) const noexcept -> usize
  {
    return usize(typename std::make_unsigned<I>::type(a));
  }
};
} // namespace nb
VEG_NIEBLOID(wrapping_plus);
VEG_NIEBLOID(checked_non_negative_plus);
VEG_NIEBLOID(wrapping_inc);
VEG_NIEBLOID(wrapping_dec);
VEG_NIEBLOID(sign_extend);
VEG_NIEBLOID(zero_extend);
} // namespace util

template<typename T>
struct DenseVecRef
{
  DenseVecRef() = default;
  DenseVecRef(FromRawParts /*from_raw_parts*/,
              T const* data,
              isize len) noexcept
    : _{ data, len }
  {
  }
  template<typename V>
  DenseVecRef(FromEigen /*from_eigen*/, V const& v) noexcept
    : _{ v.data(), v.rows() }
  {
    static_assert(V::InnerStrideAtCompileTime == 1, ".");
    static_assert(V::ColsAtCompileTime == 1, ".");
  }

  auto as_slice() const noexcept -> Slice<T>
  {
    return {
      unsafe,
      from_raw_parts,
      _.ptr,
      _.size,
    };
  }
  auto nrows() const noexcept -> isize { return _.size; }
  auto ncols() const noexcept -> isize { return 1; }

  auto to_eigen() const noexcept -> Eigen::Map<Eigen::Matrix<T, -1, 1> const>
  {
    return { _.ptr, _.size };
  }

private:
  struct
  {
    T const* ptr;
    isize size;
  } _ = {};
};

template<typename T>
struct DenseVecMut
{
  DenseVecMut() = default;
  DenseVecMut(FromRawParts /*from_raw_parts*/, T* data, isize len) noexcept
    : _{ data, len }
  {
  }
  template<typename V>
  DenseVecMut(FromEigen /*from_eigen*/, V&& v) noexcept
    : _{ v.data(), v.rows() }
  {
    static_assert(
      proxsuite::linalg::veg::uncvref_t<V>::InnerStrideAtCompileTime == 1, ".");
    static_assert(proxsuite::linalg::veg::uncvref_t<V>::ColsAtCompileTime == 1,
                  ".");
  }

  auto as_slice() const noexcept -> Slice<T>
  {
    return {
      unsafe,
      from_raw_parts,
      _.ptr,
      _.size,
    };
  }
  auto as_slice_mut() noexcept -> SliceMut<T>
  {
    return {
      unsafe,
      from_raw_parts,
      _.ptr,
      _.size,
    };
  }

  auto as_const() const noexcept -> DenseVecRef<T>
  {
    return { from_raw_parts, _.ptr, _.size };
  }
  auto nrows() const noexcept -> isize { return _.size; }
  auto ncols() const noexcept -> isize { return 1; }

  auto to_eigen() const noexcept -> Eigen::Map<Eigen::Matrix<T, -1, 1>>
  {
    return { _.ptr, _.size };
  }

private:
  struct
  {
    T* ptr;
    isize size;
  } _ = {};
};

template<typename T, typename I = isize>
struct VecRef
{
  VecRef( //
    FromRawParts /*from_raw_parts*/,
    isize nrows,
    isize nnz,
    I const* row_indices,
    T const* values)
    : _{ nrows, nnz, row_indices, values }
  {
  }

  auto nrows() const noexcept -> isize { return _.nrows; }
  auto ncols() const noexcept -> isize { return 1; }
  auto nnz() const noexcept -> isize { return _.nnz; }

  auto row_indices() const noexcept -> I const* { return _.row; }
  auto values() const noexcept -> T const* { return _.val; }

private:
  struct
  {
    isize nrows;
    isize nnz;
    I const* row;
    T const* val;
  } _;
};

namespace _detail {
template<typename D, typename I>
struct SymbolicMatRefInterface
{
private:
  template<typename U = D>
  auto _() const noexcept -> decltype((VEG_DECLVAL(U const&)._))
  {
    return static_cast<D const*>(this)->_;
  }

public:
  auto nrows() const noexcept -> isize { return _().nrows; }
  auto ncols() const noexcept -> isize { return _().ncols; }
  auto nnz() const noexcept -> isize { return _().nnz; }

  auto col_ptrs() const noexcept -> I const* { return _().col; }
  auto nnz_per_col() const noexcept -> I const* { return _().nnz_per_col; }
  auto is_compressed() const noexcept -> bool
  {
    return nnz_per_col() == nullptr;
  }

  auto row_indices() const noexcept -> I const* { return _().row; }

  auto col_start(usize j) const noexcept -> usize
  {
    return VEG_ASSERT(j < usize(ncols())), util::zero_extend(_().col[j]);
  }
  auto col_start_unchecked(Unsafe /*unsafe*/, usize j) const noexcept -> usize
  {
    return VEG_DEBUG_ASSERT(j < usize(ncols())), util::zero_extend(_().col[j]);
  }
  auto col_end(usize j) const noexcept -> usize
  {
    return VEG_ASSERT(j < usize(ncols())), col_end_unchecked(unsafe, j);
  }
  auto col_end_unchecked(Unsafe /*unsafe*/, usize j) const noexcept -> usize
  {
    return VEG_DEBUG_ASSERT(j < usize(ncols())),
           util::zero_extend(is_compressed()
                               ? _().col[j + 1]
                               : I(_().col[j] + _().nnz_per_col[j]));
  }
};
template<typename D, typename I>
struct SymbolicMatMutInterface : SymbolicMatRefInterface<D, I>
{
private:
  template<typename U = D>
  auto _() noexcept -> decltype((VEG_DECLVAL(U&)._))
  {
    return static_cast<D*>(this)->_;
  }

public:
  auto col_ptrs_mut() noexcept -> I* { return _().col; }
  auto nnz_per_col_mut() noexcept -> I* { return _().nnz_per_col; }
  auto row_indices_mut() noexcept -> I* { return _().row; }
};
} // namespace _detail

template<typename I = isize>
struct SymbolicMatRef : _detail::SymbolicMatRefInterface<SymbolicMatRef<I>, I>
{
  friend struct _detail::SymbolicMatRefInterface<SymbolicMatRef, I>;
  SymbolicMatRef(FromRawParts /*from_raw_parts*/,
                 isize nrows,
                 isize ncols,
                 isize nnz,
                 I const* col_ptrs,
                 I const* nnz_per_col,
                 I const* row_indices)
    : _{
      nrows, ncols, nnz, col_ptrs, nnz_per_col, row_indices,
    }
  {
  }

private:
  struct
  {
    isize nrows;
    isize ncols;
    isize nnz;
    I const* col;
    I const* nnz_per_col;
    I const* row;
  } _;
};
template<typename I = isize>
struct SymbolicMatMut : _detail::SymbolicMatMutInterface<SymbolicMatMut<I>, I>
{
  friend struct _detail::SymbolicMatRefInterface<SymbolicMatMut, I>;
  friend struct _detail::SymbolicMatMutInterface<SymbolicMatMut, I>;
  SymbolicMatMut(FromRawParts /*from_raw_parts*/,
                 isize nrows,
                 isize ncols,
                 isize nnz,
                 I* col_ptrs,
                 I* nnz_per_col,
                 I* row_indices)
    : _{
      nrows, ncols, nnz, col_ptrs, nnz_per_col, row_indices,
    }
  {
  }

  auto as_const() const noexcept -> SymbolicMatRef<I>
  {
    return {
      from_raw_parts,   this->nrows(),       this->ncols(),       this->nnz(),
      this->col_ptrs(), this->nnz_per_col(), this->row_indices(),
    };
  }

private:
  struct
  {
    isize nrows;
    isize ncols;
    isize nnz;
    I* col;
    I* nnz_per_col;
    I* row;
  } _;
};

template<typename T, typename I = isize>
struct MatRef : _detail::SymbolicMatRefInterface<MatRef<T, I>, I>
{
  friend struct _detail::SymbolicMatRefInterface<MatRef, I>;
  MatRef(FromRawParts /*from_raw_parts*/,
         isize nrows,
         isize ncols,
         isize nnz,
         I const* col_ptrs,
         I const* nnz_per_col,
         I const* row_indices,
         T const* values)
    : _{
      nrows, ncols, nnz, col_ptrs, nnz_per_col, row_indices, values,
    }
  {
  }

  template<typename M>
  MatRef(FromEigen /*from_eigen*/, M const& m)
    : _{
      m.rows(),
      m.cols(),
      m.nonZeros(),
      m.outerIndexPtr(),
      m.innerNonZeroPtr(),
      m.innerIndexPtr(),
      m.valuePtr(),
    }
  {
    static_assert(!bool(M::IsRowMajor), ".");
  }

  auto values() const noexcept -> T const* { return _.val; }
  auto symbolic() const noexcept -> SymbolicMatRef<I>
  {
    return {
      from_raw_parts,   this->nrows(),       this->ncols(),       this->nnz(),
      this->col_ptrs(), this->nnz_per_col(), this->row_indices(),
    };
  }

  auto to_eigen() const noexcept
    -> Eigen::Map<Eigen::SparseMatrix<T, Eigen::ColMajor, I> const>
  {
    return { _.nrows, _.ncols, _.nnz, _.col, _.row, _.val, _.nnz_per_col };
  }

private:
  struct
  {
    isize nrows;
    isize ncols;
    isize nnz;
    I const* col;
    I const* nnz_per_col;
    I const* row;
    T const* val;
  } _;
};

template<typename T, typename I = isize>
struct MatMut : _detail::SymbolicMatMutInterface<MatMut<T, I>, I>
{
  friend struct _detail::SymbolicMatRefInterface<MatMut, I>;
  friend struct _detail::SymbolicMatMutInterface<MatMut, I>;
  MatMut(FromRawParts /*from_raw_parts*/,
         isize nrows,
         isize ncols,
         isize nnz,
         I* col_ptrs,
         I* nnz_per_col,
         I* row_indices,
         T* values)
    : _{
      nrows, ncols, nnz, col_ptrs, nnz_per_col, row_indices, values,
    }
  {
  }

  template<typename M>
  MatMut(FromEigen /*from_eigen*/, M&& m)
    : _{
      m.rows(),
      m.cols(),
      m.nonZeros(),
      m.outerIndexPtr(),
      m.innerNonZeroPtr(),
      m.innerIndexPtr(),
      m.valuePtr(),
    }
  {
    static_assert(!bool(proxsuite::linalg::veg::uncvref_t<M>::IsRowMajor), ".");
  }

  auto values() const noexcept -> T const* { return _.val; }
  auto values_mut() const noexcept -> T* { return _.val; }
  auto is_compressed() const noexcept -> bool
  {
    return _.nnz_per_col == nullptr;
  }

  auto as_const() const noexcept -> MatRef<T, I>
  {
    return {
      from_raw_parts,      this->nrows(),    this->ncols(),
      this->nnz(),         this->col_ptrs(), this->nnz_per_col(),
      this->row_indices(), this->values(),
    };
  }
  auto symbolic() const noexcept -> SymbolicMatRef<I>
  {
    return {
      from_raw_parts,   this->nrows(),       this->ncols(),       this->nnz(),
      this->col_ptrs(), this->nnz_per_col(), this->row_indices(),
    };
  }
  auto symbolic_mut() const noexcept -> SymbolicMatRef<I>
  {
    return {
      from_raw_parts,          this->nrows(),
      this->ncols(),           this->nnz(),
      this->col_ptrs_mut(),    this->nnz_per_col_mut(),
      this->row_indices_mut(),
    };
  }
  auto to_eigen() const noexcept
    -> Eigen::Map<Eigen::SparseMatrix<T, Eigen::ColMajor, I>>
  {
    return { _.nrows, _.ncols, _.nnz, _.col, _.row, _.val, _.nnz_per_col };
  }
  void _set_nnz(isize new_nnz) noexcept { _.nnz = new_nnz; }

private:
  struct
  {
    isize nrows;
    isize ncols;
    isize nnz;
    I* col;
    I* nnz_per_col;
    I* row;
    T* val;
  } _;
};
} // namespace sparse
} // namespace linalg
} // namespace proxsuite

#endif /* end of include guard PROXSUITE_LINALG_SPARSE_LDLT_CORE_HPP */