[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: