LibreOffice Module sc (master)  1
recursionhelper.cxx
Go to the documentation of this file.
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3  * This file is part of the LibreOffice project.
4  *
5  * This Source Code Form is subject to the terms of the Mozilla Public
6  * License, v. 2.0. If a copy of the MPL was not distributed with this
7  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8  */
9 
10 #include <recursionhelper.hxx>
11 #include <formulacell.hxx>
12 
14 {
15  nRecursionCount = 0;
21  // Must not force clear aFGList ever.
22 }
23 
25 {
27  nIteration = 0;
28  bConverging = false;
29 }
30 
32 {
33  pFGSet = nullptr;
34  bGroupsIndependent = true;
35  Init();
36 }
37 
39 {
40  // Do not use IsInRecursionReturn() here, it decouples iteration.
41  if (b && !bInRecursionReturn)
44 }
45 
47  ScFormulaCell* p, bool bOldRunning, const ScFormulaResult & rRes )
48 {
50  bOldRunning, rRes));
51 }
52 
54 {
55  // An iteration return is always coupled to a recursion return.
58 }
59 
61 {
62  SetInIterationReturn( false);
63  nIteration = 1;
64  bConverging = false;
66 }
67 
69 {
70  SetInIterationReturn( false);
72 }
73 
75 {
76  ++nIteration;
77 }
78 
80 {
83 }
84 
85 ScFormulaRecursionList::iterator ScRecursionHelper::GetIterationStart()
86 {
87  return aRecursionFormulas.begin();
88 }
89 
90 ScFormulaRecursionList::iterator ScRecursionHelper::GetIterationEnd()
91 {
92  return aRecursionFormulas.end();
93 }
94 
96 {
97  aRecursionFormulas.clear();
98  while (!aRecursionInIterationStack.empty())
100  Init();
101 }
102 
104 {
105  if (!pCell)
106  return nullptr;
107 
108  const ScFormulaCellGroupRef& mxGroup = pCell->GetCellGroup();
109  if (!mxGroup)
110  return pCell;
111  return mxGroup->mpTopCell;
112 }
113 
115 {
116  assert(pCell);
117 
118  if (pCell->GetSeenInPath())
119  {
120  // Found a simple cycle of formula-groups.
121  // Disable group calc for all elements of this cycle.
122  sal_Int32 nIdx = aFGList.size();
123  assert(nIdx > 0);
124  do
125  {
126  --nIdx;
127  assert(nIdx >= 0);
128  const ScFormulaCellGroupRef& mxGroup = aFGList[nIdx]->GetCellGroup();
129  if (mxGroup)
130  mxGroup->mbPartOfCycle = true;
131  } while (aFGList[nIdx] != pCell);
132 
133  return false;
134  }
135 
136  pCell->SetSeenInPath(true);
137  aFGList.push_back(pCell);
138  aInDependencyEvalMode.push_back(false);
139  return true;
140 }
141 
143 {
144  assert(aFGList.size() == aInDependencyEvalMode.size());
145  if (aFGList.empty())
146  return;
147  ScFormulaCell* pCell = aFGList.back();
148  pCell->SetSeenInPath(false);
149  aFGList.pop_back();
150  aInDependencyEvalMode.pop_back();
151 }
152 
154 {
155  assert(pCell);
156 
157  if (pCell->GetSeenInPath())
158  {
159  // Found a simple cycle of formula-groups.
160  sal_Int32 nIdx = aFGList.size();
161  assert(nIdx > 0);
162  do
163  {
164  --nIdx;
165  assert(nIdx >= 0);
166  const ScFormulaCellGroupRef& mxGroup = aFGList[nIdx]->GetCellGroup();
167  // Found a cycle member FG that is in dependency evaluation mode.
168  if (mxGroup && aInDependencyEvalMode[nIdx])
169  return true;
170  } while (aFGList[nIdx] != pCell);
171 
172  return false;
173  }
174 
175  return false;
176 }
177 
179 {
180  sal_Int32 nIdx = aFGList.size() - 1;
181  while (nIdx >= 0)
182  {
183  const ScFormulaCellGroupRef& mxGroup = aFGList[nIdx]->GetCellGroup();
184  if (mxGroup)
185  return mxGroup->mbPartOfCycle;
186  --nIdx;
187  };
188  return false;
189 }
190 
192 {
193  assert(aFGList.size());
194  assert(aFGList.size() == aInDependencyEvalMode.size());
195  assert(aFGList.back()->GetCellGroup());
196  aInDependencyEvalMode.back() = bSet;
197 }
198 
200 {
203 }
204 
206 {
208 }
209 
211 {
214 }
215 
217 {
218  aTemporaryGroupCells.push_back( cell );
219 }
220 
222 {
223  if( GetRecursionCount() == 0 )
224  {
225  for( ScFormulaCell* cell : aTemporaryGroupCells )
226  cell->SetCellGroup( nullptr );
227  aTemporaryGroupCells.clear();
228  }
229 }
230 
232 {
233  if (pFGSet && pFGSet->count(pFG))
234  {
235  bGroupsIndependent = false;
236  return false;
237  }
238 
239  return true;
240 }
241 
243  mrRecHelper(rRecursionHelper)
244 {
245  if (pCell)
246  {
247  pCell = lcl_GetTopCell(pCell);
249  }
250  else
251  mbShouldPop = false;
252 }
253 
255 {
256  if (mbShouldPop)
258 }
259 
261  mrRecHelper(rRecursionHelper)
262 {
265 }
266 
268 {
271 }
272 
275  mrRecHelper(rRecursionHelper),
276  mbUsedFGSet(false)
277 {
279  {
282  mbUsedFGSet = true;
283  }
284 }
285 
287 {
288  if (mbUsedFGSet)
289  {
290  // Reset to defaults.
293  }
294 }
295 
297 {
298  if (!mbUsedFGSet)
299  return false;
300 
302 }
303 
304 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
::boost::intrusive_ptr< ScFormulaCellGroup > ScFormulaCellGroupRef
Definition: types.hxx:44
bool GetSeenInPath() const
sal_uInt16 GetRecursionCount() const
size_type count(const Value &v) const
void AddTemporaryGroupCell(ScFormulaCell *cell)
void SetInIterationReturn(bool b)
bool CheckFGIndependence(ScFormulaCellGroup *pFG)
void SetFormulaGroupSet(o3tl::sorted_vector< ScFormulaCellGroup * > *pSet)
bool PushFormulaGroup(ScFormulaCell *pCell)
Detects a simple cycle involving formula-groups and singleton formula-cells.
const ScFormulaCellGroupRef & GetCellGroup() const
const BorderLinePrimitive2D *pCandidateB assert(pCandidateA)
Store a variable formula cell result, balancing between runtime performance and memory consumption...
ScRecursionInIterationStack aRecursionInIterationStack
ScFormulaRecursionList aRecursionFormulas
ScFormulaRecursionList::iterator GetIterationEnd()
o3tl::sorted_vector< ScFormulaCellGroup * > * pFGSet
void SetSeenInPath(bool bSet)
bool AnyCycleMemberInDependencyEvalMode(const ScFormulaCell *pCell)
sal_uInt16 nRecursionCount
static ScFormulaCell * lcl_GetTopCell(ScFormulaCell *pCell)
ScFormulaRecursionList::iterator GetIterationStart()
void SetFormulaGroupDepEvalMode(bool bSet)
void SetGroupsIndependent(bool bSet)
ScFormulaRecursionList::iterator aInsertPos
bool HasFormulaGroupSet() const
sal_uInt16 nDependencyComputationLevel
void SetInRecursionReturn(bool b)
std::vector< ScFormulaCell * > aFGList
ScFormulaRecursionList::iterator aLastIterationStart
ScRecursionHelper & mrRecHelper
void Insert(ScFormulaCell *p, bool bOldRunning, const ScFormulaResult &rRes)
std::vector< bool > aInDependencyEvalMode
std::vector< ScFormulaCell * > aTemporaryGroupCells