Google
 

Trailing-Edge - PDP-10 Archives - BB-D480G-SB_FORTRAN10_V11.0_short - mthcgx.mac
There are 9 other files named mthcgx.mac in the archive. Click here to see a list.

	SEARCH	MTHPRM
	TV	MTHCGX	COMPLEX GFLOAT DOUBLE PRECISION ROUTINES ,1(4014)

;COPYRIGHT (c) DIGITAL EQUIPMENT CORPORATION 1979, 1987
;ALL RIGHTS RESERVED.
;
;THIS SOFTWARE IS FURNISHED UNDER A LICENSE AND MAY BE USED AND COPIED
;ONLY  IN  ACCORDANCE  WITH  THE  TERMS  OF  SUCH LICENSE AND WITH THE
;INCLUSION OF THE ABOVE COPYRIGHT NOTICE.  THIS SOFTWARE OR ANY  OTHER
;COPIES THEREOF MAY NOT BE PROVIDED OR OTHERWISE MADE AVAILABLE TO ANY
;OTHER PERSON.  NO TITLE TO AND OWNERSHIP OF THE  SOFTWARE  IS  HEREBY
;TRANSFERRED.

;THE INFORMATION IN THIS SOFTWARE IS SUBJECT TO CHANGE WITHOUT  NOTICE
;AND  SHOULD  NOT  BE  CONSTRUED  AS A COMMITMENT BY DIGITAL EQUIPMENT
;CORPORATION.

;DIGITAL ASSUMES NO RESPONSIBILITY FOR THE USE OR RELIABILITY  OF  ITS
;SOFTWARE ON EQUIPMENT WHICH IS NOT SUPPLIED BY DIGITAL.

	SUBTTL	REVISION HISTORY

COMMENT \

***** Begin Revision History *****

1404	EGM	6-Apr-81	--------
	Separate CDX and CGX routines.

1405	DAW	6-Apr-81
	Extended addressing support.

1464	DAW	12-May-81
	Error messages.

***** Begin Version 6A *****

2055	TGS	10-May-82	10-32471
	Fix typo in CDLOG so STOR POPJs instead of POPing P and
	plowing into YZRO.

***** Begin Mathlib *****

3200	JLC	10-May-82
	Mathlib integration. Change all LERRs to $LCALLs. Change
	TWOSEG/RELOC to SEGMENT macros.

***** Begin Version 1A *****

3237	RVM	30-Mar-83
	CGSQRT was not returning the primary square root (ie, the
	result was not in the right half-plane).  In addition,
	there was an instruction which confused register T3 with
	P3, and the underflow code didn't zero the result.

3255	20-19901	MRB	19-Nov-84
	The CGLOG routine is returning an incorrect value for the case
	(0,0) returns (+inifinity,0) should be (-infinity,0).

4014	MRB	18-Jul-84
	The double precision sine and cosine functions destroy the
	input variables. The result field gets written over the 
	input variable in some cases.

***** End Revision History *****

\

	PRGEND
TITLE	CGABS	COMPLEX ABSOLUTE VALUE FUNCTION
;		(DOUBLE PRECISION GFLOATING POINT)
SUBTTL	IMSL, INC.	JUNE 1, 1979

;COPYRIGHT (c) DIGITAL EQUIPMENT CORPORATION 1979, 1987
;ALL RIGHTS RESERVED.
;
;THIS SOFTWARE IS FURNISHED UNDER A LICENSE AND MAY BE USED AND COPIED
;ONLY  IN  ACCORDANCE  WITH  THE  TERMS  OF  SUCH LICENSE AND WITH THE
;INCLUSION OF THE ABOVE COPYRIGHT NOTICE.  THIS SOFTWARE OR ANY  OTHER
;COPIES THEREOF MAY NOT BE PROVIDED OR OTHERWISE MADE AVAILABLE TO ANY
;OTHER PERSON.  NO TITLE TO AND OWNERSHIP OF THE  SOFTWARE  IS  HEREBY
;TRANSFERRED.

;THE INFORMATION IN THIS SOFTWARE IS SUBJECT TO CHANGE WITHOUT  NOTICE
;AND  SHOULD  NOT  BE  CONSTRUED  AS A COMMITMENT BY DIGITAL EQUIPMENT
;CORPORATION.

;DIGITAL ASSUMES NO RESPONSIBILITY FOR THE USE OR RELIABILITY  OF  ITS
;SOFTWARE ON EQUIPMENT WHICH IS NOT SUPPLIED BY DIGITAL.

SEARCH	MTHPRM
NOSYM
ENTRY	CGABS
EXTERN	CGABS.
CGABS=CGABS.
PRGEND
TITLE	CGABS.	COMPLEX ABSOLUTE VALUE FUNCTION
;		(DOUBLE PRECISION GFLOATING POINT)
SUBTTL	IMSL, INC.	JUNE 1, 1979

;COPYRIGHT (c) DIGITAL EQUIPMENT CORPORATION 1979, 1987
;ALL RIGHTS RESERVED.
;
;THIS SOFTWARE IS FURNISHED UNDER A LICENSE AND MAY BE USED AND COPIED
;ONLY  IN  ACCORDANCE  WITH  THE  TERMS  OF  SUCH LICENSE AND WITH THE
;INCLUSION OF THE ABOVE COPYRIGHT NOTICE.  THIS SOFTWARE OR ANY  OTHER
;COPIES THEREOF MAY NOT BE PROVIDED OR OTHERWISE MADE AVAILABLE TO ANY
;OTHER PERSON.  NO TITLE TO AND OWNERSHIP OF THE  SOFTWARE  IS  HEREBY
;TRANSFERRED.

;THE INFORMATION IN THIS SOFTWARE IS SUBJECT TO CHANGE WITHOUT  NOTICE
;AND  SHOULD  NOT  BE  CONSTRUED  AS A COMMITMENT BY DIGITAL EQUIPMENT
;CORPORATION.

;DIGITAL ASSUMES NO RESPONSIBILITY FOR THE USE OR RELIABILITY  OF  ITS
;SOFTWARE ON EQUIPMENT WHICH IS NOT SUPPLIED BY DIGITAL.

;CGABS(Z) IS CALCULATED AS FOLLOWS

;  LET Z = X + I*Y
;  V = MAX(GABS(X),GABS(Y))
;  W = MIN(GABS(X),GABS(Y))
;  THEN
;	CGABS = V*GSQRT(1.0 + (W/V)**2)

;THE RANGE OF DEFINITION FOR CGABS IS THE REPRESENTABLE REAL NUMBERS.
;  AN OVERFLOW CAN OCCUR, IN WHICH CASE CGABS = + MACHINE INFINITY.

;REQUIRED (CALLED) ROUTINES:  GSQRT

;REGISTERS T2, T3, T4, AND T5 WERE SAVED, USED, AND RESTORED

;THE ROUTINE HAS THE FOLLOWING CALLING SEQUENCE:

;  XMOVEI	L,ARG
;  PUSHJ	P,CGABS

;THE ROUTINE IS CALLED WITH A DOUBLE PRECISION VECTOR.
;THE REAL PART OF THE ARGUMENT IS EXPECTED TO BE STORED IN THE
;FIRST DOUBLE PRECISION WORD. THE IMAGINARY PART OF THE ARGUMENT
;IS EXPECTED TO BE STORED IN THE SECOND DOUBLE PRECISION WORD.
;THE HIGH ORDER PART OF THE ANSWER IS RETURNED IN T0
;THE LOW ORDER PART OF THE ANSWER IS RETURNED IN T1

	SEARCH	MTHPRM
	SEGMENT	CODE
	SALL

	HELLO	(CGABS,.)	;ENTRY TO MODULUS ROUTINE
	PUSH	P,T2
	PUSH	P,T3
	XMOVEI	T2,@(L)		
	DMOVE	T0,(T2)		;ABS(X)
	JUMPGE	T0,XPOS		;IF X IS NEGATIVE
	  DMOVN	T0,T0		;X = -X
XPOS:	DMOVE	T2,2(T2)	;ABS(Y)
	JUMPGE	T2,YPOS		;IF Y IS NEGATIVE
	  DMOVN	T2,T2		;Y = -Y

;OBTAIN MAX(ABS(X),ABS(Y))IN T2 AND MIN IN T0.
;ONLY THE HIGH WORDS ARE COMPARED, WHICH CAN RESULT IN THE MAX AND MIN
;BEING INTERCHANGED IF |X| AND |Y| ARE VERY NEARLY EQUAL.  THIS IS OK.
;IT CAN RESULT IN SMALLER/LARGER BEING SLIGHTLY GREATER THAN 1.

YPOS:	CAMG	T0,T2		;COMPARE |X|HI WITH |Y|HI
	  JRST	LT		;|X| IS GREATER, NO EXCHANGE NECESSARY
	EXCH	T2,T0		;EXCHANGE ABS(X) AND ABS(Y)
	EXCH	T3,T1		;
LT:	JUMPE	T2,RET		;Z = 0, HENCE CGABS = O
	GFDV	T0,T2		;DIVIDE SMALLER BY LARGER; NO OVERFLOW
	   JFCL ANS		;  RATIO NEGLIGIBLE IF UNDERFLOW.
	CAMG	T0,TWOM30	;IF RATIO .LE. 2**(-30)
	   JRST	ANS		;  RATIO IS NEGLIBLE.
	GFMP	T0,T0		;**2
	GFAD	T0,ONE		;+1.0
	DMOVEM	T0,TEMP		
	FUNCT	GSQRT.,<TEMP>	;SQUARE ROOT IS IN AC T0
	GFMP	T0,T2		;*V 
	  JFCL	OVFL		;NO UNDERFLOW, GET MESSAGE ON OVERFLOW
RET:	POP	P,T3
	POP	P,T2
	GOODBY	(1)		;RETURN

OVFL:	$LCALL	ATI
;LERR	(LIB,%,<CGABS: CGABS(arg) too large; result=+infinity>)
RET1:	POP	P,T3
	POP	P,T2
	GOODBY	(1)		;RETURN

ANS:	DMOVE	T0,T2		;ANSWER = ABS(LARGER) TO T0
	POP	P,T3
	POP	P,T2
	GOODBY	(1)		;RETURN

ONE:	DOUBLE	200140000000,000000000000
TWOM30:	174340000000		;2**(-30)

	SEGMENT	DATA
TEMP:	DOUBLE	0,0		;TEMPORARY STORAGE USED FOR SQRT CALL

	PRGEND
TITLE	CGEXP	COMPLEX EXPONENTIAL FUNCTION
;		(DOUBLE PRECISION GFLOATING POINT)
SUBTTL	IMSL, INC.	JUNE 1, 1979

