Difference between revisions of "Programming:Precalculated square"
From CPCWiki - THE Amstrad CPC encyclopedia!
								
												
				PulkoMandy (Talk | contribs) m  | 
				Executioner (Talk | contribs)   (Added optimised version)  | 
				||
| Line 43: | Line 43: | ||
SQTAB		DS 512		;space for the table  | SQTAB		DS 512		;space for the table  | ||
</pre>  | </pre>  | ||
| + | |||
| + | == Performance Improvements ==  | ||
| + | |||
| + | This routine can be improved somewhat by using a page-aligned table with separate pages for LSB and MSB of the result. In order to do this, the initialisation routine needs to be:  | ||
| + | |||
| + | <pre>  | ||
| + | INITSQ		LD DE, 1	;1st odd number  | ||
| + | 		LD HL, 0	;HL = 1st square number  | ||
| + | 		LD B, H		;counter = 256  | ||
| + | 		LD IX, SQTAB	;startaddress of the square table  | ||
| + | SQLOOP		LD (IX + 0), L	;Lowbyte to table  | ||
| + | 		INC HX  | ||
| + | 		LD (IX + 0), H	;Highbyte to table  | ||
| + | 		DEC HX  | ||
| + | 		INC LX  | ||
| + | 		ADD HL, DE	;add odd number  | ||
| + | 		INC DE		;next odd number  | ||
| + | 		INC DE  | ||
| + | 		DJNZ SQLOOP	;256 times  | ||
| + | 		RET  | ||
| + | </pre>  | ||
| + | |||
| + | And the routine to get the square can now be:  | ||
| + | |||
| + | <pre>  | ||
| + | GETSQ		LD L, A  | ||
| + | 		LD H, SQTAB / 256	;HL = pointer to LSB  | ||
| + | 		LD E, (HL)		;E = Lowbyte of the result  | ||
| + | 		INC H  | ||
| + | 		LD D, (HL)		;D = Highbyte of the result  | ||
| + | 		RET  | ||
| + | </pre>  | ||
| + | |||
| + | This is now a very small routine which could easily be defined as a macro for optimal performance (without the RET).  | ||
| + | |||
[[Category:Programming]]  | [[Category:Programming]]  | ||
Latest revision as of 18:37, 18 September 2007
This article describes an algorithm which precalculates the square from 0*0 to 255*255 and the routine to get the correct square value from the table.
Initialisation
Precalculate the square table.
INITSQ LD DE, 1 ;1st odd number LD HL, 0 ;HL = 1st square number LD B, H ;counter = 256 LD IX, SQTAB ;startaddress of the square table SQLOOP LD (IX), L ;Lowbyte to table INC IX LD (IX), H ;Highbyte to table INC IX ADD HL, DE ;add odd number INC DE ;next odd number INC DE DJNZ SQLOOP ;256 times RET
Get square from the table
Input: A = Factor
Output: DE = A*A
GETSQ LD L, A LD H, 0 ;HL = factor ADD HL, HL ;* 2 LD DE, SQTAB ;+ startaddress of the table ADD HL, DE ;= tableaddress LD E, (HL) ;E = Lowbyte of the result INC HL LD D, (HL) ;D = Highbyte of the result RET
Table definition
SQTAB DS 512 ;space for the table
Performance Improvements
This routine can be improved somewhat by using a page-aligned table with separate pages for LSB and MSB of the result. In order to do this, the initialisation routine needs to be:
INITSQ LD DE, 1 ;1st odd number LD HL, 0 ;HL = 1st square number LD B, H ;counter = 256 LD IX, SQTAB ;startaddress of the square table SQLOOP LD (IX + 0), L ;Lowbyte to table INC HX LD (IX + 0), H ;Highbyte to table DEC HX INC LX ADD HL, DE ;add odd number INC DE ;next odd number INC DE DJNZ SQLOOP ;256 times RET
And the routine to get the square can now be:
GETSQ LD L, A LD H, SQTAB / 256 ;HL = pointer to LSB LD E, (HL) ;E = Lowbyte of the result INC H LD D, (HL) ;D = Highbyte of the result RET
This is now a very small routine which could easily be defined as a macro for optimal performance (without the RET).