Gauss Calculations

Date: 198x
Type: Program
Platform(s): TS 2068

This program implements Gaussian elimination with partial pivoting to solve systems of linear equations, translated from a Fortran IV mathematical routine. It accepts an N×N coefficient matrix A and a vector B (up to 20×20), prompts for an epsilon threshold for near-singular detection, and outputs the solution vector X and the determinant of A. Partial pivoting is performed by searching each column for the largest absolute pivot element and swapping rows as needed, with the determinant sign adjusted for each interchange. A subroutine at line 1000 displays the input matrix and vector before elimination begins, and lines 1500–1600 contain an unreferenced debug-style routine for printing intermediate row values. A self-contained test case using hardcoded DATA is defined at line 2000 but is never reached during normal execution flow.


Program Structure

The program is organized into several distinct phases:

  1. Initialization and input (lines 10–90): Splash screen, epsilon input with default fallback, and entry of matrix A and vector B.
  2. Matrix display subroutine (lines 1000–1050): Prints the full A matrix and B vector before elimination.
  3. Gaussian elimination with partial pivoting (lines 200–520): The main forward-elimination loop.
  4. Back substitution (lines 570–670): Solves for each X(I) from X(N) down to X(1).
  5. Output (lines 680–730): Prints the solution vector and determinant.
  6. Error handler (line 1900): Triggered when the pivot is below epsilon, indicating no unique solution.
  7. Dead code (lines 1500–1600 and 2000–2070): An unreferenced debug print routine and a hardcoded 2×2 test case that are never reached in normal execution.

Algorithm: Gaussian Elimination with Partial Pivoting

The elimination loop (lines 210–520) searches each column K for the row with the largest absolute value pivot (lines 260–300), then swaps that row with row K if necessary (lines 330–420). This is classic partial pivoting, which improves numerical stability. The determinant sign is negated at line 340 for each row swap. The inner elimination (lines 450–510) computes a multiplier FACTOR = A(I,K)/PIVOT and subtracts the appropriate multiple of the pivot row from each lower row, also updating the B vector. Zeros in the eliminated positions are not explicitly stored, consistent with the original Fortran comment at line 440.

Back substitution (lines 580–670) starts with X(N)=B(N)/A(N,N) and works upward, accumulating dot products with already-solved X values.

The determinant is accumulated in lines 120 and 690 by multiplying the diagonal elements of the upper-triangular result, with sign corrections from row swaps.

Notable Techniques and Idioms

  • POKE 23692,255 at lines 60 and 100 suppresses the scroll prompt (“scroll?”) by resetting the line counter, a standard idiom for programs with heavy screen output.
  • Epsilon is accepted as a string (E$) at line 20, allowing an empty ENTER to trigger the default of 1E-05 at line 30 via a string-empty check, rather than requiring a special sentinel numeric value.
  • VAL E$ at line 40 converts the user’s string input to a numeric epsilon, a compact idiom for optional numeric input.
  • The variable NLESS1=N-1 (line 130) pre-computes a loop bound used in multiple places, a minor efficiency measure inherited from Fortran practice.
  • PAUSE 0 at line 730 followed by GO TO 10 implements a keypress-to-restart idiom.
  • The matrix display subroutine reuses the variable names A and B as loop counters (lines 1010–1030), which shadows the arrays A() and B() within that loop. In Sinclair BASIC, simple variables and array variables share the same name space but are stored separately, so A (scalar) and A() (array) coexist without conflict — this is intentional and works correctly.

Bugs and Anomalies

LineIssue
310IF ABS ((PIVOT) <=EPSLN) — the closing parenthesis is misplaced; this parses as ABS(PIVOT <= EPSLN), evaluating the boolean comparison first and then taking its absolute value (always 0 or 1), rather than checking ABS(PIVOT) <= EPSLN. The intended singular-matrix guard will not function correctly for most values of EPSLN.
1500–1600This subroutine is defined and has a RETURN but is never called from anywhere in the program. It appears to be a debug-printing routine left over from development.
2000–2070A hardcoded 2×2 self-test using DATA and RESTORE that jumps to line 100. It is never reached in normal execution flow and appears to be an abandoned test harness.
1900GO TO 1 targets a non-existent line; execution will fall through to the next available line (line 5), effectively restarting the program. This is a known BASIC technique rather than a defect.

Variable Summary

VariableRole
A(20,20)Coefficient matrix
B(20)Right-hand side vector; modified in-place during elimination
X(20)Solution vector
NNumber of equations/unknowns
EPSLNSingularity threshold (default 1E-05)
PIVOTCurrent pivot element
FACTORRow multiplier during elimination
DETRunning determinant accumulator
LRow index of best pivot candidate
TEMPSwap temporary for row interchange
NLESS1, KPLUS1, IPLUS1Pre-computed index offsets