;COPYRIGHT (c) DIGITAL EQUIPMENT CORPORATION 1979, 1987
;ALL RIGHTS RESERVED.
;
;THIS SOFTWARE IS FURNISHED UNDER A LICENSE AND MAY BE USED AND COPIED
;ONLY  IN  ACCORDANCE  WITH  THE  TERMS  OF  SUCH LICENSE AND WITH THE
;INCLUSION OF THE ABOVE COPYRIGHT NOTICE.  THIS SOFTWARE OR ANY  OTHER
;COPIES THEREOF MAY NOT BE PROVIDED OR OTHERWISE MADE AVAILABLE TO ANY
;OTHER PERSON.  NO TITLE TO AND OWNERSHIP OF THE  SOFTWARE  IS  HEREBY
;TRANSFERRED.

;THE INFORMATION IN THIS SOFTWARE IS SUBJECT TO CHANGE WITHOUT  NOTICE
;AND  SHOULD  NOT  BE  CONSTRUED  AS A COMMITMENT BY DIGITAL EQUIPMENT
;CORPORATION.

;DIGITAL ASSUMES NO RESPONSIBILITY FOR THE USE OR RELIABILITY  OF  ITS
;SOFTWARE ON EQUIPMENT WHICH IS NOT SUPPLIED BY DIGITAL.

SEARCH	MTHPRM
NOSYM
ENTRY	CGEXP
EXTERN	CGEXP.
CGEXP=CGEXP.
PRGEND
TITLE	CGEXP.	COMPLEX EXPONENTIAL FUNCTION
;		(DOUBLE PRECISION GFLOATING POINT)
SUBTTL	IMSL, INC.	JUNE 1, 1979

;COPYRIGHT (c) DIGITAL EQUIPMENT CORPORATION 1979, 1987
;ALL RIGHTS RESERVED.
;
;THIS SOFTWARE IS FURNISHED UNDER A LICENSE AND MAY BE USED AND COPIED
;ONLY  IN  ACCORDANCE  WITH  THE  TERMS  OF  SUCH LICENSE AND WITH THE
;INCLUSION OF THE ABOVE COPYRIGHT NOTICE.  THIS SOFTWARE OR ANY  OTHER
;COPIES THEREOF MAY NOT BE PROVIDED OR OTHERWISE MADE AVAILABLE TO ANY
;OTHER PERSON.  NO TITLE TO AND OWNERSHIP OF THE  SOFTWARE  IS  HEREBY
;TRANSFERRED.

;THE INFORMATION IN THIS SOFTWARE IS SUBJECT TO CHANGE WITHOUT  NOTICE
;AND  SHOULD  NOT  BE  CONSTRUED  AS A COMMITMENT BY DIGITAL EQUIPMENT
;CORPORATION.

;DIGITAL ASSUMES NO RESPONSIBILITY FOR THE USE OR RELIABILITY  OF  ITS
;SOFTWARE ON EQUIPMENT WHICH IS NOT SUPPLIED BY DIGITAL.

;CGEXP(Z), WHERE Z = X + I*Y, IS CALCULATED AS FOLLOWS

;    CGEXP(Z) = GEXP(X)*(GCOS(Y)+I*GSIN(Y))
;THE RANGE OF DEFINITION FOR CGEXP IS AS FOLLOWS

;FOR Z = X+I*Y, IF GABS(Y) .GT. 6746518850.429 THE RESULT IS SET TO
;    (0.0,0.0) AND AN ERROR MESSAGE IS RETURNED.

;FOR X.LT. -710.475860073943942 THE RESULT IS SET TO (0.0,0.0) AND AN ERROR
;    MESSAGE IS RETURNED.

;FOR X .GT. 709.089565;
;    IF Y = 0.0, THE RESULT IS SET TO (+INFINITY,0.0) AND AN
;    ERROR MESSAGE IS RETURNED.
;    IF 709.089565 < X < 1418.179131425648102, AND A COMPONENT OF THE RESULT
;    IS OUT OF RANGE, THEN AN ERROR MESSAGE IS RETURNED AND
;    ONLY THAT COMPONENT IS SET TO +INFINITY.
;    IF X/2. IS .GT. 709.089565, THE GABS(DREAL(RESULT)) IS SET TO
;    +INFINITY AND GABS(DIMAG(RESULT)) IS SET TO +INFINITY AND
;    AN ERROR MESSAGE IS RETURNED.

;REQUIRED (CALLED) ROUTINES:  GEXP,GSIN,GCOS

;REGISTERS T2, T3, T4, AND T5 WERE SAVED, USED, AND RESTORED

;THE ROUTINE HAS THE FOLLOWING CALLING SEQUENCE:

;  XMOVEI	L,ARG
;  PUSHJ	P,CGEXP

;THE ROUTINE IS CALLED WITH TWO DOUBLE PRECISION VECTORS.
;THE REAL PART OF THE ARGUMENT IS EXPECTED TO BE STORED IN THE
;FIRST DOUBLE PRECISION WORD OF THE FIRST VECTOR.
;THE IMAGINARY PART OF THE ARGUMENT IS EXPECTED TO BE STORED IN THE
;SECOND DOUBLE PRECISION WORD OF THE FIRST VECTOR.
;THE REAL PART OF THE SOLUTION IS RETURNED IN THE FIRST DOUBLE
;PRECISION WORD OF THE SECOND VECTOR.
;THE IMAGINARY PART OF THE SOLUTION IS RETURNED IN THE SECOND DOUBLE
;PRECISION WORD OF THE SECOND VECTOR.

	SEARCH	MTHPRM
	SEGMENT	CODE
	SALL

	HELLO	(CGEXP.,CGEXP)	;ENTRY TO CGEXP ROUTINE
	PUSH	P,T2		;SAVE REGISTER T2
	PUSH	P,T3		;SAVE REGISTER T3
	PUSH	P,T4		;SAVE REGISTER T4
	XMOVEI	T2,@(L)		;GET ADDRESS OF Z
	DMOVE	T0,(T2)		;X=DREAL(Z)
	DMOVE	T2,2(T2)	;Y=IMAG(Z)
	DMOVEM	T2,YSAVQ	;SAVE Y
	JUMPGE	T2,QPOS
	  DMOVN	T2,T2
QPOS:	CAMGE	T2,QYMAXH	;IF HI OF Y < QYMAXH
	  JRST	QYOK		;  GO TO QYOK
	CAME	T2,QYMAXH	;IF HI OF Y > QYMAXH
	  JRST ERQ1		;  GO TO ERQ1
	CAMG	T3,QYMAXL	;IF LO OF Y .LE. QYMAXL
	  JRST	QYOK		;  GO TO QYOK
ERQ1:	$LCALL	AIZ
;LERR	(LIB,%,<CGEXP: DIMAG(arg) too large in absolute value; result=(0.0,0.0)>)
	SETZ	T0,		;REAL PART OF SOLUTION IS ZERO
	SETZ	T1,
	SETZ	T2,		;IMAG PART OF SOLUTION IS ZERO
	SETZ	T3,
	XMOVEI	T4,@1(L)	;GET ADDRESS OF 2ND ARGUMENT
	DMOVEM	T0,(T4)		;SAVE REAL PART OF RESULT
	DMOVEM	T2,2(T4)	;SAVE IMAG PART OF RESULT
	POP	P,T4		;RESTORE ACCUMULATORS
	POP	P,T3
	POP	P,T2
	GOODBY	(1)

QYOK:	PUSH	P,T5		;SAVE ANOTHER REGISTER
	DMOVEM	T0,QXSAVE	;SAVE X
	CAMLE	T0,QNEGH		;IF HI OF X > QNEGH
	  JRST	QXOK		;  GO TO QXOK
	CAME	T0,QNEGH		;IF HI OF X < QNEGH
	  JRST	QER		;  GO TO QER
	CAML	T1,QNEGL		;IF LO OF X .GE. QNEGL
	  JRST	QXOK		;  GO TO QXOK
QER:	SETZ	T0,		;DREAL PART OF SOLUTION IS ZERO
	SETZ	T1,
	SETZ	T2,		;IMAG PART OF SOLUTION IS ZERO
	SETZ	T3,
	JRST	QYCHK		;CHECK Y

QXOK:	FUNCT	GCOS.,<YSAVQ>	;QCOSY=GCOS(Y)
	DMOVEM	T0,QCOSY		
	FUNCT	GSIN.,<YSAVQ>	;GSINY=GSIN(Y)
	DMOVEM	T0,QSINY	
	DMOVE	T4,QXSAVE	;T4=X
	CAMG	T4,QMAXH	;IF X IS NOT TOO LARGE
	  JRST	QALG		;GO TO QALG
	SKIPN	YSAVQ		;ELSE, IF Y=0
	  JRST	QMSTK		;GO TO QMSTK
	CAMGE	T4,QTBIGH	;IF HI OF S < QTBIGH
	  JRST	QSOK		;  GO TO QSOK
	CAME	T4,QTBIGH	;IF HI OF S > QTBIGH
	  JRST	QSTIM		;  GO TO QSTIM
	CAMLE	T5,QTBIGL	;IF LO OF S > QTBIGL
	  JRST	QSTIM		;  GO TO QSTIM
QSOK:	EXTEND	T4,[GFSC -1]	;ELSE, S=X/2
	DMOVEM	T4,QEXPX
	FUNCT	GEXP.,<QEXPX>	;T=EXP(S)
	DMOVE	T2,T0		
	GFMP	T2,QSINY	;V=T*QSINY
	JUMPGE	T2,QVPOS		;IF V IS NEGATIVE
	  DMOVN	T2,T2		;NEGATE IT
QVPOS:	HRLOI	T4,377777	;G3=XMAX
	SETO	T5,
	GFDV	T4,T0		;Q=XMAX/T
	DMOVEM	T4,QQH		;SAVE Q
	CAMLE	T2,T4		;IF V .GT. Q
	  JRST	QSTIM		;THEN GO TO QSTIM
	CAME	T2,QQH		;IF V .LT. Q
	  JRST	QGETI		;THEN GO TO QGETI
	CAMG	T3,QQL		;IF V .LE. Q
	  JRST	QGETI		;THEN GO TO QGETI

QSTIM:	HRLOI	T2,377777	;ELSE, SET IMAG SOLUTION TO XMAX
	SETO	T3,
	$LCALL	RTI
;LERR	(LIB,%,<CGEXP: DREAL(arg) too large; DIMAG(result)=+infinity>)
	JRST	QD2
	
