Math

This file is part of and Timex Sinclair Public Domain Library Tape 1005. Download the collection to get this file.
Date: 198x
Type: Program
Platform(s): TS 1000

This program is a multi-section mathematics toolkit covering eight topics: greatest common divisor (Euclidean algorithm), least common multiple, prime factorisation, quadratic equations, zero-finding for functions, polynomial evaluation, polynomial multiplication, and function plotting. The zero-finding routine (lines 1440–1750) uses a sign-change bisection method with user-supplied interval, step size, and epsilon tolerance. The polynomial evaluator (lines 1940–1990) applies Horner’s method for efficient computation. The function plotter (lines 2820–2890) maps mathematical coordinates to the 64×44 pixel display grid using scaling factors MX and MY, and plots the hardcoded function sin(x)+sin(2x).


Program Analysis

Program Structure

The program is organised as a menu dispatcher with eight numbered sections. Lines 2–120 display the main menu, line 150 calls the key-reading subroutine at 8800, and lines 155–190 dispatch to each section via a chain of IF … THEN GOTO statements. Each section ends by calling the “press a key” subroutine at 9000, which offers return-to-index or re-run of the current section.

Menu OptionTopicStart Line
1Greatest Common Divisor200
2Smallest Common Multiple400
3Prime Factoring700
4Quadratic Equation1000
5Zeroes of a Function1300
6Value of a Function1800
7Polynomial (multiplication)2100
8Plot of Functions2500

Key Input Subroutine (line 8800)

The subroutine at line 8800 polls INKEY$ in a tight loop, rejecting any character outside “1”–”8″. Once a valid digit is detected it reads INKEY$ a second time at line 8810 with LET W=VAL INKEY$ to convert it to a number. This introduces a potential race condition: if the key is released between lines 8800 and 8810, INKEY$ returns an empty string and VAL "" yields 0, sending the dispatcher to an unmatched branch. In practice SLOW mode makes this unlikely but it is a latent bug.

Greatest Common Divisor (lines 200–330)

The implementation is the classic Euclidean algorithm: compute quotient Q=INT(A/B), remainder R=A-Q*B, reassign A=B, B=R, and loop while R>0. The result is left in A and printed as “LCD=” (a labelling quirk — the correct abbreviation for Largest Common Divisor/Greatest Common Divisor is GCD or HCF).

Smallest Common Multiple (lines 400–620)

The SCM routine uses brute-force trial: starting from X=A, it increments X by 1 until X is divisible by all three inputs A, B, and C. Each divisibility test restarts the scan from the current X (via GOTO 510) rather than continuing forward, which is correct behaviour. This approach is slow for large inputs but straightforward.

Prime Factorisation (lines 700–930)

The routine at line 800 takes the absolute value of the input, then iterates I from 2 to the original value Z. For each candidate divisor, an inner loop repeatedly divides and counts the multiplicity N. A running product T tracks how much of the number has been accounted for; when T=E (the original absolute value) the outer FOR loop is exited early via GOTO 910. Negative inputs are handled by printing a leading minus sign before the factorisation.

Quadratic Equation (lines 1000–1220)

The discriminant is computed as Q=B*B-4*A*C. If negative, “NO REAL SOLUTION” is printed. Otherwise the formula is evaluated as Q=SQR Q/(2*A) and C=-B/(2*A), giving X1=C+Q and X2=C-Q. Note that operator precedence means SQR Q/(2*A) is parsed as (SQR Q)/(2*A), which is the intended formula.

Zero-Finding by Bisection (lines 1300–1780)

This section implements a sign-change bisection search. The outer scan (lines 1440–1600) steps across the interval [XA, XE] with step H, calling the function subroutine FCT at line 1610 and watching for a sign change in Y. When a sign change is detected, the bisection refinement subroutine SFZ at line 1640 narrows the bracket until ABS(Y) < E. The function itself is hardcoded at line 1620 as Y = X³ - 4X² - 11X + 30, which has roots at x = -3, 2, and 5. FAST mode is engaged for the numerical search and SLOW restored afterwards.

Subroutine addresses are stored in variables (LET FCT=1610, LET SFZ=1640) and called with GOSUB FCT — a notable technique exploiting the fact that GOSUB accepts a numeric variable as its target line number.

Polynomial Evaluation — Horner’s Method (lines 1800–2090)

Coefficients are stored in array W() with W(1) holding the constant term A(0). The evaluation at lines 1940–1990 applies Horner’s scheme: initialise with the leading coefficient, then repeatedly multiply by X and add the next coefficient working down to degree 1, finally adding W(1). This minimises multiplications compared to naive power evaluation.

Polynomial Multiplication (lines 2100–2495)

