Dr. Jim's QL Dumping Ground

Anything QL Software or Programming Related.
User avatar
NormanDunbar
Forum Moderator
Posts: 2251
Joined: Tue Dec 14, 2010 9:04 am
Location: Leeds, West Yorkshire, UK
Contact:

Re: Dr. Jim's QL Dumping Ground

Post by NormanDunbar »

I see it in Chrome for Android, on my tablet.

Cheers,
Norm.


Why do they put lightning conductors on churches?
Author of Arduino Software Internals
Author of Arduino Interrupts

No longer on Twitter, find me on https://mastodon.scot/@NormanDunbar.
User avatar
dex
Gold Card
Posts: 286
Joined: Thu Dec 23, 2010 1:40 pm

Re: Dr. Jim's QL Dumping Ground

Post by dex »

O.K. in TenFourFox (PowerPC Macintosh, OS X 10.4.11).

(Safari 4.1.3 can't open ql-forum at all.)


User avatar
TMD2003
Trump Card
Posts: 168
Joined: Sat Oct 10, 2020 12:18 pm

Re: Dr. Jim's QL Dumping Ground

Post by TMD2003 »

Time to wake up this thread! Seeing as I'm running an entirely different programming competition that I can't contribute to, I've been rather quiet on the programming front. I've got a few ideas in development, but this is the only one so far this year... and it was written in one evening. In short, I'd always wondered if I could translate Stephen Keevil's Lissajous Figures, from the July 1983 issue of Sinclair Programs, for the QL, using its more powerful graphics. So I did... well, sort of. In effect, after I'd defined custom windows, all the input and error-checking procedures, and adapting the one line that actually calculates the points that form the figures, there was just about nothing left of the original...

But anyway, here it is. Take the Spectribution page or the direct download, either will do. It'll run on an unregistered version of QemuLator at regular speed, though if I can ever adapt this to make it into an animated version with constantly changing phase angle, it'll probably need a 640K+ QL and probably a Gold Card as well.

Image


Spectribution: Dr. Jim's Sinclair computing pages.
Features my own programs, modified type-ins, RZXs, character sets & UDGs, and QL type-ins... so far!
User avatar
TMD2003
Trump Card
Posts: 168
Joined: Sat Oct 10, 2020 12:18 pm

Re: Dr. Jim's QL Dumping Ground

Post by TMD2003 »

Hails!

I just went back into the QLissajous folder, where I found a factorisation program I'd been looking for. It was based on a listing in Sinclair Programs way back in the day, for the ZX81: https://archive.org/details/sinclair-pr ... 0/mode/1up

I converted it for the Spectrum as-is, and extended it so that it would run once to find out how many factors a number has, then dimension an array with that number of elements and run again to dump all those factors into the array. It wasn't very efficient, so I found a better algorithm floating around the internet that used the MOD function that the Spectrum doesn't have, though one quick DEF FN sorted that out. The new version was so efficient that it factorised 99999999 in THREE SECONDS; the based-on-the-ZX81-listing version took 53 seconds. It only needs one pass through the factorisation as the array is fixed at a length of 26, which is the largest possible number of factors for any eight-digit number (2^26 = 67,108,864).

So I thought: why not also try the QL? That has a built-in MOD function, after all! But imagine my dismay when (a) I found that the QL starts bunging numbers into scientific notation after six digits, and (b) the MOD function gave me overflow errors! Changing all the variables to % showed me what was wrong there - they top out at 32767, just like on a ZX80. So all the %s were ditched and dropped in the Spectrum's calculated-from-scratch MOD function to handle numbers that take more than two bytes. I didn't use a separate DEF FN because this means the factor_array procedure that populates the array stands by itself. Because the QL uses arrays numbering the elements from 0 onwards, I've used f(0) to hold the number of factors the initial number has, and the rest of the array to hold the factors, so that's all self-contained as well.

So you don't have to use the program the way I've written it - you could start a loop from 2 to 999999, call factor_array each time and if f(0)=1 (which indicates a prime number) you can print a list of primes or populate another array with them.

The highest six-digit prime number is 999983; QemuLator at Full Speed concludes it is prime in 33 seconds; with the Gold Card it takes around 27½ minutes, and I dare not try it on an original QL. I tried QPC2 as well, thinking it'd do the calculation instantly, but it spat back an error - it doesn't like line 350, the way I've tried to end the procedure early without a GOTO, which causes far too many people here to twitch uncontrollably. Using an extra END DEF at the end of an IF statement is something I saw regularly in magazine listings, but those were not the days of SMSQ/E... if anyone knows of a fix that would make it work on both systems, that'd be helpful.

Anyway, here's the listing. You know what to do with it.

Code: Select all

100 CLS
110 initial_input
120 factor_array(f0)
130 factors_found
140 STOP
150 REMark ==========================
160 DEFine PROCedure initial_input
170 REMark ==========================
180 PRINT "INPUT INTEGER TO FACTORISE"\"(min.2, max.999999)"\\"-> ";
190 REPeat loop1
200   INPUT f0
210   IF f0>=2 AND f0<=999999 AND f0=INT(f0) THEN EXIT loop1
220 END REPeat loop1
230 END DEFine initial_input
240 REMark ==========================
250 DEFine PROCedure factor_array(f1)
260 REMark ==========================
270 LOCal n,cf
280 DIM f(19): f1=f0
290 FOR n=1 TO f1/2 STEP 2
300 cf=n: IF n=1 THEN cf=2
310 AT 5,0: PRINT "Dividing by ";cf
320 REPeat loop2
330   IF cf*((f1/cf)-INT(f1/cf))<>0 THEN EXIT loop2
340   f1=f1/cf: f(f(0)+1)=cf: f(0)=f(0)+1
350   IF f1=1 THEN END DEFine factor_array
360 END REPeat loop2
370 NEXT n
380 IF f1=f0 THEN f(0)=1: f(1)=f1
390 END DEFine factor_array
400 REMark ==========================
410 DEFine PROCedure factors_found
420 REMark ==========================
430 LOCal n
440 AT 5,0: PRINT "NUMBER OF FACTORS = ";f(0)\\"FACTORS:"
450 FOR n=1 TO f(0)-1: PRINT f(n)!"x ";: NEXT n: PRINT f(f(0));
460 IF f(0)=1 THEN PRINT "is a PRIME NUMBER"
470 END DEFine factors_found


Spectribution: Dr. Jim's Sinclair computing pages.
Features my own programs, modified type-ins, RZXs, character sets & UDGs, and QL type-ins... so far!
User avatar
tofro
Font of All Knowledge
Posts: 2685
Joined: Sun Feb 13, 2011 10:53 pm
Location: SW Germany

Re: Dr. Jim's QL Dumping Ground

Post by tofro »

TMD2003 wrote: - it doesn't like line 350, the way I've tried to end the procedure early without a GOTO, which causes far too many people here to twitch uncontrollably. Using an extra END DEF at the end of an IF statement is something I saw regularly in magazine listings, but those were not the days of SMSQ/E... if anyone knows of a fix that would make it work on both systems, that'd be helpful.
That was wrong even back then :)

