Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 12 additions & 9 deletions src/odr/internal/common/sheet_recalculation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -163,7 +163,7 @@ class StaleCells final : public formula::CellSource {
return std::nullopt;
}
const Formula &entry = formula->second;
if (entry.output) {
if (entry.output && entry.array.has_value()) {
// the formula's own cell computes the whole range
static_cast<void>(cell(entry.array->first));
const auto known = m_results.find(position);
Expand Down Expand Up @@ -237,7 +237,7 @@ class StaleCells final : public formula::CellSource {
: formula::Value{0.0};
}
for (const std::vector<SheetPosition> &cycle : cycles(cells)) {
iterate(cycle);
iterate(cycle, *m_settings.iteration);
}
forget();
return true;
Expand Down Expand Up @@ -326,12 +326,13 @@ class StaleCells final : public formula::CellSource {
return result;
}

/// One group of @p cycle cells, swept as the document's settings state.
void iterate(const std::vector<SheetPosition> &cycle) const {
/// One group of @p cycle cells, swept as @p iteration states.
void iterate(const std::vector<SheetPosition> &cycle,
const formula::Iteration &iteration) const {
bool converged = false;
bool answered = true;
for (std::uint32_t step = 0;
step < m_settings.iteration->steps && !converged && answered; ++step) {
step < iteration.steps && !converged && answered; ++step) {
double change = 0;
for (const SheetPosition &position : cycle) {
// what reads a cell of the cycle reads this step's value
Expand All @@ -345,10 +346,11 @@ class StaleCells final : public formula::CellSource {
answered = false;
break;
}
change = std::max(change, difference(*m_iterated[position], *value));
change =
std::max(change, difference(m_iterated[position].value(), *value));
m_iterated[position] = std::move(value);
}
converged = answered && change < m_settings.iteration->difference;
converged = answered && change < iteration.difference;
}
// LibreOffice states `Err:523` for a cycle that does not converge, which
// a file cannot hold, and Excel keeps what the last step computed
Expand Down Expand Up @@ -625,8 +627,9 @@ internal::recalculate(const abstract::Document &document) {
}
};
if (!value.has_value()) {
const SheetPosition &owner =
formula.output ? formula.array->first : position;
const SheetPosition &owner = formula.output && formula.array.has_value()
? formula.array->first
: position;
(cells.is_circular(owner) ? result.circular : result.unevaluated)
.push_back(position);
// the result the file caches is stale, where the file can drop it
Expand Down
2 changes: 1 addition & 1 deletion src/odr/internal/formula/formula_dependencies.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,7 @@ std::string formula::spell_reads(
const std::function<std::optional<std::uint32_t>(std::string_view)>
&sheet_of,
const std::function<std::optional<Node>(std::string_view)> &name_of) {
const std::string unresolved = std::to_string(own_sheet) + ",0,*,0,*";
std::string unresolved = std::to_string(own_sheet) + ",0,*,0,*";
Node named = node;
put_in_names(named, name_of, 0);
const References read = references(named);
Expand Down
16 changes: 11 additions & 5 deletions src/odr/internal/formula/formula_evaluator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -524,7 +524,7 @@ class Evaluator final {
/// document that both corners name.
[[nodiscard]] std::uint32_t external_sheet_of(const CellReference &from,
const CellReference &to) const {
if (!from.sheet.has_value() ||
if (!from.document.has_value() || !from.sheet.has_value() ||
(to.document.has_value() && to.document != from.document) ||
(to.sheet.has_value() &&
!str::equals_ignore_case(*to.sheet, *from.sheet))) {
Expand Down Expand Up @@ -887,8 +887,11 @@ Value Call::value(const std::size_t index) const {
if (index >= size()) {
return Value{Empty{}};
}
if (m_given != nullptr && (*m_given)[index].has_value()) {
return *(*m_given)[index];
if (m_given != nullptr) {
if (const std::optional<Value> &given = (*m_given)[index];
given.has_value()) {
return *given;
}
}
return m_evaluator->value(m_node->children[index]);
}
Expand All @@ -905,8 +908,11 @@ Matrix Call::array(const std::size_t index) const {
if (index >= size()) {
return Matrix{1, 1, {Value{Empty{}}}};
}
if (m_given != nullptr && (*m_given)[index].has_value()) {
return m_evaluator->array_of(*(*m_given)[index]);
if (m_given != nullptr) {
if (const std::optional<Value> &given = (*m_given)[index];
given.has_value()) {
return m_evaluator->array_of(*given);
}
}
return m_evaluator->array(m_node->children[index]);
}
Expand Down
Loading