QGETI:	GFMP	T2,T0		;IRES = V*T
QD2:	SKIPGE	QSINY		;IF SINY IS LESS THAN 0.0			
	  DMOVN	T2,T2		;THEN NEGATE IRES
	MOVE	T4,QXSAVE
	CAMGE	T4,QTBIGH	;IF HI OF S < QTBIGH
	  JRST 	QOKS		;  GO TO QOKS
	CAME	T4,QTBIGH	;IF HI OF S > QTBIGH
	  JRST	QMSTK		;  GO TO QMSTK
	CAMLE	T5,QTBIGL	;IF LO OF S > QTBIGL
	  JRST	QMSTK		;  GO TO QMSTK
QOKS:	DMOVE	T4,T0
	GFMP	T0,QCOSY	;V = T*QCOSY
	JUMPGE	T0,QVOK		;IF V IS NEGATIVE
	  DMOVN	T0,T0		;NEGATE IT
QVOK:	CAMLE	T0,QQH		;IF V .GT. Q
	  JRST	QMSTK		;THEN GO TO QMSTK
	CAME	T0,QQH		;IF V .LT. Q		
	JRST	QQLAB		;THEN GO TO QQLAB
	CAMG	T1,QQL		;IF V IS .LE. Q
	JRST	QQLAB		;THEN GO TO QQLAB

QMSTK:	HRLOI	T0,377777	;RRES=XMAX
	SETO	T1,
	$LCALL	RTR
;LERR	(LIB,%,<CGEXP: DREAL(arg) too large; DREAL(result)=+infinity>)
	JRST	DQD2

QQLAB:	GFMP	T0,T4		;RRES = V*T
DQD2:	SKIPGE	QCOSY		;IF QCOSY .LT. 0.0
	  DMOVN	T0,T0		;THEN NEGATE RRES
	XMOVEI	T4,@1(L)	;GET ADDRESS OF 2ND ARGUMENT
	DMOVEM	T0,(T4)		;SAVE REAL PART OF RESULT
	DMOVEM	T2,2(T4)	;SAVE IMAG PART OF RESULT
	POP	P,T5		;RESTORE ACCUMULATORS
	POP	P,T4
	POP	P,T3
	POP	P,T2
	GOODBY	(1)		;RETURN

QALG:	FUNCT	GEXP.,<QXSAVE>	;QEXPX = DEXP(X)
	DMOVE	T2,T0
	GFMP	T2,QSINY	;IRES = QEXPX*QSINY
	JFCL
	GFMP	T0,QCOSY	;RRES = QEXPX*QCOSY
	JFCL
	JUMPN	T2,QRCHK		;IF IRES .NE. 0.0
	  			;THEN GO CHECK RRES

QYCHK:	SKIPN	YSAVQ		;IF Y .EQ. 0
	  JRST QRCHK		;THEN GO CHECK RRES
	$LCALL	IPU
;LERR	(LIB,%,<CGEXP: underflow has occurred; DIMAG(result)=0.0>)

QRCHK:	JUMPN	T0,QRET		;IF R = 0.0
	$LCALL	RPU
;LERR	(LIB,%,<CGEXP: underflow has occurred; DREAL(result)=0.0>)

QRET:	XMOVEI	T4,@1(L)	;GET ADDRESS OF 2ND ARGUMENT
	DMOVEM	T0,(T4)		;SAVE REAL PART OF RESULT
	DMOVEM	T2,2(T4)	;SAVE IMAG PART OF RESULT
	POP	P,T5		;RESTORE ACCUMULATORS
	POP	P,T4
	POP	P,T3
	POP	P,T2
    	GOODBY	(1)		;RETURN

QYMAXH:	203762207732		;HIGH ORDER PART OF YMAX
QYMAXL:	242102643021		;LOW ORDER PART OF YMAX
QTBIGH:	201354242673		;1418.179131425648102
QTBIGL:	161647554056
QNEGH:	576523460613		;-710.475860073943942
QNEGL:	202140360224
QMAXH:	201254242673		;709.089565

	SEGMENT	DATA
QQH:	0
QQL:	0
QSINY:   DOUBLE	0,0
QCOSY:   DOUBLE	0,0
QXSAVE:  DOUBLE	0,0
QEXPX:   DOUBLE	0,0
YSAVQ:  DOUBLE	0,0

	PRGEND
TITLE	CGLOG	COMPLEX NATURAL LOG FUNCTION
;		(DOUBLE PRECISION GFLOATING POINT)
SUBTTL	IMSL, INC.	JUNE 1, 1979

;COPYRIGHT (c) DIGITAL EQUIPMENT CORPORATION 1979, 1987
;ALL RIGHTS RESERVED.
;
;THIS SOFTWARE IS FURNISHED UNDER A LICENSE AND MAY BE USED AND COPIED
;ONLY  IN  ACCORDANCE  WITH  THE  TERMS  OF  SUCH LICENSE AND WITH THE
;INCLUSION OF THE ABOVE COPYRIGHT NOTICE.  THIS SOFTWARE OR ANY  OTHER
;COPIES THEREOF MAY NOT BE PROVIDED OR OTHERWISE MADE AVAILABLE TO ANY
;OTHER PERSON.  NO TITLE TO AND OWNERSHIP OF THE  SOFTWARE  IS  HEREBY
;TRANSFERRED.

;THE INFORMATION IN THIS SOFTWARE IS SUBJECT TO CHANGE WITHOUT  NOTICE
;AND  SHOULD  NOT  BE  CONSTRUED  AS A COMMITMENT BY DIGITAL EQUIPMENT
;CORPORATION.

;DIGITAL ASSUMES NO RESPONSIBILITY FOR THE USE OR RELIABILITY  OF  ITS
;SOFTWARE ON EQUIPMENT WHICH IS NOT SUPPLIED BY DIGITAL.

SEARCH	MTHPRM
NOSYM
ENTRY	CGLOG
EXTERN	CGLOG.
CGLOG=CGLOG.
PRGEND
TITLE	CGLOG	COMPLEX NATURAL LOG FUNCTION
;		(DOUBLE PRECISION FLOATING POINT)
SUBTTL  Mary Payne	8-Sep-80

;COPYRIGHT (c) DIGITAL EQUIPMENT CORPORATION 1979, 1987
;ALL RIGHTS RESERVED.
;
;THIS SOFTWARE IS FURNISHED UNDER A LICENSE AND MAY BE USED AND COPIED
;ONLY  IN  ACCORDANCE  WITH  THE  TERMS  OF  SUCH LICENSE AND WITH THE
;INCLUSION OF THE ABOVE COPYRIGHT NOTICE.  THIS SOFTWARE OR ANY  OTHER
;COPIES THEREOF MAY NOT BE PROVIDED OR OTHERWISE MADE AVAILABLE TO ANY
;OTHER PERSON.  NO TITLE TO AND OWNERSHIP OF THE  SOFTWARE  IS  HEREBY
;TRANSFERRED.

;THE INFORMATION IN THIS SOFTWARE IS SUBJECT TO CHANGE WITHOUT  NOTICE
;AND  SHOULD  NOT  BE  CONSTRUED  AS A COMMITMENT BY DIGITAL EQUIPMENT
;CORPORATION.

;CDLOG(Z) IS CALCULATED AS FOLLOWS

;  CDLOG FIRST CHECKS THE TYPE OF THE ARGUMENT SO THAT THE
;  APPROPRIATE RESULT (D OR G) IS RETURNED.

;  LET Z = X + I*Y

;  IF Y IS NOT ZERO, THEN
;    CDLOG(Z) = U + I*V
;      U = (1/2) * (DLOG (X**2 + Y**2))
;      V = DATAN2(Y,X)

;  IF X IS NOT ZERO AND Y IS ZERO, THEN
;    IF X IS POSITIVE, CDLOG(Z) = DLOG(X)
;    IF X IS NEGATIVE, CDLOG(Z) = DLOG(ABS(X)) + I*PI

;  IF X AND Y ARE ZERO, THEN
;    CDLOG(Z) = +MACHINE INFINITY
;    AND AN ERROR MESSAGE IS RETURNED

;REQUIRED (CALLED) ROUTINES:  DLOG, DATAN, DATAN2

;REGISTERS T2, T3, T4, AND T5 WERE SAVED, USED, AND RESTORED

;THE ROUTINE HAS THE FOLLOWING CALLING SEQUENCE:

;  XMOVEI	L,ARG
;  PUSHJ	P,CDLOG

;THE ROUTINE IS CALLED WITH TWO DOUBLE PRECISION VECTORS.
;THE REAL PART OF THE ARGUMENT IS EXPECTED TO BE STORED IN THE
;FIRST DOUBLE PRECISION WORD OF THE FIRST VECTOR.
;THE IMAGINARY PART OF THE ARGUMENT IS EXPECTED TO BE STORED IN THE
;SECOND DOUBLE PRECISION WORD OF THE FIRST VECTOR.
;THE REAL PART OF THE SOLUTION IS RETURNED IN THE FIRST DOUBLE
;PRECISION WORD OF THE SECOND VECTOR.
;THE IMAGINARY PART OF THE SOLUTION IS RETURNED IN THE SECOND DOUBLE
;PRECISION WORD OF THE SECOND VECTOR.

	SEARCH  MTHPRM
	SEGMENT	CODE
	SALL

	HELLO	(CGLOG.,CGLOG)		;ENTRY TO CGLOG ROUTINE
	PUSH	P,T2		;SAVE ACCUMULATORS
	PUSH	P,T3		
	PUSH	P,T4
	XMOVEI  T2,@(L)		;GET ADDRESS OF ARG
	DMOVE	T0,(T2)		;OBTAIN REAL PART OF ARGUMENT
	DMOVE	T2,2(T2)	;OBTAIN IMAG PART OF ARGUMENT

	JUMPE	T2,YZRO		;Y = 0 IS A SPECIAL CASE

	JUMPE	T0,XZRO		;X = 0 IS A SPECIAL CASE

	PUSH	P,T5		;SAVE ANOTHER REGISTER
	DMOVEM  T0,TT0		;SAVE COPIES OF X AND
	DMOVEM  T2,TT2		; Y FOR FUTURE REFERENCE
	JUMPGE	T0,XPLUS	;IF X < 0
	DMOVN	T0,T0		;  NEGATE IT
XPLUS:	JUMPGE	T2,YPLUS	;IF Y < 0
	DMOVN	T2,T2		;  NEGATE IT
