#include iolib.h
#include float.h
#include transcen.h
#asm
;
;	transcendental floating point routines
;
;	History...
;		26 Jun 83	Added 'pow'.
;		25 Jun83	Added 'sinh', 'cosh',
;			and 'tanh'.
;		8 Nov 82	Added 'sqrt'
;		7 Nov 82	Added 'atan2'
;		17 Oct 82	removed constant pi.
;		11 Oct 82	atn => atan
;			EXP constant fixed, several labels
;			changed, references to 'int' changed
;			to 'qfloor', 'qpi' inserted.
;		23 Sept 82	Added colons after labels,
;			declaring all coefficients with DBs.
;		4 Sept 82	Separated from rest of
;			floating point routines.
;		8 Aug 82	AS.COM format source code.
;		31 Jul 82	Translated to Zilog mnemonics.
;		30 Jul 82	Disassembled from Xitan Disk
;			Basic.
;
ONE:	DW	0
	DW	0
	DW	8100H
LOGCOEF: DB	6
	DB	23H,85H,0ACH,0C3H,11H,7FH
	DB	53H,0CBH,9EH,0B7H,23H,7FH
	DB	0CCH,0FEH,0A6H,0DH,53H,7FH
	DB	0CBH,5CH,60H,0BBH,13H,80H
	DB	0DDH,0E3H,4EH,38H,76H,80H
	DB	5CH,29H,3BH,0AAH,38H,82H
;
QLOG10:	CALL	QLOG	
	LD	BC,7F5EH	; 1/ln(10)
	LD	IX,5BD8H
	LD	DE,0A938H
	JP	FMUL	
;
QLOG:	CALL	SGN	
	OR	A
	JP	PE,ILLFCT
	LD	HL,FA+5	
	LD	A,(HL)
	LD	BC,8035H	; 1/sqrt(2)
	LD	IX,04F3H
	LD	DE,33FAH
	SUB	B
	PUSH	AF
	LD	(HL),B
	PUSH	DE
	PUSH	IX
	PUSH	BC
	CALL	FADD	
	POP	BC
	POP	IX
	POP	DE
	INC	B
	CALL	FDIV	
	LD	HL,ONE	
	CALL	HLSUB	
	LD	HL,LOGCOEF
	CALL	EVENPOL
	LD	BC,8080H	; -0.5
	LD	IX,0
	LD	DE,0
	CALL	FADD	
	POP	AF
	CALL	L247E	
	LD	BC,8031H	; ln(2)
	LD	IX,7217H
	LD	DE,0F7D2H
	JP	FMUL	
;
L265F:	POP	BC
	POP	IX
	POP	DE
	JP	FMUL
;
;
QEXP:	LD	BC,8138H	;1.442695041
	LD	IX,0AA3BH
	LD	DE,295CH	
	CALL	FMUL	
	LD	A,(FA+5)
	CP	88H
	JP	NC,DIV17
	CALL	PUSHFA	
	CALL	QFLOOR	
	POP	BC
	POP	IX
	POP	DE
	PUSH	AF
	CALL	FSUB	
	LD	HL,EXPCOEF
	CALL	POLY	
	LD	HL,FA+5	
	POP	AF
	OR	A
	JP	M,EXP5	
	ADD	A,(HL)
	DB	1	;"ignore next 2 bytes"
EXP5:	ADD	A,(HL)
	CCF	
	LD	(HL),A
	RET	NC
	JP	DIV17	
;
EXPCOEF: DB	10
	DB	0CCH,0D5H,45H,56H,15H,6AH
	DB	0CFH,37H,0A0H,92H,27H,6DH
	DB	0F5H,95H,0EEH,93H,00H,71H
	DB	0D0H,0FCH,0A7H,78H,21H,74H
	DB	0B1H,21H,82H,0C4H,2EH,77H
	DB	82H,58H,58H,95H,1DH,7AH
	DB	6DH,0CBH,46H,58H,63H,7CH
	DB	0E9H,0FBH,0EFH,0FDH,75H,7EH
	DB	0D2H,0F7H,17H,72H,31H,80H
	DB	0,0,0,0,0,81H
EVENPOL: CALL	PUSHFA	
	LD	DE,L265F
	PUSH	DE
	PUSH	HL
	CALL	LDBCFA	
	CALL	FMUL	
	POP	HL
