Jump to content

Lee Stewart

+AtariAge Subscriber
  • Posts

    5,848
  • Joined

  • Last visited

Everything posted by Lee Stewart

  1. I updated the first post with Part 2. Soon, I will post the XB GPL source code for RND accompanied by a translation to ALC. ...lee
  2. The use of small caps for lowercase has been around for a long time. One of my favorite such fonts is Copperplate Gothic, which was developed in 1901. Small caps has many other uses than replacement of lowercase—see this interesting Wikipedia article on small caps. Small caps use apparently dates back to, at least, the 15th century. ...lee
  3. Thank you. Well, you might be disappointed. It may well be good enough for things TI-99/4A, but LCGs are, generally, not considered good PRNGs, anymore. Here is a comment made by the authors (W. H. Press, S. A. Teukolsky, W. T. Vetterling, B. P. Flannery) of Numerical Recipes: The Art of Scientific Computing, 3rd Edition, 2007, in Chapter 7, “Random Numbers”: With hindsight, it seems clear that the whole field of random number generation was mesmerized, for far too long, by the simple recurrence equation Ij+1 = aIj + c (mod m) (7.1.1) You can read the entire chapter (or book, for that matter) at the Numerical Recipes website. The above-referenced chapter as well as Chapter 3, “Random Numbers” in D. E. Knuth’s The Art of Computer Programming, Volume 2: Seminumerical Algorithms, 3rd Edition, 1998, are very good, comprehensive discussions and references on the subject. There are, certainly, tests for assessing the quality of PRNGs, but, again, my primary mission in this thread is to explain the XB PRNG. ...lee
  4. The principal reason for this thread is to explain what XB’s PRNG is and how it is calculated—mainly, because there seems to have been a lot of misunderstanding over the years about it. I (we) will certainly be comparing it to other PRNGs, but it is not the primary purpose. ...lee
  5. More or less—I have in mind to make some sort of comparison with TI Basic’s PRNG, which is discussed here, and TI Forth and fbForth’s PRNGs. As to the Geneve ABasic’s PRNG, it is virtually identical to XB, with GPL code converted to ALC. I understand per @InsaneMultitasker that Myarc Basic II was the source for Abasic, in which case the PRNG is certainly the same. I would need that source code to be sure. That is, currently, the extent of my comparison plans. ...lee
  6. It is my intention, here, to explain the details of the pseudorandom number generator (PRNG) in TI Extended Basic (XB). Over the next few days, I will expand this first post to include my analysis to date in an effort to make it as nearly complete as I am able. I will also make any updates relevant to further insights from the ensuing discussion: ═══XB RND function═══Part 1═══════════════════════22APR2024═══ XB’s PRNG is a linear congruential generator (LCG) with the following recurrence equation: xnew = (ax + c) mod m (1) where x = current seed, which is initialized at power-up to 335212624223 a = 14389820420821 c = 21132486540519 m = 1014 xnew = pseudorandom number (PRN) sought and the new seed for the next go-round. The above converts the above PRNG to the following equation: xnew = (14389820420821x + 21132486540519) mod 1014 (2) To preserve precision for the radix-100, floating point calculations, all of the above numbers were split into a least-significant half (LSH), with subscript 1, and a most-significant half (MSH), with subscript 2, such that x = 107x2 + x1 (3) a = 107a2 + a1 (4) c = 107c2 + c1 (5) which converts (1) to xnew = ((107a2 + a1)(107x2 + x1) + 107c2 + c1) mod 1014 xnew = (1014a2x2 + 107a2x1 + 107a1x2 + a1x1 +107c2 + c1) mod 1014 (6) At the very least, the first term drops out because 1014a2x2 mod 1014 = 0 simplifying (6) to xnew = (107a2x1 + 107a1x2 + a1x1 +107c2 + c1) mod 1014 (7) ═══XB RND function═══Part 2═══════════════════════26APR2024═══ Before we go any further, the following is among the comments the TI programmers included ahead of the code for calculating (7), with the t variables being intermediate programming results discussed later: Assumptions: All numbers are integers. Fractional parts are truncated. If the variables listed below start in the ranges specified, they will also end in the ranges specified. Constants: 0 ≤ a2 < 5 x 106 0 ≤ a1 < 5 x 106 0 ≤ c2 < 107 0 ≤ c1 < 107 Variables: 0 ≤ x2 < 107 0 ≤ x1 < 107 0 ≤ t1 ≤ 1014 0 ≤ t2 < 107 0 ≤ t3 ≤ 1014 0 ≤ t4 < 107 We must remember that the recurrence equation (7) starts and ends with integers. Because the recurrence equation preserves only the remainder of division by 1014, we must preserve all of the LS digits, but we don’t care about any MS digits above 1014, because they do not contribute to the remainder. To further aid preserving precision during calculation, the terms of (7) were grouped by their contributions to the MSH of xnew (x2new) and the LSH of xnew (x1new). All terms can contribute to x2new, but only a1x1 and c1 contribute to x1new. To see why this is so, consider that Each factor of the terms in the parenthetical expression contributes a factor up to 107 or as many as 7 digits to their term, All terms with 107 as factor cannot contribute to x1new because that factor guarantees the LSH is all zeros, leaving only a1x1 and c1 with digits that can appear in the x1new. FP operations that can result in more than 14 digits must be avoided or we will lose precision, i.e., digits will fall off the right side of the result. We must also avoid changing the radix-10 exponent of a 14-digit number from its even exponent to an odd one because this will shift the radix-100 number (centimal) one decimal digit right, resulting in a loss of precision from 14 digits to 13. The reason for this is that non-zero FP numbers are always stored in normalized centimal notation, i.e., the first centimal digit (equivalent to 2 decimal digits) in the mantissa must be 1..99. This means that, for an odd number of decimal digits before the centimal point, the first byte has only one significant decimal digit. This is what would happen with the shift in even to odd number of pre-centimal digits: Integer 12345678911234 is 12.345678911234 x 1006 in normalized centimal notation and >460C >2238 >4E5B >0C22 in hexadecimal. The first byte is the sign bit and the 7-bit, excess-64 exponent. If we multiplied this by 10-7, the result would be 1234567.891123, with the normalized result as 1.234567891123 x 1003 and stored as >4301 >172D >4359 >0B17, costing us the least significant decimal digit. Of course, had we started with 0 as the rightmost digit, it would not have mattered, as you will see below. If we define MSH(x) as a function meaning “MSH of x” and similarly define LSH(x), where x is a 14-digit integer, we have MSH(x) = int(10-7 x) (8) LSH(x) = x - 107 int(10-7 x) (9) xnew = (107 LSH(a2x1 + a1x2 + c2 + MSH(a1x1 + c1))) + LSH(a1x1 + c1)) mod 1014 from (7),(8),(9) \------------------x2new-------------------/ \----x1new----/ xnew = 107 x2new + x1new from (3) To make unwieldy equations more tractable and to incorporate the same intermediate variables (shown above) used by the TI programmers, t1 = a1x1 + c1 t2 = int(10-7 t1) x1new = (t1 - 107 t2) t3 = a2x1 + a1x2 + c2 + t2 t4 = int(10-7 t3) x2new = t3 - 107 t4 and using the maximum values from the assumptions above, t1 = a1x1 + c1 = 4999999(9999999) + 9999999 = 49999995000000 t2 = int(10-7 t1) = int(4999999.5000000) = 4999999 x1new = (t1 - 107 t2) = 49999995000000 - 49999990000000 = 5000000 t3 = a2x1 + a1x2 + c2 + t2 = 4999999(9999999) + 4999999(9999999) +9999999 + 4999999 = 99999985000000 t4 = int(10-7 t3) = int(9999998.5000000) = 9999998 x2new = t3 - 107 t4 = 99999985000000 - 99999980000000 = 5000000 which shows that at no time do the FP calculations exceed 14 digits, thus preserving precision, regardless of the values. Note that, even though there are a couple of places where a 14-digit number is multiplied by 10-7, which causes a loss of the last digit, that last digit is always 0. ...lee
  7. Here are all seven volumes—no calendars: YesterdaysNews.zip ...lee
  8. So sorry to hear this. My condolences to you and your family. ...lee
  9. Nearly finished with updating FBLOCKS. I need to burn an EPROM with the latest beta so I can test my revised Compact Flash utilities. Actually, the only one I had to modify was CFPMOUNT , which is the word that writes the mounted DSK volume to the compact flash so that the mount persists past power-down. The change was necessitated by the new DSRLNK described a few posts back and here. ...lee
  10. It does save 4 bytes where the jump calculation is performed in ENDIF and BACK , and obviates the need for BACK , which saves 18 bytes for a total savings in the resident dictionary of 26 bytes. It also saves 2 trips through the inner interpreter in compiling LOOP +LOOP UNTIL AGAIN because “ , ” replaces BACK (defined as “ HERE - , ”), but time savings while compiling are not usually that important. ...lee
  11. Maybe we should get Fred ( @F.G. Kaal ) to weigh in. I believe he had significant input to later versions of the DSR---maybe even wrote it? ...lee
  12. One of my TODOs is to possibly change BRANCH and 0BRANCH to use absolute addresses (per @Willsy’s TurboForth) instead of an offset (per figFORTH/TI Forth/fbForth), but I really do not see the advantage except, possibly, at compile time, which does not seem that important. The difference at execution time is MOV *IP,IP <---IP is a register versus A *IP,IP <---IP is a register which take exactly the same amount of time, as far as I can tell. So, unless someone (@Willsy? @Tursi? @matthew180? @jedimatt42? @apersson850? @TheBF? ??) can show me a significant difference in execution time, I am inclined to leave sleeping dogs lie—the mod would be significant! ...lee
  13. I added a routine to check for the ISR hook and, if not there, to call the fbForth ERROR word with the proper error message number to print “ISR?” after the usual “ERROR ?” and abort. While adding the new message, I took the opportunity to shorten many of the messages. Now, even after adding the ISR checking routine to bank#0 and the code to call it to 3 words in the same bank, there are 256 bytes free! I should add that the free-space increase is due not only to message size reduction but also to some other changes such as the redefinition of .S and shortening of a handful of words to use newly added words. There is still a little work before release. Here is the current state of the TODO list: fbForth300_TODO.txt ...lee
  14. Regarding booting up fbForth with its ISR disabled, I will have PLAY , STREAM , SAY check for a cleared ISR hook (>83C4) and, upon seeing it cleared, exit the routine immediately. Do you think I should include a message such as, “ISR not active!” or just fail quietly? ...lee
  15. Of course, there can be many reasons for choosing one operation over another. Regarding getting the MSB to the LSB, the point of using “SRL Rn,8” over “SWPB Rn” is usually to zero the MSB in the same instruction—saving instructions can outweigh speed. If you want to duplicate SWPB with a shift, “SRC Rn,8” will do nicely. Furthermore, if you want to test the result, the shift is the only way—SWPB does not affect the status register. Regarding zeroing a register, CLR is, indeed, the clear (groan) winner—unless, for some reason, you need a comparison. Both XOR and LI affect the status register, whereas, CLR does not. LI also takes an additional 2 bytes over the other two, when dealing only with registers. ...lee
  16. With your GPLLNK routine modified to use a writable workspace and storage locations (see @Gary from OPA post above), there are several Scratchpad RAM locations and one ROM location you can store XMLRTN for the return from GPL: >8300, >830E, >831C, >831E in Scratchpad RAM and >603E in ROM. The GROM0 addresses of the corresponding GPL XML instructions to place in the DATA directive at GXMLAD are >0376, >0EDA, >1675, >00E5, and >0131. Some of them have more than one GROM0 location, but I listed the first I found. ...lee
  17. With a couple of changes (“ CELL - ” to “ 2- ” and “ ? ” to “ @ U. ”), the following code is, indeed, shorter—16 bytes less!: : .S ( -- ) CR ." | " S0 @ BEGIN 2- SP@ OVER < WHILE DUP @ U. REPEAT DROP ; ...lee
  18. #1 works, but XX is superfluous. SP! is already defined to clear the stack by storing the contents of S0 in the stack pointer. XX pushes the contents of S0 and SP! wipes it out, i.e., does not use it—so no harm done. Also, .S , though not in figFORTH, is defined in fbForth (from TI Forth) and I like it better because it shows the stack as unsigned numbers. I do like your BEGIN...WHILE...REPEAT instead of the DO...LOOP of fbForth because it looks shorter. #2 certainly works as written and, I must say, I like it a lot. I think, though, that I would define := as : := DUP 1 WORD C@ 1+ + =CELLS DP ! ; to make the string only as long as necessary. Of course, neither form is protected against a second invocation of := for the same string with a length beyond the original. #3 does not work properly for 2 reasons: (1) EXPECT must be executed (last word on the line) before typing the text following it, i.e., nothing happens until <enter> is tapped at the end of the line, so the typed string is ignored while EXPECT awaits input. (2) EXPECT stores 2 nulls after the string is entered. ...lee
  19. Yeah...I remember your tagging me with that moniker when I used this pic as my avatar on this forum: ...lee
  20. To be compatible with current SAMS hardware, the returned LSB should always be ignored when reading the SAMS registers. SAMS hardware merely repeats the page number of the MSB in both bytes, whereas Classic99 does, in fact, return the bank# in the LSB and the page# in the MSB. ...lee
  21. My TI-99/4A journey started in December, 1983, when my first wife bought one for our kids for Christmas after the price drop to $50. I was 40! When TI released TI Forth into the public domain that same month, I was hooked. I first signed on to AtariAge with this post in May of 2011: I’ve been enjoying interacting with this group ever since! ...lee
  22. I know I mentioned this before, but I am thinking seriously of booting up fbForth 3.0 without enabling the fbForth ISR. It is enabled in fbForth 2.0. Besides enabling execution of user ISRs, the only reason to have it enabled is to use the fbForth speech and sound engines. This does not affect the BEEP and HONK words. Of course, you can always do sound lists per the E/A manual, with or without the fbForth ISR. And, you can always re-enable the ISR by jamming the contents of user variable INTLNK into >83C4. The fbForth ISR does not take a lot of time, but it is not nothing. If you don’t need it, it slows the system a touch. Of course, you can always disable it by storing 0 at >83C4. What do you think? ...lee
  23. The next version of FBLOCKS will also allow exiting the old way, but with CTRL+9: Future exits from 64-column editor: FCTN+9: Exit editor to SPLIT2 SPLIT Text window CTRL+9: Exit editor to mode from which editor invoked ...lee
  24. My apologies! I actually have those working but forgot to compact and copy them to FBLOCKS. It will take me a little time to do that. In the meantime, here are the scripts: b2fexp.fbf f2bimp.fbf ...lee
×
×
  • Create New...