YPLUS:	DMOVEM	T0,TT4		;SAVE MAGNITUDES OF
	DMOVEM	T2,TT6		;  X AND Y
	AND	T0,MASK		;ISOLATE EXPONENT FIELDS
	AND	T2,MASK		;  OF X AND Y
	SUB	T2,T0		;EXPONENT OF Y - EXPONENT OF X
	CAML	T2,P30		;IF DIFFERENCE > 30
	JRST	BIG		;  |Y/X| IS LARGE
	CAMGE	T2,M30		;IF DIFFERENCE < -30
	JRST	SMALL		;  |Y/X| IS SMALL

	FUNCT	GATN2.,<TT2,TT0> ;NO EXCEPTIONS CAN OCCUR
	XMOVEI  T4,@1(L)	;GET POINTER AND STORE
	DMOVEM  T0,2(T4)	; IMAGINARY PART OF RESULT

	DMOVE	T4,TT4		;RECOVER |X|
	DMOVE	T2,TT6		;RECOVER |Y|
	CAML	T4,T2		;IF |X|HI .GE. |Y|HI,
	  JRST  NOXCH		;NO EXCHANGE NECESSARY
	EXCH	T4,T2		;|X|HI .LT. |Y|HI.  LARGER TO T4
	EXCH	T5,T3		; SMALLER TO T2
NOXCH:  MOVE	T1,T4		;HI OF LARGER TO T1
	LSH	T1,-30		;ISOLATE ITS BIASED EXPONENT
	SUBI	T1,2000		;  AND UNBIAS IT
	JUMPLE  T1,LE		;IF UNBIASED EXPONENT POSITIVE,
	  SUBI  T1,1		;  DECREMENT IT
LE:	MOVN	T1,T1		;NEGATE SCALE INDEX
	EXTEND  T4,[GFSC (T1)]  ;SCALE LARGER TO [1/2,2)
	EXTEND  T2,[GFSC (T1)]  ;  AND SMALLER BY SAME FACTOR
	  JFCL			;NO OVERFLOW, UNDERFLOW WON'T MATTER
	LSH	T1,1		;MULTIPLY NEGATED SCALE INDEX BY 2
	DMOVEM  T4,BIGGER	;SAVE SCALED LARGER OF |X| AND |Y|
	GFMP	T4,T4		;SQUARE LARGER.  NO EXCEPTIONS
	GFMP	T2,T2		;SQUARE SMALLER.  NO OVERFLOW AND
	  JFCL			;  UNDERFLOW WON'T MATTER
	GFAD	T4,T2		;GET SCALED SQUARE OF MODULUS
	CAMLE	T4,RT2		;IF T4 .GT. SQRT(2)HI
	  JRST  MORE		;  GO TO MORE SCALING
	CAMGE	T4,RT2O2	;IF T4 .LT. SQRT(1/2)HI
	  JRST  MORE		;  GO TO MORE SCALING
	JUMPN	T1,JOIN		;IF SCALE INDEX NOT 0, GO TO JOIN
	MOVEM	T1,NN		;  ELSE STORE 0 FOR FUTURE USE

;At this point the scale index is zero, which means that (A**2 + B**2)
;is unscaled. Also (A**2 + B**2) is between SQRT(1/2) and SQRT(2),
;which implies that a damaging loss of significance can occur in the
;calculation of (A**2 + B**2 - 1), which is one factor of Z, used
;in the rational approximation. Growth of error due to loss of
;significance can be avoided by calculating instead

	DMOVE	T4,BIGGER	;RECOVER LARGER
	DMOVE	T0,T4		;  AND COPY INTO T0
	GFSB	T0,ONE		;GET A - 1
	GFAD	T4,ONE		;AND A + 1
	GFMP	T4,T0		;AND THEIR PRODUCT
	GFAD	T2,T4		;T2 NOW HAS A**2 + B**2 - 1
	DMOVE	T4,T2		;COPY IT INTO T4
	GFAD	T2,TWO		;GET DENOMINATOR OF Z IN T2
	EXTEND  T4,[GFSC 1]	;  AND NUMERATOR IN T4
	JRST	MERGE		;MERGE FOR RATIONAL APPROX

;The following code applies to scaled values of (A**2 + B**2) lying
;outside the interval (SQRT(1/2),SQRT(2)); it carries out more
;scaling to get the scaled (A**2 + B**2) inside this interval.

MORE:	MOVE	T2,T4		;HI OF T4 TO T2 FOR RESCALING
	LSH	T2,-30		;ISOLATE ITS BIASED EXPONENT
	SUBI	T2,2000		;UNBIAS THE EXPONENT
	MOVN	T2,T2		;  AND NEGATE IT
	EXTEND  T4,[GFSC (T2)]  ;T4 NOW IN [1/2,1)
	ADD	T1,T2		;TOTAL NEGATED SCALE INDEX TO T1
	CAML	T4,RT2O2	;IF T4 .GT. SQRT(1/2)
	  JRST  JOIN		;  SCALING IS DONE
	EXTEND  T4,[GFSC 1]	;SCALE T4 TO [1,SQRT(2)]
	ADDI	T1,1		;  AND INCREMENT NEGATED INDEX

;At this point the scaled (A**2 + B**2) is in the interval
;[SQRT(1/2),SQRT(2)]. T1 contains the negative of the index
;necessary to compensate later for the scaling.  In the following
;lines of code, the index, together with its proper sign is
;temporarily stored.  Then a rational approximation is used to
;evaluate the natural log of the scaled (A**2 + B**2).

JOIN:	MOVNM	T1,NN		;STORE FINAL INDEX FOR FUTURE USE
	DMOVE	T2,T4		;GET COPY OF SCALED (A**2 + B**2)
	GFSB	T4,ONE		;SUBTRACT ONE AND MULTIPLY BY TWO
	EXTEND  T4,[GFSC 1]	;  TO GET NUMERATOR OF Z IN T4
	GFAD	T2,ONE		;GET DENOMINATOR OF Z IN T2

;The following code is taken from the DLOG routine.  The constants
;A0, A1, A2, B0, B1, and B2 are those given in the DLOG routine.
;Note that all tests restricting the scaled (A**2 + B**2) to
;the interval (SQRT(1/2),SQRT(2)) have been carried out only
;on the "high" words of these limiting values.  This is
;adequate for the validity of the approximation to be used,
;since only low order bits, and not the order of magnitude,
;of the error bound of the approximation are affected.

MERGE:  GFDV	T4,T2		;Z = ZNUM / ZDEN
	DMOVEM  T4,SAVEZ	;SAVE A COPY OF Z
	GFMP	T4,T4		;W = Z**2
	DMOVE	T0,T4		;  AND MAKE COPY
	GFAD	T4,B2		;FORM B(W) = W + B2
	GFMP	T4,T0		;  * W
	GFAD	T4,B1		;  + B1
	GFMP	T4,T0		;  * W
	GFAD	T4,B0		;  + B0
	DMOVE	T2,T0		;MAKE ANOTHER COPY OF 2
	GFMP	T0,A2		;FORM A(W) = W * A2
	GFAD	T0,A1		;  + A1
	GFMP	T0,T2		;  * W
	GFAD	T0,A0		;  + A0
	GFDV	T0,T4		;R(Z) = A(W) / B(W)
	GFMP	T0,SAVEZ	;  * Z
	GFMP	T0,T2		;  * W
	  JFCL			;NO OVERFLOW, UNDERFLOW WON'T HURT

;As indicated in the DLOG routine, Z still needs to be added into R(Z). 
;To increase accuracy, this addition is deferred until after the
;addition, below, of NN * LN(2))LO to the part of R(Z) so far
;obtained.

	EXTEND  T2,[GFLTR NN]	;RECOVER SCALE INDEX
	JUMPN	T2,REST		;IF NN = 0,
	GFAD	T0,SAVEZ	;  COMPLETE R(Z) BY ADDING IN Z
	JRST	DONE		;GO STORE RESULT AND RESTORE REGISTERS

;The following lines of code complete the calculation of the real
;part for NN not zero.  The real part is the sum of NN*(LN(2)HI),
;Z, R(Z), and NN*(LN(2)LO).  Of these terms the first is guaranteed
;to have the largest magnitude.  THe second has magnitude larger
;than the third by a factor of at least 2**7, and the last has
;magnitude smaller than the first by at least a factor of 2**(-10).
;The maximum value of |Z| is about 2/7, and this is the worst case
;from the point of view of accuracy, because it is only slightly
;smaller than (LN(2)HI).  The calculation of Z is accurate to a
;small multiple of its LSB, and hence the calculation of the sum
;is limited to a small multiple of ITS LSB.  Note that if |Z| is
;appreciably less than its bound of 2/7, the error bound of the
;sum decreases towards its LSB/2.  THe overall accuracy will be
;maximized by summing the terms in the reverse order in which
;they are listed above.

REST:	DMOVE	T4,T2		;GET COPY IN T4
	GFMP	T4,C2		;GET NN * LN(2)LO
	GFMP	T2,C1		;GET NN * LN(2)HI
	GFAD	T0,T4		;R(Z) + NN * LN(2)LO
	GFAD	T0,SAVEZ	;  + Z
	GFAD	T0,T2		;  + NN * LN(2)HI
	
DONE:	EXTEND  T0,[GFSC -1]	;DIVIDE BY 2 TO GET LOG OF MODULUS
	DMOVEM  T0,@1(L)	;STORE REAL PART OF RESUUT

	POP	P,T5
	POP	P,T4
	POP	P,T3
	POP	P,T2
	POPJ	P,		;DONE


BIG:	FUNCT	GLOG.,<TT6>	;GET LN(|Y|)
	DMOVE	T2,DPIO2	;IMAGINARY PART NEAR +/- PI/2
	SKIPGE	TT2		;  + FOR Y POSITIVE
	DMOVN	T2,T2		;  - FOR Y NEGATIVE
	DMOVE	T4,TT4		;RECOVER |X|
	GFDV	T4,TT2		;GET |X/Y|. NO OVERFLOW
	JFCL	UND1		;  UNDERFLOW IS POSSIBLE
	JRST	SMERG		;MERGE WITH SMALL

SMALL:	FUNCT	GLOG.,<TT4>	;GET LN(|X|)
	SETZ	T2,		;IMAGINARY PART IS NEAR
	SETZ	T3,		;  0 OR +/- PI
	SKIPGE	TT0		;0 FOR X POSITIVE
	DMOVE	T2,CPI		;  +/-PI FOR X NEGATIVE
	SKIPGE	TT2		;    + PI FOR Y POSITIVE
	DMOVN	T2,T2		;    - PI FOR Y NEGATIVE
	DMOVE	T4,TT6		;RECOVER Y
	GFDV	T4,TT4		;GET Y/X. NO OVERFLOW
	JFCL	UND2		;  UNDERFLOW IS POSSIBLE
