Changeset View
Changeset View
Standalone View
Standalone View
kmymoney/alkimia/alkvalue.h
- This file was added.
1 | /* | ||||
---|---|---|---|---|---|
2 | * Copyright 2010-2018 Thomas Baumgart <tbaumgart@kde.org> | ||||
3 | * | ||||
4 | * This program is free software; you can redistribute it and/or | ||||
5 | * modify it under the terms of the GNU General Public License as | ||||
6 | * published by the Free Software Foundation; either version 2 of | ||||
7 | * the License, or (at your option) any later version. | ||||
8 | * | ||||
9 | * This program is distributed in the hope that it will be useful, | ||||
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||||
12 | * GNU General Public License for more details. | ||||
13 | * | ||||
14 | * You should have received a copy of the GNU General Public License | ||||
15 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||||
16 | */ | ||||
17 | | ||||
18 | #ifndef ALKVALUE_H | ||||
19 | #define ALKVALUE_H | ||||
20 | | ||||
21 | #include <config-kmymoney.h> | ||||
22 | | ||||
23 | // Workaround: include before gmpxx.h to fix build with gcc-4.9 | ||||
24 | /** @todo When gmp version is higer than 5.1.3, remove cstddef include */ | ||||
25 | #include <cstddef> | ||||
26 | #ifdef MPIR_FOUND | ||||
27 | #include <mpirxx.h> | ||||
28 | #else | ||||
29 | #include <gmpxx.h> | ||||
30 | #endif | ||||
31 | #include <QString> | ||||
32 | #include <QSharedDataPointer> | ||||
33 | | ||||
34 | #include "alk_export.h" | ||||
35 | | ||||
36 | /** | ||||
37 | * This class represents a financial value within Alkimia. | ||||
38 | * It can be used to represent balances, shares, amounts etc. | ||||
39 | * | ||||
40 | * @author Thomas Baumgart | ||||
41 | */ | ||||
42 | class ALK_EXPORT AlkValue | ||||
43 | { | ||||
44 | public: | ||||
45 | enum RoundingMethod { | ||||
46 | RoundNever = 0, /**< | ||||
47 | * Don't do any rounding, simply truncate and | ||||
48 | * print a warning in case of a remainder. | ||||
49 | * Otherwise the same as RoundTrunc. | ||||
50 | */ | ||||
51 | | ||||
52 | RoundFloor, /**< | ||||
53 | * Round to the largest integral value not | ||||
54 | * greater than @p this. | ||||
55 | * e.g. 0.5 -> 0.0 and -0.5 -> -1.0 | ||||
56 | */ | ||||
57 | | ||||
58 | RoundCeil, /**< | ||||
59 | * Round to the smallest integral value not | ||||
60 | * less than @p this. | ||||
61 | * e.g. 0.5 -> 1.0 and -0.5 -> -0.0 | ||||
62 | */ | ||||
63 | | ||||
64 | RoundTruncate, /**< | ||||
65 | * No rounding, simply truncate any fraction | ||||
66 | */ | ||||
67 | | ||||
68 | RoundPromote, /**< | ||||
69 | * Use RoundCeil for positive and RoundFloor | ||||
70 | * for negative values of @p this. | ||||
71 | * e.g. 0.5 -> 1.0 and -0.5 -> -1.0 | ||||
72 | */ | ||||
73 | | ||||
74 | RoundHalfDown, /**< | ||||
75 | * Round up or down with the following | ||||
76 | * constraints: | ||||
77 | * 0.1 .. 0.5 -> 0.0 and 0.6 .. 0.9 -> 1.0 | ||||
78 | */ | ||||
79 | | ||||
80 | RoundHalfUp, /**< | ||||
81 | * Round up or down with the following | ||||
82 | * constraints: | ||||
83 | * 0.1 .. 0.4 -> 0.0 and 0.5 .. 0.9 -> 1.0 | ||||
84 | */ | ||||
85 | | ||||
86 | RoundRound /**< | ||||
87 | * Use RoundHalfDown for 0.1 .. 0.4 and | ||||
88 | * RoundHalfUp for 0.6 .. 0.9. Use RoundHalfUp | ||||
89 | * for 0.5 in case the resulting numerator | ||||
90 | * is odd, RoundHalfDown in case the resulting | ||||
91 | * numerator is even. | ||||
92 | * e.g. 0.5 -> 0.0 and 1.5 -> 2.0 | ||||
93 | */ | ||||
94 | }; | ||||
95 | | ||||
96 | // Constructors / Destructor | ||||
97 | /** | ||||
98 | * This is the standard constructor of an AlkValue object. | ||||
99 | * The value will be initialized to 0. | ||||
100 | */ | ||||
101 | AlkValue(); | ||||
102 | | ||||
103 | /// The destructor | ||||
104 | ~AlkValue(); | ||||
105 | | ||||
106 | /// Copy constructor | ||||
107 | AlkValue(const AlkValue &val); | ||||
108 | | ||||
109 | /** | ||||
110 | * This constructor converts an int into an AlkValue. It can | ||||
111 | * also convert a rational number when a @a denom is supplied. | ||||
112 | * | ||||
113 | * @param num numerator of the rational number | ||||
114 | * @param denom denominator of the rational number (defaults to 1) | ||||
115 | */ | ||||
116 | explicit AlkValue(const int num, const unsigned int denom = 1); | ||||
117 | | ||||
118 | /** | ||||
119 | * Convenience ctor for usage with mpz_class objects as numerator | ||||
120 | * and denominator. | ||||
121 | * | ||||
122 | * @param num numerator of the rational number | ||||
123 | * @param denom denominator of the rational number (defaults to 1) | ||||
124 | */ | ||||
125 | explicit AlkValue(const mpz_class &num, const mpz_class &denom); | ||||
126 | | ||||
127 | /** | ||||
128 | * Convenience ctor to create an AlkValue object based on an mpq_class object | ||||
129 | */ | ||||
130 | explicit AlkValue(const mpq_class &val); | ||||
131 | | ||||
132 | /** | ||||
133 | * This constructor converts a double into an AlkValue. In case | ||||
134 | * a @a denom is supplied with a value different from zero, the | ||||
135 | * @a val will be rounded to be based on the supplied @a denom. | ||||
136 | * e.g. val = 1.234 and denom = 100 will construct an AlkValue | ||||
137 | * of 1.23. The rounding method is @p RoundRound. | ||||
138 | * | ||||
139 | * @sa AlkValue::convertDenominator() | ||||
140 | * | ||||
141 | * @param val the double value | ||||
142 | * @param denom the denominator of the resulting AlkValue | ||||
143 | * | ||||
144 | * @note In case one wants to use the number of decimal places | ||||
145 | * to specify the length of the fractional part, use | ||||
146 | * | ||||
147 | * @code | ||||
148 | * AlkValue alk(1.234, AlkValue::precisionToDenominator(2).get_ui()); | ||||
149 | * // alk == 1.23 | ||||
150 | * @endcode | ||||
151 | */ | ||||
152 | explicit AlkValue(const double &val, const unsigned int denom = 0); | ||||
153 | | ||||
154 | /** | ||||
155 | * This constructor converts a QString into an AlkValue. | ||||
156 | * Several formats are supported: | ||||
157 | * | ||||
158 | * -# prices in the form "8 5/16" | ||||
159 | * -# our own toString() format | ||||
160 | * -# others | ||||
161 | | ||||
162 | * Others may be enclosed in "(" and ")" and treated as negative. | ||||
163 | * They may start or end with a dash and treated as negative. | ||||
164 | * The decimal symbols is identified as provided in @a decimalSymbol. | ||||
165 | * All other non-numeric characters are skipped | ||||
166 | */ | ||||
167 | AlkValue(const QString &str, const QChar &decimalSymbol); | ||||
168 | | ||||
169 | /** | ||||
170 | * Returns the current value converted to the given @a denom (default is 100 | ||||
171 | * or two digits of precision). The rounding method used is controlled by | ||||
172 | * the @a how argument and defaults to @p RoundRound. | ||||
173 | */ | ||||
174 | AlkValue convertDenominator(const int denom = 100, const RoundingMethod how = RoundRound) const; | ||||
175 | | ||||
176 | /** | ||||
177 | * This is a convenience function for convertDenom but instead of providing | ||||
178 | * the new denominator one provides the number of digits for the @a precision. | ||||
179 | * This value defaults to 2. The rounding method used is controlled by | ||||
180 | * the @a how argument and defaults to @p RoundRound. | ||||
181 | */ | ||||
182 | AlkValue convertPrecision(const int precision = 2, const RoundingMethod how = RoundRound) const; | ||||
183 | | ||||
184 | // assignment operators | ||||
185 | const AlkValue & operator=(const AlkValue &val); | ||||
186 | const AlkValue & operator=(int num); | ||||
187 | const AlkValue & operator=(double num); | ||||
188 | const AlkValue & operator=(const QString &str); | ||||
189 | | ||||
190 | // comparison | ||||
191 | bool operator==(const AlkValue &val) const; | ||||
192 | bool operator!=(const AlkValue &val) const; | ||||
193 | bool operator<(const AlkValue &val) const; | ||||
194 | bool operator>(const AlkValue &val) const; | ||||
195 | bool operator<=(const AlkValue &val) const; | ||||
196 | bool operator>=(const AlkValue &val) const; | ||||
197 | | ||||
198 | // calculation | ||||
199 | AlkValue operator+(const AlkValue &summand) const; | ||||
200 | AlkValue operator-(const AlkValue &minuend) const; | ||||
201 | AlkValue operator*(const AlkValue &factor) const; | ||||
202 | AlkValue operator/(const AlkValue &divisor) const; | ||||
203 | | ||||
204 | AlkValue operator*(int factor) const; | ||||
205 | | ||||
206 | // unary operators | ||||
207 | AlkValue operator-() const; | ||||
208 | AlkValue & operator+= (const AlkValue &val); | ||||
209 | AlkValue & operator-= (const AlkValue &val); | ||||
210 | AlkValue & operator/= (const AlkValue &val); | ||||
211 | AlkValue & operator*= (const AlkValue &val); | ||||
212 | | ||||
213 | // functions | ||||
214 | | ||||
215 | /// @return the absolute value of the AlkValue | ||||
216 | AlkValue abs() const; | ||||
217 | | ||||
218 | /// @return QString representation in form '[-]num/denom'. | ||||
219 | QString toString() const; | ||||
220 | | ||||
221 | /** | ||||
222 | * This method transforms the AlkValue into its canonicalized | ||||
223 | * form by reducing it to the smallest denominator. Example: | ||||
224 | * 25/100 will be converted to 1/4. Use this function at the | ||||
225 | * end of a longer calculation as all AlkValue methods require | ||||
226 | * the object to be in the canonicalized form. For speed purposes | ||||
227 | * the conversion is not performed before each operation. | ||||
228 | * | ||||
229 | * @return const reference to the object | ||||
230 | */ | ||||
231 | const AlkValue& canonicalize(); | ||||
232 | | ||||
233 | /// convert a denominator to a precision | ||||
234 | /// e.g. 100 -> 2, 1000 -> 3 | ||||
235 | /// in case of a negative @a denom, the function returns 0 | ||||
236 | static mpz_class denominatorToPrecision(mpz_class denom); | ||||
237 | | ||||
238 | /// convert a precision to the corresponding denominator | ||||
239 | /// e.g. 2 -> 100, 4 -> 10000 | ||||
240 | /// in case of a negative @a prec, the function returns 1 | ||||
241 | static mpz_class precisionToDenominator(mpz_class prec); | ||||
242 | | ||||
243 | protected: | ||||
244 | /// \internal unit test class | ||||
245 | friend class AlkValueTest; | ||||
246 | | ||||
247 | /// provides an access method to the private value storage | ||||
248 | /// for derived classes | ||||
249 | const mpq_class &valueRef() const; | ||||
250 | mpq_class &valueRef(); | ||||
251 | | ||||
252 | private: | ||||
253 | /// \internal d-pointer class. | ||||
254 | class Private; | ||||
255 | /// \internal d-pointer instance. | ||||
256 | QSharedDataPointer<Private> d; | ||||
257 | /// \internal shared zero value. | ||||
258 | static QSharedDataPointer<AlkValue::Private>& sharedZero(); | ||||
259 | | ||||
260 | // The following methods are not implemented (yet) | ||||
261 | // ALKIMIA_EXPORT friend QDataStream &operator<<(QDataStream &, const AlkValue &); | ||||
262 | // ALKIMIA_EXPORT friend QDataStream &operator>>(QDataStream &, AlkValue &); | ||||
263 | }; | ||||
264 | | ||||
265 | #endif | ||||
266 | |