Don't be embarrassed, trying to prematurely exit from a procedure with conditional END DEFINEs used to be so common that SuperBASIC compilers even developed a special error message for this case (to end the headache it gave them).

You exit a structure either by EXIT <structureName>, which leaves the innermost construct, or in your example, simply by using RETURN.


ʎɐqǝ ɯoɹɟ ǝq oʇ ƃuᴉoƃ ʇou sᴉ pɹɐoqʎǝʞ ʇxǝu ʎɯ 'ɹɐǝp ɥO
User avatar
Ruptor
Gold Card
Posts: 418
Joined: Fri Dec 20, 2019 2:23 pm
Location: London

Re: Dr. Jim's QL Dumping Ground

Post by Ruptor »

TMD2003 wrote:Anyway, here's the listing. You know what to do with it.
You are doing a great job of getting spaghetti code from one machine to run on another. :)


Derek_Stewart
Font of All Knowledge
Posts: 3928
Joined: Mon Dec 20, 2010 11:40 am
Location: Sunny Runcorn, Cheshire, UK

Re: Dr. Jim's QL Dumping Ground

Post by Derek_Stewart »

Hi,

The use of GOTOs in Spectrum programs, are a difficult thing to unravel.

I was trying to port Urban Upstart to the QL, but the Spectrum basic is a bit of a mess, but I have nearly got it running in QL SuperBASIC.

However, there is some Z80 assembley language routines, to draw graphics, which maybe could be convertrd to 68000 assembler or maybe SuperBasic routines.

After using QL Basic, Spectrum Basic is so bad, most of the Spectrum commands anf functions can be defined as Procedures or Functions in QL Superbasic.


Regards,

Derek
User avatar
Andrew
Aurora
Posts: 786
Joined: Tue Jul 17, 2018 9:10 pm

Re: Dr. Jim's QL Dumping Ground

Post by Andrew »

Derek_Stewart wrote: but the Spectrum basic is a bit of a mess
Spectrum Basic is ok, as long as it using the common commands, as described in the manual. But Spectrum Basic Optimized for Speed was incomprehensible for me. I simply do not have the time to learn all Spectrum tips and tricks.
(After a lot of searches on the net I found out what "BRIGHT SGN PI ;INK NOT PI" means and why it is used ... but not more than that)
e.g.:

Code: Select all

