1201 #if defined(G_OS_WIN32) && !defined(_MSC_VER)
1209 #include "finproto.h"
1210 #include "fin_static_proto.h"
1215 rnd (
double x,
unsigned places)
1220 sprintf (buf,
"%.*f", (
int) places, x);
1221 r = strtod(buf, NULL);
1231 return (x >= 0.0) ? x : -x;
1236 _A (
double eint,
unsigned per)
1238 return pow ((1.0 + eint), (
double) per) - 1.0;
1243 _B (
double eint,
unsigned beg)
1247 g_return_val_if_fail(eint != 0.0, 0.0);
1248 return (1.0 + eint * (
double) beg) / eint;
1253 _C (
double eint,
double pmt,
unsigned beg)
1255 g_return_val_if_fail(eint != 0.0, 0.0);
1256 return pmt * _B(eint, beg);
1261 fi_calc_num_payments (
fi_ptr fi)
1265 rnd (_fi_calc_num_payments
1266 (fi->ir, fi->pv, fi->pmt, fi->fv, fi->CF, fi->PF, fi->disc, fi->bep),
1277 _fi_calc_num_payments (
double nint,
1286 double eint = eff_int (nint / 100.0, CF, PF, disc);
1287 double CC = _C (eint, pmt, bep);
1288 CC = (CC - fv) / (CC + pv);
1289 return (CC > 0.0) ? log (CC) / log (1.0 + eint) : 0.0;
1294 fi_calc_interest (
fi_ptr fi)
1297 fi->ir = _fi_calc_interest (fi->npp, fi->pv, fi->pmt, fi->fv,
1298 fi->CF, fi->PF, fi->disc, fi->bep);
1312 _fi_calc_interest (
unsigned per,
1326 eint = pow ((dabs (fv) / dabs (pv)), (1.0 / (
double) per)) - 1.0;
1329 if ((pmt * fv) < 0.0)
1336 dabs ((fv + a * (
double) per * pmt) /
1338 (((
double) per - 1.0) * ((
double) per - 1.0) * pmt + pv -
1343 if ((pv * pmt) < 0.0)
1345 eint = dabs (((
double) per * pmt + pv + fv) / ((
double) per * pv));
1349 a = dabs (pmt / (dabs (pv) + dabs (fv)));
1350 eint = a + 1.0 / (a * (double) per * (
double) per * (
double) per);
1356 fi (per, eint, pv, pmt, fv, bep) / fip (per, eint, pv, pmt, fv, bep);
1358 (void) modf (ratio * (dik / eint), &a);
1364 return 100.0 * nom_int (eint, CF, PF, disc);
1369 fi_calc_present_value (
fi_ptr fi)
1372 rnd (_fi_calc_present_value
1373 (fi->npp, fi->ir, fi->pmt, fi->fv, fi->CF, fi->PF, fi->disc,
1374 fi->bep), fi->prec);
1384 _fi_calc_present_value (
unsigned per,
1393 double eint = eff_int (nint / 100.0, CF, PF, disc);
1394 double AA = _A (eint, per);
1395 double CC = _C (eint, pmt, bep);
1397 return -(fv + (AA * CC)) / (AA + 1.0);
1402 fi_calc_payment (
fi_ptr fi)
1405 rnd (_fi_calc_payment
1406 (fi->npp, fi->ir, fi->pv, fi->fv, fi->CF, fi->PF, fi->disc, fi->bep),
1417 _fi_calc_payment (
unsigned per,
1426 double eint = eff_int (nint / 100.0, CF, PF, disc);
1427 double AA = _A (eint, per);
1428 double BB = _B (eint, bep);
1429 g_return_val_if_fail(BB != 0.0, 0.0);
1431 return -(fv + pv * (AA + 1.0)) / (AA * BB);
1436 fi_calc_future_value (
fi_ptr fi)
1439 rnd (_fi_calc_future_value
1440 (fi->npp, fi->ir, fi->pv, fi->pmt, fi->CF, fi->PF, fi->disc,
1441 fi->bep), fi->prec);
1451 _fi_calc_future_value (
unsigned per,
1460 double eint = eff_int (nint / 100.0, CF, PF, disc);
1461 double AA = _A (eint, per);
1462 double CC = _C (eint, pmt, bep);
1464 return -(pv + AA * (pv + CC));
1469 nom_int (
double eint,
unsigned CF,
unsigned PF,
unsigned disc)
1481 nint = CF * (pow ((1.0 + eint), ((
double) PF / (
double) CF)) - 1.0);
1485 nint = log (pow (1.0 + eint, PF));
1492 eff_int (
double nint,
unsigned CF,
unsigned PF,
unsigned disc)
1500 eint = nint / (double) CF;
1505 pow ((1.0 + nint / (
double) CF), ((
double) CF / (
double) PF)) - 1.0;
1509 eint = exp (nint / (
double) PF) - 1.0;
1516 fi (
unsigned per,
double eint,
double pv,
double pmt,
double fv,
unsigned bep)
1518 return _A (eint, per) * (pv + _C (eint, pmt, bep)) + pv + fv;
1524 fip (
unsigned per,
double eint,
double pv,
double pmt,
double fv,
unsigned bep)
1526 double AA = _A (eint, per);
1527 double CC = _C (eint, pmt, bep);
1528 double D = (AA + 1.0) / (1.0 + eint);
1529 g_return_val_if_fail(CC != 0.0, 0.0);
1530 return (
double) per * (pv + CC) * D - (AA * CC) / eint;
1553 fi->CF = fi->PF = 12;
1581 julian_day_number (
unsigned year,
unsigned month,
unsigned day)
1587 unsigned gregorian = TRUE;
1592 yr = year + (month - 3.0) / 12.0;
1593 ljdn = (long) (367.0 * yr + pfac) - (2 * (long) (yr)) + (
long) (yr / 4.0)
1594 + (long) day + 1721117L;
1596 ljdn += -(long) (yr / 100.0) + (long) (yr / 400.0) + 2;
1604 unsigned n = amortsched->n;
1605 double nint = amortsched->nint;
1606 double pv = amortsched->pv;
1607 double pmt = amortsched->pmt;
1608 double fv = amortsched->fv;
1612 unsigned CF = amortsched->CF;
1613 unsigned PF = amortsched->PF;
1614 unsigned disc = amortsched->disc;
1615 unsigned bep = amortsched->bep;
1617 unsigned prec = amortsched->prec;
1622 julian_day_number (amortsched->year_E, amortsched->month_E,
1623 amortsched->day_E), Init_Date_jdn =
1624 julian_day_number (amortsched->year_I, amortsched->month_I,
1627 amortsched->Eff_Date_jdn = Eff_Date_jdn;
1628 amortsched->Init_Date_jdn = Init_Date_jdn;
1629 amortsched->yday_E =
1630 Eff_Date_jdn - julian_day_number (amortsched->year_E, 1, 1);
1631 amortsched->yday_I =
1632 Init_Date_jdn - julian_day_number (amortsched->year_I, 1, 1);
1633 amortsched->eint = eint = eff_int (nint / 100.0, CF, PF, disc);
1634 amortsched->fv_case = dabs (fv) > dabs (pv);
1635 amortsched->bp = bep ? 1.0 : 0.0;
1642 s = Init_Date_jdn - Eff_Date_jdn;
1644 julian_day_number (amortsched->year_I + 1, 1, 0) - Init_Date_jdn;
1652 if (Eff_Date_jdn == Init_Date_jdn)
1659 ((amortsched->year_I - amortsched->year_E) * 360) +
1660 ((amortsched->month_I - amortsched->month_E) * 30) +
1661 amortsched->day_I - amortsched->day_E;
1663 days_to_yr_end = 390 - (amortsched->month_I * 30) - amortsched->day_I;
1674 amortsched->yr_pmt = (days_to_yr_end + d) / d;
1679 amortsched->pve = pv;
1684 rnd (pv * pow ((1.0 + eint), ((
double) (s * PF) / (
double) (d * CF))),
1688 pve = amortsched->pve;
1708 amortsched->new_pmt = new_pmt =
1709 rnd (_fi_calc_payment (n, nint, pve, fv, CF, PF, disc, bep), prec);
1712 amortsched->new_n = new_n =
1714 rnd (_fi_calc_num_payments (nint, pve, pmt, fv, CF, PF, disc, bep), 0);
1721 amortsched->cpmt1 = rnd (-pv / n, prec);
1722 amortsched->final_pmt_opt_1 = -pv - amortsched->cpmt1 * (n - 1);
1723 amortsched->final_pmt_opt_1 *= eint + 1;
1727 amortsched->cpmt2 = rnd (-pve / n, prec);
1728 amortsched->final_pmt_opt_2 = -pve - amortsched->cpmt2 * (n - 1);
1729 amortsched->final_pmt_opt_2 *= eint + 1;
1733 amortsched->final_pmt_opt_3 =
1734 rnd (_fi_calc_future_value (n - 1, nint, pv, pmt, CF, PF, disc, bep) -
1735 (fv / (1.0 + eint)), prec);
1736 amortsched->final_pmt_opt_4 =
1737 rnd (_fi_calc_future_value (n - 1, nint, pve, pmt, CF, PF, disc, bep) -
1738 (fv / (1.0 + eint)), prec);
1739 amortsched->final_pmt_opt_5 =
1740 rnd (_fi_calc_future_value
1741 (n - 1, nint, pve, new_pmt, CF, PF, disc,
1742 bep) - (fv / (1.0 + eint)), prec);
1744 amortsched->final_pmt_opt_6 =
1745 rnd (_fi_calc_future_value
1746 (new_n - 1, nint, pve, pmt, CF, PF, disc,
1747 bep) - (fv / (1.0 + eint)), prec);
1749 amortsched->final_pmt_opt_6 = 0.0;
1753 amortsched->final_pmt_opt_3 =
1754 rnd (_fi_calc_future_value (n - 1, nint, pv, pmt, CF, PF, disc, bep) *
1755 (1.0 + eint) - fv, prec);
1756 amortsched->final_pmt_opt_4 =
1757 rnd (_fi_calc_future_value (n - 1, nint, pve, pmt, CF, PF, disc, bep) *
1758 (1.0 + eint) - fv, prec);
1759 amortsched->final_pmt_opt_5 =
1760 rnd (_fi_calc_future_value
1761 (n - 1, nint, pve, new_pmt, CF, PF, disc, bep) * (1.0 + eint) - fv,
1764 amortsched->final_pmt_opt_6 =
1765 rnd (_fi_calc_future_value
1766 (new_n - 1, nint, pve, pmt, CF, PF, disc,
1767 bep) * (1.0 + eint) - fv, prec);
1769 amortsched->final_pmt_opt_6 = 0.0;
1773 amortsched->delayed_int = pv - amortsched->pve;
1781 unsigned n = amortsched->n;
1782 double nint = amortsched->nint;
1783 double pv = amortsched->pv;
1784 double pmt = amortsched->pmt;
1785 double fv = amortsched->fv;
1786 double eint = amortsched->eint;
1787 unsigned CF = amortsched->CF;
1788 unsigned PF = amortsched->PF;
1789 unsigned disc = amortsched->disc;
1790 unsigned bep = amortsched->bep;
1792 double final_pmt = 0;
1793 char summary = amortsched->summary;
1794 unsigned option = amortsched->option;
1795 unsigned yr_pmt = amortsched->yr_pmt;
1796 unsigned fv_case = amortsched->fv_case;
1797 unsigned prec = amortsched->prec;
1798 unsigned j, s, yr, per_cnt, pmt_cnt = 0, k = 0, sum_prt;
1804 double yr_fv, sum_int, yr_int, prin, adv_pmt, pmt_int, hpv = 0.0;
1809 sum_int = yr_int = 0.0;
1814 amortsched->cpmt = cpmt = amortsched->cpmt1;
1817 amortsched->final_pmt = final_pmt = -pv - cpmt * (n - 1);
1818 summary = (summary ==
'y') ?
'x' :
'o';
1821 amortsched->cpmt = cpmt = amortsched->cpmt2;
1822 pv = amortsched->pve;
1825 amortsched->final_pmt = final_pmt = -pv - cpmt * (n - 1);
1826 summary = (summary ==
'y') ?
'x' :
'o';
1829 amortsched->final_pmt = final_pmt = amortsched->final_pmt_opt_3;
1832 pv = amortsched->pve;
1833 amortsched->final_pmt = final_pmt = amortsched->final_pmt_opt_4;
1836 pv = amortsched->pve;
1837 pmt = amortsched->new_pmt;
1838 amortsched->final_pmt = final_pmt = amortsched->final_pmt_opt_5;
1841 n = amortsched->new_n;
1842 pv = amortsched->pve;
1843 amortsched->final_pmt = final_pmt = amortsched->final_pmt_opt_6;
1847 yr = amortsched->year_I;
1854 amortsched->schedule.first_yr =
1859 for (per_cnt = 0, s = 1, j = n; pv != fv; j -= 2, per_cnt++)
1862 pmt_int = -rnd ((pv + (amortsched->bp * pmt)) * eint, prec);
1872 if (dabs (pmt) > dabs (pv))
1875 pmt = prin + pmt_int;
1881 prin = rnd (pmt - pmt_int, prec);
1884 pv = rnd (pv + prin, prec);
1888 adv_pmt = rnd (pmt + (pv + (amortsched->bp * pmt)) * eint, prec);
1890 if (dabs (pv) >= dabs (adv_pmt))
1894 pv = rnd (pv + adv_pmt, prec);
1909 jj = (j < yr_pmt) ? j + 1 : yr_pmt;
1917 pmtsched->period_num = s++;
1918 pmtsched->interest = pmt_int;
1919 pmtsched->principal = prin;
1920 pmtsched->advanced_pmt = adv_pmt;
1921 pmtsched->total_pmt = pmt + adv_pmt;
1922 pmtsched->balance = pv;
1930 amortyr->year = yr++;
1931 amortyr->interest_pd = yr_int;
1932 amortyr->principal_pd = pv - hpv;
1933 amortyr->yr_end_balance = pv;
1934 amortyr->total_interest_pd = sum_int;
1935 amortyr->num_periods = pmt_cnt;
1938 amortyr = amortyr->next_yr;
1946 if (dabs (pv) > 0.0)
1949 pmt_int = -rnd ((pv + (amortsched->bp * pmt)) * eint, prec);
1959 prin = rnd (pmt - pmt_int, prec);
1963 pv = rnd (pv + prin, prec);
1967 amortyr->final_pmt = final_pmt += adv_pmt;
1972 pmtsched->period_num = s++;
1973 pmtsched->interest = pmt_int;
1974 pmtsched->principal = prin;
1975 pmtsched->advanced_pmt = adv_pmt;
1976 pmtsched->total_pmt = final_pmt;
1977 pmtsched->balance = pv;
1983 if (dabs (yr_int) > 0.0)
1985 amortyr->year = yr++;
1986 amortyr->interest_pd = yr_int;
1987 amortyr->principal_pd = pv - hpv;
1988 amortyr->total_interest_pd = sum_int;
1989 amortyr->num_periods = pmt_cnt;
1992 amortsched->total_periods = per_cnt;
1996 amortsched->schedule.first_yr =
2002 adv_pmt = amortsched->fixed_pmt;
2004 for (per_cnt = 0, s = 1, j = n; j && (pv != fv); j--, per_cnt++)
2007 pmt_int = -rnd ((pv + (amortsched->bp * pmt)) * eint, prec);
2016 if (dabs (pmt) > dabs (pv))
2019 pmt = prin + pmt_int;
2025 prin = rnd (pmt - pmt_int, prec);
2028 pv = rnd (pv + prin, prec);
2030 if (dabs (pv) >= dabs (adv_pmt))
2034 pv = rnd (pv + adv_pmt, prec);
2048 jj = (j < yr_pmt) ? j + 1 : yr_pmt;
2057 (amortyr->num_periods)++;
2060 pmtsched->period_num = s++;
2061 pmtsched->interest = pmt_int;
2062 pmtsched->principal = prin;
2063 pmtsched->advanced_pmt = adv_pmt;
2064 pmtsched->total_pmt = pmt + adv_pmt;
2065 pmtsched->balance = pv;
2073 amortyr->year = yr++;
2074 amortyr->interest_pd = yr_int;
2075 amortyr->principal_pd = pv - hpv;
2076 amortyr->yr_end_balance = pv;
2077 amortyr->total_interest_pd = sum_int;
2078 amortyr->num_periods = pmt_cnt;
2081 amortyr = amortyr->next_yr;
2092 pmt_int = -rnd ((pv + (amortsched->bp * pmt)) * eint, prec);
2101 prin = rnd (pmt - pmt_int, prec);
2105 pv = rnd (pv + prin, prec);
2109 amortyr->final_pmt = final_pmt += adv_pmt;
2114 pmtsched->period_num = s++;
2115 pmtsched->interest = pmt_int;
2116 pmtsched->principal = prin;
2117 pmtsched->advanced_pmt = adv_pmt;
2118 pmtsched->total_pmt = final_pmt;
2119 pmtsched->balance = pv;
2125 if (dabs (yr_int) > 0.0)
2127 amortyr->year = yr++;
2128 amortyr->interest_pd = yr_int;
2129 amortyr->principal_pd = pv - hpv;
2130 amortyr->total_interest_pd = sum_int;
2131 amortyr->num_periods = pmt_cnt;
2134 amortsched->total_periods = per_cnt;
2140 amortsched->schedule.first_yr =
2142 amortsched->total_periods = n;
2145 for (s = 1, j = n - 1; j; j--, k++)
2147 pmt_int = -rnd (pv * eint, prec);
2155 pv = rnd (pv + cpmt, prec);
2159 jj = (j < yr_pmt) ? j + 1 : yr_pmt;
2162 amortyr->num_periods = jj;
2168 pmtsched->period_num = s++;
2169 pmtsched->interest = pmt_int;
2170 pmtsched->total_pmt = cpmt + pmt_int;
2171 pmtsched->balance = pv;
2178 amortyr->year = yr++;
2179 amortyr->interest_pd = yr_int;
2180 amortyr->principal_pd = d * cpmt;
2181 amortyr->yr_end_balance = pv;
2182 amortyr->total_interest_pd = sum_int;
2185 amortyr = amortyr->next_yr;
2195 pmt_int = -rnd (pv * eint, prec);
2203 pmtsched->period_num = s++;
2204 pmtsched->interest = -pmt_int;
2205 pmtsched->total_pmt = -pv + pmt_int;
2206 pmtsched->balance = 0.0;
2208 amortyr->final_pmt = -pv - pmt_int;
2211 if (dabs (yr_int) > 0.0)
2213 amortyr->year = yr++;
2214 amortyr->interest_pd = yr_int;
2215 amortyr->principal_pd = -pv + k * cpmt;
2216 amortyr->total_interest_pd = sum_int;
2222 amortsched->schedule.first_yr =
2224 amortsched->total_periods = n;
2227 for (s = 1, j = n - 1; j; j--)
2230 pmt_int = -rnd ((pv + (amortsched->bp * pmt)) * eint, prec);
2239 prin = rnd (pmt - pmt_int, prec);
2242 pv = rnd (pv + prin, prec);
2246 jj = (j < yr_pmt) ? j + 1 : yr_pmt;
2249 amortyr->num_periods = jj;
2256 pmtsched->period_num = s++;
2257 pmtsched->interest = pmt_int;
2258 pmtsched->balance = pv;
2263 pmtsched->period_num = s++;
2264 pmtsched->interest = pmt_int;
2265 pmtsched->principal = prin;
2266 pmtsched->balance = pv;
2274 amortyr->year = yr++;
2275 amortyr->interest_pd = yr_int;
2278 amortyr->principal_pd = pv - hpv;
2280 amortyr->yr_end_balance = pv;
2281 amortyr->total_interest_pd = sum_int;
2284 amortyr = amortyr->next_yr;
2297 final_pmt = -pv - fv / (1 + eint);
2300 pmt_int = -rnd ((pv + final_pmt) * eint, prec);
2303 prin = final_pmt + pmt_int;
2309 pmt_int = -rnd (pv * eint, prec);
2316 final_pmt = prin + pmt_int;
2331 amortyr->num_periods = 1;
2334 amortyr->final_pmt = final_pmt;
2338 pmtsched->period_num = s++;
2339 pmtsched->interest = pmt_int;
2340 pmtsched->balance = pv;
2344 pmtsched->period_num = s++;
2345 pmtsched->interest = pmt_int;
2346 pmtsched->principal = prin;
2347 pmtsched->balance = pv;
2350 if (dabs (yr_int) > 0.0)
2352 amortyr->year = yr++;
2353 amortyr->interest_pd = yr_int;
2354 amortyr->total_interest_pd = sum_int;
2357 amortyr->principal_pd = -hpv;
2368 amortsched->total_periods = j;
2369 amortsched->schedule.summary =
2373 for (j = n, sum_prt = 0; j > 0; j -= yr_pmt, yr_pmt = PF, sum_prt++)
2379 yr_fv = rnd (pv + cpmt * (s - 1), prec) + final_pmt;
2384 yr_fv = rnd (pv + cpmt * s, prec);
2386 prin = -eint * jj * (pv + (cpmt * (jj - 1) / 2.0));
2387 yr_int = -eint * s * (pv + (cpmt * (s - 1) / 2.0));
2388 yr_int = rnd (yr_int - prin, prec);
2393 yrly_sum[sum_prt].year = yr++;
2394 yrly_sum[sum_prt].interest = yr_int;
2395 yrly_sum[sum_prt].end_balance = yr_fv;
2407 amortsched->total_periods = j;
2408 amortsched->schedule.summary =
2413 for (jj = n, j = 0; jj > 0; jj -= yr_pmt, yr_pmt = PF, j++)
2418 yr_int = rnd (((jj - 1) * pmt) + hpv + final_pmt, prec);
2423 -rnd (_fi_calc_future_value
2424 (yr_pmt, nint, hpv, pmt, CF, PF, disc, bep), prec);
2425 yr_int = rnd ((yr_pmt * pmt) + hpv - yr_fv, prec);
2430 yrly_sum[j].year = yr++;
2431 yrly_sum[j].interest = yr_int;
2432 yrly_sum[j].end_balance = yr_fv;
2439 amortsched->total_interest = sum_int;
2451 switch (amortsched->summary)
2457 for (amortyr = amortsched->schedule.first_yr; amortyr; amortyr = prst_yr)
2459 if (amortyr->payments)
2460 free (amortyr->payments);
2461 prst_yr = amortyr->next_yr;
2466 free (amortsched->schedule.summary);
2470 amortsched->schedule.first_yr = NULL;