! Linked-list version of the Gauss-Seidel iteration
! =================================================
!
! works on a sparse array in which each row is a singly linked list
! (a "pencil") of possibly non-adjacent cell nodes, with missing
! cells treated as containing a value of zero.

USE gnuplot

TYPE CELL=STRUCTURE(POINTER TO CELL next; INTEGER col; REAL var, rhs)
!   declare a new STRUCTURE type. Keyword "TYPE" is optional here

POINTER TO CELL RowStart(0..20) !   declare array of row pointers
LOOP FOR ALL i !   allocate and initialize to zero the sparse-array structures
  POINTER TO POINTER TO CELL p=RowStart(i)
  LOOP FOR j=i TO i+20
    p^=NEW CELL !   here explicit dereferencing is needed for = assignment
    p.col=j; p.var=0; p.rhs=0
    p=p.next
  REPEAT LOOP
  p^=NULL !   here explicit dereferencing is needed for = assignment
REPEAT LOOP

DO p.var=1 FOR p=RowStart(HI) UNTIL p=NULL BY p=p.next
! assign some boundary condition

INLINE REAL FUNCTION val(POINTER TO POINTER TO CELL p; INTEGER c)
  LOOP WHILE p.col<c: p=p.next
  !   move pointer p until column c or end of row
  IF p.col=c THEN RESULT=p.var ELSE RESULT=0 ! return zero if element not found
END val !   otherwise return element's "var" value

LOOP FOR 100 TIMES   ! main iteration loop
  LOOP FOR i=LO+1 TO HI-1   ! for each row
    POINTER TO CELL above=RowStart(i+1),
    left=RowStart(i), center=left.next, right=center.next,
    below=RowStart(i-1)   ! initialize pointers to surrounding cells
    LOOP WHILE right#NULL
      j=center.col   ! read column index stored in central cell
      center.var=[val(above,j)+val(below,j)+val(left,j-1)+val(right,j+1)+
        center.rhs]/4
      ! with the "val" function defined, notation is very similar to standard 
      center=next(center)
      IF right=center THEN right=right.next
      ! notice that STRUCTURE elements can be indifferently accessed in either
      ! dotted or function notation. Same is true for functions.
    REPEAT LOOP
  REPEAT LOOP
REPEAT LOOP

! now plot something
RANGE 0,40,0,2
LOOP FOR i=RowStart.LO TO RowStart.HI
  STARTLINE
  DO DRAW p.col,p.var+i/20 FOR p=RowStart(i) UNTIL p=NULL BY p=p.next
REPEAT
SHOWGRAPH
READ ! wait on input and keep plot displayed until Enter is pressed

!(
  C-like (or Pascal-like) structures and pointers are a standard part of
  CPL, but dereferencing is implicit. Only three ^'s need appear in the above
  program, all at the side of = or # operators.
  !)