POLY:	CALL	PUSHFA	
	LD	A,(HL)
	INC	HL
	CALL	DLOAD	
	DB	0FEH	;"ignore next byte"
POL3:	POP	AF
	POP	BC
	POP	IX
	POP	DE
	DEC	A
	RET	Z
	PUSH	DE
	PUSH	IX
	PUSH	BC
	PUSH	AF
	PUSH	HL
	CALL	FMUL	
	POP	HL
	CALL	LDBCHL	
	PUSH	HL
	CALL	FADD	
	POP	HL
	JR	POL3	
;
QCOS:	LD	HL,HALFPI
	CALL	HLADD	
QSIN:	CALL	PUSHFA	
	LD	BC,08349H	;6.283185308... = 2*pi
	LD	IX,00FDAH
	LD	DE,0A222H
	CALL	LDFABC	
	POP	BC
	POP	IX
	POP	DE
	CALL	FDIV	
	CALL	PUSHFA	
	CALL	QFLOOR	
	POP	BC
	POP	IX
	POP	DE
	CALL	FSUB	
	LD	HL,QUARTER
	CALL	HLSUB	
	CALL	SGN	
	SCF	
	JP	P,SIN5	
	CALL	ADDHALF	
	CALL	SGN	
	OR	A
SIN5:	PUSH	AF
	CALL	P,MINUSFA
	LD	HL,QUARTER
	CALL	HLADD	
	POP	AF
	CALL	NC,MINUSFA
	LD	HL,SINCOEF
	JP	EVENPOL
;
EE:	DW	058A4H	;2.718281828... = e
	DW	0F854H
	DW	0822DH
HALFPI:	DB	022H,0A2H,0DAH,00FH,049H,081H ; pi/2
;	DW	0A222H
;	DW	00FDAH
;	DW	08149H
QUARTER: DW	0
	DW	0
	DW	7F00H
SINCOEF: DB	7
	DB	90H,0BAH,34H,76H,6AH,82H
	DB	0E4H,0E9H,0E7H,4BH,0F1H,84H
	DB	0B1H,4FH,7FH,3BH,28H,86H
	DB	31H,0B6H,64H,69H,99H,87H
	DB	0E4H,36H,0E3H,35H,23H,87H
	DB	24H,31H,0E7H,5DH,0A5H,86H
	DB	21H,0A2H,0DAH,0FH,49H,83H
QTAN:	CALL	PUSHFA	
	CALL	QSIN	
	POP	BC
	POP	IX
	POP	DE
	CALL	L2895	
	EX	DE,HL
	CALL	LDFABC	
	CALL	QCOS	
	JP	DIV1	
;
#endasm
pow(x,y)	/* x to the power y */
double x,y;
{	return exp(log(x)*y);
}
sinh(x) double x;
{	double e;
	e=exp(x);
	return .5*(e-1./e);
}
cosh(x) double x;
{	double e;
	e=exp(x);
	return .5*(e+1./e);
}
tanh(x) double x;
{	double e;
	e=exp(x);
	return (e-1./e)/(e+1./e);
}
#asm
;
QATAN:	CALL	SGN	
	CALL	M,ODD		;negate argument & answer
	LD	A,(FA+5)
	CP	81H
	JR	C,ATAN5		;c => argument less than 1
	LD	BC,8100H	;1.0
	LD	IX,0
	LD	D,C
	LD	E,C
	CALL	FDIV	
	LD	HL,HLSUB
	PUSH	HL	;will subtract answer from pi/2
ATAN5:	LD	HL,ATNCOEF
	CALL	EVENPOL
	LD	HL,HALFPI	;may use for subtraction
	RET	
;
ATNCOEF: DB	13
	DB	14H,7H,0BAH,0FEH,62H,75H
	DB	51H,16H,0CEH,0D8H,0D6H,78H
	DB	4CH,0BDH,7DH,0D1H,3EH,7AH
	DB	1,0CBH,23H,0C4H,0D7H,7BH
	DB	0DCH,3AH,0AH,17H,34H,7CH
	DB	36H,0C1H,0A3H,81H,0F7H,7CH
	DB	0EBH,16H,61H,0AEH,19H,7DH
	DB	5DH,78H,8FH,60H,0B9H,7DH
	DB	0A2H,44H,12H,72H,63H,7DH
	DB	16H,62H,0FBH,47H,92H,7EH
	DB	0C0H,0F0H,0BFH,0CCH,4CH,7EH
	DB	7EH,8EH,0AAH,0AAH,0AAH,7FH
	DB	0F6H,0FFH,0FFH,0FFH,07FH,80H
