
*	Maxon C++ Library:
*	Modul "math_doubletostr"
*	Jens Gelhar 17.10.91, 15.04.94


	xdef	_doubletostr,DoubleToFixed,DoubleToExpo

	xref	GetDoubmath
	xref	Expo10,Pwr10

i3edpAdd	= -66
i3edpMul	= -78

_doubletostr:	; Stackparameter: Doppelwort, Bufferadresse, Stellen.W
	movem.l d1-d7/a0-a6,-(a7)
	movem.l 14*4+4(a7),d0/d1/a5
	move.w  14*4+4+3*4(a7),d2
	bsr.b	DoubletoStr
	move.l	a5,d0
	movem.l	(a7)+,d1-d7/a0-a6
	rts

DoubleToFixed:	; Zahl d0|d1, Buffer a2, d2 Nachkommastellen
	move.l a2,a5
	bsr Sign
	bra.b doitFix

DoubleToExpo:	; Zahl d0|d1, Buffer a2, d2 Nachkommastellen
	move.l a2,a5
	bsr Sign
	addq.w #1,d2
	bra doitExpo

DoubletoStr:	; Zahl d0|d1, Buffer a5, ±d2 Stellen
	move.l a5,a2
	bsr Sign
	tst.w d2
	bne.b dbstFixed
	tst.l d0
	bne.b dbst1
	move.b #'0',(a2)+
dbstEnd	clr.b (a2)
	rts
dbst1	moveq #15,d2
	bsr DoubDigString
	cmp.w #4,d2
	bge.b dbst2
	cmp.w #-1,d2
	blt.b dbst2
	move.w d2,d0
	bsr AnotherInsertKomma
dbst1a	cmp.b #'0',-1(a2)
	bne.b dbst1b
	subq.l #1,a2
	bra.b dbst1a
dbst1b	cmp.b #'.',-1(a2)
	bne.b dbstEnd
	subq.l #1,a2
	bra.b dbstEnd
dbst2	move.w d2,d1
	bsr DoubExponentiere
	bra.b dbstEnd

dbstFixed:	; Festpunkt-Darstellung
	tst.w d2
	bmi.b dbstExpo
doitFix	tst.l d0
	beq.b dbst3
	jsr Expo10
	cmp.w #20,d4
	bge.b dbst1
	cmp.w #-20,d4
	blt.b dbst1
	add.w d4,d2
	addq.w #1,d2
	move.w d2,-(a7)
	cmp.w #16,d2
	blt.b dbst3c
	moveq #16,d2
dbst3c	bsr.b DoubDigString
	move.w (a7)+,d4
	cmp.w #30,d4
	bhs.b dbst3e
	sub.w #16,d4
	bls.b dbst3e
dbst3d	move.b #'0',(a2)+
	subq.w #1,d4
	bne.b dbst3d
dbst3e	move.w d2,d0
	bsr AnotherInsertKomma
	bra dbstEnd

dbst3	; "0" in Festpunkt-Darstellung
	move.b #'0',(a2)+
	tst.w d2
	beq dbstEnd
	move.b #'.',(a2)+
dbst3loop
	move.b #'0',(a2)+
	subq.w #1,d2
	bne.b dbst3loop
	bra dbstEnd

dbstExpo:
	neg.w d2
doitExpo:
	tst.l d0
	bne.b dbstr7
	move.w d2,d0
	moveq #0,d2
dbstr6	move.b #'0',(a2)+
	subq.w #1,d0
	beq.b dbstr9
	cmp.w #30,d0
	bhs.b dbstr9
	bra.b dbstr6
dbstr7	; Zahl <> 0
	cmp.w #16,d2
	bls.b dbstr7a
	moveq #16,d2
dbstr7a	bsr.b DoubDigString
	move.w (a7),d0
	neg.w d0
	cmp.w #30,d0
	bhs.b dbstr9
dbstr8	cmp.w #16,d0
	bls.b dbstr9
	move.b #'0',(a2)+
	subq.w #1,d0
	bra.b dbstr8
dbstr9	move.w d2,d1
	bra DoubExponentiere

DoubDigString:	; Ziffern von d0||d1, d2 Stück, nach (a2)+ schreiben
	; lg nach d2

	move.w d2,-(a7)

	; Auf [d2] absolute Stellen runden
	move.w d2,-(a7)
	jsr Expo10
	move.w d4,d2
	sub.w (a7)+,d2
	addq.w #1,d2
	movem.l d0/d1,-(a7)
	jsr Pwr10       ; Zehnerpotenz für Rundung
	tst.l d0
	beq.b dbdst1
	sub.l #$00100000,d0
dbdst1	jsr GetDoubmath
	movem.l (a7)+,d2/d3
	jsr i3edpAdd(a6)

	; Zahl ist gerundet, Ziffernanzahl liegt auf Stack
	jsr Expo10
	move.w (a7)+,d2
	move.w d4,-(a7)       ; Logarithmus merken!
	move.w d2,-(a7)
	sub.w d4,d2
	subq.w #1,d2
	movem.l d0/d1,-(a7)
	jsr Pwr10
	jsr GetDoubmath
	movem.l (a7)+,d2/d3
	jsr i3edpMul(a6)   ; normieren...
	bsr MyFix          ; und nach Ganzzahl
	move.w (a7)+,d2

	; Ziffern von integer d0/d1, mind. d2 Stck., nach (a2)+
	clr.w -(a7)
	subq.w #1,d2
