[Prev][Next][Index][Thread]
A85: 16-bit integer Square Root
The GUESS=(GUESS+X/GUESS)/2 algorithm works fine on floating points, but
is no good for intergers. I used a binary search kind of method. It
calculates square root of an integer and rounds it down.
#include "ti-85.h"
VAR1 = TEXT_MEM
.org
.db "SQRT by Jarno Rajala",0
ld hl,0
ld (CURSOR_ROW),hl
ld hl,54564
CALL_(SQRT)
ROM_CALL(D_HL_DECI)
GKE:
call GET_KEY
or a
jr z,GKE
ret
SQRT: ;hl=sqrt(hl) rounded to down
ld (VAR1),hl
ld a,c
cp 0
jr nz,SQRT1
ld a,b
cp 2
ret c
SQRT1:
ld b,7
ld e,128
ld c,128
SQRT3:
push de
push bc
ld b,0
ld d,0
ld e,c
CALL_(MUL)
pop bc
ld de,(VAR1)
or a
sbc hl,de
pop de
jr c,SQRT2
jr z,SQRTE
ld a,c
sub e
ld c,a
SQRT2:
or a
rr e
ld a,c
add a,e
ld c,a
djnz SQRT3
push de
push bc
ld b,0
ld d,0
ld e,c
CALL_(MUL)
pop bc
ld de,(VAR1)
or a
sbc hl,de
pop de
jr c,SQRTE
ld a,c
sub e
ld c,a
SQRTE:
ld l,c
ld h,0
ret
MUL: ;hl=bc*de
ld ix,0
ld hl,0
MUL3:
ld a,c ;if bc==0 ret
cp 0
jr nz,MUL1
ld a,b
cp 0
ret z
MUL1:
bit 0,c ;if bit0 of bc is not set -> add hl,de
jr z,MUL2
add hl,de
MUL2:
or a ;bc=bc/2
rr b
rr c
or a ;de=de*2
rl e
rl d
jr MUL3
DIV: ;hl=hl/de
ld a,0
DIV0:
bit 7,d
jr nz,DIV1
or a
rl e ;de=de*2;
rl d
inc a
jr DIV0
DIV1:
inc a
ld ix,0
ld bc,0
DIV3:
push hl ;bc=bc+de
ld l,c
ld h,b
add hl,de
ld b,h
ld c,l
pop hl
push de ;ix=ix*2
push ix
pop de
or a
rl e
rl d
push de
pop ix
ld de,1 ;ix=ix+1
add ix,de
pop de
push hl
or a ;compare hl to bc
sbc hl,bc
jr nc,DIV2
ld l,c ;hl < bc
ld h,b ;bc=bc-de
or a
sbc hl,de
ld b,h
ld c,l
push de
ld de,-1 ;ix=ix-1
add ix,de
pop de
DIV2:
pop hl
or a
rr d ;de=de/2
rr e
dec a
jr nz,DIV3
push ix
pop hl
ret
.end
Follow-Ups: