;
; Description:
;	四捨五入つき平方根
;	距離
;
; Function:
;	int pascal isqrt( long x ) ;
;	int pascal ihypot( int x, int y ) ;
;
; Parameters:
;	long x	... 平方根を求めたい数
;			0 <= x < 32767.5↑2
;			( 0 <= x <= (1073709056 = 3FFF8000h) )
;			これ以外ならばオーバーフロー
;			(a↑bはaのb乗の意味)
;
;	int x,y ... 距離を得たい座標
;
; Returns:
;	int .......... 0 〜 32767
;			x が 0 またはオーバーフローならば 0
;
; Requiring Resources:
;	CPU: i8086
;
; Author:
;	恋塚昭彦
;
; History:
;	92/ 7/31 Initial
;	92/ 8/ 1

; int ihypot( int x, int y ) ;
func IHYPOT
	push	BP
	mov	BP,SP

	@@y = (RETSIZE+2)*2
	@@x = (RETSIZE+1)*2

	mov	AX,[BP+@@x]
	imul	AX
	mov	BX,AX
	mov	CX,DX
	mov	AX,[BP+@@y]
	imul	AX
	add	BX,AX
	adc	CX,DX
	jmp	short ISQRT_ROOT
endfunc


; int pascal isqrt( long x ) ;
;
; 実装:ニュートン法
;
func ISQRT
	push	BP
	mov	BP,SP

	@@hi = (RETSIZE+2)*2
	@@lo = (RETSIZE+1)*2

	mov	BX,[BP+@@lo]
	mov	CX,[BP+@@hi]
ISQRT_ROOT:
	xor	AX,AX		; return code = 0

	mov	DX,BX
	or	DX,CX
	jz	short @@RETURN	; x = 0 なら return 0
	cmp	CX,03FFFh	; 0〜3FFF8000hでなければ OverFlow! return 0
	ja	short @@RETURN
	jne	short @@GO
	cmp	BX,08000h
	ja	short @@RETURN
@@GO:
	push	SI

	shl	BX,1		; CX:BX = x
	rcl	CX,1
	shl	BX,1
	rcl	CX,1		; x *= 4 ;
	or	CX,CX
if 0
	mov	SI,0FFFFh
	jnz	short @@LLOOP
	mov	SI,8		; SI: y, BP: lasty
else
	jz	short @@BXLOOPS

	mov	SI,1	; 8000h rol 1
	mov	AX,3	; 0c000h rol 2
@@CXLOOP:
	ror	SI,1
	ror	AX,1
	ror	AX,1
	test	CX,AX
	jz	short @@CXLOOP
	or	AX,AX
	jns	short @@LLOOP
	mov	SI,0FFFFh	; 最上位bitが立っている場合は overflowを
	jmp	short @@LLOOP	; 防ぐため特例として 0FFFFhを初期値にする

@@BXLOOPS:
	mov	SI,100h	; 80h rol 1
	mov	AX,3	; 0c000h rol 2
@@BXLOOP:
	ror	SI,1
	ror	AX,1
	ror	AX,1
	test	BX,AX
	jz	short @@BXLOOP
	; jmp short LLOOP
endif

@@LLOOP:
	mov	BP,SI		; lasty = y
	mov	AX,BX
	mov	DX,CX
	div	SI
	add	SI,AX
	rcr	SI,1		; y = ((unsigned long)x / y + y)/ 2 ;
	cmp	SI,AX
	je	short @@LEXIT
	cmp	SI,BP
	jne	short @@LLOOP	; if ( y != lasty ) goto LLOOP ;
@@LEXIT:
	xor	AX,AX
	shr	SI,1
	adc	AX,SI		; lasty = y & 1 ; return y / 2 + lasty ;

	pop	SI
@@RETURN:
	pop	BP
	ret	4
endfunc