%%HP:T(3)F(.);

@ GAR94 - Build a projected GAR-94 generational mortality table for QLIB/48.
@
@ This program will build a fully generational mortality table for a life
@ with a given age in a given year.  The generated table, reflecting the
@ necessary mortality improvement projections from Projection Scale AA, is
@ stored in a variable, and the current QLIB/48 X and/or Y mortality table is
@ changed to use the generated table.
@
@ This program can also do static mortality improvement projections, where
@ the mortality rates are all projected by a fixed number of years, rather
@ than on a fully generational basis.  In addition, the program can do
@ projections using the unloaded UP-94 (GAM-94 Basic) table rather than the
@ GAR-94 or GAM-94 Static table.
@
@ This file contains a single program (not a directory of programs).  You
@ must install QLIB/48 before you download it.
@
@
@ The GAR94 program requires the following four arguments:
@
@   sex  -  1=Male GAR-94 or GAM-94 Static
@           2=Female GAR-94 or GAM-94 Static
@          -1=Male UP-94G or UP-94
@          -2=Female UP-94G or UP-94
@   age  - Age of person for whom you want to generate a fully generational
@          table; or -1 to generate a table with mortality improvements
@          projected on a static basis for a fixed number of years.
@          The age is expected to be an integer.
@   year - Year of the specified age; or, if age=-1, the year to which the
@          table should be projected on a static basis.
@   tbl  - 1 to store table as X table; 2 for Y; 3 for both; 0 for neither
@
@
@ The following table illustrates the arguments that you would pass to GAR94
@ to select various mortality tables for a valuation in the year 2004 of a
@ male aged 65.  The generated mortality rates are assigned to the QLIB/48 X
@ table.  Note that "at" is used in place of the at-sign symbol (which
@ appears at the beginning of this line), because that character is recognized
@ by the HP 48 as the comment character.
@
@  Valuation Table    GAR94 Arguments   Assu Menu Table Title   Variable
@  ----------------   ---------------   ---------------------   ----------
@  1. GAR-94          1  65 2004 1      Male 65in2004 GAR94     M1939GAR94
@  2. GAR-94          1   0 1939 1      Male 0in1939 GAR94      M1939GAR94
@  3. GAM-94 Static   1  -1 1994 1      Male at1994 GAM94       M1994GAM94
@  4. UP-94G          -1 65 2004 1      Male 65in2004 UP94G     M1939UP94G
@  5. UP-94G at1997   -1 65 1997 1      Male 65in1997 UP94G     M1932UP94G
@  6. UP-94           -1 -1 1994 1      Male at1994 UP94        M1994UP94
@  7. UP-94 at1997    -1 -1 1997 1      Male at1997 UP94        M1997UP94
@
@ Note that 1. and 2. result in exactly the same mortality rates.  You can use
@ whichever method seems most logical to you.  In either case, the projected
@ mortality rates are stored in a variable name containing the year of birth,
@ since this is the key information that distinguishes one generational table
@ from another.
@
@ In examples 3. and 6., no projection is actually done (it's a 0-year static
@ projection), so the M94GAM or MUP94 table could have been selected directly
@ from the the QLIB/48 Assumption Menu.
@
@
@ Additional comments:
@
@ - The projected mortality rates are not rounded.
@
@ - The projected mortality table will always have the same dimensions (i.e.,
@   the same initial and terminal ages) as the original base table.
@   Mortality rates for ages before 1994 are left unchanged at the 1994 level.
@
@ - The mortality table setback is automatically set to zero when the new
@   table is stored.
@
@ - The program expects to be able to find the tables MUP94, FUP94, M94GAM,
@   F94GAM, MAA94, and FAA94.  They may be stored in your QTL library or in
@   variables.
@
@ - The variables in which the generated tables are stored are not
@   automatically deleted.  You may want to manually delete the mortality
@   table variables periodically to conserve memory.
@
@ - References: The Final Reports (to be published in volume XLVII of the
@   Transactions of the Society of Actuaries) on the GAR-94, GAM-94, and
@   UP-94 mortality tables (May 1995).
@