SMERG:	GFAD	T2,T4		;SMALL CORRECTION FOR IMAG
	GFMP	T4,T4		;GET (Y/X)**2. NO OVERFLOW
	  JFCL	UND1		;  INDERFLOW IS POSSIBLE
	EXTEND	T4,[GFSC -1]	;(1/2)*(Y/X)**2. NO OVERFLOW
	JFCL	UND1		;  UNDERFLOW IS POSSIBLE
	GFAD	T0,T4		;REAL = LN(|X|) + (1/2)*(Y/X)**2
	JRST	STOR		;NO EXCEPTIONS. GO STORE RESULTS

UND2:	JUMPN	T2,UND1		;NO MESSAGE IF |IMAG| NEAR PI OR PI/2
	$LCALL	IPU
;LERR	(LIB,%,<CDLOG: Imaginary part underflow>)

UND1:	JUMPN	T0,STOR		;NO MESSAGE IF LN NOT ZERO
	$LCALL	RPU
;LERR	(LIB,%,<CDLOG: Real part underflow>)

STOR:	XMOVEI	T4,@1(L)	;GET ADRESS FOR RESULTS
	DMOVEM	T0,(T4)		;STORE REAL PART
	DMOVEM	T2,2(T4)	;STORE IMAGINARY PART
	POP	P,T5		;RESTORE REGISTERS T5
	POP	P,T4
	POP	P,T3
	POP	P,T2		;THROUGH T2

	POPJ	P,		;RETURN

YZRO:	JUMPE	T0,XYZRO	;X = Y = 0 IS A SPECIAL CASE
	JUMPGE	T0,RPOS		;Y IS 0, X ISN'T. IF X < 0
	DMOVN	T0,T0		;X=ABS(X)
	DMOVE	T2,CPI		;V=PI

RPOS:	DMOVEM  T0,TT0		;MOVE X TO MEMORY
	FUNCT	GLOG.,<TT0>	;COMPUTE U=DLOG(X); NO EXCEPTIONS
	JRST	DONE1

XZRO:	DMOVE	T0,T2		;X IS 0, Y ISN'T. COPY Y TO T0
	DMOVE	T2,DPIO2	;IMAG PART IS +/- PI/2
	JUMPGE  T0,YPOS		;IF Y < 0,
	DMOVN	T0,T0		; MAKE IT POSITIVE, AND
	DMOVN	T2,T2		; MAKE IMAG PART NEGATIVE
YPOS:	DMOVEM  T0,TT0		;PREPARE TO GET LOG
	FUNCT	GLOG.,<TT0>	;GET LOG(|Y|), NO EXCEPTIONS

DONE1:  XMOVEI  T4,@1(L)	;GET THE ADDRESS OF THE SECOND ARGUMENT
	DMOVEM  T0,(T4)		;SAVE THE REAL PART OF THE ANSWER
	DMOVEM  T2,2(T4)	;SAVE THE IMAG PART OF THE ANSWER
	POP	P,T4
	POP	P,T3		;RESTORE ACCUMULATORS
	POP	P,T2		
	POPJ	P,		;RETURN

XYZRO:	$LCALL	ZIZ
;LERR	(LIB,%,<CDLOG: arg is (0.0,0.0); result=(-infinity,0.0)>);[3255]

	HRLOI	T0,777777	;[3255]REAL ANSWER IS NEGATIVE INFINITY
	SETO	T1,		;
	XMOVEI  T4,@1(L)	;GET THE ADDRESS OF THE SECOND ARGUMENT
	DMOVEM  T0,(T4)		;SAVE THE REAL PART OF THE ANSWER 
	DMOVEM  T2,2(T4)	;SAVE THE IMAG PART OF THE ANSWER
	POP	P,T4
	POP	P,T3		;RESTORE ACCUMULATORS
	POP	P,T2	
	POPJ	P,		;RETURN

;CONSTANTS

ONE:	EXP 200140000000,000000000000	;1.0
TWO:	EXP 200240000000,000000000000	;2.0
MASK:	EXP 377700000000		;EXPONENT MASK
P30:	EXP 003600000000		;HIGH 12 BITS = 36 OCTAL
M30:	EXP 774200000000		;HIGH 12 BITS = -36 OCTAL
CPI:	EXP 200262207732,242102643022	;PI
DPIO2:  EXP 200162207732,242102643022	;PI / 2
RT2O2:  EXP 200055202363		;SQRT(2) / 2
RT2:	EXP 200155202363		;SQRT(2)
A0:	EXP 577037740007,152304514557	;-.641249434237455811D2
A1:	EXP 200540611121,000552775450	;.163839435630215342D2
A2:	EXP 577715357522,145224132710	;-.789561128874912573D0
B0:	EXP 576517720013,037446761043	;-.769499321084948798D3
B1:	EXP 201147002037,320522317572	;.312032220919245328D3
B2:	EXP 577134251775,244603076112	;-.356679777390346462D2
B3:	EXP 577640000000,000000000000	;-1
C1:	EXP 200054300000,000000000000	;LN(2)HI
C2:	EXP 601310277575,034757152745	;LN(2)LO

;DATA
	SEGMENT	DATA
TT0:	BLOCK	2			;FOR GATN2 AND GLOG CALLS
TT2:	BLOCK	2			;FOR GATN2 CALL
TT4:	BLOCK	2			;FOR ABS(X)
TT6:	BLOCK	2			;FOR ABS(Y)
NN:	BLOCK	2			;FOR SCALE INDEX
BIGGER: BLOCK	2
SAVEZ:  BLOCK	2

	PRGEND
TITLE	CGSIN	COMPLEX SINE FUNCTION
;		(DOUBLE PRECISION GFLOATING)
SUBTTL	IMSL, INC.	JUNE 1, 1979

;COPYRIGHT (c) DIGITAL EQUIPMENT CORPORATION 1979, 1987
;ALL RIGHTS RESERVED.
;
;THIS SOFTWARE IS FURNISHED UNDER A LICENSE AND MAY BE USED AND COPIED
;ONLY  IN  ACCORDANCE  WITH  THE  TERMS  OF  SUCH LICENSE AND WITH THE
;INCLUSION OF THE ABOVE COPYRIGHT NOTICE.  THIS SOFTWARE OR ANY  OTHER
;COPIES THEREOF MAY NOT BE PROVIDED OR OTHERWISE MADE AVAILABLE TO ANY
;OTHER PERSON.  NO TITLE TO AND OWNERSHIP OF THE  SOFTWARE  IS  HEREBY
;TRANSFERRED.

;THE INFORMATION IN THIS SOFTWARE IS SUBJECT TO CHANGE WITHOUT  NOTICE
;AND  SHOULD  NOT  BE  CONSTRUED  AS A COMMITMENT BY DIGITAL EQUIPMENT
;CORPORATION.

;DIGITAL ASSUMES NO RESPONSIBILITY FOR THE USE OR RELIABILITY  OF  ITS
;SOFTWARE ON EQUIPMENT WHICH IS NOT SUPPLIED BY DIGITAL.

SEARCH  MTHPRM
NOSYM
ENTRY	CGSIN
EXTERN	CGSIN.
CGSIN=CGSIN.
PRGEND
TITLE	CGCOS	COMPLEX COSINE FUNCTION
;		(DOUBLE PRECISION GFLOATING)
SUBTTL	IMSL, INC.	JUNE 1, 1979

;COPYRIGHT (c) DIGITAL EQUIPMENT CORPORATION 1979, 1987
;ALL RIGHTS RESERVED.
;
;THIS SOFTWARE IS FURNISHED UNDER A LICENSE AND MAY BE USED AND COPIED
;ONLY  IN  ACCORDANCE  WITH  THE  TERMS  OF  SUCH LICENSE AND WITH THE
;INCLUSION OF THE ABOVE COPYRIGHT NOTICE.  THIS SOFTWARE OR ANY  OTHER
;COPIES THEREOF MAY NOT BE PROVIDED OR OTHERWISE MADE AVAILABLE TO ANY
;OTHER PERSON.  NO TITLE TO AND OWNERSHIP OF THE  SOFTWARE  IS  HEREBY
;TRANSFERRED.

;THE INFORMATION IN THIS SOFTWARE IS SUBJECT TO CHANGE WITHOUT  NOTICE
;AND  SHOULD  NOT  BE  CONSTRUED  AS A COMMITMENT BY DIGITAL EQUIPMENT
;CORPORATION.

;DIGITAL ASSUMES NO RESPONSIBILITY FOR THE USE OR RELIABILITY  OF  ITS
;SOFTWARE ON EQUIPMENT WHICH IS NOT SUPPLIED BY DIGITAL.

SEARCH  MTHPRM
NOSYM
ENTRY	CGCOS
EXTERN	CGCOS.
CGCOS=CGCOS.
PRGEND
TITLE	CGSIN.	COMPLEX SINE FUNCTION
;		(DOUBLE PRECISION GFLOATING)
SUBTTL	IMSL, INC.	JUNE 1, 1979

;COPYRIGHT (c) DIGITAL EQUIPMENT CORPORATION 1979, 1987
;ALL RIGHTS RESERVED.
;
;THIS SOFTWARE IS FURNISHED UNDER A LICENSE AND MAY BE USED AND COPIED
;ONLY  IN  ACCORDANCE  WITH  THE  TERMS  OF  SUCH LICENSE AND WITH THE
;INCLUSION OF THE ABOVE COPYRIGHT NOTICE.  THIS SOFTWARE OR ANY  OTHER
;COPIES THEREOF MAY NOT BE PROVIDED OR OTHERWISE MADE AVAILABLE TO ANY
;OTHER PERSON.  NO TITLE TO AND OWNERSHIP OF THE  SOFTWARE  IS  HEREBY
;TRANSFERRED.

;THE INFORMATION IN THIS SOFTWARE IS SUBJECT TO CHANGE WITHOUT  NOTICE
;AND  SHOULD  NOT  BE  CONSTRUED  AS A COMMITMENT BY DIGITAL EQUIPMENT
;CORPORATION.

;DIGITAL ASSUMES NO RESPONSIBILITY FOR THE USE OR RELIABILITY  OF  ITS
;SOFTWARE ON EQUIPMENT WHICH IS NOT SUPPLIED BY DIGITAL.

;CGSIN(Z) AND CGCOS(Z), WHERE Z = X + I*Y, ARE CALCULATED AS FOLLOWS

;  CGSIN(Z) =GSIN(X)*GCOSH(Y) + I*GCOS(X)*GSINH(Y)
;  CGCOS(Z) =GCOS(X)*GCOSH(Y) - I*GSIN(X)*GSINH(Y)

;  THE FUNCTIONS GSINH AND GCOSH ARE CODED IN LINE.

