26 #ifndef TILEDARRAY_SPARSE_SHAPE_H__INCLUDED
27 #define TILEDARRAY_SPARSE_SHAPE_H__INCLUDED
79 static_assert(TiledArray::detail::is_scalar_v<T>,
80 "SparseShape<T> only supports scalar numeric types for T");
85 static_assert(std::is_floating_point<T>::value,
86 "SparseShape template type T must be a floating point type");
92 mutable std::unique_ptr<Tensor<value_type>> tile_norms_unscaled_ =
94 std::shared_ptr<vector_type>
100 template <
typename Op>
102 const vector_type*
const size_vectors,
const unsigned int dim,
108 result = op(*size_vectors);
111 const unsigned int middle = (dim >> 1u) + (dim & 1u);
112 const vector_type left =
113 recursive_outer_product(size_vectors, middle, op);
114 const vector_type right =
115 recursive_outer_product(size_vectors + middle, dim - middle, op);
119 result = vector_type(left.size() * right.size());
129 enum class ScaleBy { Volume, InverseVolume };
144 template <ScaleBy ScaleBy_,
bool Screen = true>
147 const vector_type* MADNESS_RESTRICT
const size_vectors) {
150 madness::AtomicInt zero_tile_count;
159 if (ScaleBy_ == ScaleBy::Volume)
168 size_vectors[0].size(),
tile_norms.
data(), size_vectors[0].data());
175 auto noop = [](
const vector_type& size_vector) ->
const vector_type& {
179 auto inv_vec_op = [](
const vector_type& size_vector) {
180 return vector_type(size_vector, [](
const value_type size) {
186 const unsigned int middle = (dim >> 1u) + (dim & 1u);
187 const vector_type left =
188 ScaleBy_ == ScaleBy::Volume
189 ? recursive_outer_product(size_vectors, middle, noop)
190 : recursive_outer_product(size_vectors, middle, inv_vec_op);
191 const vector_type right =
192 ScaleBy_ == ScaleBy::Volume
193 ? recursive_outer_product(size_vectors + middle, dim - middle,
195 : recursive_outer_product(size_vectors + middle, dim - middle,
199 left.size(), right.size(), left.data(), right.data(),
204 if (Screen && norm < threshold) {
205 norm = value_type(0);
211 return Screen ? zero_tile_count : 0;
214 static std::shared_ptr<vector_type> initialize_size_vectors(
215 const TiledRange& trange) {
217 const unsigned int dim = trange.tiles_range().rank();
218 std::shared_ptr<vector_type> size_vectors(
219 new vector_type[dim], std::default_delete<vector_type[]>());
222 for (
unsigned int i = 0ul; i != dim; ++i) {
223 const size_type n = trange.data()[i].tiles_range().second -
224 trange.data()[i].tiles_range().first;
226 size_vectors.get()[i] =
227 vector_type(n, &(*trange.data()[i].begin()),
229 return value_type(tile.second - tile.first);
236 std::shared_ptr<vector_type> perm_size_vectors(
237 const Permutation& perm)
const {
238 const unsigned int n = tile_norms_.
range().
rank();
241 std::shared_ptr<vector_type> result_size_vectors(
242 new vector_type[n], std::default_delete<vector_type[]>());
245 for (
unsigned int i = 0u; i < n; ++i) {
246 const unsigned int perm_i = perm[i];
247 result_size_vectors.get()[perm_i] = size_vectors_.get()[i];
250 return result_size_vectors;
253 decltype(zero_tile_count_) compute_zero_tile_count() {
254 decltype(zero_tile_count_) zero_tile_count = 0;
255 for (
auto&& n : tile_norms_) {
256 if (n < threshold()) {
260 return zero_tile_count;
263 SparseShape(
const Tensor<T>& tile_norms,
264 const std::shared_ptr<vector_type>& size_vectors,
265 const size_type zero_tile_count)
266 : tile_norms_(tile_norms),
267 size_vectors_(size_vectors),
268 zero_tile_count_(zero_tile_count) {}
274 SparseShape() : tile_norms_(), size_vectors_(), zero_tile_count_(0ul) {}
285 : tile_norms_(trange.tiles_range(),
286 (tile_norm < threshold_ ? 0 : tile_norm)),
287 size_vectors_(initialize_size_vectors(trange)),
288 zero_tile_count_(tile_norm < threshold_ ? trange.tiles_range().area()
300 bool do_not_scale =
false)
301 : tile_norms_(tile_norms.
clone()),
302 size_vectors_(initialize_size_vectors(trange)),
303 zero_tile_count_(0ul) {
308 zero_tile_count_ = scale_tile_norms<ScaleBy::InverseVolume>(
309 tile_norms_, size_vectors_.get());
311 zero_tile_count_ = compute_zero_tile_count();
327 template <
typename SparseNormSequence,
328 typename = std::enable_if_t<
329 TiledArray::detail::has_member_function_begin_anyreturn<
330 std::decay_t<SparseNormSequence>>::value &&
331 TiledArray::detail::has_member_function_end_anyreturn<
332 std::decay_t<SparseNormSequence>>::value>>
334 bool do_not_scale =
false)
335 : tile_norms_(trange.tiles_range(),
value_type(0)),
336 size_vectors_(initialize_size_vectors(trange)),
337 zero_tile_count_(trange.tiles_range().
volume()) {
338 const auto dim = tile_norms_.range().rank();
339 for (
const auto& pair_idx_norm : tile_norms) {
340 auto compute_tile_volume = [dim,
this, pair_idx_norm]() -> uint64_t {
341 uint64_t tile_volume = 1;
342 for (
size_t d = 0; d != dim; ++d)
343 tile_volume *= size_vectors_.get()[d].at(pair_idx_norm.first[d]);
346 auto norm_per_element =
347 do_not_scale ? pair_idx_norm.second
348 : (pair_idx_norm.second / compute_tile_volume());
349 if (norm_per_element >= threshold()) {
350 tile_norms_[pair_idx_norm.first] = norm_per_element;
370 const TiledRange& trange,
bool do_not_scale =
false)
371 : tile_norms_(tile_norms.
clone()),
372 size_vectors_(initialize_size_vectors(trange)),
373 zero_tile_count_(0ul) {
378 world.gop.max(tile_norms_.data(), tile_norms_.size());
381 zero_tile_count_ = scale_tile_norms<ScaleBy::InverseVolume>(
382 tile_norms_, size_vectors_.get());
385 zero_tile_count_ = compute_zero_tile_count();
404 template <
typename SparseNormSequence>
408 world.gop.max(tile_norms_.data(), tile_norms_.size());
409 zero_tile_count_ = compute_zero_tile_count();
417 : tile_norms_(other.tile_norms_),
418 tile_norms_unscaled_(
419 other.tile_norms_unscaled_
420 ? std::make_unique<decltype(tile_norms_)>(
421 other.tile_norms_unscaled_.
get()->
clone())
423 size_vectors_(other.size_vectors_),
424 zero_tile_count_(other.zero_tile_count_) {}
432 tile_norms_ = other.tile_norms_;
433 tile_norms_unscaled_ = other.tile_norms_unscaled_
434 ? std::make_unique<decltype(tile_norms_)>(
435 other.tile_norms_unscaled_.get()->clone())
437 size_vectors_ = other.size_vectors_;
438 zero_tile_count_ = other.zero_tile_count_;
446 if (tile_norms_.empty())
return false;
447 return (range == tile_norms_.range());
454 template <
typename Index>
457 return tile_norms_[i] < threshold_;
470 return float(zero_tile_count_) / float(tile_norms_.size());
488 template <
typename Index>
491 return tile_norms_[index];
503 template <
typename Op>
506 madness::AtomicInt zero_tile_count;
510 auto apply_threshold = [threshold, &zero_tile_count](
value_type&
norm) {
512 if (
norm < threshold) {
521 return SparseShape_(std::move(new_norms), size_vectors_, zero_tile_count);
535 if (tile_norms_unscaled_ ==
nullptr) {
536 tile_norms_unscaled_ =
537 std::make_unique<decltype(tile_norms_)>(tile_norms_.clone());
538 [[maybe_unused]]
auto should_be_zero =
539 scale_tile_norms<ScaleBy::Volume, false>(*tile_norms_unscaled_,
540 size_vectors_.get());
543 return *(tile_norms_unscaled_.get());
549 bool empty()
const {
return tile_norms_.empty(); }
561 madness::AtomicInt zero_tile_count;
562 zero_tile_count = zero_tile_count_;
563 auto op = [threshold, &zero_tile_count](
value_type left,
565 if (left >= threshold && right < threshold) {
574 tile_norms_.
binary(mask_shape.tile_norms_, op);
576 return SparseShape_(result_tile_norms, size_vectors_, zero_tile_count);
590 template <
typename Index1,
typename Index2,
591 typename = std::enable_if_t<detail::is_integral_range_v<Index1> &&
592 detail::is_integral_range_v<Index2>>>
597 auto result_tile_norms_blk =
598 result_tile_norms.
block(lower_bound, upper_bound);
600 madness::AtomicInt zero_tile_count;
601 zero_tile_count = zero_tile_count_;
602 result_tile_norms_blk.inplace_binary(
606 if ((l < threshold) && (r >= threshold))
608 else if ((l >= threshold) && (r < threshold))
615 return SparseShape_(result_tile_norms, size_vectors_, zero_tile_count);
629 template <
typename Index1,
typename Index2,
630 typename = std::enable_if_t<std::is_integral_v<Index1> &&
631 std::is_integral_v<Index2>>>
633 const std::initializer_list<Index2>& upper_bound,
635 return update_block<std::initializer_list<Index1>,
636 std::initializer_list<Index2>>(lower_bound, upper_bound,
649 template <
typename PairRange,
650 typename = std::enable_if_t<detail::is_gpair_range_v<PairRange>>>
655 auto result_tile_norms_blk = result_tile_norms.
block(bounds);
657 madness::AtomicInt zero_tile_count;
658 zero_tile_count = zero_tile_count_;
659 result_tile_norms_blk.inplace_binary(
663 if ((l < threshold) && (r >= threshold))
665 else if ((l >= threshold) && (r < threshold))
672 return SparseShape_(result_tile_norms, size_vectors_, zero_tile_count);
684 template <
typename Index,
685 typename = std::enable_if_t<std::is_integral_v<Index>>>
687 const std::initializer_list<std::initializer_list<Index>>& bounds,
689 return update_block<std::initializer_list<std::initializer_list<Index>>>(
698 bool equal = this->zero_tile_count_ == other.zero_tile_count_;
700 const unsigned int dim = tile_norms_.range().rank();
701 for (
unsigned d = 0; d != dim && equal; ++d) {
703 equal && (size_vectors_.get()[d] == other.size_vectors_.get()[d]);
706 equal = equal && (tile_norms_ == other.tile_norms_);
719 template <
typename Index1,
typename Index2,
720 typename = std::enable_if_t<detail::is_integral_range_v<Index1> &&
721 detail::is_integral_range_v<Index2>>>
722 std::shared_ptr<vector_type> block_range(
const Index1& lower_bound,
723 const Index2& upper_bound)
const {
725 const auto rank = tile_norms_.range().rank();
726 std::shared_ptr<vector_type> size_vectors(
727 new vector_type[
rank], std::default_delete<vector_type[]>());
732 auto lower_it = begin(lower_bound);
733 auto upper_it = begin(upper_bound);
734 const auto lower_end = end(lower_bound);
735 const auto upper_end = end(upper_bound);
736 for (; lower_it != lower_end && upper_it != upper_end;
737 ++d, ++lower_it, ++upper_it) {
739 const auto lower_d = *lower_it;
740 const auto upper_d = *upper_it;
741 const auto extent_d = upper_d - lower_d;
744 TA_ASSERT(lower_d >= tile_norms_.range().lobound(d));
746 TA_ASSERT(upper_d <= tile_norms_.range().upbound(d));
749 size_vectors.get()[d] =
750 vector_type(extent_d, size_vectors_.get()[d].data() + lower_d);
762 template <
typename PairRange,
763 typename = std::enable_if_t<detail::is_gpair_range_v<PairRange>>>
764 std::shared_ptr<vector_type> block_range(
const PairRange& bounds)
const {
766 const auto rank = tile_norms_.range().rank();
767 std::shared_ptr<vector_type> size_vectors(
768 new vector_type[
rank], std::default_delete<vector_type[]>());
771 for (
auto&& bound_d : bounds) {
775 const auto extent_d = upper_d - lower_d;
778 TA_ASSERT(lower_d >= tile_norms_.range().lobound(d));
780 TA_ASSERT(upper_d <= tile_norms_.range().upbound(d));
783 size_vectors.get()[d] =
784 vector_type(extent_d, size_vectors_.get()[d].data() + lower_d);
794 template <
typename Op>
795 static SparseShape_ make_block(
796 const std::shared_ptr<vector_type>& size_vectors,
797 const TensorConstView<value_type>& block_view,
const Op& op) {
799 const value_type threshold = threshold_;
800 madness::AtomicInt zero_tile_count;
802 auto copy_op = [threshold, &zero_tile_count, &op](
803 value_type& MADNESS_RESTRICT result,
804 const value_type arg) {
806 if (result < threshold) {
808 result = value_type(0);
813 Tensor<value_type> result_norms(Range(block_view.range().extent()));
814 result_norms.inplace_binary(
shift(block_view), copy_op);
816 return SparseShape(result_norms, size_vectors, zero_tile_count);
826 template <
typename Index1,
typename Index2,
827 typename = std::enable_if_t<detail::is_integral_range_v<Index1> &&
828 detail::is_integral_range_v<Index2>>>
830 const Index2& upper_bound)
const {
831 return make_block(block_range(lower_bound, upper_bound),
832 tile_norms_.block(lower_bound, upper_bound),
833 [](
auto&& arg) { return arg; });
842 template <
typename Index1,
typename Index2,
843 typename = std::enable_if_t<std::is_integral_v<Index1> &&
844 std::is_integral_v<Index2>>>
846 const std::initializer_list<Index2>& upper_bound)
const {
848 ->
block<std::initializer_list<Index1>, std::initializer_list<Index2>>(
849 lower_bound, upper_bound);
857 template <
typename PairRange,
858 typename = std::enable_if_t<detail::is_gpair_range_v<PairRange>>>
860 return make_block(block_range(bounds), tile_norms_.block(bounds),
861 [](
auto&& arg) { return arg; });
868 template <
typename Index,
869 typename = std::enable_if_t<std::is_integral_v<Index>>>
871 const std::initializer_list<std::initializer_list<Index>>& bounds)
const {
872 return make_block(block_range(bounds), tile_norms_.block(bounds),
873 [](
auto&& arg) { return arg; });
886 template <
typename Index1,
typename Index2,
typename Scalar,
887 typename = std::enable_if_t<detail::is_integral_range_v<Index1> &&
888 detail::is_integral_range_v<Index2> &&
889 detail::is_numeric_v<Scalar>>>
891 const Scalar factor)
const {
892 const value_type abs_factor = to_abs_factor(factor);
893 return make_block(block_range(lower_bound, upper_bound),
894 tile_norms_.block(lower_bound, upper_bound),
895 [&abs_factor](
auto&& arg) { return abs_factor * arg; });
907 template <
typename Index1,
typename Index2,
typename Scalar,
908 typename = std::enable_if_t<std::is_integral_v<Index1> &&
909 std::is_integral_v<Index2> &&
910 detail::is_numeric_v<Scalar>>>
912 const std::initializer_list<Index2>& upper_bound,
913 const Scalar factor)
const {
914 return this->block<std::initializer_list<Index1>,
915 std::initializer_list<Index2>, Scalar>(
916 lower_bound, upper_bound, factor);
926 template <
typename PairRange,
typename Scalar,
927 typename = std::enable_if_t<detail::is_numeric_v<Scalar> &&
928 detail::is_gpair_range_v<PairRange>>>
930 const value_type abs_factor = to_abs_factor(factor);
931 return make_block(block_range(bounds), tile_norms_.block(bounds),
932 [&abs_factor](
auto&& arg) { return abs_factor * arg; });
943 template <
typename Index,
typename Scalar,
944 typename = std::enable_if_t<detail::is_numeric_v<Scalar> &&
945 std::is_integral_v<Index>>>
947 const std::initializer_list<std::initializer_list<Index>>& bounds,
948 const Scalar factor)
const {
949 const value_type abs_factor = to_abs_factor(factor);
950 return make_block(block_range(bounds), tile_norms_.block(bounds),
951 [&abs_factor](
auto&& arg) { return abs_factor * arg; });
962 template <
typename Index1,
typename Index2,
963 typename = std::enable_if_t<detail::is_integral_range_v<Index1> &&
964 detail::is_integral_range_v<Index2>>>
967 return block(lower_bound, upper_bound).
perm(perm);
978 template <
typename Index1,
typename Index2,
979 typename = std::enable_if_t<std::is_integral_v<Index1> &&
980 std::is_integral_v<Index2>>>
982 const std::initializer_list<Index2>& upper_bound,
984 return block(lower_bound, upper_bound).
perm(perm);
993 template <
typename PairRange,
994 typename = std::enable_if_t<detail::is_gpair_range_v<PairRange>>>
996 return block(bounds).
perm(perm);
1005 template <
typename Index,
1006 typename = std::enable_if_t<std::is_integral_v<Index>>>
1008 const std::initializer_list<std::initializer_list<Index>>& bounds,
1010 return block(bounds).
perm(perm);
1025 template <
typename Index1,
typename Index2,
typename Scalar,
1026 typename = std::enable_if_t<detail::is_integral_range_v<Index1> &&
1027 detail::is_integral_range_v<Index2> &&
1028 detail::is_numeric_v<Scalar>>>
1030 const Scalar factor,
const Permutation& perm)
const {
1031 return block(lower_bound, upper_bound, factor).
perm(perm);
1046 template <
typename Index1,
typename Index2,
typename Scalar,
1047 typename = std::enable_if_t<std::is_integral_v<Index1> &&
1048 std::is_integral_v<Index2> &&
1049 detail::is_numeric_v<Scalar>>>
1051 const std::initializer_list<Index2>& upper_bound,
1052 const Scalar factor,
const Permutation& perm)
const {
1053 return block(lower_bound, upper_bound, factor).
perm(perm);
1065 template <
typename PairRange,
typename Scalar,
1066 typename = std::enable_if_t<detail::is_numeric_v<Scalar> &&
1067 detail::is_gpair_range_v<PairRange>>>
1070 const value_type abs_factor = to_abs_factor(factor);
1071 return make_block(block_range(bounds), tile_norms_.block(bounds),
1072 [&abs_factor](
auto&& arg) { return abs_factor * arg; })
1086 template <
typename Index,
typename Scalar,
1087 typename = std::enable_if_t<detail::is_numeric_v<Scalar> &&
1088 std::is_integral_v<Index>>>
1090 const std::initializer_list<std::initializer_list<Index>>& bounds,
1091 const Scalar factor,
const Permutation& perm)
const {
1092 const value_type abs_factor = to_abs_factor(factor);
1093 return make_block(block_range(bounds), tile_norms_.block(bounds),
1094 [&abs_factor](
auto&& arg) { return abs_factor * arg; })
1103 return SparseShape_(tile_norms_.permute(perm), perm_size_vectors(perm),
1118 template <
typename Scalar,
1119 typename = std::enable_if_t<detail::is_numeric_v<Scalar>>>
1123 const value_type abs_factor = to_abs_factor(factor);
1124 madness::AtomicInt zero_tile_count;
1125 zero_tile_count = 0;
1126 auto op = [threshold, &zero_tile_count, abs_factor](
value_type value) {
1127 value *= abs_factor;
1128 if (value < threshold) {
1137 return SparseShape_(result_tile_norms, size_vectors_, zero_tile_count);
1149 template <
typename Factor>
1153 const value_type abs_factor = to_abs_factor(factor);
1154 madness::AtomicInt zero_tile_count;
1155 zero_tile_count = 0;
1156 auto op = [threshold, &zero_tile_count, abs_factor](
value_type value) {
1157 value *= abs_factor;
1158 if (value < threshold) {
1167 return SparseShape_(result_tile_norms, perm_size_vectors(perm),
1182 madness::AtomicInt zero_tile_count;
1183 zero_tile_count = 0;
1184 auto op = [threshold, &zero_tile_count](
value_type left,
1187 if (left < threshold) {
1195 tile_norms_.
binary(other.tile_norms_, op);
1197 return SparseShape_(result_tile_norms, size_vectors_, zero_tile_count);
1211 madness::AtomicInt zero_tile_count;
1212 zero_tile_count = 0;
1213 auto op = [threshold, &zero_tile_count](
value_type left,
1216 if (left < threshold) {
1224 tile_norms_.
binary(other.tile_norms_, op, perm);
1226 return SparseShape_(result_tile_norms, perm_size_vectors(perm),
1239 template <
typename Factor>
1243 const value_type abs_factor = to_abs_factor(factor);
1244 madness::AtomicInt zero_tile_count;
1245 zero_tile_count = 0;
1246 auto op = [threshold, &zero_tile_count, abs_factor](
1250 if (left < threshold) {
1258 tile_norms_.
binary(other.tile_norms_, op);
1260 return SparseShape_(result_tile_norms, size_vectors_, zero_tile_count);
1273 template <
typename Factor>
1278 const value_type abs_factor = to_abs_factor(factor);
1279 madness::AtomicInt zero_tile_count;
1280 zero_tile_count = 0;
1281 auto op = [threshold, &zero_tile_count, abs_factor](
1285 if (left < threshold) {
1293 tile_norms_.
binary(other.tile_norms_, op, perm);
1295 return SparseShape_(result_tile_norms, perm_size_vectors(perm),
1302 madness::AtomicInt zero_tile_count;
1303 zero_tile_count = 0;
1305 Tensor<T> result_tile_norms(tile_norms_.range());
1308 const unsigned int dim = tile_norms_.range().rank();
1309 const vector_type* MADNESS_RESTRICT
const size_vectors =
1310 size_vectors_.get();
1313 auto add_const_op = [threshold, &zero_tile_count, value](
1315 norm += value / std::sqrt(size);
1316 if (
norm < threshold) {
1326 result_tile_norms.
data(), tile_norms_.data(),
1327 size_vectors[0].data());
1334 auto inv_sqrt_vec_op = [](
const vector_type size_vector) {
1341 const unsigned int middle = (dim >> 1u) + (dim & 1u);
1343 recursive_outer_product(size_vectors, middle, inv_sqrt_vec_op);
1344 const vector_type right = recursive_outer_product(
1345 size_vectors + middle, dim - middle, inv_sqrt_vec_op);
1348 left.size(), right.size(), left.data(), right.data(),
1349 tile_norms_.data(), result_tile_norms.
data(),
1350 [threshold, &zero_tile_count, value](
1352 norm += value * x * y;
1353 if (norm < threshold) {
1354 norm = value_type(0);
1360 return SparseShape_(result_tile_norms, size_vectors_, zero_tile_count);
1366 return add(value).perm(perm);
1372 return add(other, perm);
1375 template <
typename Factor>
1377 return add(other, factor);
1380 template <
typename Factor>
1383 return add(other, factor, perm);
1389 return add(value, perm);
1397 Tensor<T> result_tile_norms = tile_norms_.
mult(other.tile_norms_);
1398 const size_type zero_tile_count = scale_tile_norms<ScaleBy::Volume>(
1399 result_tile_norms, size_vectors_.get());
1401 return SparseShape_(result_tile_norms, size_vectors_, zero_tile_count);
1409 Tensor<T> result_tile_norms = tile_norms_.
mult(other.tile_norms_, perm);
1410 std::shared_ptr<vector_type> result_size_vector = perm_size_vectors(perm);
1411 const size_type zero_tile_count = scale_tile_norms<ScaleBy::Volume>(
1412 result_tile_norms, result_size_vector.get());
1414 return SparseShape_(result_tile_norms, result_size_vector, zero_tile_count);
1420 template <
typename Factor>
1426 const value_type abs_factor = to_abs_factor(factor);
1428 tile_norms_.
mult(other.tile_norms_, abs_factor);
1429 const size_type zero_tile_count = scale_tile_norms<ScaleBy::Volume>(
1430 result_tile_norms, size_vectors_.get());
1432 return SparseShape_(result_tile_norms, size_vectors_, zero_tile_count);
1438 template <
typename Factor>
1445 const value_type abs_factor = to_abs_factor(factor);
1447 tile_norms_.
mult(other.tile_norms_, abs_factor, perm);
1448 std::shared_ptr<vector_type> result_size_vector = perm_size_vectors(perm);
1449 const size_type zero_tile_count = scale_tile_norms<ScaleBy::Volume>(
1450 result_tile_norms, result_size_vector.get());
1452 return SparseShape_(result_tile_norms, result_size_vector, zero_tile_count);
1458 template <
typename Factor>
1463 const value_type abs_factor = to_abs_factor(factor);
1465 madness::AtomicInt zero_tile_count;
1466 zero_tile_count = 0;
1470 other.tile_norms_.
range());
1473 std::shared_ptr<vector_type> result_size_vectors(
1478 unsigned int x = 0ul;
1481 result_size_vectors.get()[x] = size_vectors_.get()[i];
1484 result_size_vectors.get()[x] = other.size_vectors_.get()[i];
1487 const unsigned int k_rank =
1493 tile_norms_.range(), other.tile_norms_.
range()),
1498 const vector_type k_sizes = recursive_outer_product(
1510 return left * right;
1517 for (
integer i = 0ul, k = 0; k < K; i += N, ++k) {
1519 auto right_op = [=](
const value_type arg) {
return arg * factor; };
1521 other.tile_norms_.
data() + i);
1524 result_norms = left.
gemm(right, abs_factor, gemm_helper);
1528 [threshold, &zero_tile_count](
value_type& value) {
1529 if (value < threshold) {
1538 result_norms.
data(),
1539 [threshold, &zero_tile_count, abs_factor](
1541 value_type norm = left * right * abs_factor;
1542 if (norm < threshold) {
1543 norm = value_type(0);
1550 return SparseShape_(result_norms, result_size_vectors, zero_tile_count);
1556 template <
typename Factor>
1560 return gemm(other, factor, gemm_helper).perm(perm);
1563 template <
typename Archive,
1565 Archive>::value>::type* =
nullptr>
1568 const unsigned int dim = tile_norms_.range().rank();
1570 size_vectors_ = std::move(std::shared_ptr<vector_type>(
1572 for (
unsigned d = 0; d != dim; ++d) ar& size_vectors_.get()[d];
1573 ar& zero_tile_count_;
1576 template <
typename Archive,
1578 Archive>::value>::type* =
nullptr>
1581 const unsigned int dim = tile_norms_.range().rank();
1582 for (
unsigned d = 0; d != dim; ++d) ar& size_vectors_.get()[d];
1583 ar& zero_tile_count_;
1587 template <
typename Factor>
1588 static value_type to_abs_factor(
const Factor factor) {
1590 const auto cast_abs_factor =
static_cast<value_type
>(
abs(factor));
1591 TA_ASSERT(std::isfinite(cast_abs_factor));
1592 return cast_abs_factor;
1598 template <
typename T>
1599 typename SparseShape<T>::value_type SparseShape<T>::threshold_ =
1600 std::numeric_limits<T>::epsilon();
1608 template <
typename T>
1610 os <<
"SparseShape<" <<
typeid(T).name() <<
">:" << std::endl
1611 << shape.
data() << std::endl;
1621 template <
typename T>
1625 world.gop.max(data.data(),
volume);
1626 for (
size_t i = 0; i != data.size(); ++i) {
1627 if (data[i] != shape.
data()[i])
return false;
1632 #ifndef TILEDARRAY_HEADER_ONLY
1634 extern template class SparseShape<float>;
1636 #endif // TILEDARRAY_HEADER_ONLY
1640 #endif // TILEDARRAY_SPASE_SHAPE_H__INCLUDED