Two polynomials are entered separately. The first polynomial’s coefficients are copied into array A() of size K+1. The product array E() is initialised to zero, then the convolution sum E(I+J-1) += W(I)*A(J) is computed for all pairs (I,J). The result is printed as a list of coefficients E(0) through E(K+N). This is a correct discrete convolution of the coefficient arrays.

Function Plotter (lines 2500–2950)

The plotter draws axes at pixel position (31, 22) — roughly centred on the 64×44 display. Scaling factors are computed as MX=63/|XE-XA| and MY=43/|YE-YA|. The plotted function is hardcoded at line 2840 as Y = SIN(X) + SIN(2*X). Coordinate transformation applies at lines 2850–2860: X = X*MX + X0, Y = Y*MY + Y0. A bounds check at line 2870 prevents PLOT errors for out-of-range points.

Navigation Subroutine (line 9000)

The subroutine at 9000 displays a two-line prompt, waits with PAUSE 30 to debounce, then enters an INKEY$ poll loop. Pressing “R” returns to the main menu index (line 5, which is the REM crediting the source book). Any other key returns to the caller for re-entry of the same section. Line 9040 (SAVE "1024%1") is unreachable dead code following the conditional returns.

Notable Techniques and Anomalies

  • Variable-target GOSUB FCT (lines 1450, 1500, 1540, 1670) stores line numbers in variables — an efficient and flexible dispatch mechanism.
  • FAST/SLOW mode switching (lines 1310 and 1760) is used only in the zero-finding section, where the iterative bisection benefits most from faster execution.
  • The SCM section accepts three inputs but the algorithm restarts from X=A rather than incrementing by A; for large coprime numbers this will be very slow.
  • The prime factorisation loop iterates FOR I=2 TO Z using the original (potentially large) value of Z rather than the progressively reduced quotient, making it inefficient for numbers with large prime factors.
  • The key-reading race condition at lines 8800–8810 (double INKEY$ read) could return W=0, causing all dispatch conditions at lines 155–190 to fail silently and loop back to the menu display.
  • Section 6 (“Value of a Function”) shares the polynomial input subroutine code with section 7 but duplicates it at lines 1830–1930 rather than sharing lines 2130–2230, increasing program size unnecessarily.

Content

Appears On

Assembled by Tim Ward from many sources. Contains programs 10211 – 10251.

Related Products

Related Articles

Related Content

Image Gallery

