339 DCHECK_GE(new_size, 0);
381 std::unique_ptr<char[]>
buffer_;
396 void AddMultipleToSparseVectorInternal(
412template <
typename IndexType>
415 using Index = IndexType;
447template <
typename IndexType,
typename IteratorType>
452template <
typename IndexType,
typename IteratorType>
460template <
typename IndexType,
typename IteratorType>
468template <
typename IndexType,
typename IteratorType>
473template <
typename IndexType,
typename IteratorType>
480template <
typename IndexType,
typename IteratorType>
486template <
typename IndexType,
typename IteratorType>
496template <
typename IndexType,
typename IteratorType>
498 if (new_capacity <= capacity_)
return;
502 if (new_capacity.value() & 3) {
503 new_capacity += EntryIndex(4 - (new_capacity.value() & 3));
506 const size_t index_buffer_size = new_capacity.value() *
sizeof(
Index);
507 const size_t value_buffer_size = new_capacity.value() *
sizeof(
Fractional);
508 const size_t new_buffer_size = index_buffer_size + value_buffer_size;
509 std::unique_ptr<char[]> new_buffer(
new char[new_buffer_size]);
510 IndexType*
const new_index =
reinterpret_cast<Index*
>(new_buffer.get());
512 reinterpret_cast<Fractional*
>(new_index + new_capacity.value());
515 if (num_entries_ > 0) {
520 std::memmove(new_index, index_,
sizeof(IndexType) * num_entries_.value());
521 std::memmove(new_coefficient, coefficient_,
524 std::swap(buffer_, new_buffer);
526 coefficient_ = new_coefficient;
527 capacity_ = new_capacity;
530template <
typename IndexType,
typename IteratorType>
532 return num_entries_ == EntryIndex(0);
535template <
typename IndexType,
typename IteratorType>
541 std::swap(
index_, other->index_);
545template <
typename IndexType,
typename IteratorType>
557 std::vector<std::pair<Index, Fractional>> entries;
563 entries.begin(), entries.end(),
564 [](
const std::pair<Index, Fractional>& a,
565 const std::pair<Index, Fractional>& b) { return a.first < b.first; });
567 EntryIndex new_size(0);
568 for (
int i = 0; i < num_entries_; ++i) {
569 const std::pair<Index, Fractional> entry = entries[i];
570 if (entry.second == 0.0)
continue;
571 if (i + 1 == num_entries_ || entry.first != entries[i + 1].first) {
572 MutableIndex(new_size) = entry.first;
573 MutableCoefficient(new_size) = entry.second;
577 ResizeDown(new_size);
578 may_contain_duplicates_ =
false;
581template <
typename IndexType,
typename IteratorType>
583 Index previous_index(-1);
584 for (
const EntryIndex i : AllEntryIndices()) {
585 const Index index = GetIndex(i);
586 if (index <= previous_index ||
GetCoefficient(i) == 0.0)
return false;
587 previous_index = index;
589 may_contain_duplicates_ =
false;
593template <
typename IndexType,
typename IteratorType>
595 const SparseVector& sparse_vector) {
601 Reserve(sparse_vector.capacity_);
605 if (sparse_vector.num_entries_ > 0) {
610 std::memmove(
index_, sparse_vector.index_,
611 sizeof(
Index) * sparse_vector.num_entries_.value());
613 sizeof(
Fractional) * sparse_vector.num_entries_.value());
615 num_entries_ = sparse_vector.num_entries_;
616 may_contain_duplicates_ = sparse_vector.may_contain_duplicates_;
619template <
typename IndexType,
typename IteratorType>
621 const DenseVector& dense_vector) {
623 const Index num_indices(dense_vector.size());
624 for (
Index index(0); index < num_indices; ++index) {
625 if (dense_vector[index] != 0.0) {
629 may_contain_duplicates_ =
false;
632template <
typename IndexType,
typename IteratorType>
634 const SparseVector& sparse_vector,
Index offset) {
635 for (
const EntryIndex i : sparse_vector.AllEntryIndices()) {
636 const Index new_index = offset + sparse_vector.GetIndex(i);
637 DCHECK_GE(new_index, 0);
638 AddEntry(new_index, sparse_vector.GetCoefficient(i));
640 may_contain_duplicates_ =
true;
643template <
typename IndexType,
typename IteratorType>
645 StrictITIVector<IndexType, bool>* boolean_vector)
const {
649 if (!may_contain_duplicates_ || num_entries_ <= 1)
return true;
652 const Index max_index =
654 if (boolean_vector->size() <= max_index) {
655 boolean_vector->resize(max_index + 1,
false);
658 may_contain_duplicates_ =
false;
659 for (
const EntryIndex i : AllEntryIndices()) {
660 const Index index = GetIndex(i);
661 if ((*boolean_vector)[index]) {
662 may_contain_duplicates_ =
true;
665 (*boolean_vector)[index] =
true;
669 for (
const EntryIndex i : AllEntryIndices()) {
670 (*boolean_vector)[GetIndex(i)] =
false;
672 return !may_contain_duplicates_;
675template <
typename IndexType,
typename IteratorType>
679 if (!may_contain_duplicates_ || num_entries_ <= 1)
return true;
681 return CheckNoDuplicates(&boolean_vector);
686template <
typename IndexType,
typename IteratorType>
689 AddEntry(index, value);
690 may_contain_duplicates_ =
true;
693template <
typename IndexType,
typename IteratorType>
701 if (i == end)
return;
702 const int num_moved_entries = (num_entries_ - i).value() - 1;
703 std::memmove(index_ + i.value(), index_ + i.value() + 1,
704 sizeof(
Index) * num_moved_entries);
705 std::memmove(coefficient_ + i.value(), coefficient_ + i.value() + 1,
710template <
typename IndexType,
typename IteratorType>
713 DCHECK(CheckNoDuplicates());
714 EntryIndex new_index(0);
715 for (
const EntryIndex i : AllEntryIndices()) {
716 const Fractional magnitude = fabs(GetCoefficient(i));
717 if (magnitude > threshold) {
723 ResizeDown(new_index);
726template <
typename IndexType,
typename IteratorType>
728 Fractional threshold,
const DenseVector& weights) {
729 DCHECK(CheckNoDuplicates());
730 EntryIndex new_index(0);
731 for (
const EntryIndex i : AllEntryIndices()) {
732 if (fabs(GetCoefficient(i)) * weights[GetIndex(i)] > threshold) {
738 ResizeDown(new_index);
741template <
typename IndexType,
typename IteratorType>
744 DCHECK(CheckNoDuplicates());
745 for (
const EntryIndex i : AllEntryIndices()) {
746 if (GetIndex(i) == index) {
747 std::swap(MutableIndex(EntryIndex(0)), MutableIndex(i));
754template <
typename IndexType,
typename IteratorType>
757 DCHECK(CheckNoDuplicates());
758 const EntryIndex last_entry = num_entries() - 1;
759 for (
const EntryIndex i : AllEntryIndices()) {
760 if (GetIndex(i) == index) {
768template <
typename IndexType,
typename IteratorType>
771 for (
const EntryIndex i : AllEntryIndices()) {
772 MutableCoefficient(i) *= factor;
776template <
typename IndexType,
typename IteratorType>
784template <
typename IndexType,
typename IteratorType>
792template <
typename IndexType,
typename IteratorType>
800template <
typename IndexType,
typename IteratorType>
810template <
typename IndexType,
typename IteratorType>
812 const IndexPermutation& index_perm,
Index num_indices,
813 DenseVector* dense_vector)
const {
815 dense_vector->AssignToZero(num_indices);
816 for (
const EntryIndex i : AllEntryIndices()) {
821template <
typename IndexType,
typename IteratorType>
823 Fractional multiplier, DenseVector* dense_vector)
const {
825 if (multiplier == 0.0)
return;
826 for (
const EntryIndex i : AllEntryIndices()) {
827 (*dense_vector)[GetIndex(i)] += multiplier * GetCoefficient(i);
831template <
typename IndexType,
typename IteratorType>
835 Fractional drop_tolerance, SparseVector* accumulator_vector)
const {
836 AddMultipleToSparseVectorInternal(
true, multiplier, removed_common_index,
837 drop_tolerance, accumulator_vector);
840template <
typename IndexType,
typename IteratorType>
845 AddMultipleToSparseVectorInternal(
false, multiplier, removed_common_index,
846 drop_tolerance, accumulator_vector);
849template <
typename IndexType,
typename IteratorType>
850void SparseVector<IndexType, IteratorType>::AddMultipleToSparseVectorInternal(
854 DCHECK(IsCleanedUp());
855 DCHECK(accumulator_vector->IsCleanedUp());
856 DCHECK(CheckNoDuplicates());
857 DCHECK(accumulator_vector->CheckNoDuplicates());
858 DCHECK_NE(0.0, LookUpCoefficient(common_index));
859 DCHECK_NE(0.0, accumulator_vector->LookUpCoefficient(common_index));
872 const EntryIndex size_a = a.num_entries();
873 const EntryIndex size_b = b.num_entries();
874 const int size_adjustment = delete_common_index ? -2 : 0;
875 const EntryIndex new_size_upper_bound = size_a + size_b + size_adjustment;
876 c.Reserve(new_size_upper_bound);
877 c.num_entries_ = new_size_upper_bound;
878 while ((ia < size_a) && (ib < size_b)) {
879 const Index index_a = a.GetIndex(ia);
880 const Index index_b = b.GetIndex(ib);
883 if (index_a == index_b) {
884 if (index_a != common_index) {
885 const Fractional a_coeff_mul = multiplier * a.GetCoefficient(ia);
886 const Fractional b_coeff = b.GetCoefficient(ib);
891 if (std::abs(sum) > drop_tolerance) {
892 c.MutableIndex(ic) = index_a;
893 c.MutableCoefficient(ic) = sum;
896 }
else if (!delete_common_index) {
897 c.MutableIndex(ic) = b.GetIndex(ib);
898 c.MutableCoefficient(ic) = b.GetCoefficient(ib);
903 }
else if (index_a < index_b) {
904 const Fractional new_value = multiplier * a.GetCoefficient(ia);
905 if (std::abs(new_value) > drop_tolerance) {
906 c.MutableIndex(ic) = index_a;
907 c.MutableCoefficient(ic) = new_value;
912 c.MutableIndex(ic) = b.GetIndex(ib);
913 c.MutableCoefficient(ic) = b.GetCoefficient(ib);
918 while (ia < size_a) {
919 const Fractional new_value = multiplier * a.GetCoefficient(ia);
920 if (std::abs(new_value) > drop_tolerance) {
921 c.MutableIndex(ic) = a.GetIndex(ia);
922 c.MutableCoefficient(ic) = new_value;
927 while (ib < size_b) {
928 c.MutableIndex(ic) =
b.GetIndex(ib);
929 c.MutableCoefficient(ic) =
b.GetCoefficient(ib);
934 c.may_contain_duplicates_ =
false;
935 c.Swap(accumulator_vector);
936 DCHECK(accumulator_vector->IsCleanedUp());
939template <
typename IndexType,
typename IteratorType>
941 const IndexPermutation& index_perm) {
942 for (
const EntryIndex i : AllEntryIndices()) {
943 MutableIndex(i) = index_perm[GetIndex(i)];
947template <
typename IndexType,
typename IteratorType>
950 EntryIndex new_index(0);
953 if (index_perm[index] >= 0) {
959 ResizeDown(new_index);
962template <
typename IndexType,
typename IteratorType>
964 const IndexPermutation& index_perm, SparseVector* output) {
967 const EntryIndex end(num_entries_);
970 if (i >=
end)
return;
971 if (index_perm[
GetIndex(i)] >= 0)
break;
974 output->AddEntry(GetIndex(i), GetCoefficient(i));
975 for (EntryIndex j(i + 1); j < end; ++j) {
976 if (index_perm[GetIndex(j)] < 0) {
977 MutableIndex(i) = GetIndex(j);
978 MutableCoefficient(i) = GetCoefficient(j);
981 output->AddEntry(GetIndex(j), GetCoefficient(j));
989 output->may_contain_duplicates_ =
true;
992template <
typename IndexType,
typename IteratorType>
996 for (
const EntryIndex i : AllEntryIndices()) {
997 if (GetIndex(i) == index) {
1008template <
typename IndexType,
typename IteratorType>
1010 const SparseVector& other)
const {
1012 if (num_entries() != other.num_entries())
return false;
1013 for (
const EntryIndex i : AllEntryIndices()) {
1014 if (GetIndex(i) != other.GetIndex(i))
return false;
1020template <
typename IndexType,
typename IteratorType>
1023 for (
const EntryIndex i : AllEntryIndices()) {
1024 if (i != 0) s +=
", ";
1025 absl::StrAppendFormat(&s,
"[%d]=%g", GetIndex(i).value(),