dbdst2	bsr.b DoubDivmod10
	add.b #'0',d4
	move.w d4,-(a7)
	subq.w #1,d2
	bpl.b dbdst2
	tst.l d0
	bne.b dbdst2
	tst.l d1
	bne.b dbdst2
dbdst3	move.w (a7)+,d4
	beq.b ddst3
	move.b d4,(a2)+
	bra.b dbdst3
ddst3	move.w (a7)+,d2
	clr.b (a2)
	rts


DoubDivmod10:	; d0||d1 durch 10 teilen, div -> d0||d1, mod --> d4
	movem.l d2/d3,-(a7)
	move.l d0,d2
	move.l d1,d3
	move.w d0,-(a7)
	clr.w d0
	swap d0
	divu #10,d0
	move.w (a7)+,d0
	divu #10,d0
	move.w d1,-(a7)
	swap d1
	move.w d1,d0
	divu #10,d0
	move.w (a7)+,d0
	divu #10,d0
	swap d0
	move.w d0,d4   ; d0 = modulo

	move.l d2,d0
	clr.w d0
	swap d0
	divu #10,d0
	swap d0        ; Bits 63:48

	swap d2
	move.w d0,d2
	swap d2
	divu #10,d2
	move.w d2,d0   ; Bits 47:32

	swap d3
	move.w d3,d2
	divu #10,d2
	swap d2
	move.l d2,d1  ; Bits 31:16

	move.w d2,d3
	swap d3
	divu #10,d3
	move.w d3,d1        ; Bits 15:0

	movem.l (a7)+,d2/d3
	rts

DoubExponentiere:	; String 1(a5) ... (a2) in Expo-Darstellung bringen
	; Exponent d1
	move.b #'e',(a2)+
	move.b #'+',(a2)+
	tst.w d2
	bpl.b dexpoti1
	move.b #'-',-1(a2)
	neg.w d2
dexpoti1	ext.l d2
	divu #10,d2
	move.w d2,d3
	ext.l d3
	divu #10,d3
	add.b #'0',d3
	move.b d3,(a2)+
	swap d3
	add.b #'0',d3
	move.b d3,(a2)+
	swap d2
	add.b #'0',d2
	move.b d2,(a2)+
	clr.b (a2)
	moveq #0,d0
	cmp.b #'e',2(a5)
	bne.b AnotherInsertKomma
	rts    ; bei nur einer Stelle keinen Punkt

AnotherInsertKomma:
	; in Ziffernfolge in String a5 ab Pos. d0 Komma einfügen
	lea 2(a5,d0.w),a0
	tst.w d0
	bpl.b ainskomm2
	lea 1(a5),a0
ainskomm0
	addq.w #1,d0
	bpl.b ainskomm1
	bsr.b aInsa0a2
	move.b #'0',(a0)
	bra.b ainskomm0
ainskomm1
	bsr.b aInsa0a2
	move.b #'.',(a0)
	bsr.b aInsa0a2
	move.b #'0',(a0)
	rts
ainskomm2	; d0 > 0
	cmp.l a2,a0
	bhi.b ainskomm3
	beq.b ainskomm4
	; Punkt liegt in Ziffernfolge
	bsr.b aInsa0a2
	move.b #'.',(a0)
ainskomm4
	rts
ainskomm3	; Punkt hinter Ziffernfolge
	move.b #'0',(a2)+  ; Nullen anhängen
	cmp.l a0,a2
	blo.b ainskomm3
	rts

aInsa0a2	; ab a0 bis a2 ein Byte einfügen
	addq.l #1,a2
	move.l a2,a1
ainsa0a2a
	cmp.l a0,a1
	bls.b ainsa0a2b
	move.b -(a1),1(a1)
	bra.b ainsa0a2a
ainsa0a2b
	rts

MyFix:	; IEEEDPFix-Ersatz: nach 64Bit-Integer
	movem.l d2/d3,-(a7)
	move.l d0,d2
	moveq #20,d3
	lsr.l d3,d2
	and.w #$7FF,d2      ; d2 = Exponent
	cmp.w #$3FF,d2
	bhs.b myfx1
	moveq #0,d0
	moveq #0,d1
	bra.b myfx9
myfx1	and.l #$FFFFF,d0   ; Mantisse
	bset #20,d0        ; hidden Bit
	sub.w #$3FF+52,d2
	tst.w d2
	beq.b myfx9
	bpl.b myfx3
myfx2	lsr.l #1,d0
	roxr.l #1,d1
	addq.w #1,d2
	bne.b myfx2
	bra.b myfx9
myfx3	asl.l #1,d1
	roxl.l #1,d0
	subq.w #1,d2
	bne.b myfx3
myfx9	movem.l (a7)+,d2/d3
	rts

Sign:	jsr GetDoubmath
	move.b #' ',(a2)+
	tst.l d0
	bpl.b Positiv
	bclr #31,d0
	tst.l d0
	beq.b Positiv
	move.b #'-',-1(a2)
Positiv	rts

	end
