26 #ifndef TILEDARRAY_SPARSE_SHAPE_H__INCLUDED 27 #define TILEDARRAY_SPARSE_SHAPE_H__INCLUDED 60 "SparseShape<T> only supports scalar numeric types for T");
66 static_assert(std::is_floating_point<T>::value,
67 "SparseShape template type T must be a floating point type");
73 std::shared_ptr<vector_type> size_vectors_;
77 template <
typename Op>
79 recursive_outer_product(
const vector_type*
const size_vectors,
80 const unsigned int dim,
const Op& op)
86 result = op(*size_vectors);
89 const unsigned int middle = (dim >> 1u) + (dim & 1u);
90 const vector_type left = recursive_outer_product(size_vectors, middle, op);
91 const vector_type right = recursive_outer_product(size_vectors + middle, dim - middle, op);
95 result = vector_type(left.size() * right.size());
111 const unsigned int dim = tile_norms_.
range().
rank();
112 const vector_type* MADNESS_RESTRICT
const size_vectors = size_vectors_.get();
113 madness::AtomicInt zero_tile_count;
129 size_vectors[0].data());
136 auto inv_vec_op = [] (
const vector_type& size_vector) {
137 return vector_type(size_vector,
142 const unsigned int middle = (dim >> 1u) + (dim & 1u);
143 const vector_type left = recursive_outer_product(size_vectors, middle, inv_vec_op);
144 const vector_type right = recursive_outer_product(size_vectors + middle, dim - middle, inv_vec_op);
157 math::outer(left.size(), right.size(), left.data(), right.data(),
158 tile_norms_.
data(), normalize_op);
161 zero_tile_count_ = zero_tile_count;
164 static std::shared_ptr<vector_type>
165 initialize_size_vectors(
const TiledRange& trange) {
167 const unsigned int dim = trange.tiles_range().rank();
168 std::shared_ptr<vector_type> size_vectors(
new vector_type[dim],
169 std::default_delete<vector_type[]>());
172 for(
unsigned int i = 0ul; i != dim; ++i) {
173 const size_type n = trange.
data()[i].tiles_range().second - trange.data()[i].tiles_range().first;
175 size_vectors.get()[i] = vector_type(n, & (* trange.data()[i].begin()),
177 {
return value_type(tile.second - tile.first); });
183 std::shared_ptr<vector_type> perm_size_vectors(
const Permutation&
perm)
const {
184 const unsigned int n = tile_norms_.
range().
rank();
187 std::shared_ptr<vector_type> result_size_vectors(
new vector_type[n],
188 std::default_delete<vector_type[]>());
191 for(
unsigned int i = 0u; i < n; ++i) {
192 const unsigned int perm_i =
perm[i];
193 result_size_vectors.get()[perm_i] = size_vectors_.get()[i];
196 return result_size_vectors;
199 SparseShape(
const Tensor<T>& tile_norms,
const std::shared_ptr<vector_type>& size_vectors,
201 tile_norms_(tile_norms), size_vectors_(size_vectors),
202 zero_tile_count_(zero_tile_count)
210 SparseShape() : tile_norms_(), size_vectors_(), zero_tile_count_(0ul) { }
220 tile_norms_(tile_norms.
clone()), size_vectors_(initialize_size_vectors(trange)),
221 zero_tile_count_(0ul)
239 template<
typename SparseNormSequence>
242 tile_norms_(trange.tiles_range(),
value_type(0)), size_vectors_(initialize_size_vectors(trange)),
243 zero_tile_count_(trange.tiles_range().volume())
245 const auto dim = tile_norms_.
range().
rank();
246 for(
const auto& pair_idx_norm: tile_norms) {
247 auto compute_tile_volume = [dim,
this,pair_idx_norm]() -> uint64_t {
248 uint64_t tile_volume = 1;
249 for(
size_t d=0;d != dim; ++d)
250 tile_volume *= size_vectors_.get()[d].at(pair_idx_norm.first[d]);
253 auto norm_per_element = pair_idx_norm.second / compute_tile_volume();
255 tile_norms_[pair_idx_norm.first] = norm_per_element;
273 tile_norms_(tile_norms.
clone()), size_vectors_(initialize_size_vectors(trange)),
274 zero_tile_count_(0ul)
280 world.gop.sum(tile_norms_.
data(), tile_norms_.
size());
297 template<
typename SparseNormSequence>
299 const SparseNormSequence& tile_norms,
302 world.gop.sum(tile_norms_.
data(), tile_norms_.
size());
310 tile_norms_(other.tile_norms_), size_vectors_(other.size_vectors_),
311 zero_tile_count_(other.zero_tile_count_)
320 tile_norms_ = other.tile_norms_;
321 size_vectors_ = other.size_vectors_;
322 zero_tile_count_ = other.zero_tile_count_;
330 if(tile_norms_.
empty())
332 return (range == tile_norms_.
range());
339 template <
typename Index>
342 return tile_norms_[i] < threshold_;
355 return float(zero_tile_count_) / float(tile_norms_.
size());
373 template <
typename Index>
376 return tile_norms_[index];
388 template<
typename Op>
392 madness::AtomicInt zero_tile_count;
407 return SparseShape_(std::move(new_norms), size_vectors_,
431 madness::AtomicInt zero_tile_count;
432 zero_tile_count = zero_tile_count_;
445 tile_norms_.
binary(mask_shape.tile_norms_, op);
447 return SparseShape_(result_tile_norms, size_vectors_, zero_tile_count);
459 template <
typename Index>
465 auto result_tile_norms_blk = result_tile_norms.
block(lower_bound, upper_bound);
467 madness::AtomicInt zero_tile_count;
468 zero_tile_count = zero_tile_count_;
469 result_tile_norms_blk.inplace_binary(other.tile_norms_,
472 if((l < threshold) && (r >= threshold))
474 else if((l >= threshold) && (r < threshold))
481 return SparseShape_(result_tile_norms, size_vectors_, zero_tile_count);
491 template <
typename Index>
492 std::shared_ptr<vector_type>
493 block_range(
const Index& lower_bound,
const Index& upper_bound)
const {
499 const auto* MADNESS_RESTRICT
const lower =
detail::data(lower_bound);
500 const auto* MADNESS_RESTRICT
const upper =
detail::data(upper_bound);
502 std::shared_ptr<vector_type> size_vectors(
new vector_type[rank],
503 std::default_delete<vector_type[]>());
505 for(
auto i = 0ul; i < rank; ++i) {
507 const auto lower_i = lower[i];
508 const auto upper_i = upper[i];
509 const auto extent_i = upper_i - lower_i;
516 size_vectors.get()[i] = vector_type(extent_i,
517 size_vectors_.get()[i].data() + lower_i);
529 template <
typename Index>
531 std::shared_ptr<vector_type> size_vectors =
532 block_range(lower_bound, upper_bound);
536 madness::AtomicInt zero_tile_count;
549 tile_norms_.
block(lower_bound, upper_bound);
553 return SparseShape(result_norms, size_vectors, zero_tile_count);
564 template <
typename Index,
typename Factor>
566 const Factor factor)
const 568 const value_type abs_factor = to_abs_factor(factor);
569 std::shared_ptr<vector_type> size_vectors =
570 block_range(lower_bound, upper_bound);
574 madness::AtomicInt zero_tile_count;
576 auto copy_op = [abs_factor,
threshold,&zero_tile_count] (
value_type& MADNESS_RESTRICT result,
579 result = arg * abs_factor;
588 tile_norms_.
block(lower_bound, upper_bound);
592 return SparseShape(result_norms, size_vectors, zero_tile_count);
599 template <
typename Index>
613 template <
typename Index,
typename Factor>
639 template <
typename Factor>
643 const value_type abs_factor = to_abs_factor(factor);
644 madness::AtomicInt zero_tile_count;
657 return SparseShape_(result_tile_norms, size_vectors_, zero_tile_count);
671 template <
typename Factor>
675 const value_type abs_factor = to_abs_factor(factor);
676 madness::AtomicInt zero_tile_count;
704 madness::AtomicInt zero_tile_count;
718 tile_norms_.
binary(other.tile_norms_, op);
720 return SparseShape_(result_tile_norms, size_vectors_, zero_tile_count);
735 madness::AtomicInt zero_tile_count;
749 tile_norms_.
binary(other.tile_norms_, op,
perm);
766 template <
typename Factor>
770 const value_type abs_factor = to_abs_factor(factor);
771 madness::AtomicInt zero_tile_count;
786 tile_norms_.
binary(other.tile_norms_, op);
788 return SparseShape_(result_tile_norms, size_vectors_, zero_tile_count);
803 template <
typename Factor>
809 const value_type abs_factor = to_abs_factor(factor);
810 madness::AtomicInt zero_tile_count;
812 auto op = [
threshold, &zero_tile_count, abs_factor]
825 tile_norms_.
binary(other.tile_norms_, op,
perm);
834 madness::AtomicInt zero_tile_count;
840 const unsigned int dim = tile_norms_.
range().
rank();
841 const vector_type* MADNESS_RESTRICT
const size_vectors = size_vectors_.get();
858 tile_norms_.
data(), size_vectors[0].data());
865 auto inv_sqrt_vec_op = [] (
const vector_type size_vector) {
871 const unsigned int middle = (dim >> 1u) + (dim & 1u);
872 const vector_type left = recursive_outer_product(size_vectors, middle, inv_sqrt_vec_op);
873 const vector_type right = recursive_outer_product(size_vectors + middle, dim - middle, inv_sqrt_vec_op);
876 tile_norms_.
data(), result_tile_norms.data(),
880 norm += value * x * y;
888 return SparseShape_(result_tile_norms, size_vectors_, zero_tile_count);
905 template <
typename Factor>
907 return add(other, factor);
910 template <
typename Factor>
914 return add(other, factor,
perm);
928 const vector_type* MADNESS_RESTRICT
const size_vectors)
930 const unsigned int dim = tile_norms.
range().rank();
932 madness::AtomicInt zero_tile_count;
946 size_vectors[0].size(), tile_norms.
data(), size_vectors[0].data());
952 auto noop = [](
const vector_type& size_vector) ->
const vector_type& {
957 const unsigned int middle = (dim >> 1u) + (dim & 1u);
958 const vector_type left = recursive_outer_product(size_vectors, middle, noop);
959 const vector_type right = recursive_outer_product(size_vectors + middle, dim - middle, noop);
961 math::outer(left.size(), right.size(), left.data(), right.data(), tile_norms.
data(),
973 return zero_tile_count;
983 Tensor<T> result_tile_norms = tile_norms_.
mult(other.tile_norms_);
985 scale_by_size(result_tile_norms, size_vectors_.get());
987 return SparseShape_(result_tile_norms, size_vectors_, zero_tile_count);
996 std::shared_ptr<vector_type> result_size_vector = perm_size_vectors(
perm);
998 scale_by_size(result_tile_norms, result_size_vector.get());
1000 return SparseShape_(result_tile_norms, result_size_vector, zero_tile_count);
1005 template <
typename Factor>
1011 const value_type abs_factor = to_abs_factor(factor);
1012 Tensor<T> result_tile_norms = tile_norms_.
mult(other.tile_norms_, abs_factor);
1014 scale_by_size(result_tile_norms, size_vectors_.get());
1016 return SparseShape_(result_tile_norms, size_vectors_, zero_tile_count);
1021 template <
typename Factor>
1029 const value_type abs_factor = to_abs_factor(factor);
1030 Tensor<T> result_tile_norms = tile_norms_.
mult(other.tile_norms_, abs_factor,
perm);
1031 std::shared_ptr<vector_type> result_size_vector = perm_size_vectors(
perm);
1033 scale_by_size(result_tile_norms, result_size_vector.get());
1035 return SparseShape_(result_tile_norms, result_size_vector, zero_tile_count);
1040 template <
typename Factor>
1046 const value_type abs_factor = to_abs_factor(factor);
1048 madness::AtomicInt zero_tile_count;
1049 zero_tile_count = 0;
1050 integer M = 0, N = 0, K = 0;
1055 std::default_delete<vector_type[]>());
1058 unsigned int x = 0ul;
1060 result_size_vectors.get()[x] = size_vectors_.get()[i];
1062 result_size_vectors.get()[x] = other.size_vectors_.get()[i];
1069 tile_norms_.
range(), other.tile_norms_.
range()), 0);
1075 recursive_outer_product(size_vectors_.get() + gemm_helper.
left_inner_begin(),
1077 {
return size_vector; });
1085 {
return left * right; };
1088 tile_norms_.
data() + i, k_sizes.
data());
1091 for(integer i = 0ul, k = 0; k < K; i += N, ++k) {
1093 auto right_op = [=] (
const value_type arg) {
return arg * factor; };
1097 result_norms = left.
gemm(right, abs_factor, gemm_helper);
1124 return SparseShape_(result_norms, result_size_vectors, zero_tile_count);
1129 template <
typename Factor>
1137 template <
typename Factor>
1138 static value_type to_abs_factor(
const Factor factor) {
1140 const auto cast_abs_factor =
static_cast<value_type>(
abs(factor));
1141 TA_ASSERT(std::isfinite(cast_abs_factor));
1142 return cast_abs_factor;
1148 template <
typename T>
1157 template <
typename T>
1158 inline std::ostream& operator<<(std::ostream& os, const SparseShape<T>& shape) {
1159 os <<
"SparseShape<" <<
typeid(T).name() <<
">:" << std::endl
1160 << shape.data() << std::endl;
1165 #ifndef TILEDARRAY_HEADER_ONLY 1167 extern template class SparseShape<float>;
1169 #endif // TILEDARRAY_HEADER_ONLY 1173 #endif // TILEDARRAY_SPASE_SHAPE_H__INCLUDED detail::TensorInterface< T, BlockRange > block(const Index &lower_bound, const Index &upper_bound)
SparseShape block(const Index &lower_bound, const Index &upper_bound, const Factor factor) const
Create a scaled sub-block of the shape.
detail::ShiftWrapper< T > shift(T &tensor)
Shift a tensor from one range to another.
A (hyperrectangular) interval on , space of integer n-indices.
void compute_matrix_sizes(integer &m, integer &n, integer &k, const Left &left, const Right &right) const
Compute the matrix dimension that can be used in a *GEMM call.
SparseShape_ gemm(const SparseShape_ &other, const Factor factor, const math::GemmHelper &gemm_helper, const Permutation &perm) const
bool empty() const
Initialization check.
void outer_fill(const ValArray< U > &left, const ValArray< V > &right, const Op &op)
Outer fill operation.
SparseShape(const SparseShape< T > &other)
Copy constructor.
auto data(T &t)
Container data pointer accessor.
SparseShape_ add(value_type value) const
SparseShape_ subt(const SparseShape_ &other, const Permutation &perm) const
An N-dimensional tensor object.
Tensor_ permute(const Permutation &perm) const
Create a permuted copy of this tensor.
SparseShape_ scale(const Factor factor) const
Scale shape.
const range_type & range() const
Tensor range object accessor.
SparseShape(World &world, const Tensor< value_type > &tile_norms, const TiledRange &trange)
Collective "dense" constructor.
unsigned int result_rank() const
Result rank accessor.
decltype(auto) norm(const Tile< Arg > &arg)
Vector 2-norm of a tile.
bool is_zero(const Index &i) const
Check that a tile is zero.
const Tensor< value_type > & data() const
Data accessor.
SparseShape_ perm(const Permutation &perm) const
Create a permuted shape of this shape.
SparseShape_ subt(const SparseShape_ &other, const Factor factor) const
const_pointer data() const
SparseShape_ mult(const SparseShape_ &other, const Permutation &perm) const
SparseShape block(const Index &lower_bound, const Index &upper_bound, const Factor factor, const Permutation &perm) const
Create a copy of a sub-block of the shape.
SparseShape_ add(const SparseShape_ &other, const Factor factor) const
Add and scale shapes.
SparseShape< T > SparseShape_
This object type.
SparseShape(const SparseNormSequence &tile_norms, const TiledRange &trange)
"Sparse" constructor
auto abs(const ComplexConjugate< T > &a)
T value_type
The norm value type.
void outer(const std::size_t m, const std::size_t n, const X *const x, const Y *const y, A *a, const Op &op)
Compute the outer of x and y to modify a.
unsigned int rank() const
Rank accessor.
SparseShape update_block(const Index &lower_bound, const Index &upper_bound, const SparseShape &other) const
Update sub-block of shape.
R make_result_range(const Left &left, const Right &right) const
Construct a result range based on left and right ranges.
Tensor_ & inplace_binary(const Right &right, Op &&op)
Use a binary, element wise operation to modify this tensor.
float sparsity() const
Sparsity of the shape.
bool empty() const
Test if the tensor is empty.
Tensor< value_type >::size_type size_type
Size type.
size_t size(const DistArray< Tile, Policy > &a)
DistArray< Tile, Policy > clone(const DistArray< Tile, Policy > &arg)
Create a deep copy of an array.
Tensor_ mult(const Right &right) const
Multiply this by right to create a new tensor.
void outer_fill(const std::size_t m, const std::size_t n, const X *const x, const Y *const y, A *a, const Op &op)
Compute and store outer of x and y in a.
const_pointer data() const
Data direct access.
SparseShape_ mult(const SparseShape_ &other, const Factor factor) const
unsigned int left_outer_end() const
SparseShape_ transform(Op &&op) const
Transform the norm tensor with an operation.
constexpr std::size_t size(T(&)[N])
Array size accessor.
SparseShape_ add(const SparseShape_ &other, const Factor factor, const Permutation &perm) const
Add, scale, and permute shapes.
SparseShape(const Tensor< value_type > &tile_norms, const TiledRange &trange)
Constructor.
SparseShape_ add(const SparseShape_ &other, const Permutation &perm) const
Add and permute shapes.
void vector_op(Op &&op, const std::size_t n, Result *const result, const Args *const ... args)
std::pair< size_type, size_type > range_type
const range_type & tiles_range() const
Access the tile range.
Tensor_ binary(const Right &right, Op &&op) const
Use a binary, element wise operation to construct a new tensor.
SparseShape_ subt(const value_type value) const
SparseShape_ mask(const SparseShape_ &mask_shape) const
Compute union of two shapes.
SparseShape< T > & operator=(const SparseShape< T > &other)
Copy assignment operator.
SparseShape_ subt(const value_type value, const Permutation &perm) const
value_type operator[](const Index &index) const
Tile norm accessor.
static value_type threshold()
Threshold accessor.
unsigned int right_outer_begin() const
Tensor interface for external data.
SparseShape_ mult(const SparseShape_ &other, const Factor factor, const Permutation &perm) const
SparseShape(World &world, const SparseNormSequence &tile_norms, const TiledRange &trange)
Collective "sparse" constructor.
Range data of a tiled array.
SparseShape_ mult(const SparseShape_ &other) const
SparseShape_ add(const SparseShape_ &other) const
Add shapes.
SparseShape_ subt(const SparseShape_ &other) const
void inplace_vector_op(Op &&op, const std::size_t n, Result *const result, const Args *const ... args)
size_array upbound() const
Range upper bound accessor.
Tensor_ gemm(const Tensor< U, AU > &other, const V factor, const math::GemmHelper &gemm_helper) const
Contract this tensor with other.
Contraction to *GEMM helper.
size_type size() const
Tensor dimension size accessor.
static void threshold(const value_type thresh)
Set threshold to thresh.
SparseShape block(const Index &lower_bound, const Index &upper_bound, const Permutation &perm) const
Create a copy of a sub-block of the shape.
Permutation of a sequence of objects indexed by base-0 indices.
static constexpr bool is_dense()
Check density.
const range_type & range() const
Tensor range object accessor.
SparseShape_ subt(const SparseShape_ &other, const Factor factor, const Permutation &perm) const
Tensor_ & inplace_unary(Op &&op)
Use a unary, element wise operation to modify this tensor.
SparseShape()
Default constructor.
SparseShape block(const Index &lower_bound, const Index &upper_bound) const
Create a copy of a sub-block of the shape.
unsigned int left_outer_begin() const
unsigned int right_outer_end() const
bool validate(const Range &range) const
Validate shape range.
SparseShape_ gemm(const SparseShape_ &other, const Factor factor, const math::GemmHelper &gemm_helper) const
SparseShape_ scale(const Factor factor, const Permutation &perm) const
Scale and permute shape.
unsigned int left_inner_end() const
Tensor_ unary(Op &&op) const
Use a unary, element wise operation to construct a new tensor.
SparseShape_ add(const value_type value, const Permutation &perm) const
unsigned int left_inner_begin() const