;THE RANGE OF DEFINITION FOR GDSIN AND GDCOS IS AS FOLLOWS
;FOR
;      Z = X+I*Y.  IF GABS(X) > ((2**29)*PI - PI/2) THE RESULT IS SET TO 0.0 AND
;      AN ERROR MESSAGE IS RETURNED.

;  THE REAL PART OF THE RESULT CANNOT UNDERFLOW BECAUSE
;  COSH(Y) IS NEVER LESS THAN 1.	

;  THE IMAGINARY PART OF THE RESULT MAY UNDERFLOW; IF THIS HAPPENS THE
;  IMAGINARY PART IS SET TO 0 AND A MESSAGE IS PROVIDED.

;FOR GABS(Y) > 88.029692 CALCULATIONS PROCEED AS FOLLOWS:

;      FOR THE REAL PART OF THE RESULT

;          LET T = GABS(GSIN(X)), THEN

;          FOR T = 0.0 THE REAL PART OF THE RESULT IS SET TO 0.0
;          FOR GLOG(T) + GABS(Y) - GLOG(2.0) > 88.722839 THE REAL PART OF THE 
;          RESULT IS SET TO PLUS OR MINUS MACHINE INFINITY AND
;          AN ERROR MESSAGE IS RETURNED. (88.722839=88.029692+LN2)

;      FOR THE IMAGINARY PART OF THE RESULT

;          LET T = GABS(GCOS(X)), THEN

;          FOR T = 0.0 THE IMAGINARY PART OF THE RESULT IS SET TO 0.0
;          FOR GLOG(T) + GABS(Y) - GLOG(2.0) > 88.722839 THE IMAGINARY PART OF THE
;          RESULT IS SET TO PLUS OR MINUS MACHINE INFINITY AND
;          AN ERROR MESSAGE IS RETURNED. (88.722839=88.029692+LN2)


;REQUIRED (CALLED) ROUTINES:  GSIN,GCOS,GEXP,GLOG

;REGISTERS T2, T3, T4, AND T5 WERE SAVED, USED, AND RESTORED

;THE ROUTINE HAS THE FOLLOWING CALLING SEQUENCE:

;  XMOVEI	L,ARG
;  PUSHJ	P,CGSIN
;	OR
;  PUSHJ	P,CGCOS

;THE ROUTINE IS CALLED WITH TWO DOUBLE PRECISION VECTORS.
;THE REAL PART OF THE ARGUMENT IS EXPECTED TO BE STORED IN THE
;FIRST DOUBLE PRECISION WORD OF THE FIRST VECTOR.
;THE IMAGINARY PART OF THE ARGUMENT IS EXPECTED TO BE STORED IN THE
;SECOND DOUBLE PRECISION WORD OF THE FIRST VECTOR.
;THE REAL PART OF THE SOLUTION IS RETURNED IN THE FIRST DOUBLE
;PRECISION WORD OF THE SECOND VECTOR.
;THE IMAGINARY PART OF THE SOLUTION IS RETURNED IN THE SECOND DOUBLE
;PRECISION WORD OF THE SECOND VECTOR.

	SEARCH	MTHPRM
	SEGMENT	CODE
	SALL

	HELLO	(CGCOS.,CGCOS)		;ENTRY TO CGCOS ROUTINE
	PUSH	P,T5
	MOVEI	T5,1			;SET FLAG TO 1 FOR CGCOS
	JRST	GSTRT			;GO TO CGSIN ROUTINE

	HELLO	(CGSIN.,CGSIN)		;ENTRY TO CGSIN ROUTINE
	PUSH	P,T5
GBEG:	SETZI	T5,			;SET FLAG TO 0 FOR CGSIN

GSTRT:	PUSH	P,T2
	PUSH	P,T3
	PUSH	P,T4
	XMOVEI	T2,@(L)			;GET ADDRESS OF ARG
	DMOVE	T0,(T2)			;X = REAL(Z)
	DMOVE	T3,T0			;MOVE REAL PART OF ARG TO T3,T4
	JUMPGE	T3,QXPOS			;IF REAL PART OF ARG < 0
	  DMOVN	T3,T3			;REAL PART=ABS(REAL PART)
QXPOS:	CAMLE	T3,XMAXQH		;IF ABS(X) IS TOO LARGE
	  JRST	QERR1			;GO TO QERR1
	CAME	T3,XMAXQH		;IF ABS(X) IS LESS THAN XMAXQH
	  JRST	QXOK			;GO TO QXOK
	CAMG	T4,XMAXQL		;IF ABS(X) IS NOT TOO LARGE
	  JRST	QXOK			;GO TO QXOK
QERR1:	$LCALL	ARZ
;LERR	(LIB,%,<CGSIN or CGCOS: GABS(DREAL(arg)) too large; result = (0.0,0.0)>)
	SETZI	T0,			;SET REAL(RESULT) TO 0.0
	SETZ	T1,
	SETZI	T2,			;SET IMAG(RESULT) TO 0.0
	SETZ	T3,
	XMOVEI	T4,@1(L)		;GET ADDRESS OF 2ND ARGUMENT
	DMOVEM	T0,(T4)			;SAVE REAL PART OF RESULT
	DMOVEM	T2,2(T4)		;SAVE IMAGINARY PART OF RESULT
	POP	P,T4			;RESTORE ACCUMULATORS
	POP	P,T3
	POP	P,T2
	POP	P,T5
	GOODBY	(1)			;RETURN

QXOK:	DMOVE	T2,2(T2)		;Y = IMAG(Z)
	DMOVEM	T2,YSAVQ		;SAVE Y
	DMOVEM	T0,ARGSVQ
	FUNCT	GSIN.,<ARGSVQ>		;CALCULATE GSIN(X)
	DMOVEM	T0,SXQ			;SXQ = GSIN(X)
	FUNCT	GCOS.,<ARGSVQ>		;CALCULATE GCOS(X)
	DMOVEM	T0,CXQ			;CXQ = GCOS(X)
	JUMPE	T5,NQSWT		;IF THIS IS THE CGSIN ROUTINE
	  				;THEN GO TO NQSWT
	DMOVN	T2,SXQ			;OTHERWISE, PUT -GSIN(X)
	EXCH	T2,CXQ			;IN CXQ, AND COS(X)
	EXCH	T3,CXQL
	DMOVEM	T2,SXQ			;IN SXQ.

NQSWT:	DMOVE	T2,YSAVQ		;GET A COPY OF Y
   	JUMPG	T2,QYPOS			;IF Y IS NEGATIVE
	  DMOVN	T2,T2			;NEGATE IT
QYPOS:	CAMGE	T2,XQHI			;IF HI OF AY < XQHI
	  JRST	YSMALQ			;  GO TO YSMALQ
	CAME	T2,XQHI			;IF HI OF AY > XQHI
	  JRST	OVFLQ			;  GO TO OVFLQ
	CAMLE	T3,XQLO			;IF LO OF AY > XQLO
	  JRST	OVFLQ			;  GO TO OVFLQ
YSMALQ:	CAMG	T2,TWQM29		;IF ABS(Y) .LE. 2**(-29)
	  JRST	QEASY			;  GO TO QEASY CODE.
	CAMGE	T2,ONEQ			;IS ABS(Y) .GE. 1?
	  JRST	LSTH7			;  BRANCH IF NOT
	DMOVEM	T2,ARGSVQ		;GET COPY OF ABS(Y)
	FUNCT	GEXP.,<ARGSVQ>		;GET EXP(ABS(Y))
	DMOVE	T4,ONEQ			;GET EXP(-ABS(Y)) BY
	GFDV	T4,T0			;  RECIPROCATION.
	GFSB	T0,T4			;T0 GETS 
	EXTEND	T0,[GFSC -1]		;  SINH(ABS(Y))
	JRST	CCCQ			;TO REST OF CALCULATION
LSTH7:	DMOVNM	T2,ARGSVQ		;  SO AS TO GET
	FUNCT	GEXP.,<ARGSVQ>		;  EXP(-ABS(Y))
	DMOVE	T4,T0			;SAVE 1/T IN T4
	GFMP	T2,T2			;SS = AY**2
	DMOVEM	T2,TEMPQ		;SAVE A COPY OF SS
	GFAD	T2,QQ2			;XDEN = QQ2 +SS
	GFMP	T2,TEMPQ		;*SS
	GFAD	T2,QQ1			;+QQ1
	GFMP	T2,TEMPQ		;*SS
	GFAD	T2,QQ0			;+QQ0
	DMOVE	T0,TEMPQ		;SAVE A COPY OF SS
	GFMP	T0,RPQ3			;XNUM = RPQ3*SS
	GFAD	T0,RPQQ2		;+RPQQ2
	GFMP	T0,TEMPQ		;*SS
	GFAD	T0,RPQQ1		;+RPQQ1
	GFMP	T0,TEMPQ		;*SS
	GFAD	T0,RPQQ0		;+RPQQ0
	GFDV	T0,T2			;XNUM/XDEN
	DMOVN	T2,ARGSVQ		;GET AY BACK
	GFMP	T0,TEMPQ		;*SS
	GFMP	T0,ARGSVQ		;*(-AY)
	GFAD	T0,T2			;+AY

CCCQ:	DMOVE	T2,T0
     	GFAD	T0,T4			;CC = SS+(1/T)
	DMOVE	T4,YSAVQ		;RESTORE Y
	JUMPGE	T4,YOKQ			;IF Y IS LESS THAN 0.0
	  DMOVN	T2,T2			;THEN NEGATE SS
YOKQ:	GFMP	T0,SXQ			;GET REAL PART OF RESULT
	GFMP	T2,CXQ			;GET IMAG PART OF RESULT
	  JFCL	QIMUND			;UNDERFLOW POSSIBLE
	XMOVEI	T4,@1(L)		;GET ADDRESS OF 2ND ARGUMENT
	DMOVEM	T0,(T4)			;SAVE REAL PART OF RESULT
	DMOVEM	T2,2(T4)		;SAVE IMAGINARY PART OF RESULT
	POP	P,T4			;RESTORE ACCUMULATORS
	POP	P,T3
	POP	P,T2
	POP	P,T5
	GOODBY	(1)			;RETURN

OVFLQ:	DMOVE	T0,SXQ			;T=SXQ
	JUMPE	T0,GOTRQ		;IF T IS EQUAL TO 0.
	JUMPG	T0,SQXPOS		;IF SXQ IS NEGATIVE
  	DMOVN	T0,T0			;NEGATE SXQ
