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