Warning, /office/alkimia/src/alkvalue.h.in is written in an unsupported language. File is not indexed.
0001 /* 0002 SPDX-FileCopyrightText: 2010-2021 Thomas Baumgart tbaumgart @kde.org 0003 0004 This file is part of libalkimia. 0005 0006 SPDX-License-Identifier: LGPL-2.1-or-later 0007 */ 0008 0009 #ifndef ALKVALUE_H 0010 #define ALKVALUE_H 0011 0012 #include <alkimia/alk_export.h> 0013 0014 // Workaround: include before gmpxx.h to fix build with gcc-4.9 0015 /** @todo When gmp version is higher than 5.1.3, remove cstddef include */ 0016 #include <cstddef> 0017 #include <@MP_HEADER@> // krazy:exclude=camelcase 0018 #include <QString> 0019 #include <QSharedDataPointer> 0020 0021 /** 0022 * This class represents a financial value within Alkimia. 0023 * It can be used to represent balances, shares, amounts etc. 0024 * 0025 * @author Thomas Baumgart 0026 */ 0027 class ALK_EXPORT AlkValue 0028 { 0029 public: 0030 enum RoundingMethod { 0031 RoundNever = 0, /**< 0032 * Don't do any rounding, simply truncate and 0033 * print a warning in case of a remainder. 0034 * Otherwise the same as RoundTrunc. 0035 */ 0036 0037 RoundFloor, /**< 0038 * Round to the largest integral value not 0039 * greater than @p this. 0040 * e.g. 0.5 -> 0.0 and -0.5 -> -1.0 0041 */ 0042 0043 RoundCeil, /**< 0044 * Round to the smallest integral value not 0045 * less than @p this. 0046 * e.g. 0.5 -> 1.0 and -0.5 -> -0.0 0047 */ 0048 0049 RoundTruncate, /**< 0050 * No rounding, simply truncate any fraction 0051 */ 0052 0053 RoundPromote, /**< 0054 * Use RoundCeil for positive and RoundFloor 0055 * for negative values of @p this. 0056 * e.g. 0.5 -> 1.0 and -0.5 -> -1.0 0057 */ 0058 0059 RoundHalfDown, /**< 0060 * Round up or down with the following 0061 * constraints: 0062 * 0.1 .. 0.5 -> 0.0 and 0.6 .. 0.9 -> 1.0 0063 */ 0064 0065 RoundHalfUp, /**< 0066 * Round up or down with the following 0067 * constraints: 0068 * 0.1 .. 0.4 -> 0.0 and 0.5 .. 0.9 -> 1.0 0069 */ 0070 0071 RoundRound /**< 0072 * Use RoundHalfDown for 0.1 .. 0.4 and 0073 * RoundHalfUp for 0.6 .. 0.9. Use RoundHalfUp 0074 * for 0.5 in case the resulting numerator 0075 * is odd, RoundHalfDown in case the resulting 0076 * numerator is even. 0077 * e.g. 0.5 -> 0.0 and 1.5 -> 2.0 0078 */ 0079 }; 0080 0081 // Constructors / Destructor 0082 /** 0083 * This is the standard constructor of an AlkValue object. 0084 * The value will be initialized to 0. 0085 */ 0086 AlkValue(); 0087 0088 /// The destructor 0089 ~AlkValue(); 0090 0091 /// Copy constructor 0092 AlkValue(const AlkValue &val); 0093 0094 /** 0095 * This constructor converts an int into an AlkValue. It can 0096 * also convert a rational number when a @a denom is supplied. 0097 * 0098 * @param num numerator of the rational number 0099 * @param denom denominator of the rational number (defaults to 1) 0100 */ 0101 explicit AlkValue(const int num, const unsigned int denom = 1); 0102 0103 /** 0104 * Convenience ctor for usage with mpz_class objects as numerator 0105 * and denominator. 0106 * 0107 * @param num numerator of the rational number 0108 * @param denom denominator of the rational number (defaults to 1) 0109 */ 0110 explicit AlkValue(const mpz_class &num, const mpz_class &denom); 0111 0112 /** 0113 * Convenience ctor to create an AlkValue object based on an mpq_class object 0114 */ 0115 explicit AlkValue(const mpq_class &val); 0116 0117 /** 0118 * This constructor converts a double into an AlkValue. In case 0119 * a @a denom is supplied with a value different from zero, the 0120 * @a val will be rounded to be based on the supplied @a denom. 0121 * e.g. val = 1.234 and denom = 100 will construct an AlkValue 0122 * of 1.23. The rounding method is @p RoundRound. 0123 * 0124 * @sa AlkValue::convertDenominator() 0125 * 0126 * @param val the double value 0127 * @param denom the denominator of the resulting AlkValue 0128 * 0129 * @note In case one wants to use the number of decimal places 0130 * to specify the length of the fractional part, use 0131 * 0132 * @code 0133 * AlkValue alk(1.234, AlkValue::precisionToDenominator(2).get_ui()); 0134 * // alk == 1.23 0135 * @endcode 0136 */ 0137 explicit AlkValue(const double &val, const unsigned int denom = 0); 0138 0139 /** 0140 * This constructor converts a QString into an AlkValue. 0141 * Several formats are supported: 0142 * 0143 * -# prices in the form "8 5/16" 0144 * -# our own toString() format 0145 * -# others 0146 0147 * Others may be enclosed in "(" and ")" and treated as negative. 0148 * They may start or end with a dash and treated as negative. 0149 * The decimal symbols is identified as provided in @a decimalSymbol. 0150 * All other non-numeric characters are skipped 0151 */ 0152 AlkValue(const QString &str, const QChar &decimalSymbol); 0153 0154 /** 0155 * Returns the current value converted to the given @a denom (default is 100 0156 * or two digits of precision). The rounding method used is controlled by 0157 * the @a how argument and defaults to @p RoundRound. 0158 */ 0159 AlkValue convertDenominator(const int denom = 100, const RoundingMethod how = RoundRound) const; 0160 0161 /** 0162 * Returns the current value converted to the given @a denom. 0163 * The rounding method used is controlled by the @a how argument 0164 * and defaults to @p RoundRound. 0165 * 0166 * @param denom The wanted denominator (defaults to 100 representing 2 digits) 0167 * @param how The rounding method. See AlkValue::RoundingMethod for details 0168 */ 0169 AlkValue convertDenominator(const mpz_class denom, const AlkValue::RoundingMethod how = AlkValue::RoundRound) const; 0170 0171 /** 0172 * This is a convenience function for convertDenom but instead of providing 0173 * the new denominator one provides the number of digits for the @a precision. 0174 * This value defaults to 2. The rounding method used is controlled by 0175 * the @a how argument and defaults to @p RoundRound. 0176 */ 0177 AlkValue convertPrecision(const int precision = 2, const RoundingMethod how = RoundRound) const; 0178 0179 // assignment operators 0180 const AlkValue & operator=(const AlkValue &val); 0181 const AlkValue & operator=(int num); 0182 const AlkValue & operator=(double num); 0183 const AlkValue & operator=(const QString &str); 0184 0185 // comparison 0186 bool operator==(const AlkValue &val) const; 0187 bool operator!=(const AlkValue &val) const; 0188 bool operator<(const AlkValue &val) const; 0189 bool operator>(const AlkValue &val) const; 0190 bool operator<=(const AlkValue &val) const; 0191 bool operator>=(const AlkValue &val) const; 0192 0193 // calculation 0194 AlkValue operator+(const AlkValue &summand) const; 0195 AlkValue operator-(const AlkValue &minuend) const; 0196 AlkValue operator*(const AlkValue &factor) const; 0197 AlkValue operator/(const AlkValue &divisor) const; 0198 AlkValue operator%(int operand) const; 0199 0200 AlkValue operator*(int factor) const; 0201 0202 // unary operators 0203 AlkValue operator-() const; 0204 AlkValue & operator+= (const AlkValue &val); 0205 AlkValue & operator-= (const AlkValue &val); 0206 AlkValue & operator/= (const AlkValue &val); 0207 AlkValue & operator*= (const AlkValue &val); 0208 0209 // functions 0210 0211 /// @return the absolute value of the AlkValue 0212 AlkValue abs() const; 0213 0214 /// @return QString representation in form '[-]num/denom'. 0215 QString toString() const; 0216 0217 double toDouble() const; 0218 0219 /** 0220 * This method transforms the AlkValue into its canonicalized 0221 * form by reducing it to the smallest denominator. Example: 0222 * 25/100 will be converted to 1/4. Use this function at the 0223 * end of a longer calculation as all AlkValue methods require 0224 * the object to be in the canonicalized form. For speed purposes 0225 * the conversion is not performed before each operation. 0226 * 0227 * @return const reference to the object 0228 */ 0229 const AlkValue& canonicalize(); 0230 0231 /// convert a denominator to a precision 0232 /// e.g. 100 -> 2, 1000 -> 3 0233 /// in case of a negative @a denom, the function returns 0 0234 static mpz_class denominatorToPrecision(mpz_class denom); 0235 0236 /// convert a precision to the corresponding denominator 0237 /// e.g. 2 -> 100, 4 -> 10000 0238 /// in case of a negative @a prec, the function returns 1 0239 static mpz_class precisionToDenominator(mpz_class prec); 0240 0241 protected: 0242 /// \internal unit test class 0243 friend class AlkValueTest; 0244 0245 /// provides an access method to the private value storage 0246 /// for derived classes 0247 const mpq_class &valueRef() const; 0248 mpq_class &valueRef(); 0249 0250 private: 0251 /// \internal d-pointer class. 0252 class Private; 0253 /// \internal d-pointer instance. 0254 QSharedDataPointer<Private> d; 0255 /// \internal shared zero value. 0256 static QSharedDataPointer<AlkValue::Private>& sharedZero(); 0257 0258 // The following methods are not implemented (yet) 0259 // ALKIMIA_EXPORT friend QDataStream &operator<<(QDataStream &, const AlkValue &); 0260 // ALKIMIA_EXPORT friend QDataStream &operator>>(QDataStream &, AlkValue &); 0261 }; 0262 0263 #endif 0264