abs.a68
; Copyright (C) 1985 by Manx Software Systems, Inc.
; :ts=8

	public	.Pabs
	public	_abs
_abs
	movem.l	4(sp),d0/d1
	jmp	.Pabs

atof.c
/* Copyright (C) 1983 by Manx Software Systems */
#include	<ctype.h>

double
atof(cp)
register char *cp;
{
	double acc, zero = 0.0, ten = 10.0;
	int msign, esign, dpflg;
	int i, dexp;

	while (*cp == ' ' || *cp == '\t')
		++cp;
	if (*cp == '-') {
		++cp;
		msign = 1;
	} else {
		msign = 0;
		if (*cp == '+')
			++cp;
	}
	dpflg = dexp = 0;
	for (acc = zero ; ; ++cp) {
		if (isdigit(*cp)) {
			acc *= ten;
			acc += *cp - '0';
			if (dpflg)
				--dexp;
		} else if (*cp == '.') {
			if (dpflg)
				break;
			dpflg = 1;
		} else
			break;
	}
	if (*cp == 'e' || *cp == 'E') {
		++cp;
		if (*cp == '-') {
			++cp;
			esign = 1;
		} else {
			esign = 0;
			if (*cp == '+')
				++cp;
		}
		for ( i = 0 ; isdigit(*cp) ; i = i*10 + *cp++ - '0' )
			;
		if (esign)
			i = -i;
		dexp += i;
	}
	if (dexp < 0) {
		while (dexp++)
			acc /= ten;
	} else if (dexp > 0) {
		while (dexp--)
			acc *= ten;
	}
	if (msign)
		acc = -acc;
	return acc;
}

dtof.a68
;
;	FLOATING POINT ERROR VALUES
;
UNDER_FLOW	equ	1
OVER_FLOW	equ	2
DIV_BY_ZERO	equ	3
;
;	convert double to float
;
;	argument in d0/d1	result in d0
;
		public	.dtof
.dtof:	movem.l	d2/d3/d4,-(sp)
		move.l	d0,d2			;save a copy for exponent extraction
		beq		easy_exit		;no work if zero
		smi		d4				;get sign of result
		swap	d2
		lsr.w	#4,d2
		and.w	#$7ff,d2		;extract exponent
		sub.w	#1023,d2		;unbias
		and.l	#$fffff,d0		;extract mantissa
		or.l	#$100000,d0		;turn hidden bit back on
		move.l	#2,d3
dagain:
		lsl.l	#1,d1			;shift mantissa into place
		roxl.l	#1,d0
		dbra	d3,dagain
		cmp.l	#$80000000,d1	;check for round
		beq		rstar
		bcs		nornd
		add.l	#1,d0			;round up
		cmp.l	#$00ffffff,d0	;check for carry
		bls		nornd
		add.w	#1,d2			;bump exponent
		lsr.l	#1,d0			;and shift result back into place
		bra		nornd
rstar:
		or.w	#1,d0			;rstar case, force low bit to 1
nornd:
		add.w	#127,d2			;add in float bias
		bmi		underflow		;can't represent double in float
		cmp.w	#255,d2
		bgt		overflow		;ditto
		lsl.w	#7,d2			;back in place
		tst.b	d4				;need to set sign?
		beq		ndsign			;no
		or.w	#$8000,d2		;yes, set it
ndsign:
		swap	d2				;get exponent in high word
		clr.w	d2				;clear out
		and.l	#$7fffff,d0		;get rid of hidden bit
		or.l	d2,d0			; put back in number
easy_exit:
		movem.l	(sp)+,d2/d3/d4
		rts
underflow:
		move.w	#UNDER_FLOW,_flterr
		move.l	#$00800000,d0	;set to smallest number
		bra		dosign
overflow:
		move.w	#OVER_FLOW,_flterr
		move.l	#$7fffffff,d0	;set to largest number
dosign:
		tst.b	d4
		beq		dexit
		or.l	#$80000000,d0	;set sign
dexit:
		movem.l	(sp)+,d2/d3/d4
		rts
;
		global	_flterr,2
fabs.a68
; Copyright (C) 1985 by Manx Software Systems, Inc.
; :ts=8

	public	.Pabs
	public	_fabs
_fabs
	movem.l	4(sp),d0/d1
	jmp	.Pabs

