File indexing completed on 2024-05-12 05:06:39
0001 /* 0002 SPDX-FileCopyrightText: 2003-2012 Thomas Baumgart <tbaumgart@kde.org> 0003 SPDX-FileCopyrightText: 2017-2018 Łukasz Wojniłowicz <lukasz.wojnilowicz@gmail.com> 0004 SPDX-License-Identifier: GPL-2.0-or-later 0005 */ 0006 0007 #include "mymoneyfinancialcalculator.h" 0008 #include "mymoneyfinancialcalculator_p.h" 0009 0010 #include <qglobal.h> 0011 0012 // ---------------------------------------------------------------------------- 0013 // QT Includes 0014 0015 // ---------------------------------------------------------------------------- 0016 // KDE Includes 0017 0018 // ---------------------------------------------------------------------------- 0019 // Project Includes 0020 0021 #include "mymoneyexception.h" 0022 0023 static inline double dabs(const double x) 0024 { 0025 return (x >= 0.0) ? x : -x; 0026 } 0027 0028 MyMoneyFinancialCalculator::MyMoneyFinancialCalculator() : 0029 d_ptr(new MyMoneyFinancialCalculatorPrivate) 0030 { 0031 Q_D(MyMoneyFinancialCalculator); 0032 setPrec(); 0033 setPF(); 0034 setCF(); 0035 setBep(); 0036 setDisc(); 0037 0038 setNpp(0.0); 0039 setIr(0.0); 0040 setPv(0.0); 0041 setPmt(0.0); 0042 setFv(0.0); 0043 0044 // clear the mask 0045 d->m_mask = 0; 0046 } 0047 0048 MyMoneyFinancialCalculator::~MyMoneyFinancialCalculator() 0049 { 0050 Q_D(MyMoneyFinancialCalculator); 0051 delete d; 0052 } 0053 0054 void MyMoneyFinancialCalculator::setPrec(const unsigned short prec) 0055 { 0056 Q_D(MyMoneyFinancialCalculator); 0057 d->m_prec = prec; 0058 } 0059 0060 void MyMoneyFinancialCalculator::setPF(const unsigned short PF) 0061 { 0062 Q_D(MyMoneyFinancialCalculator); 0063 d->m_PF = PF; 0064 } 0065 0066 void MyMoneyFinancialCalculator::setCF(const unsigned short CF) 0067 { 0068 Q_D(MyMoneyFinancialCalculator); 0069 d->m_CF = CF; 0070 } 0071 0072 void MyMoneyFinancialCalculator::setBep(const bool bep) 0073 { 0074 Q_D(MyMoneyFinancialCalculator); 0075 d->m_bep = bep; 0076 } 0077 0078 void MyMoneyFinancialCalculator::setDisc(const bool disc) 0079 { 0080 Q_D(MyMoneyFinancialCalculator); 0081 d->m_disc = disc; 0082 } 0083 0084 void MyMoneyFinancialCalculator::setIr(const double ir) 0085 { 0086 Q_D(MyMoneyFinancialCalculator); 0087 d->m_ir = ir; 0088 d->m_mask |= IR_SET; 0089 } 0090 0091 double MyMoneyFinancialCalculator::ir() const 0092 { 0093 Q_D(const MyMoneyFinancialCalculator); 0094 return d->m_ir; 0095 } 0096 0097 void MyMoneyFinancialCalculator::setPv(const double pv) 0098 { 0099 Q_D(MyMoneyFinancialCalculator); 0100 d->m_pv = pv; 0101 d->m_mask |= PV_SET; 0102 } 0103 0104 double MyMoneyFinancialCalculator::pv() const 0105 { 0106 Q_D(const MyMoneyFinancialCalculator); 0107 return d->m_pv; 0108 } 0109 0110 void MyMoneyFinancialCalculator::setPmt(const double pmt) 0111 { 0112 Q_D(MyMoneyFinancialCalculator); 0113 d->m_pmt = pmt; 0114 d->m_mask |= PMT_SET; 0115 } 0116 0117 double MyMoneyFinancialCalculator::pmt() const 0118 { 0119 Q_D(const MyMoneyFinancialCalculator); 0120 return d->m_pmt; 0121 } 0122 0123 void MyMoneyFinancialCalculator::setNpp(const double npp) 0124 { 0125 Q_D(MyMoneyFinancialCalculator); 0126 d->m_npp = npp; 0127 d->m_mask |= NPP_SET; 0128 } 0129 0130 double MyMoneyFinancialCalculator::npp() const 0131 { 0132 Q_D(const MyMoneyFinancialCalculator); 0133 return d->m_npp; 0134 } 0135 0136 void MyMoneyFinancialCalculator::setFv(const double fv) 0137 { 0138 Q_D(MyMoneyFinancialCalculator); 0139 d->m_fv = fv; 0140 d->m_mask |= FV_SET; 0141 } 0142 0143 double MyMoneyFinancialCalculator::fv() const 0144 { 0145 Q_D(const MyMoneyFinancialCalculator); 0146 return d->m_fv; 0147 } 0148 0149 double MyMoneyFinancialCalculator::numPayments() 0150 { 0151 Q_D(MyMoneyFinancialCalculator); 0152 const unsigned short mask = PV_SET | IR_SET | PMT_SET | FV_SET; 0153 0154 if ((d->m_mask & mask) != mask) 0155 throw MYMONEYEXCEPTION_CSTRING("Not all parameters set for calculation of numPayments"); 0156 0157 double eint = d->eff_int(); 0158 0159 //add exception for zero interest 0160 if (eint == 0.0) { 0161 d->m_npp = -(d->m_pv / d->m_pmt); 0162 0163 } else { 0164 double CC = d->_Cx(eint); 0165 0166 CC = (CC - d->m_fv) / (CC + d->m_pv); 0167 d->m_npp = (CC > 0.0) ? log(CC) / log(eint + 1.0) : 0.0; 0168 0169 d->m_mask |= NPP_SET; 0170 } 0171 return d->m_npp; 0172 } 0173 0174 double MyMoneyFinancialCalculator::payment() 0175 { 0176 Q_D(MyMoneyFinancialCalculator); 0177 const unsigned short mask = PV_SET | IR_SET | NPP_SET | FV_SET; 0178 0179 if ((d->m_mask & mask) != mask) 0180 throw MYMONEYEXCEPTION_CSTRING("Not all parameters set for calculation of payment"); 0181 0182 double eint = d->eff_int(); 0183 0184 //add exception for zero interest 0185 if (eint == 0.0) { 0186 d->m_pmt = -(d->m_pv / d->m_npp); 0187 } else { 0188 double AA = d->_Ax(eint); 0189 double BB = d->_Bx(eint); 0190 0191 d->m_pmt = -d->rnd((d->m_fv + d->m_pv * (AA + 1.0)) / (AA * BB)); 0192 } 0193 0194 d->m_mask |= PMT_SET; 0195 return d->m_pmt; 0196 } 0197 0198 double MyMoneyFinancialCalculator::presentValue() 0199 { 0200 Q_D(MyMoneyFinancialCalculator); 0201 const unsigned short mask = PMT_SET | IR_SET | NPP_SET | FV_SET; 0202 0203 if ((d->m_mask & mask) != mask) 0204 throw MYMONEYEXCEPTION_CSTRING("Not all parameters set for calculation of payment"); 0205 0206 double eint = d->eff_int(); 0207 0208 //add exception for zero interest 0209 if (eint == 0.0) { 0210 d->m_pv = -(d->m_fv + (d->m_npp * d->m_pmt)); 0211 } else { 0212 double AA = d->_Ax(eint); 0213 double CC = d->_Cx(eint); 0214 0215 d->m_pv = d->rnd(-(d->m_fv + (AA * CC)) / (AA + 1.0)); 0216 0217 } 0218 0219 d->m_mask |= PV_SET; 0220 return d->m_pv; 0221 } 0222 0223 double MyMoneyFinancialCalculator::futureValue() 0224 { 0225 Q_D(MyMoneyFinancialCalculator); 0226 const unsigned short mask = PMT_SET | IR_SET | NPP_SET | PV_SET; 0227 0228 if ((d->m_mask & mask) != mask) 0229 throw MYMONEYEXCEPTION_CSTRING("Not all parameters set for calculation of payment"); 0230 0231 double eint = d->eff_int(); 0232 0233 //add exception for zero interest 0234 if (eint == 0.0) { 0235 d->m_fv = d->rnd(-(d->m_pv + (d->m_npp * d->m_pmt))); 0236 } else { 0237 double AA = d->_Ax(eint); 0238 double CC = d->_Cx(eint); 0239 d->m_fv = d->rnd(-(d->m_pv + AA * (d->m_pv + CC))); 0240 } 0241 0242 d->m_mask |= FV_SET; 0243 return d->m_fv; 0244 } 0245 0246 double MyMoneyFinancialCalculator::interestRate() 0247 { 0248 Q_D(MyMoneyFinancialCalculator); 0249 double eint = 0.0; 0250 double a = 0.0; 0251 double dik = 0.0; 0252 0253 const double ratio = 1e4; 0254 int ri; 0255 0256 if (d->m_pmt == 0.0) { 0257 eint = pow((dabs(d->m_fv) / dabs(d->m_pv)), (1.0 / d->m_npp)) - 1.0; 0258 } else { 0259 if ((d->m_pmt * d->m_fv) < 0.0) { 0260 if (d->m_pv) 0261 a = -1.0; 0262 else 0263 a = 1.0; 0264 eint = 0265 0266 dabs((d->m_fv + a * d->m_npp * d->m_pmt) / // 0267 (3.0 * // 0268 ((d->m_npp - 1.0) * (d->m_npp - 1.0) * d->m_pmt + d->m_pv - // 0269 d->m_fv))); 0270 } else { 0271 if ((d->m_pv * d->m_pmt) < 0.0) { 0272 eint = dabs((d->m_npp * d->m_pmt + d->m_pv + d->m_fv) / (d->m_npp * d->m_pv)); 0273 } else { 0274 a = dabs(d->m_pmt / (dabs(d->m_pv) + dabs(d->m_fv))); 0275 eint = a + 1.0 / (a * d->m_npp * d->m_npp * d->m_npp); 0276 } 0277 } 0278 do { 0279 try { 0280 dik = d->_fi(eint) / d->_fip(eint); 0281 eint -= dik; 0282 } catch (const MyMoneyException &) { 0283 eint = 0; 0284 } 0285 (void) modf(ratio *(dik / eint), &a); 0286 ri = static_cast<unsigned>(a); 0287 } while (ri); 0288 } 0289 d->m_mask |= IR_SET; 0290 d->m_ir = d->rnd(d->nom_int(eint) * 100.0); 0291 return d->m_ir; 0292 } 0293 0294 double MyMoneyFinancialCalculator::interestDue() const 0295 { 0296 Q_D(const MyMoneyFinancialCalculator); 0297 double eint = d->eff_int(); 0298 0299 return (d->m_pv + (d->m_bep ? d->m_pmt : 0.0)) * eint; 0300 } 0301