Functions for working with the idealized calendar of Planet Xhilr
リビジョン | bc60507b8572deb44261417ef6d3e034619bf296 (tree) |
---|---|
日時 | 2017-06-13 17:53:37 |
作者 | Joel Matthew Rees <joel.rees@gmai...> |
コミッター | Joel Matthew Rees |
progression
@@ -70,21 +70,33 @@ | ||
70 | 70 | ( fig-Forth used first three character + length significance in symbol tables. ) |
71 | 71 | |
72 | 72 | |
73 | -( UM*, FM/MOD, and S>D are already there in most modern Forths. ) | |
74 | -( These definitions are only for ancient Forths, ) | |
73 | +( UM*, FM/MOD, S>D, 2DUP, and D- are already there in most modern Forths. ) | |
74 | +( These definitions are only for ancient Forths, without the full set loaded, ) | |
75 | 75 | ( especially pre-1983 fig and bif-c. ) |
76 | 76 | ( Un-comment them if you see errors like ) |
77 | 77 | ( UM* ? err # 0 ) |
78 | 78 | ( from PRMONTH or thereabouts. ) |
79 | 79 | |
80 | -( : UM* U* ; ) ( modern name for unsigned mixed multiply ) | |
80 | +: UM* U* ; ( modern name for unsigned mixed multiply ) | |
81 | 81 | |
82 | 82 | ( This is a cheat! Behavior is not well defined for negative numbers, ) |
83 | 83 | ( but we don't do negatives here. ) |
84 | 84 | ( So this is just sloppy renaming in a sloppy fashion: ) |
85 | -( : FM/MOD M/MOD DROP ; ) ( unsigned division with modulo remainder ) | |
85 | +: FM/MOD M/MOD DROP ; ( unsigned division with modulo remainder ) | |
86 | 86 | |
87 | -( : S>D S->D ; ) ( Modern name for single-to-double. ) | |
87 | +: S>D S->D ; ( Modern name for single-to-double. ) | |
88 | + | |
89 | +: 2DUP OVER OVER ; ( d --- d d : DUPlicate top double word on stack. ) | |
90 | + | |
91 | +: 2DROP DROP DROP ; ( d --- : DROP a double, for readability. ) | |
92 | + | |
93 | +: D- DMINUS D+ ; ( d1 d2 --- d : Difference of two doubles. ) | |
94 | +( : D- DNEGATE D+ ( d1 d2 --- d : Difference of two doubles, if no DMINUS. ) | |
95 | + | |
96 | +( : R@ R ; ( Modern name for copy top of return stack. ) | |
97 | + | |
98 | + | |
99 | +( From here, we should load okay in modern Forths. ) | |
88 | 100 | |
89 | 101 | ( Showing the above in infix won't help. ) |
90 | 102 |
@@ -92,21 +104,46 @@ SP@ SP@ - ABS CONSTANT CELLWIDTH | ||
92 | 104 | ( Infix won't help here, either, but I can try to explain: ) |
93 | 105 | ( CELLWIDTH = absolute-value-of difference-between SP-without-pointer and SP-with-pointer. ) |
94 | 106 | |
107 | +( Infix will be confusing here, too. ) | |
108 | +: D@ ( adr --- d ) ( fetch a double ) | |
109 | + DUP CELLWIDTH + @ ( LS-CELL ) | |
110 | + SWAP @ ( MS-CELL ) | |
111 | +; | |
112 | + | |
113 | +( Infix will be confusing here, too. ) | |
114 | +: D! ( d adr --- ) ( store a double ) | |
115 | + SWAP OVER ! ( MS-CELL ) | |
116 | + CELLWIDTH + ! ( MS-CELL ) | |
117 | +; | |
118 | + | |
95 | 119 | ( Semi-simulate local variables with the ability to fetch and store relative to top of stack. ) |
96 | 120 | |
97 | 121 | ( Infix will be confusing here, too. ) |
98 | 122 | : LC@ ( index -- sp[ix] ) ( 0 is top. PICK is available on many modern Forths. ) |
99 | - 1 + CELLWIDTH * ( Skip over the stack address on stack. ) | |
123 | + 1 + CELLWIDTH * ( Skips over the index on stack. ) | |
100 | 124 | SP@ + @ ( Assumes push-down stack. Will fail on push-up. ) |
101 | 125 | ; |
102 | 126 | |
103 | 127 | ( Infix will be confusing here, too. ) |
104 | 128 | : LC! ( n index -- ) ( 0 is top. Just store. This is not ROLL. ) |
105 | - 2 + CELLWIDTH * ( Index and stack address are extra on stack during calculation. ) | |
129 | + 2 + CELLWIDTH * ( Skips over index and value on stack. ) | |
106 | 130 | SP@ + ( Assumes push-down stack. ) |
107 | 131 | ! ( *** Will fail in MISERABLE ways on push-up stacks! *** ) |
108 | 132 | ; |
109 | 133 | |
134 | +( Infix will be confusing here, too. ) | |
135 | +: DLC@ ( index -- sp[ix] ) ( 0 is top. PICK is available on many modern Forths. ) | |
136 | + 1 + CELLWIDTH * ( Skips over the index on stack. ) | |
137 | + SP@ + D@ ( Assumes push-down stack. Will fail on push-up. ) | |
138 | +; | |
139 | + | |
140 | +( Infix will be confusing here, too. ) | |
141 | +: DLC! ( d index -- ) ( 0 is top. Just store. This is not ROLL. ) | |
142 | + 3 + CELLWIDTH * ( Skips over index and double value on stack. ) | |
143 | + SP@ + ( Assumes push-down stack. ) | |
144 | + D! ( *** Will fail in MISERABLE ways on push-up stacks! *** ) | |
145 | +; | |
146 | + | |
110 | 147 | ( Make things easier to read. ) |
111 | 148 | ( Infix will be confusing here, too. ) |
112 | 149 |
@@ -122,6 +159,8 @@ SP@ SP@ - ABS CONSTANT CELLWIDTH | ||
122 | 159 | : PSNUM ( number -- ) |
123 | 160 | 0 .R ; |
124 | 161 | |
162 | +: PSDNUM ( number -- ) | |
163 | + 0 D.R ; | |
125 | 164 | |
126 | 165 | ( Do it in integers! ) |
127 | 166 |
@@ -156,12 +195,18 @@ MCYCLE MP2LCYC * CONSTANT 2LCYCLE ( years in double long cycle, should be 686 ) | ||
156 | 195 | |
157 | 196 | DPSKIPYEAR SCYCLE * RDSCYCLE + CONSTANT DPSCYCLE ( whole days per 7 year cycle ) |
158 | 197 | ( DPSCYCLE = DPSKIPYEAR × SCYCLE + RDSCYCLE ) |
159 | -( DPSCYCLE SPMCYC * CONSTANT DPMCYCLE ) | |
198 | +( DPSCYCLE SPMCYC * DCONSTANT DPMCYCLE ) | |
160 | 199 | ( DPMCYCLE = DPSCYCLE × SPMCYC ) |
161 | -( DPMCYCLE MP2LCYC * CONSTANT DP2LCYCLE ) | |
200 | +( DPMCYCLE MP2LCYC * DCONSTANT DP2LCYCLE ) | |
162 | 201 | ( DP2LCYCLE = DPMCYCLE × MP2LCYC ) |
163 | -( DPMCYCLE and DP2LCYCLE would overflow on 16 bit math CPUs. ) | |
164 | -( No particular problem on 32 bit CPUs. | |
202 | +( DPMCYCLE and DP2LCYCLE would overflow on 16-bit math CPUs. ) | |
203 | +( No particular problem on 32 bit CPUs. Need DCONSTANT for 16-bit CPUs. ) | |
204 | +( But we need the constants more than we need to puzzle out ) | |
205 | +( the differences between CREATE DOES> and <BUILDS DOES>. ) | |
206 | +: DPMCYCLE DPSCYCLE SPMCYC UM* ; ( Takes a little extra time this way. ) | |
207 | +( DPMCYCLE is actually 34566, so the high CELL is 0, ) | |
208 | +( but the low CELL must be treated as unsigned. ) | |
209 | +: DP2LCYCLE DPMCYCLE DROP MP2LCYC UM* ; | |
165 | 210 | |
166 | 211 | RDSCYCLE SPMCYC * 1 - CONSTANT RDMCYCLE ( remainder days in medium cycle ) |
167 | 212 | ( RDMCYCLE = RDSCYCLE × SPMCYC - 1 ) |
@@ -193,54 +238,54 @@ MDENOMINATOR 2 / CONSTANT MROUNDFUDGE | ||
193 | 238 | ( Hopefully, the comments and explanations will provide enough clues. ) |
194 | 239 | |
195 | 240 | ( Sum up the days of the months in a year. ) |
196 | -: SU1MONTH ( startfractional startdays -- endfractional enddays ) | |
197 | - FDMONTH + ( Add the whole part. ) | |
198 | - SWAP ( Make the fractional part available to work on. ) | |
241 | +: SU1MONTH ( startfractional dstartdays -- endfractional denddays ) | |
242 | + FDMONTH S>D D+ ( Add the whole part. ) | |
243 | + ROT ( Make the fractional part available to work on. ) | |
199 | 244 | MNUMERATOR + ( Add the fractional part. ) |
200 | 245 | DUP MDENOMINATOR < ( Have we got a whole day yet? ) |
201 | 246 | IF |
202 | - SWAP ( No, restore stack order for next pass. ) | |
247 | + ROT ROT ( No, restore stack order for next pass. ) | |
203 | 248 | ELSE |
204 | 249 | MDENOMINATOR - ( Take one whole day from the fractional part. ) |
205 | - SWAP 1+ ( Restore stack and add the day carried in. ) | |
250 | + ROT ROT 1 S>D D+ ( Restore stack and add the day carried in. ) | |
206 | 251 | ENDIF |
207 | 252 | ; |
208 | 253 | |
209 | -: PRMONTH ( fractional days -- fractional days ) | |
210 | - SPACE DUP PSNUM POINT ( whole days ) | |
211 | - OVER 1000 UM* ( Fake three digits of decimal precision. ) | |
212 | - MROUNDFUDGE 0 D+ ( Round the bottom digit. ) | |
254 | +: PRMONTH ( fractional ddays -- fractional ddays ) | |
255 | + SPACE 2DUP PSDNUM POINT ( whole days ) | |
256 | + 2 LC@ 1000 UM* ( Fake three digits of decimal precision. ) | |
257 | + MROUNDFUDGE S>D D+ ( Round the bottom digit. ) | |
213 | 258 | MDENOMINATOR FM/MOD ( Divide, or evaluate the fraction. ) |
214 | 259 | S>D <# # # # #> ( Formatting puts most significant digits in buffer first. ) |
215 | 260 | TYPE ( Fake decimal output. ) |
216 | 261 | DROP SPACE |
217 | 262 | ; |
218 | 263 | |
219 | -: SH1IDEALYEAR ( year daysmemory fractional days -- year daysmemory fractional days ) | |
264 | +: SH1IDEALYEAR ( year ddaysmemory fractional ddays -- year ddaysmemory fractional ddays ) | |
220 | 265 | CR |
221 | 266 | 12 0 DO |
222 | - 3 LC@ PSNUM SPACE ( year ) | |
267 | + 5 LC@ PSNUM SPACE ( year ) | |
223 | 268 | I PSNUM COLON SPACE |
224 | 269 | SU1MONTH |
225 | - DUP 3 LC@ - ( difference in days ) | |
226 | - 2 LC@ ( ceiling ) IF 1+ ENDIF | |
227 | - DUP PSNUM SPACE ( show theoretical days in month ) | |
228 | - 3 LC@ + ( sum of days ) | |
229 | - LPAREN DUP PSNUM COMMA SPACE | |
230 | - 2 LC! ( update ) | |
270 | + 2DUP 5 DLC@ D- ( difference in days ) | |
271 | + 4 LC@ ( push difference to ceiling ) IF 1. D+ ENDIF | |
272 | + 2DUP PSDNUM SPACE ( show theoretical days in month ) | |
273 | + 5 DLC@ D+ ( sum of days: adjusted difference plus daysmemory ) | |
274 | + LPAREN 2DUP PSDNUM COMMA SPACE | |
275 | + 3 DLC! ( update daysmemory ) | |
231 | 276 | PRMONTH RPAREN CR |
232 | 277 | LOOP |
233 | 278 | ; |
234 | 279 | |
235 | 280 | : SHOWIDEALMONTHS ( years -- ) |
236 | 281 | >R |
237 | - 0 0 0 0 ( year, daysmemory, fractional, days ) | |
282 | + 0 0. 0 0. ( year, ddaysmemory, fractional, ddays ) | |
238 | 283 | R> 0 DO |
239 | 284 | CR |
240 | 285 | SH1IDEALYEAR |
241 | - 3 LC@ 1+ 3 LC! | |
286 | + 5 LC@ 1+ 5 LC! | |
242 | 287 | LOOP |
243 | - DROP DROP DROP DROP | |
288 | + 2DROP DROP 2DROP DROP | |
244 | 289 | ; |
245 | 290 | |
246 | 291 | 0 CONSTANT SKMONTH |
@@ -275,19 +320,23 @@ MDENOMINATOR 2 / CONSTANT MROUNDFUDGE | ||
275 | 320 | ( On ancient Forths, VARIABLE wants an initial value. We give it a zero. ) |
276 | 321 | ( The zero stays around forever on modern Forths, or until you drop it. ) |
277 | 322 | 0 VARIABLE DIMARRAY ( Days In Months array ) |
278 | - 30 DIMARRAY ! ( 1st month ) | |
279 | - 29 , | |
280 | - 30 , | |
281 | - 29 , | |
282 | - 29 , | |
283 | - 30 , | |
284 | - 29 , | |
285 | - 30 , | |
286 | - 29 , | |
287 | - 29 , | |
288 | - 30 , | |
289 | - 29 , | |
290 | - 0 , | |
323 | +( Modern Forths don't initialize, will leave 0 on stack. ) | |
324 | + | |
325 | +CELLWIDTH - ALLOT ( Back up to store values. ) | |
326 | + | |
327 | +30 C, | |
328 | +29 C, | |
329 | +30 C, | |
330 | +29 C, | |
331 | +29 C, | |
332 | +30 C, | |
333 | +29 C, | |
334 | +30 C, | |
335 | +29 C, | |
336 | +29 C, | |
337 | +30 C, | |
338 | +29 C, | |
339 | + 0 , | |
291 | 340 | |
292 | 341 | : DIMONTH ( year month -- days ) |
293 | 342 | DUP 0 < 0= |
@@ -295,14 +344,149 @@ MDENOMINATOR 2 / CONSTANT MROUNDFUDGE | ||
295 | 344 | IF |
296 | 345 | DROP DROP 0 ( Out of range. No days. ) |
297 | 346 | ELSE |
298 | - DUP CELLWIDTH * DIMARRAY + @ ( Get the basic days. ) | |
347 | + DUP DIMARRAY + C@ ( Get the basic days. ) | |
299 | 348 | SWAP SKMONTH = ( true if skip month ) |
300 | 349 | ROT ISKIPYEAR AND ( true if skip month of skip year ) |
301 | 350 | 1 AND - ( Subtrahend is 1 only if skip month of skip year. ) |
302 | 351 | ENDIF |
303 | 352 | ; |
304 | 353 | |
305 | -: SH1YEAR ( year daysmemory fractional days -- year daysmemory fractional days ) | |
354 | +: SH1YEAR ( year ddaysmemory fractional ddays -- year ddaysmemory fractional ddays ) | |
355 | + CR | |
356 | + 12 0 DO | |
357 | + 5 LC@ PSNUM SPACE ( year ) | |
358 | + I PSNUM COLON SPACE | |
359 | + SU1MONTH ( ideal month ) | |
360 | + 5 LC@ I DIMONTH ( real month ) | |
361 | + DUP PSNUM SPACE ( show days in month ) | |
362 | + S>D 5 DLC@ D+ ( sum of days ) | |
363 | + LPAREN 2DUP PSDNUM COMMA SPACE | |
364 | + 3 DLC! ( update ) | |
365 | + PRMONTH RPAREN CR | |
366 | + LOOP | |
367 | +; | |
368 | + | |
369 | +: SHOWMONTHS ( years -- ) | |
370 | + >R | |
371 | + 0 0. 0 0. ( year, ddaysmemory, fractional, ddays ) | |
372 | + R> 0 DO | |
373 | + CR | |
374 | + SH1YEAR | |
375 | + 5 LC@ 1+ 5 LC! | |
376 | + LOOP | |
377 | + 2DROP DROP 2DROP DROP | |
378 | +; | |
379 | + | |
380 | +( Ancient Forths do not have standard WORDs, ) | |
381 | +( and that makes it hard to have portable arrays of strings for those Forths. ) | |
382 | +: TPWDAY ( n --- ) ( TYPE the name of the day of the week. ) | |
383 | + DUP 0 = IF ." Sunday " ELSE ( Fake case format to line the strings up. ) | |
384 | + DUP 1 = IF ." Moonsday" ELSE | |
385 | + DUP 2 = IF ." Aegisday" ELSE | |
386 | + DUP 3 = IF ." Gefnday" ELSE | |
387 | + DUP 4 = IF ." Freyday" ELSE | |
388 | + DUP 5 = IF ." Tewesday" ELSE | |
389 | + DUP 6 = IF ." Vensday" ELSE ( DUP here allows final single DROP. ) | |
390 | + ." ??? " | |
391 | + THEN | |
392 | + THEN | |
393 | + THEN | |
394 | + THEN | |
395 | + THEN | |
396 | + THEN | |
397 | + THEN | |
398 | + DROP ; | |
399 | + | |
400 | +: TPMONTH ( n --- ) ( TYPE the name of the month. ) | |
401 | +( DUP 6 < IF * Use this if the compile stack overflows. ) | |
402 | + DUP 0 = IF ." Time-division" ELSE ( Fake case format to line the strings up. ) | |
403 | + DUP 1 = IF ." Deep-winter " ELSE | |
404 | + DUP 2 = IF ." War-time " ELSE | |
405 | + DUP 3 = IF ." Thaw-time " ELSE | |
406 | + DUP 4 = IF ." Rebirth " ELSE | |
407 | + DUP 5 = IF ." Brides-month" ELSE | |
408 | +( ." ???" ) | |
409 | +( THEN THEN THEN THEN THEN THEN ) | |
410 | +( ELSE ) | |
411 | + DUP 6 = IF ." Imperious " ELSE | |
412 | + DUP 7 = IF ." Senatorious " ELSE | |
413 | + DUP 8 = IF ." False-summer" ELSE | |
414 | + DUP 9 = IF ." Harvest " ELSE | |
415 | + DUP 10 = IF ." Gratitude " ELSE | |
416 | + DUP 11 = IF ." Winter-month" ELSE ( DUP here allows final single DROP. ) | |
417 | + ." ???" | |
418 | + THEN | |
419 | + THEN | |
420 | + THEN | |
421 | + THEN | |
422 | + THEN | |
423 | + THEN | |
424 | + ( For 0 to 5: ) | |
425 | + THEN | |
426 | + THEN | |
427 | + THEN | |
428 | + THEN | |
429 | + THEN | |
430 | + THEN | |
431 | +( THEN ) | |
432 | + DROP ; | |
433 | + | |
434 | + | |
435 | + | |
436 | +( Below here is scratch work I'm leaving for my notes. ) | |
437 | +( It can be deleted. ) | |
438 | + | |
439 | +: oldSU1MONTH ( startfractional startdays -- endfractional enddays ) | |
440 | + FDMONTH + ( Add the whole part. ) | |
441 | + SWAP ( Make the fractional part available to work on. ) | |
442 | + MNUMERATOR + ( Add the fractional part. ) | |
443 | + DUP MDENOMINATOR < ( Have we got a whole day yet? ) | |
444 | + IF | |
445 | + SWAP ( No, restore stack order for next pass. ) | |
446 | + ELSE | |
447 | + MDENOMINATOR - ( Take one whole day from the fractional part. ) | |
448 | + SWAP 1+ ( Restore stack and add the day carried in. ) | |
449 | + ENDIF | |
450 | +; | |
451 | + | |
452 | +: oldPRMONTH ( fractional days -- fractional days ) | |
453 | + SPACE DUP PSNUM POINT ( whole days ) | |
454 | + OVER 1000 UM* ( Fake three digits of decimal precision. ) | |
455 | + MROUNDFUDGE 0 D+ ( Round the bottom digit. ) | |
456 | + MDENOMINATOR FM/MOD ( Divide, or evaluate the fraction. ) | |
457 | + S>D <# # # # #> ( Formatting puts most significant digits in buffer first. ) | |
458 | + TYPE ( Fake decimal output. ) | |
459 | + DROP SPACE | |
460 | +; | |
461 | + | |
462 | +: oldSH1IDEALYEAR ( year daysmemory fractional days -- year daysmemory fractional days ) | |
463 | + CR | |
464 | + 12 0 DO | |
465 | + 3 LC@ PSNUM SPACE ( year ) | |
466 | + I PSNUM COLON SPACE | |
467 | + oldSU1MONTH | |
468 | + DUP 3 LC@ - ( difference in days ) | |
469 | + 2 LC@ ( ceiling ) IF 1+ ENDIF | |
470 | + DUP PSNUM SPACE ( show theoretical days in month ) | |
471 | + 3 LC@ + ( sum of days ) | |
472 | + LPAREN DUP PSNUM COMMA SPACE | |
473 | + 2 LC! ( update ) | |
474 | + oldPRMONTH RPAREN CR | |
475 | + LOOP | |
476 | +; | |
477 | + | |
478 | +: oldSHOWIDEALMONTHS ( years -- ) | |
479 | + >R | |
480 | + 0 0 0 0 ( year, daysmemory, fractional, days ) | |
481 | + R> 0 DO | |
482 | + CR | |
483 | + oldSH1IDEALYEAR | |
484 | + 3 LC@ 1+ 3 LC! | |
485 | + LOOP | |
486 | + DROP DROP DROP DROP | |
487 | +; | |
488 | + | |
489 | +: oldSH1YEAR ( year daysmemory fractional days -- year daysmemory fractional days ) | |
306 | 490 | CR |
307 | 491 | 12 0 DO |
308 | 492 | 3 LC@ PSNUM SPACE ( year ) |
@@ -317,7 +501,7 @@ MDENOMINATOR 2 / CONSTANT MROUNDFUDGE | ||
317 | 501 | LOOP |
318 | 502 | ; |
319 | 503 | |
320 | -: SHOWMONTHS ( years -- ) | |
504 | +: oldSHOWMONTHS ( years -- ) | |
321 | 505 | >R |
322 | 506 | 0 0 0 0 ( year, daysmemory, fractional, days ) |
323 | 507 | R> 0 DO |
@@ -327,10 +511,6 @@ MDENOMINATOR 2 / CONSTANT MROUNDFUDGE | ||
327 | 511 | LOOP |
328 | 512 | DROP DROP DROP DROP |
329 | 513 | ; |
330 | - | |
331 | - | |
332 | -( Below here is scratch work I'm leaving for my notes. ) | |
333 | -( It can be deleted. ) | |
334 | 514 | |
335 | 515 | : V2-SHOWMONTHS ( years -- ) |
336 | 516 | >R |