1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <subtotal.hxx>
21 #include <sal/mathconf.h>
24 bool SubTotal::SafePlus(double& fVal1
, double fVal2
)
27 SAL_MATH_FPEXCEPTIONS_OFF();
29 if (!std::isfinite(fVal1
))
40 bool SubTotal::SafeMult(double& fVal1
, double fVal2
)
43 SAL_MATH_FPEXCEPTIONS_OFF();
45 if (!std::isfinite(fVal1
))
53 bool SubTotal::SafeDiv(double& fVal1
, double fVal2
)
56 SAL_MATH_FPEXCEPTIONS_OFF();
58 if (!std::isfinite(fVal1
))
66 void ScFunctionData::update(double fNewVal
)
73 case SUBTOTAL_FUNC_SUM
:
74 if (!SubTotal::SafePlus(getValueRef(), fNewVal
))
77 case SUBTOTAL_FUNC_PROD
:
78 if (getCountRef() == 0) // copy first value (nVal is initialized to 0)
80 getValueRef() = fNewVal
;
81 getCountRef() = 1; // don't care about further count
83 else if (!SubTotal::SafeMult(getValueRef(), fNewVal
))
86 case SUBTOTAL_FUNC_CNT
:
87 case SUBTOTAL_FUNC_CNT2
:
90 case SUBTOTAL_FUNC_SELECTION_COUNT
:
91 getCountRef() += fNewVal
;
93 case SUBTOTAL_FUNC_AVE
:
94 if (!SubTotal::SafePlus(getValueRef(), fNewVal
))
99 case SUBTOTAL_FUNC_MAX
:
100 if (getCountRef() == 0) // copy first value (nVal is initialized to 0)
102 getValueRef() = fNewVal
;
103 getCountRef() = 1; // don't care about further count
105 else if (fNewVal
> getValueRef())
106 getValueRef() = fNewVal
;
108 case SUBTOTAL_FUNC_MIN
:
109 if (getCountRef() == 0) // copy first value (nVal is initialized to 0)
111 getValueRef() = fNewVal
;
112 getCountRef() = 1; // don't care about further count
114 else if (fNewVal
< getValueRef())
115 getValueRef() = fNewVal
;
117 case SUBTOTAL_FUNC_VAR
:
118 case SUBTOTAL_FUNC_STD
:
119 case SUBTOTAL_FUNC_VARP
:
120 case SUBTOTAL_FUNC_STDP
:
121 maWelford
.update(fNewVal
);
129 double ScFunctionData::getResult()
137 case SUBTOTAL_FUNC_CNT
:
138 case SUBTOTAL_FUNC_CNT2
:
139 case SUBTOTAL_FUNC_SELECTION_COUNT
:
140 fRet
= getCountRef();
142 case SUBTOTAL_FUNC_SUM
:
143 case SUBTOTAL_FUNC_MAX
:
144 case SUBTOTAL_FUNC_MIN
:
145 // Note that nVal is 0.0 for MAX and MIN if nCount==0, that's also
146 // how it is defined in ODFF.
147 fRet
= getValueRef();
149 case SUBTOTAL_FUNC_PROD
:
150 fRet
= (getCountRef() > 0) ? getValueRef() : 0.0;
152 case SUBTOTAL_FUNC_AVE
:
153 if (getCountRef() == 0)
156 fRet
= getValueRef() / getCountRef();
158 case SUBTOTAL_FUNC_VAR
:
159 case SUBTOTAL_FUNC_STD
:
160 if (maWelford
.getCount() < 2)
164 fRet
= maWelford
.getVarianceSample();
167 else if (meFunc
== SUBTOTAL_FUNC_STD
)
171 case SUBTOTAL_FUNC_VARP
:
172 case SUBTOTAL_FUNC_STDP
:
173 if (maWelford
.getCount() < 1)
175 else if (maWelford
.getCount() == 1)
179 fRet
= maWelford
.getVariancePopulation();
182 else if (meFunc
== SUBTOTAL_FUNC_STDP
)
187 assert(!"unhandled unknown");
196 void WelfordRunner::update(double fVal
)
199 const double fDelta
= fVal
- mfMean
;
200 mfMean
+= fDelta
/ mnCount
;
201 mfM2
+= fDelta
* (fVal
- mfMean
);
204 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */