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{
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{
63 nIteration = 1;
64 bConverging = false;
66}
67
69{
72}
73
75{
76 ++nIteration;
77}
78
80{
83}
84
85ScFormulaRecursionList::iterator ScRecursionHelper::GetIterationStart()
86{
87 return aRecursionFormulas.begin();
88}
89
90ScFormulaRecursionList::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{
201 assert( nDependencyComputationLevel > 0 );
203}
204
206{
208}
209
211{
214}
215
217{
218 aTemporaryGroupCells.push_back( cell );
219}
220
222{
223 if( GetRecursionCount() == 0 )
224 {
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: */
ScRecursionHelper & mrRecHelper
const ScFormulaCellGroupRef & GetCellGroup() const
void SetSeenInPath(bool bSet)
bool GetSeenInPath() const
Store a variable formula cell result, balancing between runtime performance and memory consumption.
bool PushFormulaGroup(ScFormulaCell *pCell)
Detects a simple cycle involving formula-groups and singleton formula-cells.
o3tl::sorted_vector< ScFormulaCellGroup * > * pFGSet
void SetGroupsIndependent(bool bSet)
sal_uInt16 nDependencyComputationLevel
void SetInRecursionReturn(bool b)
ScRecursionInIterationStack aRecursionInIterationStack
bool CheckFGIndependence(ScFormulaCellGroup *pFG)
void SetFormulaGroupDepEvalMode(bool bSet)
void AddTemporaryGroupCell(ScFormulaCell *cell)
std::vector< ScFormulaCell * > aFGList
void SetInIterationReturn(bool b)
ScFormulaRecursionList::iterator aInsertPos
ScFormulaRecursionList::iterator GetIterationStart()
void Insert(ScFormulaCell *p, bool bOldRunning, const ScFormulaResult &rRes)
bool HasFormulaGroupSet() const
ScFormulaRecursionList aRecursionFormulas
void SetFormulaGroupSet(o3tl::sorted_vector< ScFormulaCellGroup * > *pSet)
ScFormulaRecursionList::iterator aLastIterationStart
bool AnyCycleMemberInDependencyEvalMode(const ScFormulaCell *pCell)
std::vector< bool > aInDependencyEvalMode
std::vector< ScFormulaCell * > aTemporaryGroupCells
sal_uInt16 GetRecursionCount() const
ScFormulaRecursionList::iterator GetIterationEnd()
sal_uInt16 nRecursionCount
size_type count(const Value &v) const
void * p
static ScFormulaCell * lcl_GetTopCell(ScFormulaCell *pCell)
::boost::intrusive_ptr< ScFormulaCellGroup > ScFormulaCellGroupRef
Definition: types.hxx:43