;/*	arc tangent of y/x  */
;atan2(y,x) double x,y;
QATAN2:
;{	double a;
	PUSH BC
	PUSH BC
	PUSH BC
;	if(fabs(x)>=fabs(y))
	LD HL,8
	ADD HL,SP
	CALL DLOAD
	CALL DPUSH
	CALL QFABS
	POP BC
	POP BC
	POP BC
	PUSH HL
	LD HL,16
	ADD HL,SP
	CALL DLOAD
	CALL DPUSH
	CALL QFABS
	POP BC
	POP BC
	POP BC
	CALL CCGE
	LD A,H
	OR L
	JP Z,ATAN23
;		{a=atan(y/x);
	LD HL,0
	ADD HL,SP
	PUSH HL
	LD HL,16
	ADD HL,SP
	CALL DLOAD
	CALL DPUSH
	LD HL,16
	ADD HL,SP
	CALL DLOAD
	CALL DDIV
	CALL DPUSH
	CALL QATAN
	POP BC
	POP BC
	POP BC
	POP HL
	CALL DSTORE
;		if(x<0.)
	LD HL,8
	ADD HL,SP
	CALL DLOAD
	CALL DPUSH
	LD HL,ATAN27+0
	CALL DLOAD
	CALL DLT
	LD A,H
	OR L
	JR Z,ATAN22
;			{if(y>=0.) a=a+3.14159265358979;
	LD HL,14
	ADD HL,SP
	CALL DLOAD
	CALL DPUSH
	LD HL,ATAN27+6
	CALL DLOAD
	CALL DGE
	LD A,H
	OR L
	JR Z,ATAN20
	LD HL,0
	ADD HL,SP
	PUSH HL
	LD HL,2
	ADD HL,SP
	CALL DLOAD
	CALL DPUSH
	LD HL,ATAN27+12
	CALL DLOAD
	CALL DADD
	POP HL
	CALL DSTORE
;			else a=a-3.14159265358979;
	JR ATAN21
ATAN20:
	LD HL,0
	ADD HL,SP
	PUSH HL
	LD HL,2
	ADD HL,SP
	CALL DLOAD
	CALL DPUSH
	LD HL,ATAN27+18
	CALL DLOAD
	CALL DSUB
	POP HL
	CALL DSTORE
ATAN21:
;			}
;		}
ATAN22:
;	else
	JR ATAN26
ATAN23:
;		{a=-atan(x/y);
	LD HL,0
	ADD HL,SP
	PUSH HL
	LD HL,10
	ADD HL,SP
	CALL DLOAD
	CALL DPUSH
	LD HL,22
	ADD HL,SP
	CALL DLOAD
	CALL DDIV
	CALL DPUSH
	CALL QATAN
	POP BC
	POP BC
	POP BC
	CALL MINUSFA
	POP HL
	CALL DSTORE
;		if(y<0.) a=a-1.57079632679489;  /* pi/2 */
	LD HL,14
	ADD HL,SP
	CALL DLOAD
	CALL DPUSH
	LD HL,ATAN27+24
	CALL DLOAD
	CALL DLT
	LD A,H
	OR L
	JR Z,ATAN24
	LD HL,0
	ADD HL,SP
	PUSH HL
	LD HL,2
	ADD HL,SP
	CALL DLOAD
	CALL DPUSH
	LD HL,ATAN27+30
	CALL DLOAD
	CALL DSUB
	POP HL
	CALL DSTORE
;		else     a=a+1.57079632679489;
	JR ATAN25
ATAN24:
	LD HL,0
	ADD HL,SP
	PUSH HL
	LD HL,2
	ADD HL,SP
	CALL DLOAD
	CALL DPUSH
	LD HL,ATAN27+36
	CALL DLOAD
	CALL DADD
	POP HL
	CALL DSTORE
ATAN25:
;		}
ATAN26:
;	return a;
	LD HL,0
	ADD HL,SP
	CALL DLOAD
	POP BC
	POP BC
	POP BC
	RET
;}
ATAN27:	DB 0,0,0,0,0,0
	DB 0,0,0,0,0,0
	DB 33,162,218,15,73,130
	DB 33,162,218,15,73,130
	DB 0,0,0,0,0,0
	DB 34,162,218,15,73,129
	DB 34,162,218,15,73,129