SQXPOS:	DMOVEM	T0,ARGSVQ		;OTHERWISE
	FUNCT	GLOG.,<ARGSVQ>		;CALCULATE LOG(T)
	GFAD	T0,T2			;T = LOG(T)+AY
	GFAD	T0,LN2Q			;T = T-LOG(2.0)
	CAMGE	T0,XQHI			;IF HI OF T < XQHI
	  JRST	QONTIN			;  GO TO QONTIN
	CAME	T0,XQHI			;IF HI OF T > XQHI
	  JRST	QERR2			;  GO TO QERR2
	CAMG	T1,XQLO			;IF LO OF T .LE. XQLO
	  JRST	QONTIN			; GO TO QONTIN
QERR2:	$LCALL	AIR
;LERR	(LIB,%,<CGSIN or CGCOS: GABS(DIMAG(arg)) too large; DREAL(result) = infinity>)
	HRLOI	T0,377777	        ;REAL PART OF RESULT SET TO INFINITY
	SETO	T1,			;SET SECOND WORD
	JRST	SKPQQ2			;SKIP NEXT 2 INSTRUCTIONS

QONTIN:	DMOVEM	T0,ARGSVQ
	FUNCT	GEXP.,<ARGSVQ>		;RRES = EXP(T)

SKPQQ2:	SKIPGE	SXQ			;IF SXQ IS LESS THAN 0.
	  DMOVN	T0,T0			;THEN NEGATE RRES

GOTRQ:	SKIPN	T4,CXQ		        ;IF CXQ = 0,
	   JRST	IMAG7			;THEN PREPARE TO RETURN
	MOVE	T5,CXQL			;OTHERWISE GET LOWER WORD
	DMOVEM	T0,SXQ			;SAVE RRES
	JUMPGE	T4,TPOSQ		;IF T IS NEGATIVE
	  DMOVN	T4,T4			;THEN GET ABS(T)
TPOSQ:	DMOVEM	T4,ARGSVQ
	FUNCT	GLOG.,<ARGSVQ>		;CALCULATE T=LOG(T)
	GFAD	T2,T0			;T = T+AY
	GFAD	T2,LN2Q			;T = T-LOG(2)
	CAMGE	T2,XQHI			;IF HI OF T < XQHI
	  JRST	QONTN2			;  GO TO QONTN2
	CAME	T2,XQHI			;IF HI OF T > XQHI
 	  JRST	QERR3			;GO TO QERR3
	CAMG	T3,XQLO			;IF LO OF T .LE. XQLO
	  JRST	QONTN2			;  GO TO QONTN2
QERR3:	$LCALL	AII
;LERR	(LIB,%,<CGSIN or CGCOS: GABS(DIMAG(arg)) too large; DIMAG(result) = infinity>)
	HRLOI	T2,377777		;SET IRES TO INFINITY
	SETO	T3,
	JRST	SKPQ3			;SKIP NEXT 3 INSTRUCTIONS
	
QONTN2:	DMOVEM	T2,ARGSVQ
	FUNCT	GEXP.,<ARGSVQ>		;IRES = EXP(T)
	DMOVE	T2,T0

SKPQ3:	DMOVE	T0,SXQ
	MOVE	T4,YSAVQ
	XOR	T4,CXQ			;T4 HAS THE SIGN OF CXQ*Y
	JUMPGE	T4,RETQ			;IF T4 IS LESS THAN 0.
	  DMOVN	T2,T2			;THEN NEGATE IRES
	JRST    RETQ			;RETURN
IMAG7:	SETZ	T2,			;SET IMAGINARY PART
	SETZ	T3,			;  OF RESULT TO ZERO.
	JRST	RETQ			;RETURN

QEASY:	DMOVE	T2,YSAVQ		;GET SIGNED VALUE OF Y
	GFMP	T2,CXQ			;SINH(Y)*COS(X) = Y*COS(X)
	  JFCL	QIMUND			;  UNDERFLOW POSSIBLE
	DMOVE	T0,SXQ			;COSH(Y)*SIN(X) = SIN(X).

RETQ:	XMOVEI	T4,@1(L)		;[4014]GET ADDRESS OF 2ND ARGUMENT
	DMOVEM	T0,(T4)			;SAVE REAL PART OF RESULT
	DMOVEM	T2,2(T4)		;SAVE IMAGINARY PART OF RESULT
	POP	P,T4
	POP	P,T3
	POP	P,T2
	POP	P,T5
	GOODBY	(1)

QIMUND:	$LCALL	IPU,RETQ
;LERR	(LIB,%,<CDSIN or CDCOS: imaginary part underflow>,RETQ)

TWQM29:	174440000000				;2**(-29)
XQHI:	201254242673				;709.089565712824051
XQLO:	161647554056				;
XMAXQH:	203762207732				;HIGH ORDER 2**29 * PI
XMAXQL:	236772245275				;LOW ORDER  2**29 * PI
ONEQ:	DOUBLE	200140000000,000000000000
LN2Q:    DOUBLE  577723506750,010134302063       ;-(NATURAL LOG OF 2.0)          
RPQQ0:    DOUBLE  202352744232,262463203065       ;.35181283430177117881D+6       
RPQQ1:    DOUBLE  201655127025,264501221757       ;.11563521196851768270D+5       
RPQQ2:    DOUBLE  201050741013,034133711232       ;.16375798202630751372D+3       
RPQ3:    DOUBLE  200062423475,303374403264       ;.78966127417357099479D+0       
QQ0:     DOUBLE  575137624613,372031435521       ;-.21108770058106271242D+7      
QQ1:     DOUBLE  202043241271,035545730675       ;.36162723109421836460D+5       
QQ2:     DOUBLE  576635220743,361550001577       ;-.27773523119650701667D+3      

	SEGMENT	DATA
CXQ:	0
CXQL:	0
SXQ:	DOUBLE	0,0
YSAVQ:	DOUBLE	0,0
ARGSVQ: DOUBLE	0,0
TEMPQ:	DOUBLE	0,0

	PRGEND
TITLE	CGSQRT	COMPLEX SQUARE ROOT FUNCTION
;		(DOUBLE PRECISION GFLOATING POINT)
SUBTTL	IMSL, INC.	JUNE 1, 1979

;COPYRIGHT (c) DIGITAL EQUIPMENT CORPORATION 1979, 1987
;ALL RIGHTS RESERVED.
;
;THIS SOFTWARE IS FURNISHED UNDER A LICENSE AND MAY BE USED AND COPIED
;ONLY  IN  ACCORDANCE  WITH  THE  TERMS  OF  SUCH LICENSE AND WITH THE
;INCLUSION OF THE ABOVE COPYRIGHT NOTICE.  THIS SOFTWARE OR ANY  OTHER
;COPIES THEREOF MAY NOT BE PROVIDED OR OTHERWISE MADE AVAILABLE TO ANY
;OTHER PERSON.  NO TITLE TO AND OWNERSHIP OF THE  SOFTWARE  IS  HEREBY
;TRANSFERRED.

;THE INFORMATION IN THIS SOFTWARE IS SUBJECT TO CHANGE WITHOUT  NOTICE
;AND  SHOULD  NOT  BE  CONSTRUED  AS A COMMITMENT BY DIGITAL EQUIPMENT
;CORPORATION.

;DIGITAL ASSUMES NO RESPONSIBILITY FOR THE USE OR RELIABILITY  OF  ITS
;SOFTWARE ON EQUIPMENT WHICH IS NOT SUPPLIED BY DIGITAL.

SEARCH	MTHPRM
NOSYM
ENTRY	CGSQRT
EXTERN	CGSQT.
CGSQRT=CGSQT.
PRGEND
TITLE	CGSQT.	COMPLEX SQUARE ROOT FUNCTION
;		(DOUBLE PRECISION GFLOATING POINT)
SUBTTL	IMSL, INC.	JUNE 1, 1979

;COPYRIGHT (c) DIGITAL EQUIPMENT CORPORATION 1979, 1987
;ALL RIGHTS RESERVED.
;
;THIS SOFTWARE IS FURNISHED UNDER A LICENSE AND MAY BE USED AND COPIED
;ONLY  IN  ACCORDANCE  WITH  THE  TERMS  OF  SUCH LICENSE AND WITH THE
;INCLUSION OF THE ABOVE COPYRIGHT NOTICE.  THIS SOFTWARE OR ANY  OTHER
;COPIES THEREOF MAY NOT BE PROVIDED OR OTHERWISE MADE AVAILABLE TO ANY
;OTHER PERSON.  NO TITLE TO AND OWNERSHIP OF THE  SOFTWARE  IS  HEREBY
;TRANSFERRED.

;THE INFORMATION IN THIS SOFTWARE IS SUBJECT TO CHANGE WITHOUT  NOTICE
;AND  SHOULD  NOT  BE  CONSTRUED  AS A COMMITMENT BY DIGITAL EQUIPMENT
;CORPORATION.

;DIGITAL ASSUMES NO RESPONSIBILITY FOR THE USE OR RELIABILITY  OF  ITS
;SOFTWARE ON EQUIPMENT WHICH IS NOT SUPPLIED BY DIGITAL.

;  LET Z = X + I*Y
;  THEN THE ANSWER CGSQRT(Z) = U + I*V IS DEFINED AS FOLLOWS

;  IF X >= 0.0, THEN
;    U = GSQRT((GABS(X)+CGABS(Z))/2.0)
;    V = Y/(2.0*U)

;  IF X < 0.0 AND Y >= 0.0, THEN
;    U = Y/(2.0*V)
;    V = GSQRT((GABS(X)+CGABS(Z))/2.0)

;  IF X AND Y ARE BOTH < 0.0, THEN
;    U = Y/(2.0*V)
;    V = GSQRT((GABS(X)+CGABS(Z))/2.0)

;  THE RESULT IS IN THE RIGHT HALF PLANE, THAT IS, THE POLAR ANGLE OF THE
;    RESULT LIES IN THE INTERVAL [-PI/2,+PI/2].

;REQUIRED (CALLED) ROUTINES:  GSQRT

;REGISTERS T2, T3, T4, T5, P1, P3, AND P4 WERE SAVED, USED, AND RESTORED

;THE ROUTINE HAS THE FOLLOWING CALLING SEQUENCE:

;  XMOVEI	L,ARG
;  PUSHJ	P,CGSQRT