Image Gallery

Source Code

    5 REM BASIC translation of Fortran IV mathematicsprogram circa 1970 
   10 DIM a(20,20):DIM B(20):DIM X(20)
   15 INK 0:PAPER 7:BORDER 7:CLS :PRINT AT 8,6;"GAUSS Calculations"
   20 PRINT AT 20,0;"GIVE NUMBER OF ELEMENTS ";:INPUT N:PRINT N:PRINT "GIVE EPSILON                    (small positive number eg 1e-04) ENTER for default";:INPUT E$
   30 IF E$="" THEN LET EPSLN=1E-05:PRINT EPSLN:GO TO 50
   40 LET EPSLN= VAL E$:PRINT EPSLN
   50 FOR I=1 TO N:FOR J=1 TO N
   60 POKE 23692,255:PRINT "GIVE A(";I;",";J;")  ":INPUT A(I,J)
   70 NEXT J
   80 PRINT "GIVE B(";I;")  ":INPUT B(I)
   90 NEXT I
  100 POKE 23692,255:LET K=1
  110 GO SUB 1000
  120 LET DET=1.0
  130 LET NLESS1=N-1
  200 REM ***BEGIN GAUSSIAN ELIM*
  210 FOR K=1 TO NLESS1
  220 LET KPLUS1=K+1
  230 REM **SEARCH FOR PIVOT***
  240 LET PIVOT=A(K,K)
  250 LET L=K
  260 FOR I=KPLUS1 TO N
  270 IF (ABS (PIVOT) >= ABS (A(I,K))) THEN GO TO 310
  280 LET PIVOT=A(I,K)
  290 LET L=I
  300 NEXT I
  310 IF ABS ((PIVOT) <=EPSLN) THEN GO TO 1900
  320 IF L=K THEN GO TO 450
  330 REM **ROW INTERCHANGE****
  340 LET DET=-DET
  350 FOR J=K TO N
  360 LET TEMP=A(K,J)
  370 LET A(K,J)=A(L,J)
  380 LET A(L,J)=TEMP
  390 NEXT J
  400 LET TEMP=B(K)
  410 LET B(K)=B(L)
  420 LET B(L)=TEMP
  440 REM **ELIMINATE X(K) IN THE Kth COLUMN BELOW THE Kth ROW.  WE DO NOT WASTE TIME COMPUTING  OR STORING ZEROS IN THOSE POSIT-IONS
  450 FOR I=KPLUS1 TO N
  460 LET FACTOR=A(I,K)/PIVOT
  470 FOR J=KPLUS1 TO N
  480 LET A(I,J)=A(I,J)-FACTOR*A(K,J)
  490 NEXT J
  500 LET B(I)=B(I)-FACTOR*B(K)
  510 NEXT I
  520 NEXT K
  560 IF ABS (A(N,N)) <=EPSLN THEN GO TO 1900
  570 REM ***BACK SOLUTION***
  580 LET X(N)=B(N)/A(N,N)
  590 FOR K=1 TO NLESS1
  600 LET I=N-K
  610 LET IPLUS1=I+1
  620 LET X(I)=B(I)
  630 FOR J=IPLUS1 TO N
  640 LET X(I)=X(I)-A(I,J)*X(J)
  650 NEXT J
  660 LET X(I)=X(I)/A(I,I)
  670 NEXT K
  680 FOR I=1 TO N
  690 LET DET=DET*A(I,I)
  700 PRINT "X(";I;") = ";X(I)
  710 NEXT I
  720 PRINT "DETERMINANT = ";DET
  730 PRINT ''"Press a key for a new start":PAUSE 0:GO TO 10
 1000 PRINT "MATRIX A AND VECTOR B"
 1010 FOR A=1 TO N
 1020 PRINT "ROW ";A;"    ";:FOR B=1 TO N:PRINT A(A,B);"  ";:NEXT B:PRINT "** ";B(A)'
 1030 NEXT A
 1050 RETURN 
 1500 FOR L=K TO N
 1510 PRINT "ROW ";L
 1520 FOR M=K TO N
 1530 PRINT A(L,M)
 1540 NEXT M
 1550 PRINT "B(";L;")= ";B(L)
 1560 NEXT L
 1600 RETURN 
 1900 PRINT "NO UNIQUE SOLUTION":PAUSE 600:GO TO 1
 2000 RESTORE :LET N=1:LET EPSLN=1E-05
 2005 FOR A=1 TO 2
 2010 FOR B=1 TO 2
 2020 READ A(A,B)
 2030 NEXT B
 2040 NEXT A
 2050 READ B(1):READ B(2)
 2060 DATA 2,1,1,2,4,5
 2070 GO TO 100
 9000 SAVE "GAUSS2.BA" LINE 10

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