frexp.a68
;
;	FLOATING POINT ERROR VALUES
;
UNDER_FLOW	equ	1
OVER_FLOW	equ	2
DIV_BY_ZERO	equ	3
;
;	frexp(d, &i)
;
;	returns 1/2 <= |x| < 1
;	such that d = x *2^i
;
		public	_frexp
_frexp:	move.l	d2,-(sp)
		move.l	16(sp),a0		;get address for int
		move.l	8(sp),d0		; get double value
		move.l	12(sp),d1
		move.l	d0,d2
		swap	d2
		and.w	#$7ff0,d2
		bne		notzero
		move.l	#0,d2
		beq		done
notzero:
		and.l	#$800fffff,d0	;get rid of old exponent
		lsr.w	#4,d2
		sub.w	#1022,d2
		or.l	#$3fe00000,d0	;change exponent to -1
done:
		if INT32
		ext.l	d2
		move.l	d2,(a0)
		else
		move.w	d2,(a0)
		endc
		move.l	(sp)+,d2
		rts
ftoa.c
/* Copyright (C) 1984 by Manx Software Systems, Inc. */

static double round[] = { 10, 1,
	5e-1, 5e-2, 5e-3, 5e-4, 5e-5, 5e-6, 5e-7, 5e-8, 5e-9, 5e-10,
	5e-11, 5e-12, 5e-13, 5e-14, 5e-15, 5e-16 };

ftoa(number, buffer, maxwidth, flag)
double number; register char *buffer;
{
	register int i;
	int exp, digit, decpos, ndig;

	ndig = maxwidth+1;
	exp = 0;
	if (number < 0.0) {
		number = -number;
		*buffer++ = '-';
	}
	if (number > 0.0) {
		while (number < round[1]) {
			number *= round[0];
			--exp;
		}
		while (number >= round[0]) {
			number /= round[0];
			++exp;
		}
	}

	if (flag == 2) {		/* 'g' format */
		ndig = maxwidth;
		if (exp < -4 || exp > maxwidth)
			flag = 0;		/* switch to 'e' format */
	} else if (flag == 1)	/* 'f' format */
		ndig += exp;

	if (ndig >= 0) {
		if ((number += round[(ndig>16?16:ndig)+1]) >= round[0]) {
			number = round[1];
			++exp;
			if (flag)
				++ndig;
		}
	}

	if (flag) {
		if (exp < 0) {
			*buffer++ = '0';
			*buffer++ = '.';
			i = -exp - 1;
			if (ndig <= 0)
				i = maxwidth;
			while (i--)
				*buffer++ = '0';
			decpos = 0;
		} else {
			decpos = exp+1;
		}
	} else {
		decpos = 1;
	}

	if (ndig > 0) {
		for (i = 0 ; ; ++i) {
			if (i < 16) {
				digit = (int)number;
				*buffer++ = digit+'0';
				number = (number - digit) * round[0];
			} else
				*buffer++ = '0';
			if (--ndig == 0)
				break;
			if (decpos && --decpos == 0)
				*buffer++ = '.';
		}
	}

	if (!flag) {
		*buffer++ = 'e';
		if (exp < 0) {
			exp = -exp;
			*buffer++ = '-';
		} else
			*buffer++ = '+';
		if (exp >= 100) {
			*buffer++ = exp/100 + '0';
			exp %= 100;
		}
		*buffer++ = exp/10 + '0';
		*buffer++ = exp%10 + '0';
	}
	*buffer = 0;
}

ftod.a68
;
;	convert float to double
;
;	argument in d0 result in d0/d1
;
		public	.ftod
.ftod:	movem.l	d3/d4,-(sp)
		tst.l	d0				;save sign
		smi		d3
		clr.l	d1				;clear out LL of result
		and.l	#$7fffffff,d0	;extract exponent and mantissa
		move.l	#2,d4
fagain:
		lsr.l	#1,d0			;shift exponent and mantissa into position
		roxr.l	#1,d1
		dbra	d4,fagain
		move.l	d0,d4
		or.l	d1,d4			;check for 0
		beq		1$
		add.l	#$38000000,d0	;adjust bias for double (1023-127) << 20
1$:
		tst.b	d3				; have to set sign?
		beq		fexit			; no
		or.l	#$80000000,d0	;yes, set it