;THE ROUTINE IS CALLED WITH TWO DOUBLE PRECISION VECTORS.
;THE REAL PART OF THE ARGUMENT IS EXPECTED TO BE STORED IN THE
;FIRST DOUBLE PRECISION WORD OF THE FIRST VECTOR.
;THE IMAGINARY PART OF THE ARGUMENT IS EXPECTED TO BE STORED IN THE
;SECOND DOUBLE PRECISION WORD OF THE FIRST VECTOR.
;THE REAL PART OF THE SOLUTION IS RETURNED IN THE FIRST DOUBLE
;PRECISION WORD OF THE SECOND VECTOR.
;THE IMAGINARY PART OF THE SOLUTION IS RETURNED IN THE SECOND DOUBLE
;PRECISION WORD OF THE SECOND VECTOR.

	SEARCH	MTHPRM
	SEGMENT	CODE
	SALL

	HELLO	(CGSQT.,CGSQRT)	;ENTRY TO COMPLEX SQUARE ROOT ROUTINE.
	PUSH	P,T2		;SAVE ACCUMULATORS
	PUSH	P,T3
	XMOVEI	T2,@0(L)	;PICK UP ADDRESS OF ARGUMENT
	DMOVE	T0,(T2)		;PICK UP X IN AC T0.
	DMOVE	T2,2(T2)	;PICK UP Y IN AC T2.
	PUSH	P,T4		;SAVE AC T4.
	PUSH	P,T5
	JUMPE	T2,ZREAL	;JUMP IF Y=0
	JUMPE	T0,ZIMAG	;JUMP IF X=0
	DMOVE	T4,T0		;DABS(X) TO AC T4.
	JUMPGE	T0,XPOS		;IF X IS NEGATIVE
	DMOVN	T4,T4		;NEGATE

XPOS:	PUSH	P,P1		;SAVE REGISTER P1.
	PUSH	P,P3		;SAVE REGISTER P3
	PUSH	P,P4		;SAVE REGISTER P4
	DMOVEM	T0,XSAVE	;SAVE X IN XSAVE
	DMOVEM	T2,YSAVE	;SAVE Y IN YSAVE
	DMOVE	P3,T2		;DABS(Y) TO AC P3.
	JUMPGE	T2,YPOS		;IF Y IS NEGATIVE
	  DMOVN	P3,T2		;NEGATE IT
YPOS:	HRRZI	P1,1		;SET P1 TO 1
	CAML	T4,P3		;IF ABS(X) > ABS(Y)
	  JRST	DWN		;THEN GO TO DWN
				;IF HIGH WORDS OF |X| AND |Y| ARE EQUAL,
				; DON'T BOTHER DECIDING WHETHER TO EXCHANGE
				; THEM.  IF |X| AND |Y| ARE NEARLY EQUAL,
				; THEIR MAX AND MIN MAY BE SWITCHED BELOW.
				; THIS MEANS THAT S/L MAY BE SLIGHTLY GREATER
				; THAN 1, BUT THIS DOES NOT HURT.
XCHNG:	EXCH	T4,P3		;PUT MAX(ABS(X),ABS(Y)) IN T4
	EXCH	T5,P4		;AND MIN(ABS(X),ABS(Y)) IN P3,P4
	SETZ	P1,		;SET P1 TO 0
DWN:	GFDV	P3,T4		;CALC S/L.
	JFCL			;NO UNDERFLOW ERROR MESSAGE ALLOWED.
	GFMP	P3,P3		;CALC (S/L)**2.
	JFCL			;NO UNDERFLOW ERROR MESSAGE ALLOWED.
	GFAD	P3,ONE		;HAVE (1+(S/L)**2) IN AC P3.
	DMOVEM	P3,TEMP
	FUNCT	GSQRT.,<TEMP>	;CALC. THE GSQRT OF
				;(1+(S/L)**2)=1+EPS.
	JUMPE	P1,YGTX		;GO TO YGTX IF DABS(Y) > DABS(X).

XGTY:	GFAD	T0,ONE		;CALC. 2 + EPS.
	EXTEND	T0,[GFSC -1]	;CALC. 1+EPS/2.
	DMOVEM	T0,TEMP		;PUT IN TEMP FOR
	FUNCT	GSQRT.,<TEMP>	;CALL TO GSQRT
	DMOVE	P3,T0		;SAVE GSQRT(1+EPS/2) IN AC P3.
	DMOVEM	T4,TEMP
	FUNCT	GSQRT.,<TEMP>	;CALC.
	GFMP	T0,P3		;CALC. GSQRT(DABS(X)*(1+EPS/2)).
	JRST	OUT1		;GO TO REST OF CALC.

YGTX:	CAIGE	T4,200140	;IF DABS(Y)>1, GO TO POSSIBLE OVERFLOW CASE.
	JRST	YXSMAL		;ELSE, GO TO POSSIBLE UNDERFLOW.
	EXTEND	T0,[GFSC -3]	;CALC. (1+EPS)/8.
	GFMP	T4,T0		;CALC. DABS(Y)*(1+EPS)/8
	DMOVE	T0,XSAVE	;DABS(X) TO AC T0
	JUMPGE	T0,NXT
	  DMOVN	T0,T0
NXT:	EXTEND	T0,[GFSC -3]	;CALC. DABS(X)/8
	JFCL			;SUPPRESS UNDERFLOW ERROR MESSAGE.
	GFAD	T0,T4		;CALC.(DABS(X)/8)+(DABS(Y)*(1+EPS)/8).
	DMOVEM	T0,TEMP
	FUNCT	GSQRT.,<TEMP>	;CALC.
	EXTEND	T0,[GFSC 1]	;GET DSQRT(|X|/2 + |Y|*(1+EPS)/2)

OUT1:	JUMPGE	T2,POSY
	  DMOVN	T2,T2
POSY:	GFDV	T2,T0		;DIVIDE DABS(Y)/2 BY THE
	  JFCL	UNDFL
	EXTEND	T2,[GFSC -1]	;SQRT TERM.
	  JFCL	UNDFL
	JRST	SIGNS		;GO TO REST OF CALC.

YXSMAL:	GFMP	T0,T4		;DABS(Y)*(1+EPS) = CDABS(Z).
	DMOVE	P3,XSAVE	;DABS(X) TO AC P3.
	JUMPGE	P3,XOK		;IF X IS NEGATIVE
	  DMOVN	P3,P3		;NEGATE IT
XOK:	GFAD	P3,T0		;GET |X| + CDABS(Z)
	EXTEND	P3,[GFSC 1]	;[3237] MULTIPLY ARG BY 2
	DMOVEM	P3,TEMP		;SAVE FOR DSQRT
	FUNCT	GSQRT.,<TEMP>	;CALC. GSQRT OF 2 * (|X| + CDABS(Z))
	DMOVE	P3,T0		;GET DSQRT((|X| + CDABS(Z))*2)
	EXTEND	T0,[GFSC -1]	;GET DSQRT((|X| + CDABS(Z))/2)
	GFDV	T4,P3		;GET |Y| / DSQRT (2 * (|X| + CDABS(Z)))
	DMOVE	T2,T4		;PUT A TEMP ANSWER IN AC T2.

SIGNS:	SKIPL	XSAVE		;IF NEGATIVE X, SWITCH REAL & IMAG
	  JRST	OK		;  PARTS OF RESULT
	EXCH	T2,T0		;EXCHANGE
	EXCH	T1,T3		;EXCHANGE
				;SET UP THE REAL AND
  	  			;THE IMAGINARY ANSWERS WITH
OK:	SKIPGE	YSAVE		;THE APPROPRIATE
	  DMOVN	T2,T2		;[3237] SIGNS.
	XMOVEI	T4,@1(L)	;GET THE ADDRESS OF THE SECOND ARGUMENT
	DMOVEM	T0,(T4)		;SAVE REAL PART OF RESULT
	DMOVEM	T2,2(T4)	;SAVE IMAG PART OF RESULT
	POP	P,P4		;RESTORE AC P4
	POP	P,P3		;RESTORE AC P3
	POP	P,P1		;RESTORE AC P1
	POP	P,T5		;RESTORE AC T5
	POP	P,T4		;RESTORE AC T4
	POP	P,T3		;RESTORE AC T3
	POP	P,T2		;RESTORE AC T2
	GOODBY	(1)		;RETURN

ZREAL:	JUMPE	T0,DONE		;Y = 0, HOW ABOUT X?
	MOVE	T4,T0		;X NOT ZERO, SAVE IT.
	JUMPGE	T0,POSX		;GET DABS(X) FOR GSQRT
	  DMOVN	T0,T0
POSX:	DMOVEM	T0,TEMP
	FUNCT	GSQRT.,<TEMP>	;T0,T1 GET GSQRT(DABS(X))
	JUMPG	T4,DONE		;T0,T1 AND T2,T3 OK FOR X .GE. 0
	  EXCH	T0,T2		;INTERCHANGE FOR X<0
	  EXCH	T1,T3		;
	JRST	DONE		;FINISHED

ZIMAG:	MOVE	T4,T2		;X=0, SAVE Y
	JUMPGE	T2,PSY		;IF Y < 0
	  DMOVN	T2,T2		;  NEGATE IT
PSY:	EXTEND	T2,[GFSC -1]	;GET |Y|/2
	DMOVEM	T2,TEMP		; AND STORE IT FOR GSQRT
	FUNCT	GSQRT.,<TEMP>	;T0,T1 GETS GSQRT(DABS(Y/2))
	DMOVE	T2,T0		;T2,T3  ALSO
	JUMPG	T4,DONE		;DONE IF Y > 0
	  DMOVN	T2,T2		;[3237] NEGATE IMAGINARY PART IF Y < 0

DONE:	XMOVEI	T4,@1(L)	;GET THE ADDRESS OF THE SECOND ARGUMENT
	DMOVEM	T0,(T4)		;SAVE REAL PART OF RESULT
	DMOVEM	T2,2(T4)	;SAVE IMAG PART OF RESULT
	POP	P,T5		;RESTORE ACCUMULATORS
	POP	P,T4
	POP	P,T3
	POP	P,T2		;RESTORE AC T2.
	GOODBY	(1)		;RETURN

UNDFL:	SKIPGE	XSAVE		;DOES RESULT HAVE REAL & IMAG PARTS SWITCHED?
	 $LCALL	RPU,UFCONT	;[3237] Go to UFCONT to do fixup when through
;	 LERR	(LIB,%,<CDSQRT: real part underflow>,UFCONT)
	$LCALL	IPU		;[3237] Go to UFCONT to do fixup when through
;	LERR	(LIB,%,<CDSQRT: imaginary part underflow>)
UFCONT:	SETZB	T2,T3		;[3237] STORE 0 FOR RESULT OF UNDERFLOW
	JRST	SIGNS		;[3237]


ONE:	DOUBLE	200140000000,000000000000	;1.0D0

	SEGMENT	DATA
TEMP:	DOUBLE	0,0		;TEMPORARY STORAGE FOR GSQRT ARGS
XSAVE:	DOUBLE	0,0
YSAVE:	DOUBLE	0,0

	END