\ Find Easter Sunday for a Given Year.
\ Algorithm by Lilius & Clavius (16th Century)
\ Comments by Knuth - Art of Computer Programming 1.3.2 ex 14 (2nd set)
\ Code by Charlton - 21Apr95.
[UNDEFINED] easterSunday [IF]
\ Algorithm E (Date of Easter) )
\ Let Y be the year for which the date of Easter be required.
\ E1. [Golden number] Set G <- (y mod 19) + 1. (G is the so called
\ "golden number" of the year in the 19-year Metonic cycle)
: goldenNumber ( y--g ) 19 MOD 1+ ;
\ E2. [Century] Set C <- [Y/100] + 1. (When Y is not a multiple of 100,
\ C is the century number; ie, 1984 is in the twentieth century.)
: century ( y--c ) 100 / 1+ ;
\ E3. [Corrections] Set X <- [3C/4] - 12, Z <- [(8C + 5)/25] - 5. (X
\ is the number of years, such as 1900, in which leap year was
\ dropped in order to keep in step with the sun. Z is a special
\ correction designed to synchronize Easter with the moon's orbit.)
: corrections ( c--x z ) DUP 3 * 4 / 12 -
SWAP 8 * 5 + 25 / 5 - ;
\ E4. [Find Sunday] Set d <- [5Y/4] - X - 10. [March ((-D) mod 7)
\ actually will be a Sunday.] )
: findSunday ( x y--d ) 5 * 4 / SWAP - 10 - ;
\ E5. [Epact] Set E <- (11G + 20 + Z - X) mod 30. If E = 25 and the
\ golden number G is greater than 11, or if E = 24, then increase
\ E by 1. (E is the so-called "epact," which specifies when a
\ full moon occurs.)
: epact ( z x g--e ) DUP >R 11 * 20 +
ROT + SWAP - 30 MOD
DUP 25 = R> 11 > AND
OVER 24 = OR
IF 1+ THEN ;
\ E6. [Find full moon] Set N <- 44 - E. If N < 21 then set N <- N + 30.
\ (Easter is supposedly the "fisrt Sunday following the first full
\ moon which occurs on or after March 21." Actually pertubations in
\ the moon's orbit do not make this strictly true, but we are
\ concerned here with the "calendar moon" rather than the actual
\ moon. The Nth of March is a calendar full moon.)
: findFullMoon ( e--n ) 44 SWAP -
DUP 21 < IF 30 + THEN ;
\ E7. [Advance to sunday] Set N <- N + 7 - ((D + N) mod 7).
: advanceToSunday ( n d--n ) OVER + 7 MOD - 7 + ;
\ E8. [Get month] If N > 31, the date is (N - 31)APRIL; otherwise the
\ date is N MARCH. )
: getMonth ( n--d m ) DUP 31 > IF 31 - 4 ELSE 3 THEN ;
: easterSunday ( y--d m y) DUP >R goldenNumber
R@ century corrections
OVER R@ findSunday >R
SWAP ROT epact findFullMoon
R> advanceToSunday
getMonth R> ;
[DEFINED] 4TH# [IF]
hide goldenNumber
hide century
hide corrections
hide findSunday
hide epact
hide findFullMoon
hide advanceToSunday
hide getMonth
[THEN]
[THEN]
|