• R/O
  • HTTP
  • SSH
  • HTTPS

Commit

Tags
No Tags

Frequently used words (click to add to your profile)

javac++androidlinuxc#windowsobjective-ccocoa誰得qtpythonphprubygameguibathyscaphec計画中(planning stage)翻訳omegatframeworktwitterdomtestvb.netdirectxゲームエンジンbtronarduinopreviewer

Functions for working with the idealized calendar of Planet Xhilr


Commit MetaInfo

Revisiónbc537f1f710d466134764828000b7a88aa9fe7e7 (tree)
Tiempo2017-06-13 17:28:36
AutorJoel Matthew Rees <joel.rees@gmai...>
CommiterJoel Matthew Rees

Log Message

pursuing two separate paths

Cambiar Resumen

Diferencia incremental

--- a/econcalcmonths.fs
+++ b/econcalcmonths.fs
@@ -39,7 +39,7 @@
3939 ( For ancient, especially pre-1983 fig, Forths: )
4040 ( Do not use these in modern Forths like gforth. )
4141 : UM* U* ;
42-: FM/MOD M/MOD DROP ; ( Cheat! Behavior is not well defined for negative numbers. )
42+: FM/MOD M/MOD DROP ; ( Cheat! fm/mod is supposed to be floored, not unsigned. )
4343 ( This is just renaming in a sloppy fashion, )
4444 ( to accomodate the difference between ancient fig-Forths and modern Forths. )
4545 ( Showing it in infix won't help. )
--- /dev/null
+++ b/econmonths.fs
@@ -0,0 +1,363 @@
1+(
2+// Forth programs for calculating idealized lengths of months
3+// relative to skip years
4+// for the world of Bobbie, Karel, Dan, and Kristie,
5+//
6+// by Joel Matthew Rees, winter/spring 2017.
7+// Copyright 2017, Joel Matthew Rees
8+//
9+// Permission granted to use for personal entertainment only.
10+// -- You really shouldn't write programs like this on modern computers.
11+//
12+// http://joel-rees-economics.blogspot.com/2017/03/soc500-03-08-calendar-math.html
13+// http://joel-rees-economics.blogspot.com/2017/03/soc500-03-09-calculating-skip-years.html
14+//
15+// Novel here:
16+// http://joel-rees-economics.blogspot.com/2017/01/soc500-00-00-toc.html
17+//
18+//
19+// Save as "econcalcmonth.fs"
20+//
21+// In gforth and most modern or emulated environments,
22+// just paste it into the terminal of a running Forth session.
23+//
24+// Run it with
25+// 7 SHOWMONTHS
26+// for seven years, etc.
27+)
28+
29+( Using integer math. )
30+( Forth expression syntax is mostly postfix. )
31+( Only the definition syntax is prefix or infix. )
32+( I've added comments with equivalent infix expressions to help those unfamiliar with Forth. )
33+
34+
35+( Using baroque identifiers for ancient Forths. )
36+( fig-Forth used first three character significant symbol tables. )
37+
38+
39+( For ancient, especially pre-1983 fig, Forths: )
40+( Do not use these in modern Forths like gforth. )
41+: UM* U* ;
42+: FM/MOD M/MOD DROP ; ( Cheat! Behavior is not well defined for negative numbers. )
43+( This is just renaming in a sloppy fashion, )
44+( to accomodate the difference between ancient fig-Forths and modern Forths. )
45+( Showing it in infix won't help. )
46+: S>D S->D ; ( Old fashioned name for single-to-double. )
47+
48+( Semi-simulate local variables. )
49+SP@ SP@ - ABS CONSTANT CELLWIDTH
50+( Infix won't help here, either, but I can try to explain: )
51+( CELLWIDTH = absolute-value-of difference-between SP-without-pointer and SP-with-pointer. )
52+
53+( Infix will be confusing here, too. )
54+: LC@ ( index -- sp[ix] ) ( 0 is top. PICK is available on many modern Forths. )
55+ 1 + CELLWIDTH * ( Skip over the stack address on stack. )
56+ SP@ + @ ( Assumes push-down stack. Will fail on push-up. )
57+;
58+
59+( Infix will be confusing here, too. )
60+: LC! ( n index -- ) ( 0 is top. Just store. This is not ROLL. )
61+ 2 + CELLWIDTH * ( Index and stack address are extra on stack during calculation. )
62+ SP@ + ( Assumes push-down stack. )
63+ ! ( *** Will fail in MISERABLE ways on push-up stacks! *** )
64+;
65+
66+( Make things easier to read. )
67+( Infix will be confusing here, too. )
68+
69+: PRCH EMIT ;
70+
71+: COMMA 44 PRCH ;
72+: COLON 58 PRCH ;
73+: POINT 46 PRCH ;
74+: LPAREN 40 PRCH ;
75+: RPAREN 41 PRCH ;
76+
77+( No trailing space. )
78+: PSNUM ( number -- )
79+ 0 .R ;
80+
81+
82+: NUMERATORS ( count -- )
83+DUP 1+ 0 DO
84+ I PSNUM COLON SPACE
85+ I 1000 * OVER / PSNUM COMMA ( 1000 times I, divided by count )
86+ SPACE LOOP
87+DROP ;
88+
89+: FRACTIONS ( count -- )
90+1 DO
91+ I NUMERATORS CR
92+LOOP ;
93+
94+
95+( Watch limits on 16 bit processors. )
96+( Do it in integers! )
97+
98+7 CONSTANT SCYCLE ( years in short cycle )
99+( SCYCLE = 7 )
100+
101+7 2 * CONSTANT SPMCYC ( short cycles in medium cycle )
102+( SPMCYC = 7 × 2 )
103+
104+SCYCLE SPMCYC * CONSTANT MCYCLE ( years in medium cycle, should be 98 )
105+( MCYCLE = SCYCLE × SPMCYC )
106+
107+7 7 * CONSTANT SPLCYC ( short cycles in single long cycle )
108+( SPLCYC = 7 × 7 )
109+
110+SCYCLE SPLCYC * CONSTANT LCYCLE ( years in single long cycle, should be 343 )
111+( LCYCLE = SCYCLE × SPLCYC )
112+
113+7 CONSTANT MP2LCYC ( medium cycles in double long cycle )
114+( MP2LCYC = 7 )
115+( MPLCYC would not be an integer: 3 1/2 )
116+
117+MCYCLE MP2LCYC * CONSTANT 2LCYCLE ( years in double long cycle, should be 686 )
118+( 2LCYCLE = MCYCLE × MP2LCYC )
119+
120+352 CONSTANT DPSKIPYEAR ( floor of days per year )
121+
122+
123+5 CONSTANT RDSCYCLE ( remainder days in short cycle )
124+
125+DPSKIPYEAR SCYCLE * RDSCYCLE + CONSTANT DPSCYCLE ( whole days per 7 year cycle )
126+( DPSCYCLE = DPSKIPYEAR × SCYCLE + RDSCYCLE )
127+( DPMCYCLE and DP2LCYCLE would overflow on 16 bit math CPUs. )
128+
129+RDSCYCLE SPMCYC * 1 - CONSTANT RDMCYCLE ( remainder days in medium cycle )
130+( RDMCYCLE = RDSCYCLE × SPMCYC - 1 )
131+
132+RDMCYCLE MP2LCYC * 2 + CONSTANT RD2LCYCLE ( remainder days in double long cycle -- odd number )
133+( RD2LCYCLE = RDMCYCLE × MP2LCYC + 2 )
134+( RD2LCYCLE / 2LCYCLE is fractional part of year. )
135+( Ergo, length of year is DPSKIPYEAR + RD2LCYCLE / 2LCYCLE, )
136+( or 352 485/686 days. )
137+
138+12 CONSTANT MPYEAR ( months per year )
139+
140+DPSKIPYEAR MPYEAR /MOD CONSTANT FDMONTH ( floor of days per month )
141+( FDMONTH = DPSKIPYEAR / MPYEAR )
142+CONSTANT FRMONTH ( floored minimum remainder days per month )
143+( FRMONTH = DPSKIPYEAR MOD MPYEAR )
144+
145+2LCYCLE MPYEAR * CONSTANT MDENOMINATOR ( denominator of month fractional part )
146+( MDENOMINATOR = 2LCYCLE × MPYEAR )
147+
148+FRMONTH 2LCYCLE * RD2LCYCLE + CONSTANT MNUMERATOR ( numerator of month fractional part )
149+( MNUMERATOR = FRMONTH × 2LCYCLE + RD2LCYCLE )
150+( Ergo, length of month is FDMONTH + MNUMERATOR / MDENOMINATOR, )
151+( or 29 3229/8232 days. )
152+
153+MDENOMINATOR 2 / CONSTANT MROUNDFUDGE
154+
155+( Infix will be confusing below here, as well. )
156+( Hopefully, the comments and explanations will provide enough clues. )
157+
158+( Sum up the days of the months in a year. )
159+: SU1MONTH ( startfractional startdays -- endfractional enddays )
160+ 29 + ( Add the whole part. )
161+ SWAP ( Make the fractional part available to work on. )
162+ MNUMERATOR + ( Add the fractional part. )
163+ DUP MDENOMINATOR < ( Have we got a whole day yet? )
164+ IF
165+ SWAP ( No, restore stack order for next pass. )
166+ ELSE
167+ MDENOMINATOR - ( Take one whole day from the fractional part. )
168+ SWAP 1+ ( Restore stack and add the day carried in. )
169+ ENDIF
170+;
171+
172+: PRMONTH ( fractional days -- fractional days )
173+ SPACE DUP PSNUM POINT ( whole days )
174+ OVER 1000 UM* ( Fake three digits of decimal precision. )
175+ MROUNDFUDGE 0 D+ ( Round the bottom digit. )
176+ MDENOMINATOR FM/MOD ( Divide, or evaluate the fraction. )
177+ S>D <# # # # #> ( Formatting puts most significant digits in buffer first. )
178+ TYPE ( Fake decimal output. )
179+ DROP SPACE
180+;
181+
182+: SH1IDEALYEAR ( year daysmemory fractional days -- year daysmemory fractional days )
183+ CR
184+ 12 0 DO
185+ 3 LC@ PSNUM SPACE ( year )
186+ I PSNUM COLON SPACE
187+ SU1MONTH
188+ DUP 3 LC@ - ( difference in days )
189+ 2 LC@ ( ceiling ) IF 1+ ENDIF
190+ DUP PSNUM SPACE ( show theoretical days in month )
191+ 3 LC@ + ( sum of days )
192+ LPAREN DUP PSNUM COMMA SPACE
193+ 2 LC! ( update )
194+ PRMONTH RPAREN CR
195+ LOOP
196+;
197+
198+: SHOWIDEALMONTHS ( years -- )
199+ >R
200+ 0 0 0 0 ( year, daysmemory, fractional, days )
201+ R> 0 DO
202+ CR
203+ SH1IDEALYEAR
204+ 3 LC@ 1+ 3 LC!
205+ LOOP
206+ DROP DROP DROP DROP
207+;
208+
209+ 0 CONSTANT SKMONTH
210+ 1 CONSTANT SK1SHORTCYC
211+ 4 CONSTANT SK2SHORTCYC
212+ 48 CONSTANT SKMEDIUMCYC
213+186 CONSTANT LPLONGCYC ( Must be short1 or short2 within the seven year cycle. )
214+
215+( Since skipyears are the exception, )
216+( we test for skipyears instead of leapyears. )
217+( Calendar system starts with year 0, not year 1. )
218+( Would need to check and adjust if the calendar started with year )
219+: ISKIPYEAR ( year -- flag )
220+ DUP MCYCLE MOD SKMEDIUMCYC =
221+ IF DROP -1 ( One specified extra skip year in medium cycle. )
222+ ELSE
223+ DUP SCYCLE MOD DUP
224+ SK1SHORTCYC =
225+ SWAP SK2SHORTCYC = OR ( Two specified skip years in short cycle, but ... )
226+ SWAP LCYCLE MOD LPLONGCYC = 0= AND ( not the specified exception in the long cycle. )
227+ ENDIF
228+;
229+
230+
231+( At this point, I hit a condundrum. )
232+( Modern "standard" Forths want uninitialized variables, )
233+( but ancient, especially fig-Forths want initialized variables. )
234+( The lower-level <BUILDS DOES> for fig is only partially part of the modern standard. )
235+( And CREATE is initialized as a CONSTANT in the fig-Forth, )
236+( but has no initial characteristic code or value in modern standards. )
237+( So. )
238+( On ancient Forths, VARIABLE wants an initial value. We give it one. )
239+( It stays around forever. )
240+0 VARIABLE DIMARRAY ( Days In Months array )
241+ 30 DIMARRAY ! ( 1st month )
242+ 29 ,
243+ 30 ,
244+ 29 ,
245+ 29 ,
246+ 30 ,
247+ 29 ,
248+ 30 ,
249+ 29 ,
250+ 29 ,
251+ 30 ,
252+ 29 ,
253+ 0 ,
254+
255+: DIMONTH ( year month -- days )
256+ DUP 0 < 0=
257+ OVER MPYEAR < AND 0=
258+ IF
259+ DROP DROP 0 ( Out of range. No days. )
260+ ELSE
261+ DUP CELLWIDTH * DIMARRAY + @ ( Get the basic days. )
262+ SWAP SKMONTH = ( true if skip month )
263+ ROT ISKIPYEAR AND ( true if skip month of skip year )
264+ 1 AND - ( Subtrahend is 1 only if skip month of skip year. )
265+ ENDIF
266+;
267+
268+: SH1YEAR ( year daysmemory fractional days -- year daysmemory fractional days )
269+ CR
270+ 12 0 DO
271+ 3 LC@ PSNUM SPACE ( year )
272+ I PSNUM COLON SPACE
273+ SU1MONTH ( ideal month )
274+ 3 LC@ I DIMONTH ( real month )
275+ DUP PSNUM SPACE ( show days in month )
276+ 3 LC@ + ( sum of days )
277+ LPAREN DUP PSNUM COMMA SPACE
278+ 2 LC! ( update )
279+ PRMONTH RPAREN CR
280+ LOOP
281+;
282+
283+: SHOWMONTHS ( years -- )
284+ >R
285+ 0 0 0 0 ( year, daysmemory, fractional, days )
286+ R> 0 DO
287+ CR
288+ SH1YEAR
289+ 3 LC@ 1+ 3 LC!
290+ LOOP
291+ DROP DROP DROP DROP
292+;
293+
294+
295+
296+( Below here is scratch work I'm leaving for my notes. )
297+( It isn't necessary to the above, and can be deleted. )
298+
299+: V2-SHOWIDEALMONTHS ( years -- )
300+ >R
301+ 0 0 0 ( daysmemory, fractional, days )
302+ R> 0 DO
303+ CR
304+ 12 0 DO
305+ J PSNUM SPACE ( year )
306+ I PSNUM COLON SPACE
307+ SU1MONTH
308+ DUP 3 LC@ - ( difference in days )
309+ 2 LC@ ( ceiling ) IF 1+ ENDIF
310+ DUP PSNUM SPACE ( show theoretical days in month )
311+ 3 LC@ + ( sum of days )
312+ LPAREN DUP PSNUM COMMA SPACE
313+ 2 LC! ( update )
314+ PRMONTH RPAREN CR
315+ LOOP
316+ LOOP
317+ DROP DROP DROP
318+;
319+
320+
321+( : ABS number -- absolute-value *** built in! ***
322+DUP 0< IF NEGATE THEN ; )
323+
324+: WITHIN1 ( n1 n2 -- flag )
325+ - ABS 1 <= ; ( n1 and n2 are within 1 of each other )
326+
327+( Negatives end in division by zero or infinite loop. )
328+: SQRT ( number -- square-root )
329+DUP IF ( square root of zero is zero. )
330+ ABS
331+ 2 ( initial guess )
332+ BEGIN
333+ OVER OVER / ( test guess by divide )
334+ OVER OVER - ABS 1 <= ( number guess quotient flag )
335+ IF ( number guess quotient )
336+ MIN -1 ( number result flag )
337+ ELSE
338+ OVER + 2 / ( number guess avg )
339+ SWAP OVER ( number avg guess avg )
340+ - 1 <= ( number avg flag ) ( Integer average will always be floored. )
341+ ENDIF
342+ UNTIL ( number result )
343+ SWAP DROP
344+ENDIF ;
345+
346+
347+353 CONSTANT DPYEAR ( nominal days per year )
348+
349+7 CONSTANT 7YEARS
350+
351+2 CONSTANT DS7CYCLE ( days short in seven year cycle )
352+
353+DPYEAR 7YEARS * DS7CYCLE - CONSTANT DP7YEAR ( whole days per 7 year cycle )
354+
355+7YEARS 7 2 * * CONSTANT 98YEARS
356+
357+98YEARS 7YEARS / DS7CYCLE * 1 + CONSTANT DS98CYCLE ( days short in 98 year cycle )
358+
359+98YEARS 7 * CONSTANT 686YEARS
360+
361+686YEARS 98YEARS / DS98CYCLE * 2 - CONSTANT DS686CYCLE ( days short in 686 year cycle )
362+
363+