fexit:
		movem.l	(sp)+,d3/d4
		rts
ldexp.a68
;
;	FLOATING POINT ERROR VALUES
;
UNDER_FLOW	equ	1
OVER_FLOW	equ	2
DIV_BY_ZERO	equ	3
;
;		ldexp(d, i)
;
;		return x = d * 2^i
;
		public	_ldexp
_ldexp	move.l	d2,-(sp)
		move.l	8(sp),d0		;get the number
		move.l	12(sp),d1
		move.l	d0,d2			;get exponent
		and.l	#$800fffff,d0	;get old exponent out
		swap	d2
		and.l	#$7ff0,d2
		lsr.w	#4,d2
		if INT32
		add.w	18(sp),d2
		else
		add.w	16(sp),d2
		endc
		bmi		ldunder
		beq		ldunder
		cmp.w	#2047,d2
		bgt		ldover
		lsl.w	#4,d2
		swap	d2
		or.l	d2,d0			;put new exponent in
		move.l	(sp)+,d2
		rts
ldunder:
		move.w	#UNDER_FLOW,_flterr
		or.l	#$00100000,d0
		move.l	(sp)+,d2
		rts
ldover:
		move.w	#OVER_FLOW,_flterr
		or.l	#$7ff00000,d0
		move.l	(sp)+,d2
		rts
;
		global	_flterr,2
lvo.a68
; Copyright (C) 1986 by Manx Software Systems, Inc.
; :ts=8

_LVOIEEEDPCeil	equ	-96
_LVOIEEEDPFloor	equ	-90
_LVOIEEEDPDiv	equ	-84
_LVOIEEEDPMul	equ	-78
_LVOIEEEDPSub	equ	-72
_LVOIEEEDPAdd	equ	-66
_LVOIEEEDPNeg	equ	-60
_LVOIEEEDPAbs	equ	-54
_LVOIEEEDPTst	equ	-48
_LVOIEEEDPCmp	equ	-42
_LVOIEEEDPFlt	equ	-36
_LVOIEEEDPFix	equ	-30

	public	_LVOIEEEDPCeil
	public	_LVOIEEEDPFloor
	public	_LVOIEEEDPDiv
	public	_LVOIEEEDPMul
	public	_LVOIEEEDPSub
	public	_LVOIEEEDPAdd
	public	_LVOIEEEDPNeg
	public	_LVOIEEEDPAbs
	public	_LVOIEEEDPTst
	public	_LVOIEEEDPCmp
	public	_LVOIEEEDPFlt
	public	_LVOIEEEDPFix

makebig
.c.l:
	cc +bcdfi -o $@ $*.c
.c.l32:
	cc +bpfi -o $@ $*.c

.a68.l:
	as -cdo $@ $*.a68
.a68.l32:
	as -eINT32 -cdo $@ $*.a68

C=atof.l ftoa.l
ASM=abs.l dtof.l fabs.l frexp.l ftod.l\
	ldexp.l math.l modf.l pabs.l padd.l\
	pcmp.l pdiv.l pfix.l pflt.l pmul.l\
	pneg.l psub.l ptst.l
ASM32=frexp.l32 ldexp.l32
C32=ftoa.l32



all:	$(C) $(ASM) $(C32) $(ASM32) lvo.l

makefile
.c.o:
	cc +bfi -o $@ $*.c
.c.o32:
	cc +blfi -o $@ $*.c

.a68.o:
	as -o $@ $*.a68
.a68.o32:
	as -eINT32 -o $@ $*.a68

C=atof.o ftoa.o
ASM=abs.o dtof.o fabs.o frexp.o ftod.o\
	ldexp.o math.o modf.o pabs.o padd.o\
	pcmp.o pdiv.o pfix.o pflt.o pmul.o\
	pneg.o psub.o ptst.o
ASM32=frexp.o32 ldexp.o32
C32=ftoa.o32



all:	$(C) $(ASM) $(C32) $(ASM32) lvo.o

math.a68
; Copyright (C) 1986 by Manx Software Systems, Inc.
; :ts=8

	public	_exit
	public	__Write
	public	__Output
	public	__OpenLibrary
	public	_MathIeeeDoubBasBase

	public	amiga_ieee