Source Code

   2 SLOW 
   5 REM "FROM BOOK BY ING. WINFRIED HOFACKER PUBLISHING COMPANY"
  10 CLEAR 
  15 CLS 
  20 PRINT "WELCOME TO MATHEMATICS"
  25 PRINT 
  30 PRINT "PRESS DESIRED SELECTION NUMBER"
  35 PRINT 
  40 PRINT "1> LARGEST COMMON DIVISOR"
  45 PRINT 
  50 PRINT "2> SMALLEST COMMON MULTIPLE" 
  55 PRINT 
  60 PRINT "3> PRIME FACTORING OF NUMBERS"
  65 PRINT 
  70 PRINT "4> QUADRATIC EQUATION"
  75 PRINT 
  80 PRINT "5> ZEROES OF A FUNCTION"
  85 PRINT 
  90 PRINT "6> VALUE OF A FUNCTION"
  95 PRINT 
 100 PRINT "7> POLYNOMIAL"
 105 PRINT 
 110 PRINT "8> PLOT OF FUNCTIONS"
 120 PRINT AT 21,4;" RUN IN SLOW MODE"
 150 GOSUB 8800
 155 IF W=1 THEN GOTO 200
 160 IF W=2 THEN GOTO 400
 165 IF W=3 THEN GOTO 700
 170 IF W=4 THEN GOTO 1000
 175 IF W=5 THEN GOTO 1300
 180 IF W=6 THEN GOTO 1800
 185 IF W=7 THEN GOTO 2100
 190 IF W=8 THEN GOTO 2500
 200 CLS 
 205 CLEAR 
 208 PRINT "LARGEST COMMON DIVISOR"
 209 PRINT 
 210 PRINT "A=";
 220 INPUT A
 230 PRINT A
 240 PRINT "B=";
 250 INPUT B
 260 PRINT B
 270 LET Q=INT (A/B)
 280 LET R=A-Q*B
 290 LET A=B
 300 LET B=R
 310 IF R>0 THEN GOTO 270
 320 PRINT "LCD=";A
 325 GOSUB 9000
 330 GOTO 200
 400 CLS 
 405 CLEAR 
 408 PRINT "SMALLEST COMMON MULTIPLE"
 409 PRINT 
 410 PRINT "A=";
 420 INPUT A
 430 PRINT A
 440 PRINT "B=";
 450 INPUT B
 460 PRINT B
 470 PRINT "C=";
 480 INPUT C
 490 PRINT C
 500 LET X=A
 510 IF INT (X/A)=X/A THEN GOTO 540
 520 LET X=X+1
 530 GOTO 510
 540 IF INT (X/B)=X/B THEN GOTO 570
 550 LET X=X+1
 560 GOTO 510
 570 IF INT (X/C)=X/C THEN GOTO 600
 580 LET X=X+1
 590 GOTO 510
 600 PRINT "SCM=";X
 610 GOSUB 9000
 620 GOTO 400
 700 CLS 
 705 CLEAR 
 708 PRINT "PRIME FACTORING OF NUMBERS"
 710 PRINT 
 720 PRINT "NUMBER=";
 730 INPUT Z
 740 PRINT Z
 750 PRINT Z;"=";
 760 IF Z<0 THEN PRINT "-";
 770 PRINT "1";
 800 LET Z=ABS Z
 805 LET E=Z
 808 LET T=1
 810 FOR I=2 TO Z
 820 LET N=0
 830 IF Z/I<>INT (Z/I) THEN GOTO 870
 840 LET Z=Z/I
 850 LET N=N+1
 860 GOTO 830
 870 IF N=0 THEN GOTO 900
 880 FOR J=1 TO N
 885 PRINT "*";I;
 887 LET T=T*I
 888 IF T=E THEN GOTO 910
 890 NEXT J
 900 NEXT I
 910 PRINT 
 920 GOSUB 9000
 930 GOTO 700
 1000 CLS 
 1002 CLEAR 
 1004 PRINT "QUADRATIC EQUATION"
 1006 PRINT 
 1008 PRINT "A*X*X+B*X+C=0"
 1010 PRINT "A=";
 1020 INPUT A
 1030 PRINT A
 1040 PRINT "B=";
 1050 INPUT B
 1060 PRINT B
 1070 PRINT "C=";
 1080 INPUT C
 1090 PRINT C
 1100 LET Q=B*B-4*A*C
 1110 IF Q<0 THEN GOTO 1200
 1120 LET Q=SQR Q/(2*A)
 1130 LET C=-B/(2*A)
 1140 LET X1=C+Q
 1145 PRINT "X1=";
 1150 PRINT X1
 1160 LET X2=C-Q
 1165 PRINT "X2=";
 1170 PRINT X2
 1180 GOSUB 9000
 1190 GOTO 1000
 1200 PRINT "NO REAL SOLUTION"
 1210 GOSUB 9000
 1220 GOTO 1000
 1300 CLS 
 1302 CLEAR 
 1304 PRINT "ZEROES OF A FUNCTION"
 1305 PRINT 
 1306 REM "FUNCTION IS FCT"
 1308 REM "SEARCHING FOR ZEROES IS SFZ"
 1310 FAST 
 1312 PRINT "XA=";
 1315 INPUT XA
 1320 PRINT XA
 1330 PRINT "XE=";
 1340 INPUT XE
 1350 PRINT XE
 1360 PRINT "H=";
 1370 INPUT H
 1380 PRINT H
 1390 PRINT "EPS=";
 1400 INPUT E
 1410 PRINT E
 1420 LET FCT=1610
 1430 LET SFZ=1640
 1440 LET X=XA
 1450 GOSUB FCT
 1460 LET YA=Y
 1470 LET XA=X
 1480 LET X=XA+H
 1490 IF X>XE THEN GOTO 1760
 1500 GOSUB FCT
 1510 IF SGN Y=SGN YA THEN GOTO 1580
 1520 LET YN=Y
 1530 LET XN=X
 1540 GOSUB SFZ
 1550 PRINT "ZERO AT POSITION X=";X
 1560 IF X<XE THEN LET X=X+E
 1570 GOTO 1450
 1580 LET YA=Y
 1590 LET XA=X
 1600 GOTO 1480
 1610 REM FCT
 1620 LET Y=X*X*X-4*X*X-11*X+30
 1630 RETURN 
 1640 REM SFZ
 1650 IF ABS (Y)<E THEN RETURN 
 1660 LET X=(XN-XA)/2+XA
 1670 GOSUB FCT
 1680 IF ABS Y<E THEN RETURN 
 1690 IF SGN Y=SGN YN THEN GOTO 1730
 1700 LET YA=Y
 1710 LET XA=X
 1720 GOTO 1660
 1730 LET YN=Y
 1740 LET XN=X
 1750 GOTO 1660
 1760 SLOW 
 1770 GOSUB 9000
 1780 GOTO 1300
 1800 CLS 
 1805 CLEAR 
 1810 PRINT "VALUE OF A FUNCTION"
 1815 PRINT 
 1820 GOTO 2000
 1830 REM POLYNOMIAL
 1840 PRINT "N=";
 1850 INPUT N
 1860 PRINT N
 1870 DIM W(N+1)
 1880 FOR I=1 TO N+1
 1890 PRINT "A(";I-1;")=";
 1900 INPUT W(I)
 1910 PRINT W(I)
 1920 NEXT I
 1930 RETURN 
 1940 LET Y=W(N+1)*X
 1950 FOR I=N TO 2 STEP -1
 1960 LET Y=(Y+W(I))*X
 1970 NEXT I
 1980 LET Y=Y+W(1)
 1990 RETURN 
 2000 GOSUB 1830
 2010 PRINT "X=";
 2020 INPUT X
 2030 PRINT X
 2040 GOSUB 1940
 2050 PRINT "Y=";Y
 2060 PRINT "NEW X? (Y/N)"
 2070 IF INKEY$="" THEN GOTO 2070
 2080 IF INKEY$="Y" THEN GOTO 2010
 2085 GOSUB 9000
 2090 GOTO 1800
 2100 CLS 
 2105 CLEAR 
 2120 GOTO 2240
 2130 REM "POLYNOMIAL"
 2135 PRINT 
 2140 PRINT "N=";
 2150 INPUT N
 2160 PRINT N
 2170 DIM W(N+1)
 2180 FOR I=1 TO N+1
 2190 PRINT "A(";I-1;")=";
 2200 INPUT W(I)
 2210 PRINT W(I)
 2220 NEXT I
 2230 RETURN 
 2240 PRINT "1. POLYNOMIAL"
 2250 GOSUB 2130
 2260 LET K=N
 2270 DIM A(K+1)
 2280 FOR I=1 TO K+1
 2290 LET A(I)=W(I)
 2300 NEXT I
 2310 CLS 
 2320 PRINT "2. POLYNOMIAL"
 2330 GOSUB 2130
 2340 LET L=N+K+1
 2350 DIM E(L)
 2360 FOR I=1 TO L
 2370 LET E(I)=0
 2380 NEXT I
 2390 FOR I=1 TO N+1
 2400 FOR J=1 TO K+1
 2410 LET L=I+J-1
 2420 LET E(L)=E(L)+W(I)*A(J)
 2430 NEXT J
 2440 NEXT I
 2450 CLS 
 2460 LET L=K+N+1
 2470 FOR I=1 TO L
 2480 PRINT "E(";I-1;")=";E(I)
 2485 NEXT I
 2490 GOSUB 9000
 2495 GOTO 2100
 2500 CLS 
 2505 CLEAR 
 2510 PRINT "PLOT"
 2515 REM "PLOT OF FUNCTIONS"
 2520 GOTO 2900
 2530 FOR I=0 TO 63
 2540 PLOT I,22
 2550 NEXT I
 2560 FOR I=0 TO 43
 2570 PLOT 31,I
 2580 NEXT I
 2590 PRINT AT 0,14;"Y"
 2600 PRINT AT 11,31;"X"
 2610 RETURN 
 2620 LET X0=31
 2630 LET Y0=22
 2640 PRINT "XA=";
 2650 INPUT XA
 2660 PRINT XA
 2670 PRINT "XE=";
 2680 INPUT XE
 2690 PRINT XE
 2700 PRINT "YA=";
 2710 INPUT YA
 2720 PRINT YA
 2730 PRINT "YE=";
 2740 INPUT YE
 2750 PRINT YE
 2760 LET MX=63/ABS (XE-XA)
 2770 LET MY=43/ABS (YE-YA)
 2780 PRINT "H=";
 2790 INPUT H
 2800 PRINT H
 2810 RETURN 
 2820 FOR L=XA TO XE STEP H
 2830 LET X=L
 2840 LET Y=SIN X+SIN (2*X)
 2850 LET X=X*MX+X0
 2860 LET Y=Y*MY+Y0
 2870 IF X>=0 AND X<=63 AND Y>=0 AND Y<=43 THEN PLOT X,Y
 2880 NEXT L
 2890 RETURN 
 2900 GOSUB 2620
 2910 CLS 
 2920 GOSUB 2530
 2930 GOSUB 2820
 2940 GOSUB 9000
 2950 GOTO 2500
 8800 IF INKEY$<>"1" AND INKEY$<>"2" AND INKEY$<>"3" AND INKEY$<>"4" AND INKEY$<>"5" AND INKEY$<>"6" AND INKEY$<>"7" AND INKEY$<>"8" THEN GOTO 8800
 8810 LET W=VAL INKEY$
 8815 RETURN 
 9000 PRINT AT 20,0;"PRESS <R> TO GET INDEX,PRESS ANY"
 9003 PRINT AT 21,0;"OTHER KEY TO RERUN THIS SECTION"
 9005 PAUSE 30
 9010 IF INKEY$="" THEN GOTO 9010
 9015 IF INKEY$="R" THEN GOTO 5
 9020 IF INKEY$<>"R" THEN RETURN 
 9040 SAVE "1024%1"
 9050 GOTO 2

Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.

People

No people associated with this content.

Scroll to Top