15 IF INKEY$ ="<12/delete>" THEN GO TO VAL "9e3"
19 LET p=1:PRINT AT a-2,b;"$%" AND NOT w;"()" AND w;AT a-1,b;"45" AND NOT w;"89" AND w;AT a,b;"ST" AND NOT w;"UV" AND w:GO TO 2
90 LET x=VAL "5":LET v=VAL "-43"
92 LET x=x-SGN PI :IF NOT x THEN LET v=VAL "-42":LET x=VAL "7+INT (RND *(9-ve+sk))":LET z=VAL "a-1-INT (RND *2)":LET q=VAL "6":PRINT AT z,q;"<21/over><1><19/bright><1>|"
93 GO TO 100
94 IF q<= b-2 THEN PRINT AT z,q;"<21/over><1>|<8 left>}" AND q=6;AT z,q;"<17/paper><0><21/over><1>}<17/paper><1><19/bright><1><16/ink><5>}"<17/paper><0><16/ink><7><19/bright><0><21/over><0>:LET q=q+1:GO TO 100
96 BEEP 0.01,NOT PI :BEEP 0.01,VAL "15":LET v=VAL "-43":PRINT AT z,q;"<17/paper><0> " AND VAL "e<= 2" AND q=b-SGN PI :IF a-z<> 3-e THEN GO TO VAL "2500"
101 IF e THEN GO TO 2*e+128
103 IF POINT (IN l,r) THEN LET p=1:LET n=RND >0.5:PRINT AT a-2,b;"!#";AT a-1,b;"-" AND NOT n;"5" AND n;".";AT a,b;"@A":BEEP 0.005,30:LET e=3:GO TO 150
.....
131 PRINT AT a-2,b;"<21/over><1>($<8 left><8 left>+,";AT a-1,b;"<21/over><0>>?";AT a,b;"KL":LET e=0:LET p=1:GO TO 150
132 IF POINT (IN k,c) THEN GO TO 150
133 PRINT AT a-2,b;"+,";AT a-1,b;"<21/over><0><21/over><1><=<8 left><8 left>>?<21/over><0>";AT a,b;"KL":LET e=0:LET p=1:GO TO 150
134 PRINT AT a-2,b;"$ ";AT a-1,b-1;"<21/over><1>/<21/over><0>01" AND NOT n;"<21/over><1>6<21/over><0>71" AND n;AT a,b-1;"<21/over><1>B<21/over><0>CD":BEEP 0.005,40:LET e=4:GO TO 150
136 PRINT AT a-2,b-2;"<21/over><1>%&<21/over><0>," AND NOT n;"<21/over><1> &<21/over><0>," AND n;AT a-1,b-2;"<21/over><1> /<8 left>2<21/over><0>31<8 left>4" AND NOT n;"<21/over><1>86<8 left>9<21/over><0>34" AND n;AT a,b-1;"<21/over><1>B<8 left>E<21/over><0>FG":BEEP 0.005,40:LET e=5:IF b=t+3 AND v<> n+1 THEN GO SUB 400:IF z>20 THEN GO TO 2


User avatar
janbredenbeek
Super Gold Card
Posts: 629
Joined: Wed Jan 21, 2015 4:54 pm
Location: Hilversum, The Netherlands

Re: Dr. Jim's QL Dumping Ground

Post by janbredenbeek »

Andrew wrote:
Derek_Stewart wrote: but the Spectrum basic is a bit of a mess
Spectrum Basic is ok, as long as it using the common commands, as described in the manual. But Spectrum Basic Optimized for Speed was incomprehensible for me. I simply do not have the time to learn all Spectrum tips and tricks.
(After a lot of searches on the net I found out what "BRIGHT SGN PI ;INK NOT PI" means and why it is used ... but not more than that)
This was a way to avoid one of Spectrum Basic's idiosyncrasies: literal numbers are stored in ASCII and in binary form, using 5 bytes + 1 marker byte. So 'GO TO 1' takes up 8 bytes rather than 2. If your program is full of numbers, e.g. in DATA statements, you might run out of memory much quicker than expected.
This was a 'feature' carried over from ZX81 Basic, but Spectrum Basic was enhanced in that it can store integers between -65535 and +65535 in integer form rather than floating point form as the ZX81 does. IMHO this obsoletes most of the speed gain that storing numbers in binary had on the ZX81 (most numbers in programs tend to be small integers which can quickly be converted from ASCII to binary).

Now the trick to avoid numbers being stored twice was not to use literal numbers but arithmetic or logical expressions, such as NOT PI for 0, SGN PI for 1, or VAL "number" which don't store the 6 extra bytes. In most cases this will be slower than using literal numbers since the expression evaluator has to evaluate them first rather than just copy the 5 binary bytes to the math stack. And of course it makes the program a lot harder to read.

Incidentally, S*BASIC stores literal numbers internally in binary (as float, but Minerva and SMSQ/E use integers where possible), but as ASCII when stored as file. This may lead to loss of accuracy of real numbers, e.g. 10000001 is rounded to '1E7'. To avoid this, you would have to enter it as '10000001' in quotes so it will be stored as a string and accurately coerced into a number (at the cost of speed).


stevepoole
Super Gold Card
Posts: 712
Joined: Mon Nov 24, 2014 2:03 pm

Re: Dr. Jim's QL Dumping Ground

Post by stevepoole »

Hi TMD,

After adapting your 'factors' program for SGC and QPC2, (using END FOR instead of NEXT etc), any number on my systems is factorised in less than a second....

The limiting factor on big numbers is not so much MOD as INT(). MOD is easy to rewrite, but not so INT().

DIY arithmetic operators on big numbers are quite slow, compared to ROM ones, but I might try the adaptation...

Nice piece of programming mister TMD !

Steve.


Post Reply