amiga_ieee:
	tst.l	_MathIeeeDoubBasBase
	bne	skip
	movem.l	d0/d1/a0/a1,-(sp)
	clr.l	-(sp)
	pea	libnam
	jsr	__OpenLibrary
	add.w	#8,sp
	move.l	d0,_MathIeeeDoubBasBase
	bne	done
	move.l	#16,-(sp)
	pea	msg
	jsr	__Output
	move.l	d0,-(sp)
	jsr	__Write
	move.l	#1,(sp)
	jsr	_exit
done
	movem.l	(sp)+,d0/d1/a0/a1
skip
	movem.l	a0,-(sp)
	move.l	4(sp),a0
	move.l	a6,4(sp)
	move.l	_MathIeeeDoubBasBase,a6
	jsr	(a6,a0.l)
	movem.l	(sp)+,a0/a6
	rts

libnam	dc.b	'mathieeedoubbas.library',0

msg	dc.b	'no ieee library',$a
modf.a68
;
;	FLOATING POINT ERROR VALUES
;
UNDER_FLOW	equ	1
OVER_FLOW	equ	2
DIV_BY_ZERO	equ	3
;
;		modf(d, dptr)
;
;		return fractional part of d and
;		stores integral part in	*dptr
;

		public	.Pfix
		public	.Pflt
		public	.Psub

		public	_modf
_modf:
		movem.l	d2/d3,-(sp)
		move.l	12(sp),d0		;pick up double
		move.l	16(sp),d1
		move.l	d0,d2			;copy number
		move.l	d1,d3			;
		jsr		.Pfix			;fix the number
		jsr		.Pflt			;float it again
		move.l	20(sp),a0
		move.l	d0,(a0)+		;store integral part
		move.l	d1,(a0)
		exg.l	d0,d2
		exg.l	d1,d3
		jsr		.Psub			;get rid of integral part
		movem.l	(sp)+,d2/d3
		rts

pabs.a68
; Copyright (C) 1986 by Manx Software Systems, Inc.
; :ts=8

	public	.Pabs
.Pabs:
	move.l	#_LVOIEEEDPAbs#,-(sp)
	jmp	amiga_ieee#

padd.a68
; Copyright (C) 1986 by Manx Software Systems, Inc.
; :ts=8

	public	.Padd
.Padd:
	move.l	#_LVOIEEEDPAdd#,-(sp)
	jmp	amiga_ieee#

pcmp.a68
; Copyright (C) 1986 by Manx Software Systems, Inc.
; :ts=8

	public	.Pcmp
.Pcmp:
	move.l	#_LVOIEEEDPCmp#,-(sp)
	jmp	amiga_ieee#

pdiv.a68
; Copyright (C) 1986 by Manx Software Systems, Inc.
; :ts=8

	public	.Pdiv
.Pdiv:
	move.l	#_LVOIEEEDPDiv#,-(sp)
	jmp	amiga_ieee#

pfix.a68
; Copyright (C) 1986 by Manx Software Systems, Inc.
; :ts=8

	public	.Pfix
.Pfix:
	move.l	#_LVOIEEEDPFix#,-(sp)
	jmp	amiga_ieee#

pflt.a68
; Copyright (C) 1986 by Manx Software Systems, Inc.
; :ts=8

	public	.Pflt
.Pflt:
	move.l	#_LVOIEEEDPFlt#,-(sp)
	jmp	amiga_ieee#

pmul.a68
; Copyright (C) 1986 by Manx Software Systems, Inc.
; :ts=8

	public	.Pmul
.Pmul:
	move.l	#_LVOIEEEDPMul#,-(sp)
	jmp	amiga_ieee#

pneg.a68
; Copyright (C) 1986 by Manx Software Systems, Inc.
; :ts=8

	public	.Pneg
.Pneg:
	move.l	#_LVOIEEEDPNeg#,-(sp)
	jmp	amiga_ieee#

psub.a68
; Copyright (C) 1986 by Manx Software Systems, Inc.
; :ts=8

	public	.Psub
.Psub:
	move.l	#_LVOIEEEDPSub#,-(sp)
	jmp	amiga_ieee#

ptst.a68
; Copyright (C) 1986 by Manx Software Systems, Inc.
; :ts=8

	public	.Ptst
.Ptst:
	move.l	#_LVOIEEEDPTst#,-(sp)
	jmp	amiga_ieee#

