GnuCash 2.4.99
fin.c
00001 /***************************************************************************
00002                           fin.c  -  description
00003                              -------------------
00004     begin                : Thursday June 15 2000
00005     email                : tboldt@attglobal.net
00006     Author               : Terry D. Boldt
00007  ***************************************************************************/
00008 
00009 /***************************************************************************
00010  *                                                                         *
00011  *   This program is free software; you can redistribute it and/or modify  *
00012  *   it under the terms of the GNU General Public License as published by  *
00013  *   the Free Software Foundation; either version 2 of the License, or     *
00014  *   (at your option) any later version.                                   *
00015  *                                                                         *
00016  ***************************************************************************/
00017 
00018 /*
00019  *  Functions to compute financial equations and amortization schedules
00020  *  6-15-2000
00021  *
00022  */
00023 
00024 /*
00025  * Financial Calculator
00026  *
00027  * This version for use WITH ANSI.SYS display driver
00028  *
00029  *  This is a complete financial computation utility to solve for the
00030  *  five * standard financial values: n, %i, PV, PMT and FV
00031  *
00032  *    n   == number of payment periods
00033  *    %i  == nominal interest rate, NAR, charged
00034  *    PV  == Present Value
00035  *    PMT == Periodic Payment
00036  *    FV  == Future Value
00037  *
00038  *  In addition, two additional parameters may be specified:
00039  *
00040  *    1) Compounding Frequency per year, CF. The compounding frequency
00041  *    per year may be discrete or continuous and may be different from
00042  *    the Payment Frequency per year
00043  *
00044  *    2) Payment Frequency per year, PF. Payments may be made at the
00045  *    beginning or the end of the payment period.
00046  *
00047  *  When an amortization schedule is desired, the financial
00048  *  transaction Effective Date, ED, and Initial Payment Date, IP, must
00049  *  also be entered.
00050  *
00051  *  Canadian and European style mortgages can be handled in a simple,
00052  *  straight-forward manner. Standard financial sign conventions are
00053  *  used:
00054  *
00055  *          "Money paid out is Negative, Money received is Positive"
00056  *
00057  *  Time value of money:
00058  *
00059  *  If you borrow money, you can expect  to pay rent or interest for its  use;
00060  * conversely you expect to receive rent interest on money you loan or invest.
00061  * When you rent property, equipment,  etc., rental payments are normal;  this
00062  * is  also  true  when  renting  or  borrowing  money.  Therefore,  money  is
00063  * considered to have a "time value". Money available now, has a greater value
00064  * than money available at some future date because of its rental value or the
00065  * interest that it can produce during the intervening period.
00066  *
00067  *  Simple Interest:
00068  *
00069  *  If you loaned $800 to  a friend with an agreement  that at the end of  one
00070  * year he would  would repay you  $896, the "time  value" you placed  on your
00071  * $800 (principal) was $96 (interest) for  the one year period (term) of  the
00072  * loan. This  relationship of  principal, interest,  and time (term) is  most
00073  * frequently expressed as an Annual  Percentage Rate (APR). In this  case the
00074  * APR  was  12.0%  [(96/800)*100].  This  example  illustrates the four basic
00075  * factors involved  in a  simple interest  case. The  time period (one year),
00076  * rate (12.0%  APR), present  value of  the principal  ($800) and  the future
00077  * value of the principal including interest ($896).
00078  *
00079  *  Compound Interest:
00080  *
00081  *  In many cases the interest charge is computed periodically during the term
00082  * of  the  agreement.  For  example,  money  left  in a savings account earns
00083  * interest that  is periodically  added to  the principal  and in  turn earns
00084  * additional interest during succeeding periods. The accumulation of interest
00085  * during  the  investment  period  represents  compound interest. If the loan
00086  * agreement you  made with  your friend  had specified  a "compound  interest
00087  * rate" of  12% (compounded  monthly) the  $800 principal  would have  earned
00088  * $101.46 interest for the  one year period. The  value of the original  $800
00089  * would be increased  by 1% the  first month to  $808 which in  turn would be
00090  * increased  by  1%  to  816.08 the second month,  reaching a future value of
00091  * $901.46 after the twelfth iteration. The monthly compounding of the nominal
00092  * annual rate (NAR) of 12% produces an effective Annual Percentage Rate (APR)
00093  * of 12.683% [(101.46/800)*100].  Interest may be  compounded at any  regular
00094  * interval; annually, semiannually, monthly, weekly, daily, even continuously
00095  * (a specification in some financial models).
00096  *
00097  *  Periodic Payments:
00098  *
00099  *  When money is loaned for longer  periods of time, it is customary  for the
00100  * agreement to require the borrower  to make periodic payments to  the lender
00101  * during the term of the loan. The payments may be only large enough to repay
00102  * the interest,  with the  principal due  at the  end of  the loan period (an
00103  * interest only loan), or large enough  to fully repay both the interest  and
00104  * principal during the term of the loan (a fully amoritized loan). Many loans
00105  * fall somewhere between, with payments that do not fully cover repayment  of
00106  * both the principal and interst. These loans require a larger final  payment
00107  * (balloon)  to  complete  their  amortization.  Payments  may  occur  at the
00108  * beginning or end of a payment period. If you and your friend had agreed  on
00109  * monthly repayment of  the $800 loan  at 12% NAR  compounded monthly, twelve
00110  * payments of $71.08 for a total of $852.96 would be required to amortize the
00111  * loan. The $101.46  interest from the  annual plan is  more than the  $52.96
00112  * under the monthly plan because under the monthly plan your friend would not
00113  * have had the use of $800 for a full year.
00114  *
00115  *  Financial Transactions:
00116  *
00117  *  The  above  paragraphs  introduce  the  basic  factors  that  govern  most
00118  * financial  transactions;  the  time  period,  interest rate, present value,
00119  * payments and  the future  value. In  addition, certain  conventions must be
00120  * adhered to: the interest rate must be relative to the compounding frequency
00121  * and payment periods, and the term must be expressed as the total number  of
00122  * payments (or compounding periods if there are no payments). Loans,  leases,
00123  * mortgages, annuities, savings plans, appreciation, and compound growth  are
00124  * amoung the many financial problems that can be defined in these terms. Some
00125  * transactions do not involve payments, but  all of the other factors play  a
00126  * part in "time value of money" transactions. When any one of the five  (four
00127  * - if no payments are involved)  factors is unknown, it can be  derived from
00128  * formulas using the known factors.
00129  *
00130  * Standard Financial Conventions Are:
00131  *
00132  *  Money RECEIVED is a POSITIVE value and is represented by an arrow
00133  *  above * the line
00134  *
00135  *  Money PAID OUT is a NEGATIVE value and is represented by an arrow
00136  *  below * the line.
00137  *
00138  *  If payments are a part of the transaction, the number of payments
00139  *  must * equal the number of periods (n).
00140  *
00141  *  Payments may be represented as occuring at the end or beginning of
00142  *  the * periods.
00143  *
00144  *  Diagram to visualize the positive and negative cash flows (cash
00145  *  flow * diagrams):
00146  *
00147  *  Amounts shown above the line are positve, received, and amounts
00148  *  shown below the line are negative, paid out.
00149  *
00150  * 1)
00151  *                                                                 FV*
00152  *          1   2   3   4   .   .   .   .   .   .   .   .   .   n ³
00153  * Period ÚÄÄÄÁÄÄÄÁÄÄÄÁÄÄÄÁÄÄÄÁÄÄÄÁÄÄÄÁÄÄÄÁÄÄÄÁÄÄÄÁÄÄÄÁÄÄÄÁÄÄÄÁÄÄÄÙ
00154  *        ³
00155  *
00156  *        PV
00157  *
00158  *     Appreciation
00159  *     Depreciation
00160  *     Compound Growth
00161  *     Savings Account
00162  *
00163  * ****************************************************************************
00164  *
00165  * 2)                                                               FV
00166  *     PV = 0
00167  *                                                                ³
00168  * Period ÚÄÄÄÂÄÄÄÂÄÄÄÂÄÄÄÂÄÄÄÂÄÄÄÂÄÄÄÂÄÄÄÂÄÄÄÂÄÄÄÂÄÄÄÂÄÄÄÂÄÄÄÂÄÄÄÙ
00169  *        ³ 1 ³ 2 ³ 3 ³ 4 ³ . ³ . ³ . ³ . ³ . ³ . ³ . ³ . ³ . ³ n
00170  *
00171  *       PMT PMT PMT PMT PMT PMT PMT PMT PMT PMT PMT PMT PMT PMT
00172  *
00173  *     Annuity (series of payments)
00174  *     Pension Fund
00175  *     Savings Plan
00176  *     Sinking Fund
00177  *
00178  * ****************************************************************************
00179  *
00180  * 3)
00181  *     PV
00182  *        ³                                                      FV=0
00183  * Period ÀÄÄÄÂÄÄÄÂÄÄÄÂÄÄÄÂÄÄÄÂÄÄÄÂÄÄÄÂÄÄÄÂÄÄÄÂÄÄÄÂÄÄÄÂÄÄÄÂÄÄÄÂÄÄÄ¿
00184  *          1 ³ 2 ³ 3 ³ 4 ³ . ³ . ³ . ³ . ³ . ³ . ³ . ³ . ³ . ³ n ³
00185  *
00186  *           PMT PMT PMT PMT PMT PMT PMT PMT PMT PMT PMT PMT PMT PMT
00187  *
00188  *     Amortization
00189  *     Direct Reduction Loan
00190  *     Mortgage (fully amortized)
00191  *
00192  * ****************************************************************************
00193  *
00194  * 4)
00195  *                                                                 FV*
00196  *           PMT PMT PMT PMT PMT PMT PMT PMT PMT PMT PMT PMT PMT  ³ +
00197  *                                                    PMT
00198  *          1 ³ 2 ³ 3 ³ 4 ³ . ³ . ³ . ³ . ³ . ³ . ³ . ³ . ³ . ³ n ³
00199  * Period ÚÄÄÄÁÄÄÄÁÄÄÄÁÄÄÄÁÄÄÄÁÄÄÄÁÄÄÄÁÄÄÄÁÄÄÄÁÄÄÄÁÄÄÄÁÄÄÄÁÄÄÄÁÄÄÄÙ
00200  *        ³
00201  *
00202  *        PV
00203  *
00204  *     Annuity
00205  *     Lease (with buy back or residual)*
00206  *     Loan or Mortgage (with balloon)*
00207  *
00208  * ****************************************************************************
00209  *
00210  *   First lets discuss interest before discussing the financial
00211  *   equation. Most financial transactions utilize a nominal interest
00212  *   rate, NAR, i.e., the interest rate per year. The NAR must be
00213  *   converted to the interest rate per payment interval and the
00214  *   compounding accounted for before it can be used in computing an
00215  *   interest payment. After this conversion process, the interest
00216  *   used is the effective interest rate, EIR. In converting NAR to
00217  *   EIR, there are two concepts to discuss first, the Compounding
00218  *   Frequency and the Payment Frequency and * whether the interest is
00219  *   coumpounded in discrete intervals or continuously. The
00220  *   compounding Frequency, CF, is simply the number of times per
00221  *   year, the monies in the financial transaction are compounded. In
00222  *   the U.S., monies are usually compounded daily on bank deposits,
00223  *   and monthly on loans. Somtimes Long term deposits are compounded
00224  *   quarterly or weekly.
00225  *
00226  *   The Payment Frequency, PF, is simply how often during a year
00227  *   payments are made in the transaction. Payments are usually
00228  *   scheduled on a regular basis and can be made at the beginning or
00229  *   end of the payment period. If made at the beginning of the
00230  *   payment period, interest must be applied to the payment as well
00231  *   as any previous money paid or money still owed.
00232  *
00233  *   Normal values for CF and PF are:
00234  *   1   == annual
00235  *   2   == semi-annual
00236  *   3   == tri-annual
00237  *   4   == quaterly
00238  *   6   == bi-monthly
00239  *   12  == monthly
00240  *   24  == semi-monthly
00241  *   26  == bi-weekly
00242  *   52  == weekly
00243  *   360 == daily
00244  *   365 == daily
00245  *
00246  *  a) the Compounding Frequency per year, CF, need not be identical
00247  *  to the Payment Frequency per year, PF, and/or,
00248  *
00249  *  b) Interest may be compounded in either discrete intervals or continuously
00250  *     compounded.
00251  *
00252  *  c) Also, payments may be made at the beginning of the payment
00253  *  period or at the end of the payment period.
00254  *
00255  *  CF and PF are defaulted to 1. The default is for discrete interest
00256  *  intervals and payments are defaulted to the end of the payment
00257  *  period.
00258  *
00259  *  When a solution  for n, PV,  PMT or FV  is required, the  nominal interest
00260  * rate, i, must first be converted to the effective interest rate per payment
00261  * period. This rate, ieff, is then used to compute the selected variable.  To
00262  * convert i to ieff, the following expressions are used:
00263  *
00264  *  Discrete interest periods:
00265  *
00266  * 19) ieff = (1 + i/CF)^(CF/PF) - 1
00267  *
00268  *  Continuous Interest
00269  *
00270  * 20) ieff = e^(i/PF) - 1 = exp(i/PF) - 1
00271  *
00272  *  When interest is computed, the computation produces the effective interest
00273  * rate, ieff. This value must then be converted to the nominal interest rate.
00274  * Function  _I  below  returns  the  nominal  interest rate NOT the effective
00275  * interest rate. ieff is converted to i using the following expressions:
00276  *
00277  *  Discrete Case:
00278  *
00279  *     i = CF*[(1+ieff)^(PF/CF) - 1]
00280  *
00281  *  Continuous Case:
00282  *
00283  *     i = ln[(1+ieff)^PF]
00284  *
00285  * ****************************************************************************
00286  *
00287  *   NOTE: in the equations below for the financial transaction, all
00288  *   interest rates are the effective interest rate, ieff. The symbol
00289  *   will be shortned to just 'i'.
00290  *
00291  * ****************************************************************************
00292  *
00293  * The basic financial equation used is:
00294  *
00295  *  1) PV*(1 + i)^n + PMT*(1 + iX)*[(1+i)^n - 1]/i + FV = 0
00296  *   Where: X = 0 for end of period payments, and
00297  *          X = 1 for beginning of period payments
00298  *
00299  * ****************************************************************************
00300  *
00301  *   NOTE: this equation is derived in the following manner:
00302  *
00303  *   Start with the basic equation to find the balance or Present
00304  *   Value, PV[1], after one payment period. Note PV[1] is the Present
00305  *   value after on payment and PV[0] is the initial Present
00306  *   Value. PV[0] will be shortened to just PV.
00307  *
00308  *   The interest due at the end of the first payment period is:
00309  *
00310  *   ID[1] = (PV + X * PMT) * i
00311  *       where: X = 0 for end of period payments, and
00312  *              X = 1 for beginning of period payments.
00313  *
00314  *   Thus:
00315  *   PV[1] = PV + (PMT + ID[1])
00316  *         = PV + (PMT + (PV + X * PMT) * i)
00317  *         = PV * (1 + i) + PMT * (1 + Xi)
00318  *
00319  *   This equation works for all of the money diagrams shown
00320  *   above. The Present Value, money received or paid, is modified by
00321  *   a payment made at the beginning of a payment period and
00322  *   multiplied by the effective interest rate to compute the interest
00323  *   due during the payment period. The interest due is then added to
00324  *   the payment to obtain the amount to be added to the Present Value
00325  *   to compute the new Present Value.
00326  *
00327  *   For diagram 1): PV <  0, PMT == 0, PV[1] < 0
00328  *   For diagram 2): PV == 0, PMT <  0, PV[1] < 0
00329  *   For Diagram 3): PV >  0, PMT <  0, PV[1] >= 0 or PV[1] <= 0
00330  *   For Diagram 4): PV <  0, PMT >  0, PV[1] <= 0 or PV[1] >= 0
00331  *
00332  *   X may be 0 or 1 for any diagram.
00333  *
00334  *   For the standard loan, PV is the money borrowed, PMT is the
00335  *   periodic payment to repay the loan and i is the effective
00336  *   interest rate agreed upon.
00337  *
00338  *   To calculate the Present Value after the second payment period,
00339  *   the above calculation is applied iteratively to PV_1:
00340  *
00341  *   PV[2] = PV[1] + (PMT + (PV[1] + X * PMT) * i)
00342  *         = PV[1] * (1 + i) + PMT * (1 + iX)
00343  *         = (PV * (1 + i) + PMT * (1 + iX)) * (1 + i) + PMT * (1 + iX)
00344  *         = PV * (1 + i)^2 + PMT * (1 + iX) * (1 + i)
00345  *                          + PMT * (1 + iX)
00346  *
00347  *   Similarly:
00348  *
00349  *   PV[3] = PV[2] + (PMT + (PV[2] + X * PMT) * i)
00350  *         = PV[2] * (1 + i) + PMT * (1 + iX)
00351  *         = PV * (1 + i)^2 + PMT * (1 + iX) * (1 + i)
00352  *                          + PMT * (1+  iX)) * ( 1 + i)
00353  *                          + PMT * (1+  iX)
00354  *         = PV * (1 + i)^3 + PMT * (1 + iX) * (1 + i)^2
00355  *                          + PMT * (1 + iX) * (1 + i)^2
00356  *                          + PMT * (1 + iX) * (1 + i)
00357  *                          + PMT * (1 + iX)
00358  *
00359  *   And for the n'th payment:
00360  *
00361  *   PV[n] = PV[n-1] + (PMT + (PV[n-1] + X * PMT) * i)
00362  *   PV[n] = PV * (1 + i)^n + PMT * (1 + iX) * (1 + i)^(n-1)
00363  *                          + PMT * (1 + iX) * (1 + i)^(n-2) +
00364  *                          .
00365  *                          .
00366  *                          .
00367  *                          + PMT * (1 + iX) * (1 + i)
00368  *                          + PMT * (1 + iX)
00369  *   PV[n] = PV * (1 + i)^n + PMT * (1 + iX) * [(1 + i)^(n-1) + ...
00370  *           + (1 + i) + 1]
00371  *
00372  * ****************************************************************************
00373  *
00374  *       The sum of the finite series:
00375  *
00376  *       1 + k + (k^2) + (k^3) + ... + (k^n) = (1-k^(n+1))/(1-k)
00377  *
00378  *       as can be seen by the following. Let S(n) be the series sum. Then
00379  *
00380  *       S(n) - k * S(n) = 1 - k^(n+1)
00381  *
00382  *       and solving for S(n):
00383  *
00384  *       S(n) = [1-k^(n+1)]/[1-k] = 1 + k + (k^2) + (k^3) + ... + (k^n)
00385  *
00386  * ****************************************************************************
00387  *
00388  *   PV[n] = PV * (1 + i)^n + PMT * (1 + iX) * [(1 + i)^(n-1) + ...
00389  *           + (1 + i) + 1]
00390  *         = PV * (1 + i)^n + PMT * (1 + iX) * [1 - (1 + i)^n]/[1 - (1 + i)]
00391  *         = PV * (1 + i)^n + PMT * (1 + iX) * [1 - (1 + i)^n]/[-i]
00392  *         = PV * (1 + i)^n + PMT * (1 + iX) * [(1 + i)^n - 1]/i
00393  *
00394  *   The formaula for PV[n] can be proven using mathematical induction.
00395  *
00396  *   or:
00397  *
00398  *   PV * (1 + i)^n + PMT * [(1 + i)^n - 1]/i - PV[n] = 0
00399  *
00400  *   If after n payments, the remaining balance is repaid as a lump
00401  *   sum, the lump sum is known as the Future Value, FV[n]. Since
00402  *   FV[n] is negative if paid and positive if received, FV[n] is the
00403  *   negative of PV[n]. Since n is assumed to be the last payment,
00404  *   FV[n] will be shortened to simply FV.
00405  *
00406  *   Setting: FV = -PV[N]
00407  *
00408  *   1)  PV*(1 + i)^n + PMT*(1 + iX)*[(1 + i)^n - 1]/i + FV = 0
00409  *
00410  *   Up to this point, we have said nothing about the value of
00411  *   PMT. PMT can be any value mutually agreed upon by the lender and
00412  *   the borrower. From the equation for PV[1]:
00413  *
00414  *   PV[1] = PV + (PMT + (PV + X * PMT) * i),
00415  *
00416  *   Several things can be said about PMT.
00417  *
00418  *   1. If PMT = PV * i, and X = 0 (end of period payments):
00419  *
00420  *      The payment is exactly equal to the interest due and PV[1] =
00421  *      PV. In this case, the borrower must make larger future
00422  *      payments to reduce the balance due, or make a single payment,
00423  *      after some agreed upon number of payments, with PMT = PV to
00424  *      completely pay off the loan. This is an interest only payment
00425  *      with a balloon payment at the end.
00426  *
00427  *   2. If PMT < PV * i, and X = 0
00428  *
00429  *      The payment is insufficient to cover even the interest charged
00430  *      and the balance due grows
00431  *
00432  *   3. If PMT > PV * i, and X = 0
00433  *
00434  *      The payment is sufficient to cover the interest charged with a
00435  *      residual amount to be applied to reduce the balance due. The
00436  *      larger the residual amount, the faster the loan is repaid. For
00437  *      most mortgages or other loans made today, the lender and
00438  *      borrower agree upon a certain number of repayment periods and
00439  *      the interest to be charged per payment period.  The interest
00440  *      may be multiplied by 12 and stated as an annual interest
00441  *      rate. Then the lender and borrower want to compute a periodic
00442  *      payment, PMT, which will reduce the balance due to zero after
00443  *      the agreed upon number of payment have been made. If N is the
00444  *      agreed upon number of periodic payments, then we want to use:
00445  *
00446  *      PV * (1 + i)^N + PMT*(1 +iX)*[(1 + i)^N - 1]/i + FV = 0
00447  *
00448  *      with FV = 0 to compute PMT:
00449  *
00450  *      PMT = -[PV * i * (1 + i)^(N - X)]/[(1 + i)^N - 1]
00451  *
00452  *      The value of PMT computed will reduce the balance due to zero
00453  *      after N periodic payments.
00454  *
00455  * ****************************************************************************
00456  *
00457  *
00458  * With a simple alegebraic re-arrangement, The financial Equation becomes:
00459  *
00460  *  2) [PV + PMT*(1 + iX)/i][(1 + i)^n - 1] + PV + FV = 0
00461  *
00462  * or
00463  *
00464  *  3) (PV + C)*A + PV + FV = 0
00465  *
00466  * where:
00467  *  4) A = (1 + i)^n - 1
00468  *
00469  *  5) B = (1 + iX)/i
00470  *
00471  *  6) C = PMT*B
00472  *
00473  * The form of equation 3) simplifies the calculation procedure for all five
00474  * variables, which are readily solved as follows:
00475  *
00476  *  7) n = ln[(C - FV)/(C + PV)]/ln((1 + i)
00477  *
00478  *  8) PV = -[FV + A*C]/(A + 1)
00479  *
00480  *  9) PMT = -[FV + PV*(A + 1)]/[A*B]
00481  *
00482  * 10) FV = -[PV + A*(PV + C)]
00483  *
00484  * Equations 4), 5) and 6) are computed by functions:
00485  *
00486  *  _A
00487  *  _B
00488  *  _C
00489  *
00490  * respectively. Equations 7), 8), 9) and 10) are computed by functions:
00491  *
00492  *  _N
00493  *  _PV
00494  *  _PMT
00495  *  _FV
00496  *
00497  * respectively.
00498  *
00499  * The solution for interest is broken into two cases:
00500  *
00501  *  PMT == 0
00502  *       i = [FV/PV]^(1/n) - 1
00503  *
00504  *  PMT != 0
00505  *
00506  *       Since equation 3) cannot be solved explicitly for i in this
00507  *       case, an iterative technique must be employed. Newton's
00508  *       method, using exact expressions for the function of i and its
00509  *       derivative, are employed. The expressions are:
00510  *
00511  * 12) i[k+1] = i[k] - f(i[k])/f'(i[k])
00512  *       where: i[k+1] == (k+1)st iteration of i
00513  *              i[k]   == kth iteration of i
00514  *       and:
00515  *
00516  * 13) f(i) = A*(PV+C) + PV + FV
00517  *
00518  * 14) f'(i) = n*D*(PV+C) - (A*C)/i
00519  *
00520  * 15) D = (1 + i)^(n-1) = (A+1)/(1+i)
00521  *
00522  *       To start the iterative solution for i, an initial guess must be made
00523  *       for the value of i. The closer this guess is to the actual value,
00524  *       the fewer iterations will have to be made, and the greater the
00525  *       probability that the required solution will be obtained. The initial
00526  *       guess for i is obtained as follows:
00527  *
00528  *       if PMT*FV >= 0, then PV case
00529  *       if PMT*FV <  0, then FV case
00530  *
00531  *     PV case:
00532  *                | n*PMT + PV + FV |
00533  * 16)     i[0] = | ----------------|
00534  *                |      n*PV       |
00535  *
00536  *              = abs[(n*PMT + PV + FV)/(n*PV)]
00537  *
00538  *     FV case:
00539  *         a) PV != 0
00540  *
00541  *                    |      FV - n*PMT           |
00542  * 17)         i[0] = |---------------------------|
00543  *                    | 3*[PMT*(n-1)^2 + PV - FV] |
00544  *
00545  *                  = abs[(FV-n*PMT)/(3*(PMT*(n-1)^2+PV-FV))]
00546  *         b) PV == 0
00547  *
00548  *                    |      FV + n*PMT           |
00549  * 18)         i[0] = |---------------------------|
00550  *                    | 3*[PMT*(n-1)^2 + PV - FV] |
00551  *
00552  *                  = abs[(FV+n*PMT)/(3*(PMT*(n-1)^2+PV-FV))]
00553  *
00554  * ****************************************************************************
00555  * Constant payment to principal loan
00556  *
00557  *   In this loan, each total payment is different, with each
00558  *   succeeding payment less than the preceeding payment. Each payment
00559  *   is the total of the constant ammount to the principal plus the
00560  *   interest for the period. The constant payment to the principal is
00561  *   computed as:
00562  *
00563  *           C = -PV / N
00564  *
00565  *   Where PV is the loan amount to be repaid in N payments
00566  *   (periods). Note that the constant payment to principal could be
00567  *   any value agreed to by the two parties involved.
00568  *
00569  *   Thus the principal after the first payment is:
00570  *       PV[1] = PV[0] + C = PV + C
00571  *   after the second payment, the principal is:
00572  *       PV[2] = PV[1] + C = PV[0] + 2C
00573  *   In general, the remaining principal after n payments is:
00574  *       PV[n] = PV[0] + nC = PV + nC
00575  *
00576  *   If the effective interest per payment period is i, then the
00577  *   interest for the first payment is:
00578  *
00579  *       I[1] = -i*PV[0] = -i*PV
00580  *   and for the second:
00581  *       I[2] = -i * PV[1]
00582  *   and in general, for the n'th payment the interest is:
00583  *       I[n] = -i * PV[n-1]
00584  *            = -i * (PV + (n-1)C)
00585  *   The total payment for any period, n, is:
00586  *       P[n] = C + I[n]
00587  *            = C + i * (PV + (n-1)C)
00588  *            = C(1 + i) - i * (PV + nC)
00589  *   The total interest paid to period n is:
00590  *       T[n] = I[1] + I[2] + I[3] + ... + I[n]
00591  *       T[n] = sum(j = 1 to n: I[j])
00592  *       T[n] = sum(j = 1 to n: -i * (PV + (j-1)C))
00593  *       T[n] = sum(j=1 to n: -i*PV) + sum(j=1 to n: iC) + sum(j=1 to n: -iCj)
00594  *       T[n] = -i*n*PV + i*n*C - i*C*sum(j=1 to n:j)
00595  *           sum(j=1 to n:j) = n(n+1)/2
00596  *       T[n] = -i*n*(PV + C) - i*C*n(n+1)/2
00597  *       T[n] = -i*n*(PV + (C*(n - 1)/2))
00598  *
00599  * Note: substituing for C = -PV/N, in the equations for PV[n], I[n],
00600  *   P[n], and T[n] would give the following equations:
00601  *
00602  *       PV[n] = PV*(1 - n/N)
00603  *       I[n]  = -i*PV*(1 + N - n)/N
00604  *       P[n]  = -i*PV*(2 + N - n)/N
00605  *       T[n]  = -i*n*PV*(2*N - n + 1)/(2*N)
00606  *
00607  *   Using these equations for the calculations would eliminate the
00608  *   dependence on C, but only if C is always defined as above and
00609  *   would eliminate the possibility of another value for C. If the
00610  *   value of C was less than -PV/N then a balloon payment would be
00611  *   due at the final payment and this is a possible alternative for
00612  *   some people.
00613  *
00614  * ****************************************************************************
00615  *
00616  *   Amortization Schedules.
00617  *
00618  *   Financial Transactions have an effective Date, ED, and an Initial Payment
00619  *   Date, IP. ED may or may not be the same as IP, but IP is always the same
00620  *   or later than ED. Most financial transaction calculators assume that
00621  *   IP is equal to ED for beginning of period payments or at the end of the
00622  *   first payment period for end of period payments.
00623  *
00624  *   This is not always true. IP may be delayed for financial reasons
00625  *   such as cash flow or accounting calender. The subsequent payments
00626  *   then follow the agreed upon periodicity. Since money has a time
00627  *   value, the "delayed" IP must be accounted for. Computing an
00628  *   "Effective PV", pve, is one means of handling a delayed IP.
00629  *
00630  *   EDj == the Julian Day Number of ED, and
00631  *   IPj == the Julian Day Number of IP in the following.
00632  *
00633  *   pve is be computed as:
00634  *
00635  *   pve = pv*(1 + i)^(s*PF/d*CF)
00636  *
00637  *   Where: d = length of the payment period in days, and
00638  *          s = IPj - EDj - d*X
00639  *
00640  *   Computing an amortization Schedule for a given financial transaction is
00641  *   simply applying the basic equation iteratively for each payment period:
00642  *
00643  *   PV[n] = PV[n-1] + (PMT + (PV[n-1] + X * PMT) * i)
00644  *
00645  *   At the end of each iteration, PV[n] is rounded to the nearest cent. For
00646  *   each payment period, the interest due may be computed separately as:
00647  *
00648  *   ID[n] = (PMT + (PV[n-1] + X * PMT) * i)
00649  *
00650  *   and rounded to the nearest cent. PV[n] then becomes:
00651  *
00652  *   PV[n] = PV[n-1] + PMT + ID[n]
00653  *
00654  *   For those cases where a yearly summary only is desired, it is not
00655  *   necessary to compute each transaction for each payment period,
00656  *   rather the PV may be be computed for the beginning of each year,
00657  *   PV[yr], and the FV computed for the end of the year, FV[yr]. The
00658  *   interest paid during the year is the computed as:
00659  *
00660  *   ID[yr] = (NP * PMT) + PV[yr] + FV[yr]
00661  *
00662  *   Since the final payment may not be equal to the periodic payment,
00663  *   the final payment must be computed separately as follows. Two
00664  *   derivations are given below for the final payment equation. Both
00665  *   derivations are given below since one or the other may be clearer
00666  *   to some readers. Both derivations are essentially the same, they
00667  *   just have different starting points. The first is the fastest.
00668  *
00669  *   1) final_pmt == final payment @ payment n == int(n)
00670  *       from above the basic financial equation:
00671  *       PV[n] = PV[n-1]*(1 + i) + final_pmt * (1 + iX),
00672  *       i == effective interest rate
00673  *
00674  *       solving for final_pmt, we have:
00675  *
00676  *       final_pmt * (1 + iX) = PV[n] - PV[n-1]*(1 + i)
00677  *                            = FV[n-1]*(1 + i) - FV[n]
00678  *       final_pmt = FV[n-1]*(1+i)/(1 + iX) - FV[n]/(1 + iX)
00679  *
00680  *       final_pmt = FV[n-1]*(1 + i) - FV[n],
00681  *                   for X == 0, end of period payments
00682  *
00683  *                 = FV[n-1] - FV[n]/(1 + i),
00684  *                   for X == 1, beginning of period payments
00685  *
00686  *   2) final_pmt == final payment @ payment n == int(n)
00687  *       i[n] == interest due @ payment n
00688  *       i[n] = (PV[n-1] + X * final_pmt) * i, i == effective interest rate
00689  *            = (X * final_pmt - FV[n]) * i
00690  *
00691  *       Now the final payment is the sum of the interest due, plus
00692  *       the present value at the next to last payment plus any
00693  *       residual future value after the last payment:
00694  *
00695  *       final_pmt = -i[n] - PV[n-1] - FV[n]
00696  *                 = FV[n-1] - i[n] - FV[n]
00697  *                 = FV[n-1] - (X *final_pmt - FV[n-1])*i - FV[n]
00698  *                 = FV[n-1]*(1 + i) - X*final_pmt*i - FV[n]
00699  *
00700  *       solving for final_pmt:
00701  *       final_pmt*(1 + iX) = FV[n-1]*(1 + i) - FV[n]
00702  *       final_pmt = FV[n-1]*(1 + i)/(1 + iX) - FV[n]/(1 + iX)
00703  *
00704  *       final_pmt = FV[n-1]*(1 + i) - FV[n],
00705  *                   for X == 0, end of period payments
00706  *
00707  *                 = FV[n-1] - FV[n]/(1 + i),
00708  *                   for X == 1, beginning of period payments
00709  *
00710  *============================================================================
00711  *
00712  *   The amortization schedule is computed for four different situations:
00713  *
00714  *   1) The original financial data is used. This ignores any possible
00715  *   agjustment to the Present value due to any delay in the initial
00716  *   payment. This is quite common in mortgages where end of period
00717  *   payments are used and the first payment is scheduled for the end
00718  *   of the first whole period, i.e., any partial payment period from
00719  *   ED to the beginning of the next payment period is ignored.
00720  *
00721  *   2) The original periodic payment is used, the Present Value is
00722  *   adjusted for the delayed Initial Payment. The total number of
00723  *   payments remains the same. The final payment is adjusted to bring
00724  *   the balance into agreement with the agreed upon final Future
00725  *   Value.
00726  *
00727  *   3) A new periodic payment is computed based upon the adjusted
00728  *   Present Value, the agreed originally upon number of total
00729  *   payments and the agreed upon Future Value.  The new periodic
00730  *   payments are computed to minimize the final payment in accordance
00731  *   with the Future Value after the last payment.
00732  *
00733  *   4) The original periodic payment is retained and a new number of
00734  *   total payments is computed based upon the adjusted Present Value
00735  *   and the agreed upon Future Value.
00736  *
00737  *   The amortization schedule may be computed and displayed in three manners:
00738  *
00739  *   1. The payment *, interest paid, principal paid and remaining PV
00740  *   for each payment period are computed and displayed. At the end of
00741  *   each year a summary is computed and displayed and the total
00742  *   interest paid is diplayed at the end.
00743  *
00744  *   2. A summary is computed and displayed for each year. The
00745  *   interest paid during the year is computed and displayed as well
00746  *   as the remaining balance at years end.  The total interest paid
00747  *   is diplayed at the end.
00748  *
00749  *   3. An amortization schedule is computed for a common method of
00750  *   advanced payment of principal is computed and displayed. In this
00751  *   amortization, the principal for the next payment is computed and
00752  *   added into the current payment. This method will cut the number
00753  *   of total payments in half and will cut the interest paid almost
00754  *   in half. For mortgages, this method of prepayment has the
00755  *   advantage of keeping the total payments small during the initial
00756  *   payment periods The payments grow until the last payment period
00757  *   when presumably the borrower can afford larger payments.
00758  *
00759  * ===========================================================================
00760  *   NOTE: For Payment Frequencies, PF, semi-monthly or less, i.e., PF
00761  *   == 12 or PF == 24, a 360 day calender year and 30 day month are
00762  *   used. For Payment Frequencies, PF, greater than semi-monthly, PF
00763  *   > 24, the actual number of days per year and per payment period
00764  *   are used. The actual values are computed using the built-in
00765  *   'julian_day_number' function
00766  *
00767  * ****************************************************************************
00768  *
00769  * Note: in the following examples, the user input is preceeded by the
00770  * prompt "<>". The result of evaluating the input expression is then
00771  * displayed.  I have taken the liberty of including comments in the
00772  * example input/output sessions by preceeding with ' *'. Thus, for
00773  * the line: <>n=5 *set number of periods the comment that setting the
00774  * number of periods is not really input and the true input is only:
00775  * <>n=5
00776  *
00777  * Example 1: Simple Interest
00778  * Find annual simple interest rate (%) for an $800 loan to be repayed at the
00779  * end of one year with a single payment of $896.
00780  * <>d
00781  * <>CF=PF=1
00782  *         1.00
00783  * <>n=1
00784  *         1.00
00785  * <>pv=-800
00786  *         -800.00
00787  * <>fv=896
00788  *         896.00
00789  * <>I
00790  *         12.00
00791  *
00792  * Example 2: Compound Interest
00793  * Find the future value of $800 after one year at a nominal rate of 12%
00794  * compounded monthly. No payments are specified, so the payment frequency is
00795  * set equal to the compounding frequency at the default values.
00796  * <>d
00797  * <>n=12
00798  *         12.00
00799  * <>i=12
00800  *         12.00
00801  * <>pv=-800
00802  *         -800.00
00803  * <>FV
00804  *         901.46
00805  *
00806  * Example 3: Periodic Payment:
00807  * Find the monthly end-of-period payment required to fully amortize the loan
00808  * in Example 2. A fully amortized loan has a future value of zero.
00809  * <>fv=0
00810  *        0.00
00811  * <>PMT
00812  *        71.08
00813  *
00814  * Example 4: Conventional Mortgage
00815  *
00816  * Find the number of monthly payments necessary to fully amortize a
00817  * loan of $100,000 at a nominal rate of 13.25% compounded monthly, if
00818  * monthly end-of-period payments of $1125.75 are made.
00819  *
00820  * <>d
00821  * <>i=13.25
00822  *         13.25
00823  * <>pv=100000
00824  *         100,000.00
00825  * <>pmt=-1125.75
00826  *         -1,125.75
00827  * <>_N(i,pv,pmt,fv,CF,PF,disc,bep)
00828  *         360.10
00829  * <>N
00830  *         360
00831  *
00832  * Example 5: Final Payment
00833  * Using the data in example 4, find the amount of the final payment if n is
00834  * changed to 360. The final payment will be equal to the regular payment plus
00835  * any balance, future value, remaining at the end of period number 360.
00836  * <>n=360
00837  *        360.00
00838  * <>FV
00839  *        -108.87
00840  * <>pmt+fv
00841  *        -1,234.62
00842  *
00843  * Using the data from this loan, compute the amortization schedule
00844  *   when the Effective date of the loan is June 6, 1996 and the
00845  *   initial payment is made on August 1, 1996. Ignore any change in
00846  *   the PV due to the delayed initial payment caused by the partial
00847  *   payment period from June 6 to July 1.
00848  *
00849  * <>ED = 06/06/1996
00850  *   Effective Date set: 06/06/1996 ( 2450241 )
00851  * <>IP = 08/01/1996
00852  *   Initial Payment Date set: 08/01/1996 ( 2450297 )
00853  * <>a
00854  *   Effective       Date: 06/06/96
00855  *   Initial Payment Date: 08/01/96
00856  *   The amortization options are:
00857  *   The Old Present Value (pv)     was: 100,000.00
00858  *   The Old Periodic Payment (pmt) was: -1,125.75
00859  *   The Old Future  Value (fv)     was: -108.87
00860  *   1: Amortize with Original Transaction Values
00861  *       and balloon final payment: -1,125.75
00862  *
00863  *   The New Present Value (pve)  is:  100,919.30
00864  *   The New Periodic Payment (pmt) is:  -1,136.10
00865  *   2: Amortize with Original Periodic Payment
00866  *       and balloon final payment: -49,023.68
00867  *   3: Amortize with New Periodic Payment
00868  *       and balloon final payment: -1,132.57
00869  *   4: Amortize with Original Periodic Payment,
00870  *       new number of total payments (n): 417
00871  *       and final payment: -2,090.27
00872  *
00873  *   Enter choice 1, 2, 3 or 4: <>
00874  *
00875  *  Press '1'
00876  *    Amortization Schedule:
00877  *   Yearly, y, per Payment, p, or Advanced Payment, a, Amortization
00878  *   Enter choice y, p or a:
00879  *   <>
00880  *
00881  *  Press 'y'
00882  *   Enter Filename for Amortization Schedule.
00883  *     (null string uses Standard Output):
00884  *  Press enter to display output on screen
00885  *
00886  *  Amortization Table
00887  *  Effective       Date: Thu Jun 06 00:00:00 1996
00888  *  Initial Payment Date: Thu Aug 01 00:00:00 1996
00889  *  Compounding Frequency per year: 12
00890  *  Payment     Frequency per year: 12
00891  *  Compounding: Discrete
00892  *  Payments: End of Period
00893  *  Payments (359): -1,125.75
00894  *  Final payment: -1,125.75
00895  *  Nominal Annual Interest Rate: 13.25
00896  *    Effective Interest Rate Per Payment Period: 0.0110417
00897  *  Present Value: 100,000.00
00898  *  Year      Interest   Ending Balance
00899  *  1996     -5,518.42       -99,889.67
00900  *  1997    -13,218.14       -99,598.81
00901  *  1998    -13,177.17       -99,266.98
00902  *  1999    -13,130.43       -98,888.41
00903  *  2000    -13,077.11       -98,456.52
00904  *  2001    -13,016.28       -97,963.80
00905  *  2002    -12,946.88       -97,401.68
00906  *  2003    -12,867.70       -96,760.38
00907  *  2004    -12,777.38       -96,028.76
00908  *  2005    -12,674.33       -95,194.09
00909  *  2006    -12,556.76       -94,241.85
00910  *  2007    -12,422.64       -93,155.49
00911  *  2008    -12,269.63       -91,916.12
00912  *  2009    -12,095.06       -90,502.18
00913  *  2010    -11,895.91       -88,889.09
00914  *  2011    -11,668.70       -87,048.79
00915  *  2012    -11,409.50       -84,949.29
00916  *  2013    -11,113.78       -82,554.07
00917  *  2014    -10,776.41       -79,821.48
00918  *  2015    -10,391.53       -76,704.01
00919  *  2016     -9,952.43       -73,147.44
00920  *  2017     -9,451.49       -69,089.93
00921  *  2018     -8,879.99       -64,460.92
00922  *  2019     -8,227.99       -59,179.91
00923  *  2020     -7,484.16       -53,155.07
00924  *  2021     -6,635.56       -46,281.63
00925  *  2022     -5,667.43       -38,440.06
00926  *  2023     -4,562.94       -29,494.00
00927  *  2024     -3,302.89       -19,287.89
00928  *  2025     -1,865.36        -7,644.25
00929  *  2026       -236.00          -108.87
00930  *
00931  *  Total Interest: -305,270.00
00932  *
00933  * NOTE: The amortization table leaves the FV as it was when the amortization
00934  *   function was entered. Thus, a balance of 108.87 is due at the end of the
00935  *   table. To completely pay the loan, set fv to 0.0:
00936  * <>fv=0
00937  *   0.0
00938  * <>a
00939  *   Effective       Date: 06/06/96
00940  *   Initial Payment Date: 08/01/96
00941  *   The amortization options are:
00942  *   The Old Present Value (pv)     was: 100,000.00
00943  *   The Old Periodic Payment (pmt) was: -1,125.75
00944  *   The Old Future  Value (fv)     was: 0.00
00945  *   1: Amortize with Original Transaction Values
00946  *       and balloon final payment: -1,234.62
00947  *
00948  *   The New Present Value (pve)  is:  100,919.30
00949  *   The New Periodic Payment (pmt) is:  -1,136.12
00950  *   2: Amortize with Original Periodic Payment
00951  *       and balloon final payment: -49,132.55
00952  *   3: Amortize with New Periodic Payment
00953  *       and balloon final payment: -1,148.90
00954  *   4: Amortize with Original Periodic Payment,
00955  *       new number of total payments (n): 417
00956  *       and final payment: -2,199.14
00957  *
00958  *   Enter choice 1, 2, 3 or 4: <>
00959  * Press '1'
00960  *    Amortization Schedule:
00961  *   Yearly, y, per Payment, p, or Advanced Payment, a, Amortization
00962  *   Enter choice y, p or a:
00963  *   <>
00964  * Press 'y'
00965  *   Enter Filename for Amortization Schedule.
00966  *     (null string uses Standard Output):
00967  *  Press enter to display output on screen
00968  *
00969  *  Amortization Table
00970  *  Effective       Date: Thu Jun 06 00:00:00 1996
00971  *  Initial Payment Date: Thu Aug 01 00:00:00 1996
00972  *  Compounding Frequency per year: 12
00973  *  Payment     Frequency per year: 12
00974  *  Compounding: Discrete
00975  *  Payments: End of Period
00976  *  Payments (359): -1,125.75
00977  *  Final payment: -1,234.62
00978  *  Nominal Annual Interest Rate: 13.25
00979  *    Effective Interest Rate Per Payment Period: 0.0110417
00980  *  Present Value: 100,000.00
00981  *  Year      Interest   Ending Balance
00982  *  1996     -5,518.42       -99,889.67
00983  *  1997    -13,218.14       -99,598.81
00984  *  1998    -13,177.17       -99,266.98
00985  *  1999    -13,130.43       -98,888.41
00986  *  2000    -13,077.11       -98,456.52
00987  *  2001    -13,016.28       -97,963.80
00988  *  2002    -12,946.88       -97,401.68
00989  *  2003    -12,867.70       -96,760.38
00990  *  2004    -12,777.38       -96,028.76
00991  *  2005    -12,674.33       -95,194.09
00992  *  2006    -12,556.76       -94,241.85
00993  *  2007    -12,422.64       -93,155.49
00994  *  2008    -12,269.63       -91,916.12
00995  *  2009    -12,095.06       -90,502.18
00996  *  2010    -11,895.91       -88,889.09
00997  *  2011    -11,668.70       -87,048.79
00998  *  2012    -11,409.50       -84,949.29
00999  *  2013    -11,113.78       -82,554.07
01000  *  2014    -10,776.41       -79,821.48
01001  *  2015    -10,391.53       -76,704.01
01002  *  2016     -9,952.43       -73,147.44
01003  *  2017     -9,451.49       -69,089.93
01004  *  2018     -8,879.99       -64,460.92
01005  *  2019     -8,227.99       -59,179.91
01006  *  2020     -7,484.16       -53,155.07
01007  *  2021     -6,635.56       -46,281.63
01008  *  2022     -5,667.43       -38,440.06
01009  *  2023     -4,562.94       -29,494.00
01010  *  2024     -3,302.89       -19,287.89
01011  *  2025     -1,865.36        -7,644.25
01012  *  2026       -344.87             0.00
01013  *
01014  *  Total Interest: -305,378.87
01015  *
01016  * Example 6: Balloon Payment
01017  * On long term loans, small changes in the periodic payments can generate
01018  * large changes in the future value. If the monthly payment in example 5 is
01019  * rounded down to $1125, how much addtional (balloon) payment will be due
01020  * with the final regular payment.
01021  * <>pmt=-1125
01022  * -1,125
01023  * <>FV
01024  * -3,579.99
01025  *
01026  * Example 7: Canadian Mortgage
01027  * Find the monthly end-of-period payment necessary to fully amortize a 25 year
01028  * $85,000 loan at 11% compounded semi-annually.
01029  * <>d
01030  * <>CF=2
01031  *         2.00
01032  * <>n=300
01033  *         300.00
01034  * <>i=11
01035  *         11.00
01036  * <>pv=85000
01037  *         85,000.00
01038  * <>PMT
01039  *         -818.15
01040  *
01041  * Example 8: European Mortgage
01042  * The "effective annual rate (EAR)" is used in some countries (especially
01043  * in Europe) in lieu of the nominal rate commonly used in the United States
01044  * and Canada. For a 30 year $90,000 mortgage at 14% (EAR), compute the monthly
01045  * end-of-period payments. When using an EAR, the compounding frequency is
01046  * set to 1.
01047  * <>d
01048  * <>CF=1
01049  *         1.00
01050  * <>n=30*12
01051  *         360.00
01052  * <>i=14
01053  *         14.00
01054  * <>pv=90000
01055  *         90,000.00
01056  * <>PMT
01057  *         -1,007.88
01058  *
01059  * Example 9: Bi-weekly Savings
01060  * Compute the future value, fv, of bi-weekly savings of $100 for 3 years at a
01061  * nominal annual rate of 5.5% compounded daily. (Set payment to
01062  * beginning-of-period, bep = TRUE)
01063  * <>d
01064  * <>bep=TRUE
01065  *         1.00
01066  * <>CF=365
01067  *         365.00
01068  * <>PF=26
01069  *         26.00
01070  * <>n=3*26
01071  *         78.00
01072  * <>i=5.5
01073  *         5.50
01074  * <>pmt=-100
01075  *         -100.00
01076  * <>FV
01077  *         8,489.32
01078  *
01079  * Example 10: Present Value - Annuity Due
01080  * What is the present value of $500 to be received at the beginning of each
01081  * quarter over a 10 year period if money is being discounted at 10% nominal
01082  * annual rate compounded monthly?
01083  * <>d
01084  * <>bep=TRUE
01085  *         1.00
01086  * <>PF=4
01087  *         4.00
01088  * <>n=4*10
01089  *         40.00
01090  * <>i=10
01091  *         10.00
01092  * <>pmt=500
01093  *         500.00
01094  * <>PV
01095  *         -12,822.64
01096  *
01097  * Example 11: Effective Rate - 365/360 Basis
01098  * Compute the effective annual rate (%APR) for a nominal annual rate of 12%
01099  * compounded on a 365/360 basis used by some Savings & Loan Associations.
01100  * <>d
01101  * <>n=365
01102  *         365.00
01103  * <>CF=365
01104  *         365.00
01105  * <>PF=360
01106  *         360.00
01107  * <>i=12
01108  *         12.00
01109  * <>pv=-100
01110  *         -100.00
01111  * <>FV
01112  *         112.94
01113  * <>fv+pv
01114  *         12.94
01115  *
01116  * Example 12: Mortgage with "Points"
01117  *
01118  * What is the true APR of a 30 year, $75,000 loan at a nominal rate
01119  * of 13.25% compounded monthly, with monthly end-of-period payments,
01120  * if 3 "points" are charged? The pv must be reduced by the dollar
01121  * value of the points and/or any lenders fees to establish an
01122  * effective pv. Because payments remain the same, the true APR will
01123  * be higher than the nominal rate. Note, first compute the payments
01124  * on the pv of the loan amount.
01125  *
01126  * <>d
01127  * <>CF=PF=1
01128  *         1.00
01129  * <>n=30*12
01130  *         360.00
01131  * <>i=13.25/12
01132  *         1.10
01133  * <>pv=75000
01134  *         75,000.00
01135  * <>PMT
01136  *         -844.33
01137  * <>pv -= pv*.03
01138  *         72,750.00
01139  * <>CF=PF=12
01140  *         12.00
01141  * <>I
01142  *         13.69
01143  *
01144  * Example 13: Equivalent Payments
01145  * Find the equivalent monthly payment required to amortize a 20 year $40,000
01146  * loan at 10.5% nominal annual rate compounded monthly, with 10 annual
01147  * payments of $5029.71 remaining. Compute the pv of the remaining annual
01148  * payments, then change n, the number of periods, and the payment frequency,
01149  * PF, to a monthly basis and compute the equivalent monthly pmt.
01150  * <>d
01151  * <>PF=1
01152  *         1.00
01153  * <>n=10
01154  *         10.00
01155  * <>i=10.5
01156  *         10.50
01157  * <>pmt=-5029.71
01158  *         -5,029.71
01159  * <>PV
01160  *         29,595.88
01161  * <>PF=12
01162  *         12.00
01163  * <>n=120
01164  *         120.00
01165  * <>PMT
01166  *         -399.35
01167  *
01168  * Example 14: Perpetuity - Continuous Compounding
01169  * If you can purchase a single payment annuity with an initial investment of
01170  * $60,000 that will be invested at 15% nominal annual rate compounded
01171  * continuously, what is the maximum monthly return you can receive without
01172  * reducing the $60,000 principal? If the principal is not disturbed, the
01173  * payments can go on indefinitely (a perpetuity). Note that the term,n, of
01174  * a perpetuity is immaterial. It can be any non-zero value.
01175  * <>d
01176  * <>disc=FALSE
01177  *         0.00
01178  * <>n=12
01179  *         12.00
01180  * <>CF=1
01181  *         1.00
01182  * <>i=15
01183  *         15.00
01184  * <>fv=60000
01185  *         60,000.00
01186  * <>pv=-60000
01187  *         -60,000.00
01188  * <>PMT
01189  *         754.71
01190  *
01191  * references:
01192  * 1. PPC ROM User's Manual
01193  *    pages 148 - 164
01194  *
01195  */
01196 
01197 #include <time.h>
01198 #include <stdio.h>
01199 #include <glib.h>
01200 #include <math.h>
01201 #if defined(G_OS_WIN32) && !defined(_MSC_VER)
01202 #include <pow.h>
01203 #endif
01204 #include <string.h>
01205 #include <stdlib.h>
01206 
01207 #define FIN_STATICS
01208 #include "finvar.h"
01209 #include "finproto.h"
01210 #include "fin_static_proto.h"
01211 
01212 /* return 'x' rounded to 'places' past decimal if 'places' < 0, return
01213  * 'x' */
01214 static double
01215 rnd (double x, unsigned places)
01216 {
01217     double r;
01218     char buf[50];                       /* make buffer large enough */
01219 
01220     if (places >= 0)
01221     {
01222         sprintf (buf, "%.*f", (int) places, x);
01223         r = strtod(buf, NULL);
01224     }
01225     else
01226         r = x;
01227 
01228     return r;
01229 }                               /* rnd */
01230 
01231 /* return absolute value of 'x' this function is provided by a macro
01232  * in C */
01233 static double
01234 dabs (double x)
01235 {
01236     return (x >= 0.0) ? x : -x;
01237 }                               /* dabs */
01238 
01239 /* Compute constant used in calculations */
01240 static double
01241 _A (double eint, unsigned per)
01242 {
01243     return pow ((1.0 + eint), (double) per) - 1.0;
01244 }                               /* _A */
01245 
01246 /* Compute constant used in calculations */
01247 static double
01248 _B (double eint, unsigned beg)
01249 {
01250     /* if eint == 0.0, all processing _must_ stop or
01251       a recursive loop will start. */
01252     g_return_val_if_fail(eint != 0.0, 0.0);
01253     return (1.0 + eint * (double) beg) / eint;
01254 }                               /* _B */
01255 
01256 /* Compute constant used in calculations */
01257 static double
01258 _C (double eint, double pmt, unsigned beg)
01259 {
01260     g_return_val_if_fail(eint != 0.0, 0.0);
01261     return pmt * _B(eint, beg);
01262 }                               /* _C */
01263 
01264 /* compute Number of Periods from preset data */
01265 unsigned
01266 fi_calc_num_payments (fi_ptr fi)
01267 {
01268     return fi->npp =
01269                (unsigned)
01270                rnd (_fi_calc_num_payments
01271                     (fi->ir, fi->pv, fi->pmt, fi->fv, fi->CF, fi->PF, fi->disc, fi->bep),
01272                     0);
01273 }                               /* fi_calc_num_payments */
01274 
01275 /* Compute number of periods from:
01276  *   1. Nominal Interest
01277  *   2. Present Value
01278  *   3. Periodic Payment
01279  *   4. Future Value
01280  */
01281 double
01282 _fi_calc_num_payments (double nint,     /* nominal interest rate    */
01283                        double pv,       /* present value            */
01284                        double pmt,      /* periodic payment         */
01285                        double fv,       /* future value             */
01286                        unsigned CF,     /* compounding frequency    */
01287                        unsigned PF,     /* payment frequency        */
01288                        unsigned disc,   /* discrete/continuous compounding */
01289                        unsigned bep)    /* beginning/end of period payment */
01290 {
01291     double eint = eff_int (nint / 100.0, CF, PF, disc);
01292     double CC = _C (eint, pmt, bep);
01293     CC = (CC - fv) / (CC + pv);
01294     return (CC > 0.0) ? log (CC) / log (1.0 + eint) : 0.0;
01295 }                               /* _fi_calc_num_payments */
01296 
01297 /* compute Interest from preset data */
01298 double
01299 fi_calc_interest (fi_ptr fi)
01300 {
01301     if (fi->npp)
01302         fi->ir = _fi_calc_interest (fi->npp, fi->pv, fi->pmt, fi->fv,
01303                                     fi->CF, fi->PF, fi->disc, fi->bep);
01304 
01305     return fi->ir;
01306 }                               /* fi_calc_interest */
01307 
01308 double ratio = 1e4; /* ratio used in iterative solution for interest */
01309 
01310 /* Compute Nominal Interest from:
01311  *   1. Number of periods
01312  *   2. Present Value
01313  *   3. Periodic Payment
01314  *   4. Future Value
01315  */
01316 double
01317 _fi_calc_interest (unsigned per,/* number of periods        */
01318                    double pv,   /* present value            */
01319                    double pmt,  /* periodic payment         */
01320                    double fv,   /* future value             */
01321                    unsigned CF, /* compounding frequency    */
01322                    unsigned PF, /* payment frequency        */
01323                    unsigned disc, /* discrete/continuous compounding */
01324                    unsigned bep)  /* beginning/end of period payment */
01325 {
01326     double eint;
01327     double a, dik;
01328     int ri;
01329 
01330     if (pmt == 0.0)
01331         eint = pow ((dabs (fv) / dabs (pv)), (1.0 / (double) per)) - 1.0;
01332     else
01333     {
01334         if ((pmt * fv) < 0.0)
01335         {
01336             if (pv)
01337                 a = -1.0;
01338             else
01339                 a = 1.0;
01340             eint =
01341                 dabs ((fv + a * (double) per * pmt) /
01342                       (3.0 *
01343                        (((double) per - 1.0) * ((double) per - 1.0) * pmt + pv -
01344                         fv)));
01345         }
01346         else
01347         {
01348             if ((pv * pmt) < 0.0)
01349             {
01350                 eint = dabs (((double) per * pmt + pv + fv) / ((double) per * pv));
01351             }
01352             else
01353             {
01354                 a = dabs (pmt / (dabs (pv) + dabs (fv)));
01355                 eint = a + 1.0 / (a * (double) per * (double) per * (double) per);
01356             }
01357         }
01358         do
01359         {
01360             dik =
01361                 fi (per, eint, pv, pmt, fv, bep) / fip (per, eint, pv, pmt, fv, bep);
01362             eint -= dik;
01363             (void) modf (ratio * (dik / eint), &a);
01364             ri = (unsigned) a;
01365         }
01366         while (ri);
01367     }                           /* endif */
01368 
01369     return 100.0 * nom_int (eint, CF, PF, disc);
01370 }                               /* _fi_calc_interest */
01371 
01372 /* compute Present value from preset data */
01373 double
01374 fi_calc_present_value (fi_ptr fi)
01375 {
01376     return fi->pv =
01377                rnd (_fi_calc_present_value
01378                     (fi->npp, fi->ir, fi->pmt, fi->fv, fi->CF, fi->PF, fi->disc,
01379                      fi->bep), fi->prec);
01380 }                               /* fi_calc_present_value */
01381 
01382 /* Compute Present Value from:
01383  *   1. Number of periods
01384  *   2. Nominal Interest
01385  *   3. Periodic Payment
01386  *   4. Future Value
01387  */
01388 double
01389 _fi_calc_present_value (unsigned per,   /* number of periods        */
01390                         double nint,    /* nominal interest rate    */
01391                         double pmt,     /* periodic payment         */
01392                         double fv,      /* future value             */
01393                         unsigned CF,    /* compounding frequency    */
01394                         unsigned PF,    /* payment frequency        */
01395                         unsigned disc,  /* discrete/continuous compounding */
01396                         unsigned bep)   /* beginning/end of period payment */
01397 {
01398     double eint = eff_int (nint / 100.0, CF, PF, disc);
01399     double AA = _A (eint, per);
01400     double CC = _C (eint, pmt, bep);
01401 
01402     return -(fv + (AA * CC)) / (AA + 1.0);
01403 }                               /* _fi_calc_present_value */
01404 
01405 /* compute Periodic Payment from preset data */
01406 double
01407 fi_calc_payment (fi_ptr fi)
01408 {
01409     return fi->pmt =
01410                rnd (_fi_calc_payment
01411                     (fi->npp, fi->ir, fi->pv, fi->fv, fi->CF, fi->PF, fi->disc, fi->bep),
01412                     fi->prec);
01413 }                               /* fi_calc_payment */
01414 
01415 /* Compute Periodic Payment from:
01416  *   1. Number of periods
01417  *   2. Nominal Interest
01418  *   3. Present Value
01419  *   4. Future Value
01420  */
01421 double
01422 _fi_calc_payment (unsigned per, /* number of periods        */
01423                   double nint,  /* nominal interest rate    */
01424                   double pv,    /* present value            */
01425                   double fv,    /* future value             */
01426                   unsigned CF,  /* compounding frequency    */
01427                   unsigned PF,  /* payment frequency        */
01428                   unsigned disc,/* discrete/continuous compounding */
01429                   unsigned bep) /* beginning/end of period payment */
01430 {
01431     double eint = eff_int (nint / 100.0, CF, PF, disc);
01432     double AA = _A (eint, per);
01433     double BB = _B (eint, bep);
01434     g_return_val_if_fail(BB != 0.0, 0.0);
01435 
01436     return -(fv + pv * (AA + 1.0)) / (AA * BB);
01437 }                               /* _fi_calc_payment */
01438 
01439 /* compute Future Value from preset data */
01440 double
01441 fi_calc_future_value (fi_ptr fi)
01442 {
01443     return fi->fv =
01444                rnd (_fi_calc_future_value
01445                     (fi->npp, fi->ir, fi->pv, fi->pmt, fi->CF, fi->PF, fi->disc,
01446                      fi->bep), fi->prec);
01447 }                               /* fi_calc_future_value */
01448 
01449 /* Compute Future Value from:
01450  *   1. Number of periods
01451  *   2. Nominal Interest
01452  *   3. Present Value
01453  *   4. Periodic Payments
01454  */
01455 double
01456 _fi_calc_future_value (unsigned per,    /* number of periods        */
01457                        double nint,     /* nominal interest rate    */
01458                        double pv,       /* present value            */
01459                        double pmt,      /* periodic payment         */
01460                        unsigned CF,     /* compounding frequency    */
01461                        unsigned PF,     /* payment frequency        */
01462                        unsigned disc,   /* discrete/continuous compounding */
01463                        unsigned bep)    /* beginning/end of period payment */
01464 {
01465     double eint = eff_int (nint / 100.0, CF, PF, disc);
01466     double AA = _A (eint, per);
01467     double CC = _C (eint, pmt, bep);
01468 
01469     return -(pv + AA * (pv + CC));
01470 }                               /* _fi_calc_future_value */
01471 
01472 /* compute Nominal Interest Rate from Effective Interest Rate */
01473 static double
01474 nom_int (double eint, unsigned CF, unsigned PF, unsigned disc)
01475 {
01476     double nint;
01477 
01478     if (disc)
01479     {
01480         if (CF == PF)
01481         {
01482             nint = CF * eint;
01483         }
01484         else
01485         {
01486             nint = CF * (pow ((1.0 + eint), ((double) PF / (double) CF)) - 1.0);
01487         }                               /* * endif   */
01488     }
01489     else
01490         nint = log (pow (1.0 + eint, PF));
01491 
01492     return nint;
01493 }                               /* nom_int */
01494 
01495 /* Compute Effective Interest Rate from Nominal Interest Rate */
01496 static double
01497 eff_int (double nint, unsigned CF, unsigned PF, unsigned disc)
01498 {
01499     double eint;
01500 
01501     if (disc)
01502     {
01503         if (CF == PF)
01504         {
01505             eint = nint / (double) CF;
01506         }
01507         else
01508         {
01509             eint =
01510                 pow ((1.0 + nint / (double) CF), ((double) CF / (double) PF)) - 1.0;
01511         }                               /* endif */
01512     }
01513     else
01514         eint = exp (nint / (double) PF) - 1.0;
01515 
01516     return eint;
01517 }                               /* eff_int */
01518 
01519 /* calculation used in interest computation */
01520 static double
01521 fi (unsigned per, double eint, double pv, double pmt, double fv, unsigned bep)
01522 {
01523     return _A (eint, per) * (pv + _C (eint, pmt, bep)) + pv + fv;
01524 }                               /* fi */
01525 
01526 /* calculation used in interest computation
01527  */
01528 static double
01529 fip (unsigned per, double eint, double pv, double pmt, double fv, unsigned bep)
01530 {
01531     double AA = _A (eint, per);
01532     double CC = _C (eint, pmt, bep);
01533     double D = (AA + 1.0) / (1.0 + eint);
01534     g_return_val_if_fail(CC != 0.0, 0.0);
01535     return (double) per * (pv + CC) * D - (AA * CC) / eint;
01536 }                               /* fip */
01537 
01538 void
01539 set_default (fi_ptr fi)
01540 {
01541     /* flag whether accrueing interest at beginning or end of period
01542      * FALSE --> end
01543      * TRUE  --> beginning
01544      * default to end of period payment s
01545      */
01546     fi->bep = FALSE;
01547 
01548     /* flag for discrete or continuous interest
01549      * TRUE  --> discrete
01550      * FALSE --> continuous
01551      * default to discrete interest
01552      */
01553     fi->disc = TRUE;
01554 
01555     /* set compounding, CF, and payment, PF, frequency per year
01556      * default to monthly payments and compounding
01557      */
01558     fi->CF = fi->PF = 12;
01559 
01560     /* standard loan quantities:
01561      * number of periods: n
01562      */
01563     fi->npp = 0;
01564 
01565     /* annual interest: i
01566      */
01567     fi->ir = 0.0;
01568 
01569     /* Present Value: pv
01570      */
01571     fi->pv = 0.0;
01572 
01573     /* Payment: pmt
01574      */
01575     fi->pmt = 0.0;
01576 
01577     /* Future Value: fv
01578      */
01579     fi->fv = 0.0;
01580 
01581 }                               /* set_default */
01582 
01583 /* compute Julian Day Number from calender date
01584  */
01585 unsigned long
01586 julian_day_number (unsigned year, unsigned month, unsigned day)
01587 {
01588     /*  Gregorian/Julian Calender Flag.
01589      *  TRUE  == Julian
01590      *  FALSE == Gregorian
01591      */
01592     unsigned gregorian = TRUE; /* assume we are dealing with current dates */
01593     double yr;
01594     double pfac = 0.6;
01595     unsigned long ljdn;
01596 
01597     yr = year + (month - 3.0) / 12.0;
01598     ljdn = (long) (367.0 * yr + pfac) - (2 * (long) (yr)) + (long) (yr / 4.0)
01599            + (long) day + 1721117L;
01600     if (gregorian)
01601         ljdn += -(long) (yr / 100.0) + (long) (yr / 400.0) + 2;
01602 
01603     return ljdn;
01604 }                               /* julian_day_number */
01605 
01606 amort_sched_ptr
01607 Amortization_init (amort_sched_ptr amortsched)
01608 {
01609     unsigned n = amortsched->n;
01610     double nint = amortsched->nint;
01611     double pv = amortsched->pv;
01612     double pmt = amortsched->pmt;
01613     double fv = amortsched->fv;
01614     double eint;
01615     double new_pmt;
01616     double pve;
01617     unsigned CF = amortsched->CF;
01618     unsigned PF = amortsched->PF;
01619     unsigned disc = amortsched->disc;
01620     unsigned bep = amortsched->bep;
01621     unsigned new_n;
01622     unsigned prec = amortsched->prec;
01623     unsigned long s,
01624              d,
01625              days_to_yr_end,
01626              Eff_Date_jdn =
01627                  julian_day_number (amortsched->year_E, amortsched->month_E,
01628                                     amortsched->day_E), Init_Date_jdn =
01629                      julian_day_number (amortsched->year_I, amortsched->month_I,
01630                                         amortsched->day_I);
01631 
01632     amortsched->Eff_Date_jdn = Eff_Date_jdn;
01633     amortsched->Init_Date_jdn = Init_Date_jdn;
01634     amortsched->yday_E =
01635         Eff_Date_jdn - julian_day_number (amortsched->year_E, 1, 1);
01636     amortsched->yday_I =
01637         Init_Date_jdn - julian_day_number (amortsched->year_I, 1, 1);
01638     amortsched->eint = eint = eff_int (nint / 100.0, CF, PF, disc);
01639     amortsched->fv_case = dabs (fv) > dabs (pv);
01640     amortsched->bp = bep ? 1.0 : 0.0;
01641 
01642     if (PF > 24)
01643     {
01644         /* Payment frequency per year greater than bi-monthly
01645          * use actual number of days
01646          */
01647         s = Init_Date_jdn - Eff_Date_jdn;
01648         days_to_yr_end =
01649             julian_day_number (amortsched->year_I + 1, 1, 0) - Init_Date_jdn;
01650         d = 366 / PF;
01651     }
01652     else
01653     {
01654         /* Payment frequency per year bi-monthly or less
01655          * use 30 days/month, 360 days/year
01656          */
01657         if (Eff_Date_jdn == Init_Date_jdn)
01658         {
01659             s = 0;
01660         }
01661         else
01662         {
01663             s =
01664                 ((amortsched->year_I - amortsched->year_E) * 360) +
01665                 ((amortsched->month_I - amortsched->month_E) * 30) +
01666                 amortsched->day_I - amortsched->day_E;
01667         }                               /* endif */
01668         days_to_yr_end = 390 - (amortsched->month_I * 30) - amortsched->day_I;
01669         d = 360 / PF;
01670     }                           /* endif */
01671 
01672     if (!bep)
01673     {
01674         /* ordinary annuity
01675          */
01676         s -= d;
01677     }                           /* endif */
01678 
01679     amortsched->yr_pmt = (days_to_yr_end + d) / d;
01680 
01681     if (pmt == 0.0)
01682     {
01683         s = 0;
01684         amortsched->pve = pv;
01685     }
01686     else
01687     {
01688         amortsched->pve =
01689             rnd (pv * pow ((1.0 + eint), ((double) (s * PF) / (double) (d * CF))),
01690                  prec);
01691     }                           /* endif */
01692 
01693     pve = amortsched->pve;
01694 
01695     /*   compute new data to fully amortize loan:
01696      *       new periodic payment, new_pmt
01697      *
01698      *   option 1: Amortize with original transaction - ignore interest
01699      *   due to delayed initial payment
01700      *
01701      *   option 2: Amortize with new pv, pve == original pv adjusted for
01702      *   delayed initial payment, original payment, original fv and
01703      *   original total number of payments, adjust final payment
01704      *
01705      *   option 3: amortize with new pv, pve, and new payments adjusted to
01706      *   minimize final payment, keep original number of payments and
01707      *   original fv
01708      *
01709      *   option 4: amortize with new pv, pve, original payments and new
01710      *   number of payments to keep original final fv */
01711 
01712     /* option 3, compute new periodic payment */
01713     amortsched->new_pmt = new_pmt =
01714                               rnd (_fi_calc_payment (n, nint, pve, fv, CF, PF, disc, bep), prec);
01715 
01716     /* option 4: compute new number of total payments, new_n */
01717     amortsched->new_n = new_n =
01718                             (unsigned)
01719                             rnd (_fi_calc_num_payments (nint, pve, pmt, fv, CF, PF, disc, bep), 0);
01720 
01721     /* following used in QTAwk to insure integer value, not needed in C */
01722     /*    n = int(n); */
01723 
01724     /* compute payment for constant payment to principal loan and final
01725      * payment for original loan amount include interest due */
01726     amortsched->cpmt1 = rnd (-pv / n, prec);
01727     amortsched->final_pmt_opt_1 = -pv - amortsched->cpmt1 * (n - 1);
01728     amortsched->final_pmt_opt_1 *= eint + 1;
01729 
01730     /* compute payment for constant payment to principal loan and final
01731      * payment for delayed loan amount include interest due */
01732     amortsched->cpmt2 = rnd (-pve / n, prec);
01733     amortsched->final_pmt_opt_2 = -pve - amortsched->cpmt2 * (n - 1);
01734     amortsched->final_pmt_opt_2 *= eint + 1;
01735 
01736     if (bep)
01737     {
01738         amortsched->final_pmt_opt_3 =
01739             rnd (_fi_calc_future_value (n - 1, nint, pv, pmt, CF, PF, disc, bep) -
01740                  (fv / (1.0 + eint)), prec);
01741         amortsched->final_pmt_opt_4 =
01742             rnd (_fi_calc_future_value (n - 1, nint, pve, pmt, CF, PF, disc, bep) -
01743                  (fv / (1.0 + eint)), prec);
01744         amortsched->final_pmt_opt_5 =
01745             rnd (_fi_calc_future_value
01746                  (n - 1, nint, pve, new_pmt, CF, PF, disc,
01747                   bep) - (fv / (1.0 + eint)), prec);
01748         if (new_n)
01749             amortsched->final_pmt_opt_6 =
01750                 rnd (_fi_calc_future_value
01751                      (new_n - 1, nint, pve, pmt, CF, PF, disc,
01752                       bep) - (fv / (1.0 + eint)), prec);
01753         else
01754             amortsched->final_pmt_opt_6 = 0.0;
01755     }
01756     else
01757     {
01758         amortsched->final_pmt_opt_3 =
01759             rnd (_fi_calc_future_value (n - 1, nint, pv, pmt, CF, PF, disc, bep) *
01760                  (1.0 + eint) - fv, prec);
01761         amortsched->final_pmt_opt_4 =
01762             rnd (_fi_calc_future_value (n - 1, nint, pve, pmt, CF, PF, disc, bep) *
01763                  (1.0 + eint) - fv, prec);
01764         amortsched->final_pmt_opt_5 =
01765             rnd (_fi_calc_future_value
01766                  (n - 1, nint, pve, new_pmt, CF, PF, disc, bep) * (1.0 + eint) - fv,
01767                  prec);
01768         if (new_n)
01769             amortsched->final_pmt_opt_6 =
01770                 rnd (_fi_calc_future_value
01771                      (new_n - 1, nint, pve, pmt, CF, PF, disc,
01772                       bep) * (1.0 + eint) - fv, prec);
01773         else
01774             amortsched->final_pmt_opt_6 = 0.0;
01775     }                           /* endif */
01776 
01777     /* compute delayed interest */
01778     amortsched->delayed_int = pv - amortsched->pve;
01779 
01780     return amortsched;
01781 }                               /* Amortization_init */
01782 
01783 amort_sched_ptr
01784 Amortization_Schedule (amort_sched_ptr amortsched)
01785 {
01786     unsigned n = amortsched->n;
01787     double nint = amortsched->nint;
01788     double pv = amortsched->pv;
01789     double pmt = amortsched->pmt;
01790     double fv = amortsched->fv;
01791     double eint = amortsched->eint;
01792     unsigned CF = amortsched->CF;
01793     unsigned PF = amortsched->PF;
01794     unsigned disc = amortsched->disc;
01795     unsigned bep = amortsched->bep;
01796     double cpmt = 0;
01797     double final_pmt = 0;
01798     double delayed_int = amortsched->delayed_int;
01799     char summary = amortsched->summary;
01800     unsigned option = amortsched->option;
01801     unsigned yr_pmt = amortsched->yr_pmt;
01802     unsigned fv_case = amortsched->fv_case;
01803     unsigned prec = amortsched->prec;
01804     unsigned j, s, yr, per_cnt, pmt_cnt = 0, k = 0, sum_prt;
01805 
01806     int jj;
01807 
01808     unsigned long d;
01809 
01810     double yr_fv, sum_int, yr_int, prin, adv_pmt, pmt_int, hpv = 0.0;
01811     yearly_summary_ptr yrly_sum;
01812     amort_sched_yr_ptr amortyr;
01813     sched_pmt_ptr pmtsched = NULL;
01814 
01815     sum_int = yr_int = 0.0;
01816 
01817     switch (option)
01818     {
01819     case 1:
01820         amortsched->cpmt = cpmt = amortsched->cpmt1;
01821         /* re-compute final payment without interest
01822          */
01823         amortsched->final_pmt = final_pmt = -pv - cpmt * (n - 1);
01824         summary = (summary == 'y') ? 'x' : 'o';
01825         break;
01826     case 2:
01827         amortsched->cpmt = cpmt = amortsched->cpmt2;
01828         pv = amortsched->pve;
01829         /* re-compute final payment without interest
01830          */
01831         amortsched->final_pmt = final_pmt = -pv - cpmt * (n - 1);
01832         summary = (summary == 'y') ? 'x' : 'o';
01833         break;
01834     case 3:
01835         delayed_int = 0.0;
01836         amortsched->final_pmt = final_pmt = amortsched->final_pmt_opt_3;
01837         break;
01838     case 4:
01839         pv = amortsched->pve;
01840         amortsched->final_pmt = final_pmt = amortsched->final_pmt_opt_4;
01841         break;
01842     case 5:
01843         pv = amortsched->pve;
01844         pmt = amortsched->new_pmt;
01845         amortsched->final_pmt = final_pmt = amortsched->final_pmt_opt_5;
01846         break;
01847     case 6:
01848         n = amortsched->new_n;
01849         pv = amortsched->pve;
01850         amortsched->final_pmt = final_pmt = amortsched->final_pmt_opt_6;
01851         break;
01852     }                           /* endswitch */
01853 
01854     yr = amortsched->year_I;
01855     sum_prt = TRUE;
01856     switch (summary)
01857     {
01858     case 'a':
01859         /* variable advanced prepayment schedule.  prepayment equals next
01860          * period principal.  */
01861         amortsched->schedule.first_yr =
01862             amortyr = (amort_sched_yr_ptr) calloc (1, sizeof (amort_sched_yr));
01863 
01864         d = pv;
01865 
01866         for (per_cnt = 0, s = 1, j = n; pv != fv; j -= 2, per_cnt++)
01867         {
01868             /* basic equation to compute interest this payment period */
01869             pmt_int = -rnd ((pv + (amortsched->bp * pmt)) * eint, prec);
01870 
01871             /* sum yearly interest paid */
01872             yr_int += pmt_int;
01873 
01874             /* sum total interest paid */
01875             sum_int += pmt_int;
01876 
01877             /* compute principal paid this payment period and round to
01878              nearest cent */
01879             if (dabs (pmt) > dabs (pv))
01880             {
01881                 prin = -pv;
01882                 pmt = prin + pmt_int;
01883                 adv_pmt = 0.0;
01884                 pv = fv;
01885             }
01886             else
01887             {
01888                 prin = rnd (pmt - pmt_int, prec);
01889 
01890                 /* compute remaining pv and round to nearest cent */
01891                 pv = rnd (pv + prin, prec);
01892 
01893                 /* compute principal for next payment cycle and round to
01894                  nearest cent */
01895                 adv_pmt = rnd (pmt + (pv + (amortsched->bp * pmt)) * eint, prec);
01896 
01897                 if (dabs (pv) >= dabs (adv_pmt))
01898                 {
01899                     /* remaining pv greater than advanced principal payment
01900                      * compute remaining pv and round to nearest cent */
01901                     pv = rnd (pv + adv_pmt, prec);
01902                 }
01903                 else
01904                 {
01905                     /* remaining pv less than advanced principal payment reduce
01906                      * advanced pricipla payment to remaining pv */
01907                     adv_pmt = -pv;
01908 
01909                     /* and set remaining pv to fv */
01910                     pv = fv;
01911                 }                       /* ## endif   */
01912             }                           /* # endif */
01913 
01914             if (sum_prt)
01915             {
01916                 jj = (j < yr_pmt) ? j + 1 : yr_pmt;
01917                 amortyr->payments =
01918                     pmtsched = (sched_pmt_ptr) calloc (jj, sizeof (sched_pmt));
01919                 pmt_cnt = 0;
01920 
01921                 sum_prt = FALSE;
01922             }                           /* endif */
01923 
01924             pmtsched->period_num = s++;
01925             pmtsched->interest = pmt_int;
01926             pmtsched->principal = prin;
01927             pmtsched->advanced_pmt = adv_pmt;
01928             pmtsched->total_pmt = pmt + adv_pmt;
01929             pmtsched->balance = pv;
01930             pmtsched++;
01931             pmt_cnt++;
01932 
01933             if (!--yr_pmt)
01934             {
01935                 yr_pmt = PF;
01936 
01937                 amortyr->year = yr++;
01938                 amortyr->interest_pd = yr_int;
01939                 amortyr->principal_pd = pv - hpv;
01940                 amortyr->yr_end_balance = pv;
01941                 amortyr->total_interest_pd = sum_int;
01942                 amortyr->num_periods = pmt_cnt;
01943                 amortyr->next_yr =
01944                     (amort_sched_yr_ptr) calloc (1, sizeof (amort_sched_yr));
01945                 amortyr = amortyr->next_yr;
01946 
01947                 hpv = pv;
01948                 yr_int = 0.0;
01949                 sum_prt = TRUE;
01950             }                           /* endif */
01951         }                               /* endfor */
01952 
01953         if (dabs (pv) > 0.0)
01954         {
01955             /* basic equation to compute interest this payment period */
01956             pmt_int = -rnd ((pv + (amortsched->bp * pmt)) * eint, prec);
01957 
01958             /* sum yearly interest paid */
01959             yr_int += pmt_int;
01960 
01961             /* sum total interest paid */
01962             sum_int += pmt_int;
01963 
01964             /* compute principal paid this payment period and round to
01965              nearest cent */
01966             prin = rnd (pmt - pmt_int, prec);
01967             final_pmt = pmt;
01968 
01969             /* compute remaining pv and round to nearest cent */
01970             pv = rnd (pv + prin, prec);
01971 
01972             /* Set advanced principal payment to remaining pv */
01973             adv_pmt = -pv;
01974             amortyr->final_pmt = final_pmt += adv_pmt;
01975 
01976             /* and set remaining pv to fv */
01977             pv = fv;
01978 
01979             pmtsched->period_num = s++;
01980             pmtsched->interest = pmt_int;
01981             pmtsched->principal = prin;
01982             pmtsched->advanced_pmt = adv_pmt;
01983             pmtsched->total_pmt = final_pmt;
01984             pmtsched->balance = pv;
01985 
01986             per_cnt++;
01987             pmt_cnt++;
01988         }                               /* endif */
01989 
01990         if (dabs (yr_int) > 0.0)
01991         {
01992             amortyr->year = yr++;
01993             amortyr->interest_pd = yr_int;
01994             amortyr->principal_pd = pv - hpv;
01995             amortyr->total_interest_pd = sum_int;
01996             amortyr->num_periods = pmt_cnt;
01997         }                               /* endif */
01998 
01999         amortsched->total_periods = per_cnt;
02000         break;
02001     case 'f':
02002         /* fixed prepaymet schedule prepayment specified by user */
02003         amortsched->schedule.first_yr =
02004             amortyr = (amort_sched_yr_ptr) calloc (1, sizeof (amort_sched_yr));
02005 
02006         d = pv;
02007 
02008         /*  set advnaced payment */
02009         adv_pmt = amortsched->fixed_pmt;
02010 
02011         for (per_cnt = 0, s = 1, j = n; j && (pv != fv); j--, per_cnt++)
02012         {
02013             /* basic equation to compute interest this payment period */
02014             pmt_int = -rnd ((pv + (amortsched->bp * pmt)) * eint, prec);
02015             /*  sum yearly interest paid
02016              */
02017             yr_int += pmt_int;
02018             /*  sum total interest paid */
02019             sum_int += pmt_int;
02020 
02021             /* compute principal paid this payment period and round to
02022              nearest cent */
02023             if (dabs (pmt) > dabs (pv))
02024             {
02025                 prin = -pv;
02026                 pmt = prin + pmt_int;
02027                 adv_pmt = 0.0;
02028                 pv = 0.0;
02029             }
02030             else
02031             {
02032                 prin = rnd (pmt - pmt_int, prec);
02033 
02034                 /*  compute remaining pv and round to nearest cent */
02035                 pv = rnd (pv + prin, prec);
02036 
02037                 if (dabs (pv) >= dabs (adv_pmt))
02038                 {
02039                     /* remaining pv greater than advanced principal payment
02040                      * compute remaining pv and round to nearest cent */
02041                     pv = rnd (pv + adv_pmt, prec);
02042                 }
02043                 else
02044                 {
02045                     /* remaining pv less than advanced principal payment reduce
02046                      * advanced pricipal payment to remaining pv and set
02047                      * remaining pv to fv */
02048                     adv_pmt = -pv;
02049                     pv = fv;
02050                 }                       /*## endif */
02051             }                           /* # endif */
02052 
02053             if (sum_prt)
02054             {
02055                 jj = (j < yr_pmt) ? j + 1 : yr_pmt;
02056                 amortyr->payments =
02057                     pmtsched = (sched_pmt_ptr) calloc (jj, sizeof (sched_pmt));
02058                 pmt_cnt = 0;
02059 
02060                 sum_prt = FALSE;
02061             }
02062             else
02063             {
02064                 (amortyr->num_periods)++;
02065             }                           /* ## endif */
02066 
02067             pmtsched->period_num = s++;
02068             pmtsched->interest = pmt_int;
02069             pmtsched->principal = prin;
02070             pmtsched->advanced_pmt = adv_pmt;
02071             pmtsched->total_pmt = pmt + adv_pmt;
02072             pmtsched->balance = pv;
02073             pmt_cnt++;
02074             pmtsched++;
02075 
02076             if (!--yr_pmt)
02077             {
02078                 yr_pmt = PF;
02079 
02080                 amortyr->year = yr++;
02081                 amortyr->interest_pd = yr_int;
02082                 amortyr->principal_pd = pv - hpv;
02083                 amortyr->yr_end_balance = pv;
02084                 amortyr->total_interest_pd = sum_int;
02085                 amortyr->num_periods = pmt_cnt;
02086                 amortyr->next_yr =
02087                     (amort_sched_yr_ptr) calloc (1, sizeof (amort_sched_yr));
02088                 amortyr = amortyr->next_yr;
02089 
02090                 hpv = pv;
02091                 yr_int = 0.0;
02092                 sum_prt = TRUE;
02093             }                           /* ## endif */
02094         }                               /* ## endfor */
02095 
02096         if (pv != fv)
02097         {
02098             /* # basic equation to compute interest this payment period */
02099             pmt_int = -rnd ((pv + (amortsched->bp * pmt)) * eint, prec);
02100 
02101             /* # sum yearly interest paid */
02102             yr_int += pmt_int;
02103             /* # sum total interest paid */
02104             sum_int += pmt_int;
02105 
02106             /* # compute principal paid this payment period and round to
02107              nearest cent */
02108             prin = rnd (pmt - pmt_int, prec);
02109             final_pmt = pmt;
02110 
02111             /* # compute remaining pv and round to nearest cent */
02112             pv = rnd (pv + prin, prec);
02113 
02114             /* # Set advanced principal payment to remaining pv */
02115             adv_pmt = -pv;
02116             amortyr->final_pmt = final_pmt += adv_pmt;
02117 
02118             /* # and set remaining pv to fv */
02119             pv = fv;
02120 
02121             pmtsched->period_num = s++;
02122             pmtsched->interest = pmt_int;
02123             pmtsched->principal = prin;
02124             pmtsched->advanced_pmt = adv_pmt;
02125             pmtsched->total_pmt = final_pmt;
02126             pmtsched->balance = pv;
02127 
02128             per_cnt++;
02129             pmt_cnt++;
02130         }                               /* # endif */
02131 
02132         if (dabs (yr_int) > 0.0)
02133         {
02134             amortyr->year = yr++;
02135             amortyr->interest_pd = yr_int;
02136             amortyr->principal_pd = pv - hpv;
02137             amortyr->total_interest_pd = sum_int;
02138             amortyr->num_periods = pmt_cnt;
02139         }                               /* endif */
02140 
02141         amortsched->total_periods = per_cnt;
02142         break;
02143     case 'o':
02144         /* Constant payment to principal use constant payment equal to
02145          * original pv divided by number of periods.  constant payment to
02146          * pricipal could be amount specified by user.  */
02147         amortsched->schedule.first_yr =
02148             amortyr = (amort_sched_yr_ptr) calloc (1, sizeof (amort_sched_yr));
02149         amortsched->total_periods = n;
02150 
02151         d = yr_pmt;
02152         for (s = 1, j = n - 1; j; j--, k++)
02153         {
02154             pmt_int = -rnd (pv * eint, prec);
02155 
02156             /* sum yearly interest paid */
02157             yr_int += pmt_int;
02158 
02159             /* sum total interest paid */
02160             sum_int += pmt_int;
02161 
02162             pv = rnd (pv + cpmt, prec);
02163 
02164             if (sum_prt)
02165             {
02166                 jj = (j < yr_pmt) ? j + 1 : yr_pmt;
02167                 amortyr->payments =
02168                     pmtsched = (sched_pmt_ptr) calloc (jj, sizeof (sched_pmt));
02169                 amortyr->num_periods = jj;
02170                 k = 0;
02171 
02172                 sum_prt = FALSE;
02173             }                           /* endif */
02174 
02175             pmtsched->period_num = s++;
02176             pmtsched->interest = pmt_int;
02177             pmtsched->total_pmt = cpmt + pmt_int;
02178             pmtsched->balance = pv;
02179             pmtsched++;
02180 
02181             if (!--yr_pmt)
02182             {
02183                 yr_pmt = PF;
02184 
02185                 amortyr->year = yr++;
02186                 amortyr->interest_pd = yr_int;
02187                 amortyr->principal_pd = d * cpmt;
02188                 amortyr->yr_end_balance = pv;
02189                 amortyr->total_interest_pd = sum_int;
02190                 amortyr->next_yr =
02191                     (amort_sched_yr_ptr) calloc (1, sizeof (amort_sched_yr));
02192                 amortyr = amortyr->next_yr;
02193 
02194                 d = PF;
02195                 yr_int = 0.0;
02196                 sum_prt = TRUE;
02197             }                           /* endif */
02198         }                               /* endfor */
02199 
02200         if (pv)
02201         {
02202             pmt_int = -rnd (pv * eint, prec);
02203 
02204             /* sum yearly interest paid */
02205             yr_int += pmt_int;
02206 
02207             /* sum total interest paid */
02208             sum_int += pmt_int;
02209 
02210             pmtsched->period_num = s++;
02211             pmtsched->interest = -pmt_int;
02212             pmtsched->total_pmt = -pv + pmt_int;
02213             pmtsched->balance = 0.0;
02214 
02215             amortyr->final_pmt = -pv - pmt_int;
02216         }                               /* endif */
02217 
02218         if (dabs (yr_int) > 0.0)
02219         {
02220             amortyr->year = yr++;
02221             amortyr->interest_pd = yr_int;
02222             amortyr->principal_pd = -pv + k * cpmt;
02223             amortyr->total_interest_pd = sum_int;
02224         }                               /* endif */
02225         break;
02226     case 'p':
02227         /* normal amortization schedule interest, principal and balance
02228          * per payment period */
02229         amortsched->schedule.first_yr =
02230             amortyr = (amort_sched_yr_ptr) calloc (1, sizeof (amort_sched_yr));
02231         amortsched->total_periods = n;
02232 
02233         hpv = pv;
02234         for (s = 1, j = n - 1; j; j--)
02235         {
02236             /* basic equation for computing interest paid in payment period */
02237             pmt_int = -rnd ((pv + (amortsched->bp * pmt)) * eint, prec);
02238 
02239             /* sum yearly interest paid */
02240             yr_int += pmt_int;
02241 
02242             /* sum total interest paid */
02243             sum_int += pmt_int;
02244 
02245             /* compute principal paid this payment period */
02246             prin = rnd (pmt - pmt_int, prec);
02247 
02248             /* compute remaining pv and round to nearest cent */
02249             pv = rnd (pv + prin, prec);
02250 
02251             if (sum_prt)
02252             {
02253                 jj = (j < yr_pmt) ? j + 1 : yr_pmt;
02254                 amortyr->payments =
02255                     pmtsched = (sched_pmt_ptr) calloc (jj, sizeof (sched_pmt));
02256                 amortyr->num_periods = jj;
02257 
02258                 sum_prt = FALSE;
02259             }                           /* endif */
02260 
02261             if (fv_case)
02262             {
02263                 pmtsched->period_num = s++;
02264                 pmtsched->interest = pmt_int;
02265                 pmtsched->balance = pv;
02266                 pmtsched++;
02267             }
02268             else
02269             {
02270                 pmtsched->period_num = s++;
02271                 pmtsched->interest = pmt_int;
02272                 pmtsched->principal = prin;
02273                 pmtsched->balance = pv;
02274                 pmtsched++;
02275             }                           /* endif */
02276 
02277             if (!--yr_pmt)
02278             {
02279                 yr_pmt = PF;
02280 
02281                 amortyr->year = yr++;
02282                 amortyr->interest_pd = yr_int;
02283                 if (!fv_case)
02284                 {
02285                     amortyr->principal_pd = pv - hpv;
02286                 }                       /* endif */
02287                 amortyr->yr_end_balance = pv;
02288                 amortyr->total_interest_pd = sum_int;
02289                 amortyr->next_yr =
02290                     (amort_sched_yr_ptr) calloc (1, sizeof (amort_sched_yr));
02291                 amortyr = amortyr->next_yr;
02292 
02293                 hpv = pv;
02294                 yr_int = 0.0;
02295                 sum_prt = TRUE;
02296             }                           /* * endif */
02297         }                               /* * endfor */
02298 
02299         /* determine if payment due at beginning or end of period in order
02300          * to correctly compute final payment, interest and principal */
02301         if (bep)
02302         {
02303             /* paying remainder at beginning of period compute final payment */
02304             final_pmt = -pv - fv / (1 + eint);
02305 
02306             /* then compute interest paid with final final payment */
02307             pmt_int = -rnd ((pv + final_pmt) * eint, prec);
02308 
02309             /* then compute the principal paid */
02310             prin = final_pmt + pmt_int;
02311         }
02312         else
02313         {
02314             /* basic equation for computing interest paid in payment period
02315              * for payment at end of period */
02316             pmt_int = -rnd (pv * eint, prec);
02317 
02318             /* compute principal paid this payment period */
02319             prin = -pv;
02320 
02321             /* compute the final payment note the final payment may be
02322              * computed either of two ways both are equivalent */
02323             final_pmt = prin + pmt_int;
02324         }                               /* * endif   */
02325 
02326         pv = -fv;
02327 
02328         /* sum yearly interest paid */
02329         yr_int += pmt_int;
02330 
02331         /* sum total interest paid */
02332         sum_int += pmt_int;
02333 
02334         if (sum_prt)
02335         {
02336             amortyr->payments =
02337                 pmtsched = (sched_pmt_ptr) calloc (1, sizeof (sched_pmt));
02338             amortyr->num_periods = 1;
02339         }                               /* endif */
02340 
02341         amortyr->final_pmt = final_pmt;
02342 
02343         if (fv_case)
02344         {
02345             pmtsched->period_num = s++;
02346             pmtsched->interest = pmt_int;
02347             pmtsched->balance = pv;
02348         }
02349         else
02350         {
02351             pmtsched->period_num = s++;
02352             pmtsched->interest = pmt_int;
02353             pmtsched->principal = prin;
02354             pmtsched->balance = pv;
02355         }                               /* endif */
02356 
02357         if (dabs (yr_int) > 0.0)
02358         {
02359             amortyr->year = yr++;
02360             amortyr->interest_pd = yr_int;
02361             amortyr->total_interest_pd = sum_int;
02362             if (!bep)
02363             {
02364                 amortyr->principal_pd = -hpv;
02365             }                           /* endif */
02366         }                               /* endif */
02367 
02368         break;
02369     case 'x':
02370         /* constant payment to principal - annual summary */
02371         /* compute number of years to summarize */
02372         j = n / PF;
02373         if (yr_pmt < PF)
02374             j++;
02375         amortsched->total_periods = j;
02376         amortsched->schedule.summary =
02377             yrly_sum = (yearly_summary_ptr) calloc (j, sizeof (yearly_summary));
02378 
02379         jj = 0;
02380         for (j = n, sum_prt = 0; j > 0; j -= yr_pmt, yr_pmt = PF, sum_prt++)
02381         {
02382             if (j <= PF)
02383             {
02384                 s = jj + j;
02385                 yr_pmt = j;
02386                 yr_fv = rnd (pv + cpmt * (s - 1), prec) + final_pmt;
02387             }
02388             else
02389             {
02390                 s = jj + yr_pmt;
02391                 yr_fv = rnd (pv + cpmt * s, prec);
02392             }                           /* endif */
02393             prin = -eint * jj * (pv + (cpmt * (jj - 1) / 2.0));
02394             yr_int = -eint * s * (pv + (cpmt * (s - 1) / 2.0));
02395             yr_int = rnd (yr_int - prin, prec);
02396             jj += yr_pmt;
02397 
02398             sum_int += yr_int;
02399 
02400             yrly_sum[sum_prt].year = yr++;
02401             yrly_sum[sum_prt].interest = yr_int;
02402             yrly_sum[sum_prt].end_balance = yr_fv;
02403         }                               /* endfor */
02404 
02405         break;
02406     case 'y':
02407         /* normal amortization - annual summary */
02408         /* compute number of years to summarize */
02409         j = n / PF;
02410         if (yr_pmt < PF)
02411             j++;
02412         if (n > (j * PF))
02413             j++;
02414         amortsched->total_periods = j;
02415         amortsched->schedule.summary =
02416             yrly_sum = (yearly_summary_ptr) calloc (j, sizeof (yearly_summary));
02417 
02418         hpv = pv;
02419 
02420         for (jj = n, j = 0; jj > 0; jj -= yr_pmt, yr_pmt = PF, j++)
02421         {
02422             if (jj <= (int)PF)
02423             {
02424                 yr_fv = fv;
02425                 yr_int = rnd (((jj - 1) * pmt) + hpv + final_pmt, prec);
02426             }
02427             else
02428             {
02429                 yr_fv =
02430                     -rnd (_fi_calc_future_value
02431                           (yr_pmt, nint, hpv, pmt, CF, PF, disc, bep), prec);
02432                 yr_int = rnd ((yr_pmt * pmt) + hpv - yr_fv, prec);
02433             }                           /* * endif */
02434 
02435             sum_int += yr_int;
02436 
02437             yrly_sum[j].year = yr++;
02438             yrly_sum[j].interest = yr_int;
02439             yrly_sum[j].end_balance = yr_fv;
02440             hpv = yr_fv;
02441         }                               /* * endfor */
02442 
02443         break;
02444     }                           /* * endswitch */
02445 
02446     amortsched->total_interest = sum_int;
02447 
02448     return amortsched;
02449 }                               /* Amortization_Schedule */
02450 
02451 /* function to free dynamically allocated memory used for amortization
02452    schedule */
02453 void
02454 Amortization_free (amort_sched_ptr amortsched)
02455 {
02456     amort_sched_yr_ptr amortyr, prst_yr;
02457 
02458     switch (amortsched->summary)
02459     {
02460     case 'a':
02461     case 'f':
02462     case 'o':
02463     case 'p':
02464         for (amortyr = amortsched->schedule.first_yr; amortyr; amortyr = prst_yr)
02465         {
02466             if (amortyr->payments)
02467                 free (amortyr->payments);
02468             prst_yr = amortyr->next_yr;
02469             free (amortyr);
02470         }                               /* endfor */
02471         break;
02472     case 'y':
02473         free (amortsched->schedule.summary);
02474         break;
02475     }                           /* endswitch */
02476 
02477     amortsched->schedule.first_yr = NULL;
02478 }                               /* amort_free */
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Defines