#!/usr/bin/env bash # SCRIPT TO COMPUTE OR PLOT US FEDERAL TAX RATES, TAX YEARS 1987 - 2012 # Last update: Dec 31, 2011 # # Usage: (run with no arguments for an explanation) # # NO WARRANTY ON THIS DATA. USE AT YOUR OWN RISK. # # I suggest you use this for estimates only, such as with a spreadsheet, and # refer to IRS tables for actual values. (If you ever detect a discrepancy, # however, please let me know.) The formulas used for 1988 and later years are # explained below. # # WARNING: Doesn't know that 1991-2012 long term capital gains, or later # qualified dividends, are taxed at a reduced rate (depending on your tax # bracket). This can result in an overestimate of tax due. # # WARNING: Doesn't plot correctly if asked (via $maxti, see below) to plot # rates for 1988-1990 above C3 (see below) for any tax status, but it gives # warnings if this applies. Above C3 the curves branch into families depending # on number of exemptions. This doesn't apply to very many people. # # See below for explanations of the algorithms. # # Below $100000 taxable income ($50000 before 1993 (?)), you have to use the # tax tables, which are quantized into $50 steps (or $25 steps below $3000, # ignores smaller steps in $0-25 range). The tax computation understands this # (I hope), but the plot doesn't show this detail. # AMOUNT OF WITHHOLDING REQUIRED (as of 9606): # # You must make quarterly estimated tax payments if: # # tax - (withholding + credits) >= $500 # AND (withholding + credits) < MIN (prev_year_tax, 0.9 * curr_year_tax) # EXPLANATION OF RATES FOR 1988 - 1990: # # Variables: # # T taxable income (total income less all adjustments and deductions) # E number of exemptions # t tax due # # Tax formula: # # t = 0.15 * T (a) 15%, lowest bracket. # + 0.13 * (max (0, T - C1)) (b) 28%, next bracket. # + 0.05 * ( max (0, T - C2) (c) 33%, Rate Adjustment brkt. # - max (0, T - C3) (d) 28%-of-total bracket. # + min ((E * K), (e) Phaseout of Personal # max (0, T - C3))) (f) Exemptions adjustment. # # C1, C2, C3, and K values vary for each year. They are listed in the tables # below. # # When (T >= C3), part (d) comes in to cancel part (c) except for 5% of (C3 - # C2), so the rate reverts to 28%. But now it applies all of T, not just the # amount above C1. In other words, the amount saved in the 15% lowest bracket # is added back in: # # 0.13 * C1 = 0.05 * (C3 - C2) # # Working through the math for (T >= C3), parts (a) through (d) collapse: # # t = 0.15 * T # + 0.13 * (T - C1) # + 0.05 * (T - C2 - T + C3) # # = 0.28 * T # - 0.13 * C1 # + 0.05 * (C3 - C2) # # = 0.28 * T # # There's one exception. Status ms (married, single) is structured so 5% of # (C3 - C2) is twice 13% of C1. Apparently there is a discontinuity. People # just below C3 pay almost $2000 more tax than those just above it, because the # latter pay a flat 28% (unless the Phaseout of Personal Exemption applies). # There's a note in the 1989 worksheet that might counteract this; I'm not # sure. # # The Phaseout of Personal Exemptions may delay the reversion to 28% (of all of # T) until higher income levels, depending on your exemptions. Part (f) tries # to add back the extra 5%, but can only do so if less than part (e). This # creates a family of curves above C3 for each filing status. # EXPLANATION OF RATES FOR 1991 - 2012: # # They apparently lowered the top tax rate and got rid of the Phaseout of # Personal Exemptions. So the formula is similar to but simpler than that # above, more like the 1987 formula, but with even fewer brackets (until the # 1993 tax act retroactively added more brackets, sigh). # # Variables: # # T taxable income (total income less all adjustments and deductions) # t tax due # # Tax formula: # # t = 0.15 * T (a) 15%, lowest bracket. # + 0.13 * (max (0, T - C1)) (b) 28%, next bracket. # + 0.03 * (max (0, T - C2)) (c) 31%, top bracket. # 1993 and later: # + 0.05 * (max (0, T - C3)) (d) 36%, next bracket. # + 0.036 * (max (0, T - C4)) (e) 39.6%, top bracket. # # 2001 and later, brackets change and a new 10% bracket is added starting in # 2002. For 2001 the same effect is provided by a rebate and using the old 15% # base rate; nope, the tax rate schedules in the 2001 workbook are actually as # shown below, probably because the rebate was all-year but the new tax rates # were half-year? # # 2001 2002 # . 10% # 15% 15% # 27.5% 27% # 30.5% 30% # 35.5% 35% # 39.1% 38.6% # # 030604: Tax law just passed apparently puts 2006 rates in place for 2004. # INITIALIZE: spool='' device='' # use defaults in program (or $PLOTDEV). driver='' # alternate options: # spool='' # device='-d/dev/tty' # driver='-rhp2623' # spool='-sa' # device="-d$PWD/temp" # driver='-rhpgl' maxti='50000' # default right sides (max X values) of plots. plotdir='/var/tmp/taxplotdata' # holds files to plot. # CHECK INVOCATION: if [[ ($# != 1) && ($# != 2) && ($# != 3) && ($# != 4) ]] # wrong args. then # This is an interpreted here-doc: cat >&2 <<-! usage: $0 year [year2 | status taxable-income [exemptions]] Year must be 87..99 or 00..12. Status must be s, mj, ms, or hh. Taxable-income is the net dollar figure after all adjustments, exemptions, and deductions. Given only a year (or two), does a rates plot to device $device using driver "$driver". (The device and driver are hardwired into the script or set with \$PLOTDEV.) With additional arguments, computes and prints the tax (in dollars) for the given year, status, and taxable-income. For example: $0 91 mj 45319 Exemptions (default: 0) are ignored except for high incomes for 1988-1990. ! exit 1 fi # CHECK ARGUMENTS: case "x$1" in x87 | x88 | x89 | \ x90 | x91 | x92 | x93 | x94 | x95 | x96 | x97 | x98 | x99 | \ x00 | x01 | x02 | x03 | x04 | x05 | x06 | x07 | x08 | x09 | \ x10 | x11 | x12 ) ;; * ) echo "$0: year must be 87..99 or 00..12" >&2 exit 1 ;; esac if [[ (${1#0} -ge 87) && (${1#0} -lt 93) ]] # old range. then table='50000' else table='100000' fi if [[ $# -ge 3 ]] # need to check status, etc. then case "x$2" in xs | xmj | xms | xhh ) ;; *) echo "$0: status must be s, mj, ms, or hh" >&2 exit 1 ;; esac # Modify taxable income ($3) to center of bracket in which it falls: # Also set exemptions to 0 if not specified. set -- "$1" "$2" `awk < /dev/null 'END { if ('"$3"' < 5) print 0; else if ('"$3"' < 15) print 10; else if ('"$3"' < 25) print 20; else if ('"$3"' < 3000) print (int ('"$3"' / 25) * 25) + 12.5; else if ('"$3"' < '$table') print (int ('"$3"' / 50) * 50) + 25; else print '"$3"'; }'` "${4:-0}" fi # CONSTANTS FOR 1987 (based on 1040 tax rate schedules): case $1 in 87 ) # Constants are tops of 11%, 15%, 28%, and 35% brackets. # Above that is 38.5%. # # status C1 C2 C3 C4 cat <<-'!' s 1800 16800 27000 54000 mj 3000 28000 45000 90000 ms 1500 14000 22500 45000 hh 2500 23000 38000 80000 ! ;; # CONSTANTS FOR 1988 (based on 1988 1040ES): 88 ) # Constants are tops of 15%, 28%, and 33% brackets. # Above that it gets complicated. See explanation above. # # status C1 C2 C3 K cat <<-'!' s 17850 43150 89560 10920 mj 29750 71900 149250 10920 ms 14875 35950 113300 10920 hh 23900 61650 123790 10920 ! ;; # CONSTANTS FOR 1989 (based on 1989 1040 workbook, page 41): 89 ) # Constants are tops of 15%, 28%, and 33% brackets. # Above that it gets complicated. See explanation above. # # status C1 C2 C3 K cat <<-'!' s 18550 44900 93130 11200 mj 30950 74850 155320 11200 ms 15475 37425 117895 11200 hh 24850 64200 128810 11200 ! ;; # CONSTANTS FOR 1990 (based on 1990 1040ES): 90 ) # Constants are tops of 15%, 28%, and 33% brackets. # Above that it gets complicated. See explanation above. # # status C1 C2 C3 K cat <<-'!' s 19450 47050 97620 11480 mj 32450 78400 162770 11480 ms 16225 39200 123570 11480 hh 26050 67200 134930 11480 ! ;; # CONSTANTS FOR 1991 (based on 1991 1040ES): 91 ) # Constants are tops of 15% and 28% brackets. Above that is 31%. # # status C1 C2 cat <<-'!' s 20350 49300 mj 34000 82150 ms 17000 41075 hh 27300 70450 ! ;; # CONSTANTS FOR 1992 (based on 1992 1040ES) (each exemption = $2300): 92 ) # Constants are tops of 15% and 28% brackets. Above that is 31%. # # status C1 C2 cat <<-'!' s 21450 51900 mj 35800 86500 ms 17900 43250 hh 28750 74150 ! ;; # CONSTANTS FOR 1993 (based on 1993 1040) (each exemption = $2350): 93 ) # Constants are tops of 15%, 28%, 31%, and 36% brackets. Above # that is 39.6%. # # status C1 C2 C3 C4 cat <<-'!' s 22100 53500 115000 250000 mj 36900 89150 140000 250000 ms 18450 44575 70000 125000 hh 29600 76400 127500 250000 ! ;; # CONSTANTS FOR 1994 (based on 1994 1040 Pub 919) (each exemption = $2450): 94 ) # Constants are tops of 15%, 28%, 31%, and 36% brackets. Above # that is 39.6%. Note, C3 and C4 are unchanged from 1993. # # status C1 C2 C3 C4 cat <<-'!' s 22750 55100 115000 250000 mj 38000 91850 140000 250000 ms 19000 45925 70000 125000 hh 30500 78700 127500 250000 ! ;; # CONSTANTS FOR 1995 (based on 1995 1040ES) (each exemption = $2500): 95 ) # Constants are tops of 15%, 28%, 31%, and 36% brackets. Above # that is 39.6%. # # status C1 C2 C3 C4 cat <<-'!' s 23350 56550 117950 256500 mj 39000 94250 143600 256500 ms 19500 47125 71800 128250 hh 31250 80750 130800 256500 ! ;; # CONSTANTS FOR 1996 (based on 1996 1040ES) (each exemption = $2550): 96 ) # Constants are tops of 15%, 28%, 31%, and 36% brackets. Above # that is 39.6%. # # status C1 C2 C3 C4 cat <<-'!' s 24000 58150 121300 263750 mj 40100 96900 147700 263750 ms 20050 48450 73850 131875 hh 32150 83050 134500 263750 ! ;; # CONSTANTS FOR 1997 (based on 1997 1040ES) (each exemption = $2650): 97 ) # Constants are tops of 15%, 28%, 31%, and 36% brackets. Above # that is 39.6%. # # status C1 C2 C3 C4 cat <<-'!' s 24650 59750 124650 271050 mj 41200 99600 151750 271050 ms 20600 49800 75875 135525 hh 33050 85350 138200 271050 ! ;; # CONSTANTS FOR 1998 (based on 1998 1040ES) (each exemption = $2700): 98 ) # Constants are tops of 15%, 28%, 31%, and 36% brackets. Above # that is 39.6%. # # status C1 C2 C3 C4 cat <<-'!' s 25350 61400 128100 278450 mj 42350 102350 155950 278450 ms 21175 51150 77975 139225 hh 33950 87700 142000 278450 ! ;; # CONSTANTS FOR 1999 (based on 1999 1040ES) (each exemption = $2750): 99 ) # Constants are tops of 15%, 28%, 31%, and 36% brackets. Above # that is 39.6%. # # status C1 C2 C3 C4 cat <<-'!' s 25750 62450 130250 283150 mj 43050 104050 158550 283150 ms 21525 52025 79275 141575 hh 34550 89150 144400 283150 ! ;; # CONSTANTS FOR 2000 (based on 2000 1040ES) (each exemption = $2800): 00 ) # Constants are tops of 15%, 28%, 31%, and 36% brackets. Above # that is 39.6%. # # status C1 C2 C3 C4 cat <<-'!' s 26250 63550 132600 288350 ms 21925 52975 80725 144175 mj 43850 105950 161450 288350 hh 35150 90800 147050 288350 ! ;; # CONSTANTS FOR 2001 (based on 2001 1040ES) (each exemption = $2900): 01 ) # Constants are tops of 15%, 27.5%, 30.5%, and 35.5% brackets. # Above that is 39.1%. # # status C1 C2 C3 C4 cat <<-'!' s 27050 65550 136750 297350 mj 45200 109250 166500 297350 ms 22600 54625 83250 148675 hh 36250 93650 151650 297350 ! ;; # CONSTANTS FOR 2002 (based on 2002 1040ES) (each exemption = $3000): 02 ) # Constants are tops of 10%, 15%, 27%, 30%, and 35% brackets. # Above that is 38.6%. # # status C1 C2 C3 C4 C5 cat <<-'!' s 6000 27950 67700 141250 307050 mj 12000 46700 112850 171950 307050 ms 6000 23350 56425 85975 153625 hh 10000 37450 96700 156600 307050 ! ;; # CONSTANTS FOR 2003 (based on 2003 1040ES) (each exemption = $3050): # # "Long-term capital gains rates. Effective for sales of assets on or after # May 6, 2003, the new law reduced the maximum rate on long-term capital gains # (those on assets owned for more than a year). Through 2009, taxpayers in the # higher income-tax brackets will pay a capital gains rate of 15% (down from # 20% previously), while those in the 10% and 15% brackets will pay a rate of # 5% through 2007 and 0% in 2008... Qualified dividend income. As of January # 1, 2003, tax rates on "qualified dividend income" (QDI).generally dividends # generated from stock or stock mutual funds.have been reduced to the same # rates as those for long-term capital gains..." # # Also note marriage penalty abatement, now C2 for MJ is 2x for S. 03 ) # Constants are tops of 10%, 15%, 25%, 28%, and 33% brackets. # Above that is 35%. # # status C1 C2 C3 C4 C5 cat <<-'!' s 7000 28400 68800 143500 311950 mj 14000 56800 114650 174700 311950 ms 7000 28400 57325 87350 155975 hh 10000 38050 98250 159100 311950 ! ;; # CONSTANTS FOR 2004 (based on 2004 1040ES) (each exemption = $3100): 04 ) # Constants are tops of 10%, 15%, 25%, 28%, and 33% brackets. # Above that is 35% (same as revised in TY 2003). # # status C1 C2 C3 C4 C5 cat <<-'!' s 7150 29050 70350 146750 319100 mj 14300 58100 117250 178650 319100 ms 7150 29050 58625 89325 159550 hh 10200 38900 100500 162700 319100 ! ;; # CONSTANTS FOR 2005 (based on 2005 1040ES) (each exemption = $3200): 05 ) # Constants are tops of 10%, 15%, 25%, 28%, and 33% brackets. # Above that is 35% (same as revised in TY 2003). # # status C1 C2 C3 C4 C5 cat <<-'!' s 7300 29700 71950 150150 326450 mj 14600 59400 119950 182800 326450 ms 7300 29700 59975 91400 163225 hh 10450 39800 102800 166450 326450 ! ;; # CONSTANTS FOR 2006 (based on 2006 1040ES) (each exemption = $3300): 06 ) # Constants are tops of 10%, 15%, 25%, 28%, and 33% brackets. # Above that is 35% (same as revised in TY 2003). # # status C1 C2 C3 C4 C5 cat <<-'!' s 7550 30650 74200 154800 336550 mj 15100 61300 123700 188450 336550 ms 7550 30650 61850 94225 168275 hh 10750 41050 106000 171650 336550 ! ;; # CONSTANTS FOR 2007 (based on 2007 1040ES) (each exemption = $3400): 07 ) # Constants are tops of 10%, 15%, 25%, 28%, and 33% brackets. # Above that is 35% (same as revised in TY 2003). # # status C1 C2 C3 C4 C5 cat <<-'!' s 7825 31850 77100 160850 349700 mj 15650 63700 128500 195850 349700 ms 7825 31850 64250 97925 174850 hh 11200 42650 110100 178350 349700 ! ;; # CONSTANTS FOR 2008 (based on 2008 1040ES) (each exemption = $3500): 08 ) # Constants are tops of 10%, 15%, 25%, 28%, and 33% brackets. # Above that is 35% (same as revised in TY 2003). # # status C1 C2 C3 C4 C5 cat <<-'!' s 8025 32550 78850 164550 357700 mj 16050 65100 131450 200300 357700 ms 8025 32550 65725 100150 178850 hh 11450 43650 112650 182400 357700 ! ;; # CONSTANTS FOR 2009 (based on 2009 1040ES) (each exemption = $3650): 09 ) # Constants are tops of 10%, 15%, 25%, 28%, and 33% brackets. # Above that is 35% (same as revised in TY 2003). # # status C1 C2 C3 C4 C5 cat <<-'!' s 8350 33950 82250 171550 372950 mj 16700 67900 137050 208950 372950 ms 8350 33950 68525 104425 196475 hh 11950 45500 117450 190200 372950 ! ;; # CONSTANTS FOR 2010 (based on 2010 1040ES) (each exemption = $3650, unchanged): 10 ) # Constants are tops of 10%, 15%, 25%, 28%, and 33% brackets. # Above that is 35% (same as revised in TY 2003). # # status C1 C2 C3 C4 C5 cat <<-'!' s 8375 34000 82400 171850 373650 mj 16750 68000 137300 209250 373650 ms 8375 34000 68650 104625 186825 hh 11950 45550 117650 190550 373650 ! ;; # CONSTANTS FOR 2011 (based on 2011 1040ES) (each exemption = $3700): 11 ) # Constants are tops of 10%, 15%, 25%, 28%, and 33% brackets. # Above that is 35% (same as revised in TY 2003). # # status C1 C2 C3 C4 C5 cat <<-'!' s 8500 34500 83600 174400 379150 mj 17000 69000 139350 212300 379150 ms 8500 34500 69675 106150 189575 hh 12150 46250 119400 193350 379150 ! ;; # CONSTANTS FOR 2012 (based on 2012 1040ES) (each exemption = $3800): 12 ) # Constants are tops of 10%, 15%, 25%, 28%, and 33% brackets. # Above that is 35% (same as revised in TY 2003). # # status C1 C2 C3 C4 C5 cat <<-'!' s 8700 35350 85650 178650 388350 mj 17400 70700 142700 217450 388350 ms 8700 35350 71350 108725 194175 hh 12400 47350 122300 198050 388350 ! ;; esac | # note piping of output. # FIGURE TAX: # # Uses constants piped to standard input, and script arguments, with taxable # income already adjusted to center of bracket. # # Note: I know, this could be a lot shorter (although more complex) if it was # parameterized better... if [[ $# -ge 3 ]] then # 1987: if [[ $1 = 87 ]] then awk ' # Save appropriate constants for given status: ($1 == "'$2'") { C1 = $2; C2 = $3; C3 = $4; C4 = $5 } END { ti = '"$3"'; tax = 0.11 * ti; if (ti > C1) tax += 0.04 * (ti - C1); if (ti > C2) tax += 0.13 * (ti - C2); if (ti > C3) tax += 0.07 * (ti - C3); if (ti > C4) tax += 0.035 * (ti - C4); # round to whole dollar; exact half dollar rounds up: if (ti <= 100000) printf ("%.0f\n", tax + 0.0001); else printf ("%.2f\n", tax); }' # 1988 - 1990: elif [[ ($1 = 88) || ($1 = 89) || ($1 = 90) ]] then awk ' # Save appropriate constants for given status: ($1 == "'$2'") { C1 = $2; C2 = $3; C3 = $4; K = $5 } END { ti = '"$3"'; if (ti <= C3) # due to non-linearity. { tax = 0.15 * ti; if (ti > C1) tax += 0.13 * (ti - C1); if (ti > C2) tax += 0.05 * (ti - C2); } else # handle high-income case. { tax = 0.28 * ti; if ((excess = ('"$4"' * K)) > (ti - C3)) excess = ti - C3; tax += 0.05 * excess; } # round to whole dollar; exact half dollar rounds up: if (ti <= 100000) printf ("%.0f\n", tax + 0.0001); else printf ("%.2f\n", tax); }' # 1991 - 1992: elif [[ ($1 = 91) || ($1 = 92) ]] then awk ' # Save appropriate constants for given status: ($1 == "'$2'") { C1 = $2; C2 = $3 } END { ti = '"$3"'; tax = 0.15 * ti; if (ti > C1) tax += 0.13 * (ti - C1); if (ti > C2) tax += 0.03 * (ti - C2); # round to whole dollar; exact half dollar rounds up: if (ti <= 100000) printf ("%.0f\n", tax + 0.0001); else printf ("%.2f\n", tax); }' # 1993 - 2000: elif [[ (${1#0} -ge 93) || (${1#0} = 00) ]] then awk ' # Save appropriate constants for given status: ($1 == "'$2'") { C1 = $2; C2 = $3; C3 = $4; C4 = $5 } END { ti = '"$3"'; tax = 0.15 * ti; if (ti > C1) tax += 0.13 * (ti - C1); if (ti > C2) tax += 0.03 * (ti - C2); if (ti > C3) tax += 0.05 * (ti - C3); if (ti > C4) tax += 0.036 * (ti - C4); # round to whole dollar; exact half dollar rounds up: if (ti <= 100000) printf ("%.0f\n", tax + 0.0001); else printf ("%.2f\n", tax); }' # 2001: elif [[ $1 = 01 ]] then awk ' # Save appropriate constants for given status: ($1 == "'$2'") { C1 = $2; C2 = $3; C3 = $4; C4 = $5 } END { ti = '"$3"'; tax = 0.15 * ti; if (ti > C1) tax += 0.125 * (ti - C1); if (ti > C2) tax += 0.03 * (ti - C2); if (ti > C3) tax += 0.05 * (ti - C3); if (ti > C4) tax += 0.036 * (ti - C4); # round to whole dollar; exact half dollar rounds up: if (ti <= 100000) printf ("%.0f\n", tax + 0.0001); else printf ("%.2f\n", tax); }' # 2002: elif [[ $1 = 02 ]] then awk ' # Save appropriate constants for given status: ($1 == "'$2'") { C1 = $2; C2 = $3; C3 = $4; C4 = $5; C5 = $6 } END { ti = '"$3"'; tax = 0.10 * ti; if (ti > C1) tax += 0.05 * (ti - C1); if (ti > C2) tax += 0.12 * (ti - C2); if (ti > C3) tax += 0.03 * (ti - C3); if (ti > C4) tax += 0.05 * (ti - C4); if (ti > C5) tax += 0.036 * (ti - C5); # round to whole dollar; exact half dollar rounds up: if (ti <= 100000) printf ("%.0f\n", tax + 0.0001); else printf ("%.2f\n", tax); }' # 2003 - 2011: elif [[ ($1 = 03) \ || ($1 = 04) \ || ($1 = 05) \ || ($1 = 06) \ || ($1 = 07) \ || ($1 = 08) \ || ($1 = 09) \ || ($1 = 10) \ || ($1 = 11) \ || ($1 = 12) \ ]] then awk ' # Save appropriate constants for given status: ($1 == "'$2'") { C1 = $2; C2 = $3; C3 = $4; C4 = $5; C5 = $6 } END { ti = '"$3"'; tax = 0.10 * ti; if (ti > C1) tax += 0.05 * (ti - C1); if (ti > C2) tax += 0.10 * (ti - C2); if (ti > C3) tax += 0.03 * (ti - C3); if (ti > C4) tax += 0.05 * (ti - C4); if (ti > C5) tax += 0.02 * (ti - C5); # round to whole dollar; exact half dollar rounds up: if (ti <= 100000) printf ("%.0f\n", tax + 0.0001); else printf ("%.2f\n", tax); }' # TAIL END: # # This also makes it easier to add new sections above. else echo >&1 "$0: Internal error, \$1 = \"$1\" unexpected." exit 1 fi # PREPARE TO PLOT RATE CHART: # # Note that stdin is piped from cat's above. # # If two args, call the script recursively (before cd'ing) to get the data for # the second year; then do the first year. else [[ $# = 1 ]] || TAXRECURSE=1 $0 $2 # recurse for second year. mkdir -p $plotdir # ensure already made. cd $plotdir [[ ($1 -ge 91) || ($1 -lt 50) ]] && maxti='100000' # wider plot. # 1987: if [[ $1 = 87 ]] then awk '{ stat = $1 "'"$1"'"; # name of status. $1 = 0; # reuse $1 as base number. tax = 0; split ("0 0.11 0.15 0.28 0.35 0.385", rate); # Set upper bound in constants array: for (step = 2; step <= 5; ++step) if ($step >= '$maxti') break; $step = '$maxti'; # replace or append. $(step + 1) = '$maxti' + 1; print ".", 0, 0 > stat; for (step = 2; $step <= '$maxti'; ++step) { tax += (rate [step]) * ($step - $(step - 1)); print ".", $step, tax > stat; } }' # 1988 - 1990: elif [[ ($1 = 88) || ($1 = 89) || ($1 = 90) ]] then awk '{ stat = $1 "'"$1"'"; # name of status. $1 = 0; # reuse $1 as base number. tax = 0; split ("0 0.15 0.28 0.33 0", rate); # Set upper bound in constants array: for (step = 2; step <= 4; ++step) if ($step >= '$maxti') break; if (step == 5) # top constant is less than $maxti. { print "'"$0"': warning: inaccurate plot for status", \ stat, "above $" $4; } $step = '$maxti'; # replace or append. $(step + 1) = '$maxti' + 1; print ".", 0, 0 > stat; for (step = 2; $step <= '$maxti'; ++step) { tax += (rate [step]) * ($step - $(step - 1)); print ".", $step, tax > stat; } }' # 1991 - 1992: elif [[ ($1 = 91) || ($1 = 92) ]] then awk '{ stat = $1 "'"$1"'"; # name of status. $1 = 0; # reuse $1 as base number. tax = 0; split ("0 0.15 0.28 0.31", rate); # Set upper bound in constants array: for (step = 2; step <= 3; ++step) if ($step >= '$maxti') break; $step = '$maxti'; # replace or append. $(step + 1) = '$maxti' + 1; print ".", 0, 0 > stat; for (step = 2; $step <= '$maxti'; ++step) { tax += (rate [step]) * ($step - $(step - 1)); print ".", $step, tax > stat; } }' # 1993 - 2000: elif [[ ($1 -ge 93) || ($1 = 00) ]] then awk '{ stat = $1 "'"$1"'"; # name of status. $1 = 0; # reuse $1 as base number. tax = 0; split ("0 0.15 0.28 0.31 0.36 0.396", rate); # Set upper bound in constants array: for (step = 2; step <= 5; ++step) if ($step >= '$maxti') break; $step = '$maxti'; # replace or append. $(step + 1) = '$maxti' + 1; print ".", 0, 0 > stat; for (step = 2; $step <= '$maxti'; ++step) { tax += (rate [step]) * ($step - $(step - 1)); print ".", $step, tax > stat; } }' # 2001: elif [[ $1 = 01 ]] then awk '{ stat = $1 "'"$1"'"; # name of status. $1 = 0; # reuse $1 as base number. tax = 0; # See file header comments: split ("0 0.15 0.275 0.305 0.355 0.391", rate); # Set upper bound in constants array: for (step = 2; step <= 5; ++step) if ($step >= '$maxti') break; $step = '$maxti'; # replace or append. $(step + 1) = '$maxti' + 1; print ".", 0, 0 > stat; for (step = 2; $step <= '$maxti'; ++step) { tax += (rate [step]) * ($step - $(step - 1)); print ".", $step, tax > stat; } }' # 2002: else awk '{ stat = $1 "'"$1"'"; # name of status. $1 = 0; # reuse $1 as base number. tax = 0; # See file header comments: split ("0 0.10 0.15 0.27 0.30 0.35 0.386", rate); # Set upper bound in constants array: for (step = 2; step <= 6; ++step) if ($step >= '$maxti') break; $step = '$maxti'; # replace or append. $(step + 1) = '$maxti' + 1; print ".", 0, 0 > stat; for (step = 2; $step <= '$maxti'; ++step) { tax += (rate [step]) * ($step - $(step - 1)); print ".", $step, tax > stat; } }' fi # PLOT RATE CHART: # # Filenames, hence curves, are ordered highest to lowest so they # look rational on a monochrome display: if [[ -z "$TAXRECURSE" ]] # else don't plot now. then if [[ $# = 1 ]] # single year only: then [[ $1 -lt 50 ]] && century='20' || century='19' dataplot -Gx -t0 $spool $device $driver \ "US Federal Tax Rates, $century$1" \ 'Based on filing status' 'Taxable Income' 'Tax' \ ms* s* hh* mj* else # multiple years: [[ $1 -lt 50 ]] && century1='20' || century1='19' [[ $2 -lt 50 ]] && century2='20' || century2='19' dataplot -Gx -t0,1,0,1,0,1,0,1 -c1,1,2,2,3,3,4,4 \ $spool $device $driver \ "US Federal Tax Rates, $century1$1 + $century2$2"\ 'Based on filing status' 'Taxable Income' 'Tax' \ ms* s* hh* mj* fi fi cd .. # so $plotdir is removable. # Unfortunately "trap" doesn't work: [[ -n "$TAXRECURSE" ]] || rm -r $plotdir fi