[net.lang.forth] Integer Square Root

toma@tekchips.UUCP (Tom Almy) (09/04/85)

The following is a Z-80 square root routine for STOIC.  Sorry, it is the
best I can do, but at least the algorithm is described.  This algorithm 
is faster than a divide (so you know what you can do with Newton's 
aproximation).

% SQUARE ROOT ROUTINE

RADIX @  HEX  % SET RADIX TO HEX

ASSEMBLER< DEFINITIONS  

% Z-80 ASSEMBLER DEFINITIONS (FOR SQRT, AT LEAST)

% LET US DEFINE SOME ASSEMBLER CONTROL STRUCTURES
18 'CY CONSTANT   10 'NC CONSTANT   8 'Z CONSTANT   0 'NZ CONSTANT
28 'PE CONSTANT   20 'PO CONSTANT   38 'N CONSTANT  30 'P CONSTANT
'JMPC, : 0C2 + B, , ; % CONDITIONAL JUMP (Z80 STYLE...BETTER FOR STRUCTURES)
'IF,  : 8 XOR 0 SWAP JMPC, . 2- ;  % SUPPLY FORWARD JUMP TARGET
'BEGIN, : . ;
'END, : 8 XOR JMPC, ; % JUMP BACK TO BEGIN IF COND FALSE
'REPEAT,  : SWAP JMP,  THEN, ;  % BEGIN, ..  IF, ... REPEAT,  STRUCTURE

'RL, : 0CB B,  10 + B, ;  % DEFINE Z-80 OPS FOR RL, RR, SLA, AND SRL
'RR, : 0CB B,  18 + B, ;
'SLA, : 0CB B,  20 + B, ;
'SRL, : 0CB B,  38 + B, ;
'DSBB, : 0ED B,  8 * 42 + B, ; % SUBTRACT FROM HL WITH BORROW (Z80 AGAIN)
'DADC, : 0ED B, 8 * 4A + B,  ; % ADD TO HL WITH CARRY
'EXREGS, : 0D9 B, ;  % EXCHANGE REGISTER SETS

> DEFINITIONS 

% THE ALGORITHM USED TO TAKE THE SQUARE ROOT IS AS FOLLOWS:

% A IS ARGUMENT (N BITS), R IS ROOT ACCUMULATOR (N/2+1 BITS), 
% B IS HIGH END OF ARGUMENT (N/2+1 BITS, I THINK)

% REPEAT N/2 TIMES :	SHIFT B,A LEFT TWO BITS
%			R := R * 2 + 1
%			B := B - R
%			IF B<0 THEN B:=B+R  R:=R-1  (NO BORROW CAN OCCUR)
%				ELSE R:=R+1
%
% ROOT IS R/2, "REMAINDER" IS B.


% SINGLE PRECISION SQUARE ROOT
% IN THIS ROUTINE, DE HOLDS ROOT, BC THE ARGUMENT, AND HL THE EXTENSION
% THE COUNTER IS THE A REGISTER
ASSEMBLER<  .    % THIS IS DONE AS A SUBROUTINE
  A XRA, A D MOV, A E MOV, A H MOV, A L MOV, 8 A MVI, % INITIALIZE
	BEGIN,
	E SLA,  D RL,  E INR, % ROOT <- ROOT*2+1
	2 ( C RL,  B RL,  H DADC, ) % SHIFT DEBC LEFT BY TWO BITS
	D DSBB, % SUBTRACT PARTIAL ROOT FROM END OF ARGUMENT
	N IF,
	 D DAD, E DCR,  % WON'T FIT, RESTORE ARG AND DECREMENT PARTIAL ROOT
	ELSE,
	 E INR, % FITS -- INCREMENT PARTIAL ROOT
	THEN,
	A DCR, Z END,
	RET, >  % RETURN RESULT (*2) IN DE, REMAINDER IN HL
'(SQRT) CONSTANT

'SQRT CODE<  B POP,  (SQRT) CALL,  XCHG,
	H SRL,  L RR,   % CORRECT ROOT (DIVIDE BY 2)
	PUSH JMP, >  % RETURN



% DOUBLE PRECISION SQUARE ROOT
% ROOT IS FORMED IN REGISTERS C,D,E; COUNTER IS IN REGISTER B
% ARGUMENT EXTENSION IS STORED IN AHL
% THE ARGUMENT IS ON THE STACK IN STANDARD DOUBLE PRECISION FORMAT:
%	3 4(MSB) 1 2.  



'DSQRT  CODE<           % INITIALIZE
	B POP,  (SQRT) CALL, % TAKE PARTIAL SQUARE ROOT
	A XRA,  A C MOV,  8 B MVI,
	EXREGS, H POP, EXREGS,
	BEGIN, 
	2 ( EXREGS, H DAD, EXREGS,
	    H DADC,  A ADC, ) % SHIFT LEFT ARGUMENT&EXTENSION BY 2 BITS
	E SLA,  D RL,  C RL,  E INR, % R <- R*2+1
	D DSBB, C SBB,  % DO SUBTRACT
	N IF,
		D DAD,  C  ADC,
		E DCR,  % ADJ PARTIAL ROOT
	ELSE, % >=0 SO COMPLETE SUBTRACT
		E INR,  % ADJ PARTIAL ROOT
	THEN,
	B DCR,  Z END,
	C SRL,  D RR,  E RR,  % CORRECT RESULT BY DIVIDING BY 2
	XCHG,  	PUSH JMP, >  % FINISHED, SO RETURN


% THE FOLLOWING IS A FASTER VERSION 

'FDSQRT  CODE<           % INITIALIZE
	B POP,  (SQRT) CALL, % TAKE PARTIAL SQUARE ROOT
	A XRA,  A C MOV,  6 B MVI,
	EXREGS, H POP, EXREGS,  % GET REST OF ARGUMENT
	BEGIN, 
	2 ( EXREGS, H DAD, EXREGS, 
	    H DADC,  ) % SHIFT LEFT ARGUMENT&EXTENSION BY 2 BITS
	E SLA,  D RL,  E INR, % R <- R*2+1
	D DSBB, % DO SUBTRACT
	CY IF,
		D DAD,  
		E DCR,  % ADJ PARTIAL ROOT
	ELSE, % >=0 SO COMPLETE SUBTRACT
		E INR,  % ADJ PARTIAL ROOT
	THEN,
	B DCR,  Z END,
% DO LAST TWO ITERATION MORE LESS EFFICIENTLY
	2 B MVI, BEGIN, 
	2 ( EXREGS, H DAD, EXREGS,
	    H DADC,  A ADC, ) % SHIFT LEFT ARGUMENT&EXTENSION BY 2 BITS
	E SLA,  D RL,  C RL,  E INR, % R <- R*2+1
	D DSBB, C SBB,  % DO SUBTRACT
	N IF,
	%	D DAD,  C  ADC,    % DONT BOTHER WITH THIS IF REMAINDER NOT
		E DCR,  % ADJ PARTIAL ROOT			% WANTED
	ELSE, % >=0 SO COMPLETE SUBTRACT
		E INR,  % ADJ PARTIAL ROOT
	THEN,
	B DCR, Z END,
	
	C SRL,  D RR,  E RR,  % CORRECT RESULT BY DIVIDING BY 2
	XCHG,  	PUSH JMP, >  % FINISHED, SO RETURN


RADIX ! % RESTORE RADIX
;F      % **EOF**


Tom Almy
Tektronix, Inc