#endasm
#asm
;double extra; /* current approximate root */
;sqrt(x) double x;
QSQRT:
;{	char *px,	/* points to x */
	PUSH BC
;	*pextra;		/* points to extra */
	PUSH BC
;	int i;		/* loop counter */
	PUSH BC
;	if(x==0.)return 0.;
	LD HL,8
	ADD HL,SP
	CALL DLOAD
	CALL DPUSH
	LD HL,SQRT10
	CALL DLOAD
	CALL DEQ
	LD A,H
	OR L
	JR Z,SQRT2
	LD HL,SQRT10
	JP SQRT9
;	if(x<0.)
SQRT2:
	LD HL,8
	ADD HL,SP
	CALL DLOAD
	CALL DPUSH
	LD HL,SQRT10
	CALL DLOAD
	CALL DLT
	LD A,H
	OR L
	JR Z,SQRT4
;		{err("ill sqrt"); return 0.;
	LD HL,SQRT12
	PUSH HL
	CALL QERR
	POP BC
	LD HL,SQRT10
	JP SQRT9
;		}
;	px=&x; pextra=&extra;	/* set the pointers */
SQRT4:
	LD HL,4
	ADD HL,SP
	PUSH HL
	LD HL,10
	ADD HL,SP
	CALL CCPINT
	LD HL,2
	ADD HL,SP
	PUSH HL
	LD HL,EXTRA
	CALL CCPINT
;	extra=.707;	/* initialize fraction at sqrt(.5) */
	LD HL,SQRT14
	CALL DLOAD
	LD HL,EXTRA
	CALL DSTORE
;	pextra[5]=(px[5]>>1)^64; /* answer exponent is half
;				of "x" exponent */
	LD HL,2
	ADD HL,SP
	CALL CCGINT
	PUSH HL
	LD HL,5
	POP DE
	ADD HL,DE
	PUSH HL
	LD HL,6
	ADD HL,SP
	CALL CCGINT
	PUSH HL
	LD HL,5
	POP DE
	ADD HL,DE
	CALL CCGCHAR
	PUSH HL
	LD HL,1
	POP DE
	CALL CCASR
	PUSH HL
	LD HL,64
	CALL CCXOR
	POP DE
	LD A,L
	LD (DE),A
;	i=5;	/* 5 iterations of Newton's algorithm */
	LD HL,0
	ADD HL,SP
	PUSH HL
	LD HL,5
	CALL CCPINT
;	while(i--)
SQRT6:
	LD HL,0
	ADD HL,SP
	PUSH HL
	CALL CCGINT
	DEC HL
	CALL CCPINT
	INC HL
	LD A,H
	OR L
	JR Z,SQRT8
;		{extra=(extra+x/extra);
	LD HL,EXTRA
	CALL DLOAD
	CALL DPUSH
	LD HL,14
	ADD HL,SP
	CALL DLOAD
	CALL DPUSH
	LD HL,EXTRA
	CALL DLOAD
	CALL DDIV
	CALL DADD
	LD HL,EXTRA
	CALL DSTORE
;		pextra[5]--;	/* /2 */
	LD HL,2
	ADD HL,SP
	CALL CCGINT
	PUSH HL
	LD HL,5
	POP DE
	ADD HL,DE
	PUSH HL
	CALL CCGCHAR
	DEC HL
	POP DE
	LD A,L
	LD (DE),A
	INC HL
;		}
	JR SQRT6
SQRT8:
;	return extra;
	LD HL,EXTRA
SQRT9:	CALL DLOAD
	POP BC
	POP BC
	POP BC
	RET
;}
SQRT10:	DB 0,0,0,0,0,0
SQRT12:	DB 'ill sqrt',0
SQRT14:	DB 70,182,243,253,52,128
#endasm
                                           
