LibreOffice Module sc (master) 1
subtotal.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 * This file incorporates work covered by the following license notice:
10 *
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 .
18 */
19
20#include <subtotal.hxx>
21#include <sal/mathconf.h>
22#include <cfloat>
23
24bool SubTotal::SafePlus(double& fVal1, double fVal2)
25{
26 bool bOk = true;
28 fVal1 += fVal2;
29 if (!std::isfinite(fVal1))
30 {
31 bOk = false;
32 if (fVal2 > 0.0)
33 fVal1 = DBL_MAX;
34 else
35 fVal1 = -DBL_MAX;
36 }
37 return bOk;
38}
39
40bool SubTotal::SafeMult(double& fVal1, double fVal2)
41{
42 bool bOk = true;
44 fVal1 *= fVal2;
45 if (!std::isfinite(fVal1))
46 {
47 bOk = false;
48 fVal1 = DBL_MAX;
49 }
50 return bOk;
51}
52
53bool SubTotal::SafeDiv(double& fVal1, double fVal2)
54{
55 bool bOk = true;
57 fVal1 /= fVal2;
58 if (!std::isfinite(fVal1))
59 {
60 bOk = false;
61 fVal1 = DBL_MAX;
62 }
63 return bOk;
64}
65
66void ScFunctionData::update(double fNewVal)
67{
68 if (mbError)
69 return;
70
71 switch (meFunc)
72 {
74 if (!SubTotal::SafePlus(getValueRef(), fNewVal))
75 mbError = true;
76 break;
78 if (getCountRef() == 0) // copy first value (nVal is initialized to 0)
79 {
80 getValueRef() = fNewVal;
81 getCountRef() = 1; // don't care about further count
82 }
83 else if (!SubTotal::SafeMult(getValueRef(), fNewVal))
84 mbError = true;
85 break;
88 ++getCountRef();
89 break;
91 getCountRef() += fNewVal;
92 break;
94 if (!SubTotal::SafePlus(getValueRef(), fNewVal))
95 mbError = true;
96 else
97 ++getCountRef();
98 break;
100 if (getCountRef() == 0) // copy first value (nVal is initialized to 0)
101 {
102 getValueRef() = fNewVal;
103 getCountRef() = 1; // don't care about further count
104 }
105 else if (fNewVal > getValueRef())
106 getValueRef() = fNewVal;
107 break;
109 if (getCountRef() == 0) // copy first value (nVal is initialized to 0)
110 {
111 getValueRef() = fNewVal;
112 getCountRef() = 1; // don't care about further count
113 }
114 else if (fNewVal < getValueRef())
115 getValueRef() = fNewVal;
116 break;
121 maWelford.update(fNewVal);
122 break;
123 default:
124 // unhandled unknown
125 mbError = true;
126 }
127}
128
130{
131 if (mbError)
132 return 0.0;
133
134 double fRet = 0.0;
135 switch (meFunc)
136 {
140 fRet = getCountRef();
141 break;
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();
148 break;
150 fRet = (getCountRef() > 0) ? getValueRef() : 0.0;
151 break;
153 if (getCountRef() == 0)
154 mbError = true;
155 else
156 fRet = getValueRef() / getCountRef();
157 break;
160 if (maWelford.getCount() < 2)
161 mbError = true;
162 else
163 {
165 if (fRet < 0.0)
166 mbError = true;
167 else if (meFunc == SUBTOTAL_FUNC_STD)
168 fRet = sqrt(fRet);
169 }
170 break;
173 if (maWelford.getCount() < 1)
174 mbError = true;
175 else if (maWelford.getCount() == 1)
176 fRet = 0.0;
177 else
178 {
180 if (fRet < 0.0)
181 mbError = true;
182 else if (meFunc == SUBTOTAL_FUNC_STDP)
183 fRet = sqrt(fRet);
184 }
185 break;
186 default:
187 assert(!"unhandled unknown");
188 mbError = true;
189 break;
190 }
191 if (mbError)
192 fRet = 0.0;
193 return fRet;
194}
195
196void WelfordRunner::update(double fVal)
197{
198 ++mnCount;
199 const double fDelta = fVal - mfMean;
200 mfMean += fDelta / mnCount;
201 mfM2 += fDelta * (fVal - mfMean);
202}
203
204/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
double & getValueRef()
Definition: subtotal.hxx:78
sal_uInt64 & getCountRef()
Definition: subtotal.hxx:79
void update(double fNewVal)
Definition: subtotal.cxx:66
WelfordRunner maWelford
Definition: subtotal.hxx:74
double getResult()
Check getError() after (!) obtaining the result.
Definition: subtotal.cxx:129
ScSubTotalFunc meFunc
Definition: subtotal.hxx:75
static bool SafePlus(double &fVal1, double fVal2)
Definition: subtotal.cxx:24
static bool SafeMult(double &fVal1, double fVal2)
Definition: subtotal.cxx:40
static bool SafeDiv(double &fVal1, double fVal2)
Definition: subtotal.cxx:53
sal_uInt64 mnCount
Definition: subtotal.hxx:56
double mfM2
Definition: subtotal.hxx:55
double mfMean
Definition: subtotal.hxx:54
double getVariancePopulation() const
Definition: subtotal.hxx:45
sal_uInt64 getCount() const
Definition: subtotal.hxx:43
void update(double fVal)
Definition: subtotal.cxx:196
double getVarianceSample() const
Definition: subtotal.hxx:44
@ SUBTOTAL_FUNC_STDP
Definition: global.hxx:869
@ SUBTOTAL_FUNC_MAX
Definition: global.hxx:865
@ SUBTOTAL_FUNC_CNT2
Definition: global.hxx:864
@ SUBTOTAL_FUNC_AVE
Definition: global.hxx:862
@ SUBTOTAL_FUNC_VARP
Definition: global.hxx:872
@ SUBTOTAL_FUNC_VAR
Definition: global.hxx:871
@ SUBTOTAL_FUNC_SELECTION_COUNT
Definition: global.hxx:874
@ SUBTOTAL_FUNC_SUM
Definition: global.hxx:870
@ SUBTOTAL_FUNC_STD
Definition: global.hxx:868
@ SUBTOTAL_FUNC_MIN
Definition: global.hxx:866
@ SUBTOTAL_FUNC_CNT
Definition: global.hxx:863
@ SUBTOTAL_FUNC_PROD
Definition: global.hxx:867
#define SAL_MATH_FPEXCEPTIONS_OFF()