\<< \-> sex age year tbl \<<

   @ Recall and break apart the mortality and projection scale tables
   CASE
      sex  1 == THEN "M94GAM" "MAA94" END
      sex  2 == THEN "F94GAM" "FAA94" END
      sex -1 == THEN "MUP94"  "MAA94" END
      sex -2 == THEN "FUP94"  "FAA94" END
      @ Note: The table names are compiled at run time so that the program
      @ isn't dependent on where the tables are stored (variables or QTL)
      @ or on the order of the QTL library.
      @else@ "Invalid sex" DOERR
   END
   OBJ\-> OBJ\-> DROP @ qtable-name AA-title AA-initage AA-rates
   4 ROLLD DROP DROP @ AA-rates qtable-name
   OBJ\-> OBJ\-> DROP @ AA-rates q-title q-initage q-rates
   3 ROLLD SWAP DROP
   @ AA-rates q-rates q-initage

   @ Calc projection parameters and build new table title
   RCLF STD @ get current modes, change to STD display mode
   IF sex ABS 1 == THEN "Male" ELSE "Female" END
   IF age 0 < THEN @ static projection
      0 @ age-dep? (no)
      year 1994 - @ const-yrs
      year \->STR
      IF sex SIGN 0 < THEN "UP94" ELSE "GAM94" END
      @ "sex" age-dep? const-years "year" "qtbl"
      5 PICK @"sex"@ " @" + 3 PICK @"year"@ + " " + OVER @"qtbl"@ + @ "title"
      @ "sex" age-dep? const-years "year" "qtbl" "title"
   ELSE @ full generational mortality
      @ Stack: q-initage flags "sex"
      1 @age-dep? (yes)
      4 PICK @q-initage@ age - 1 - year + 1994 - @ const-yrs
      year age - \->STR @ "yob"
      age \->STR "in" + year \->STR +
      IF sex SIGN 0 < THEN "UP94G" ELSE "GAR94" END
      @ "sex" age-dep? const-years "yob" "xxinyear" "qtbl"
      6 PICK @"sex"@ " " + ROT @"xxinyear"@ + " " + OVER @"qtbl"@ + @ title
      @ "sex" age-dep? const-yrs "yob" "qtbl" "title"
   END
   @ flags "sex" age-dep? const-yrs "year" "qtbl" "title"
   7 ROLL STOF @ restore user's mode settings
   @ AA-rates q-rates q-initage "sex" age-dep? const-yrs "year" "qtbl" "title"

   @ Build variable name
   "'"
   7 ROLL @"sex"@ 1 1 SUB +
   4 ROLL @"year"@ +
   ROT @"qtbl"@ +
   OBJ\-> @ 'var'
   @ AA-rates q-rates q-initage age-dep? const-yrs "title" 'var'

   @ Calc range of indices of rates to be projected
   7 ROLLD 6 ROLLD ROT 5 ROLLD @ AA-rates q-rates age-dep? const-yrs
   4 ROLLD 4 ROLLD @ age-dep? const-yrs AA-rates q-rates
   OVER @AA-rates@ SIZE OBJ\-> DROP @ m=number of q's
   IF 5 PICK @age-dep?@ THEN
      4 PICK @const-yrs@ NEG 1 + 1 MAX @ i-beg
   ELSE
      IF 4 PICK @const-yrs@ 0 > THEN 1 ELSE DUP @m@ 1 + END @ i-beg
   END
   SWAP
   @ 'var' "title" initage age-dep? const-yrs AA-rates q-rates i-beg m

   @ Loop through and project mortality rates
   IF DUP2 > THEN
      DROP DROP @ nothing to loop through
   ELSE
      @i-beg@ @m@ FOR i
         @ age-dep? const-yrs AA-rates q-rates
         DUP @q-rates@ i GET @ q[i]
         1 4 PICK @AA-rates@ i GET - @ 1-AA[i]
         i 7 PICK @age-dep?@ * 6 PICK @const-yrs@ + @ q 1-AA prj-yrs
         ^ * @ projected q
         i SWAP @ q-rates i new-q
         PUT @ age-dep const-yrs AA-rates q-rates
      NEXT
   END
   4 ROLLD 3 DROPN
   @ 'var' "title" initage q-rates

   @ Build table and store in variable
   3 \->LIST @ qtable
   OVER @'var'@ STO
   @ 'var'

   @ Store table as X and/or Y table
   IF tbl 1 == tbl 3 == OR THEN
      DUP @'var'@ QTBLXSTO
      0 QSBXSTO
   END
   IF tbl 2 == tbl 3 == OR THEN
      DUP @'var'@ QTBLYSTO
      0 QSBYSTO
   END
   @'var'@ DROP
\>>
