
* Maxon C++ Library:
* Modul "math_floattostr"
* Jens Gelhar 08.09.91, 15.04.94

	xdef	_floattostr,_fpwr10

	xref	GetMathbase
	xref	uintdiv

SPAdd	= -66
SPMul	= -78
SPDiv	= -84

Halb	= $3F000000
Eins	= $3F800000
Zehn	= $41200000

_floattostr: ; Stack-Parameter: float, char[], short
	movem.l	d2-d7/a2-a6,-(a7)
	move.l	11*4+4(a7),d0
	move.l	11*4+8(a7),a5
	move.w	11*4+12(a7),d1
	bsr.b	RealStr
	move.l	a5,d0
	movem.l (a7)+,d2-d7/a2-a6
	rts

RealStr: ; Zahl d0, ±d1 Stellen, nach a5
	move.w	d1,-(a7)
	move.l	a5,a2
	move.b	#' ',(a2)+
	tst.l	d0
	bpl.b	.posi
	move.b	#'-',-1(a2)
	bclr	#31,d0
.posi	tst.w	(a7)		; Stellenzahl
	bne.b	.fixed
	tst.l	d0
	bne.b	.1
	move.b	#'0',(a2)+	; d0 = 0F
	clr.b	(a2)
	bra	wrreEnd
.1	moveq	#6,d1
	bsr	DigitString
	cmp.w	#4,d1
	bge.b	.4
	cmp.w	#-1,d1
	blt.b	.4
	move.w	d1,d0
	bsr	InsertKomma
.2	cmp.b	#'0',-1(a2)	; Nullen am Ende entfernen
	bne.b	.3
	clr.b	-(a2)
	bra.b	.2
.3	cmp.b	#'.',-1(a2)
	bne	wrreEnd
	clr.b	-(a2)
	bra	wrreEnd
.4	bsr	Exponentiere
	bra	wrreEnd

.fixed:	; Festpunkt - Darstellung
	move.w	(a7),d1
	bmi.b	.expo
	tst.l	d0
	bpl.b	.8
	bsr	Exponent	; d0 <> 0F
	cmp.w	#9,d1
	bge.b	.1
	cmp.w	#-9,d1
	ble.b	.1
	add.w	(a7),d1
	addq.w	#1,d1
	move.w	d1,-(a7)
	cmp.w	#7,d1
	bls.b	.5
	moveq	#7,d1
.5	bsr.b	DigitString
	move.w	(a7)+,d2
	cmp.w	#20,d2
	bhi.b	.7
	subq.w	#7,d2
	bls.b	.7
.6	move.b	#'0',(a2)+
	subq.w	#1,d2
	bne.b	.6
.7
	move.w	d1,d0
	bsr	InsertKomma
	bra.b	wrreEnd

.8	; d0 = 0F
	move.b	#'0',(a2)+
	move.b	#'.',(a2)+
.loop8	move.b	#'0',(a2)+
	subq.w	#1,d1
	bne.b	.loop8
	bra.b	wrreEnd

.expo	; Exponential-Darsetllung
	neg.w	d1
	tst.l	d0
	bne.b	.10
	move.w	d1,d0
	moveq	#0,d1
.9	move.b	#'0',(a2)+	; d0=0F
	subq.w	#1,d0
	beq.b	.13
	cmp.w	#20,d0
	bhs.b	.13
	bra.b	.9
.10	; d0 <> 0F
	cmp.w	#7,d1
	blo.b	.11
	moveq	#7,d1
.11	bsr.b	DigitString
	move.w	(a7),d0
	neg.w	d0		; Ziffern-anzahl
	cmp.w	#20,d0
	bhi.b	.13
.12	cmp.w	#7,d0
	bls.b	.13
	move.b	#'0',(a2)+  ; Nullen anhängen
	subq.w	#1,d0
	bra.b	.12
.13	bsr	Exponentiere

wrreEnd	addq.w #2,a7
	rts

DigitString:
	; Ziffern von d0, d1 Stück, nach (a2)+ schreiben
	; Logarithmus nach d1
	pea	0(a2,d1.w)
	move.l	a2,-(a7)
	move.w	d1,-(a7)
	bsr	Exponent	; 10er-Logarithmus
	move.w	d1,-(a7)
	neg.w	d1
	add.w	2(a7),d1	; Ziffernzahl addieren
	move.l	d0,-(a7)
	move.w	d1,d0
	subq.w	#1,d0
	jsr	GetMathbase
	bsr	power
	move.l	(a7)+,d1
	jsr	SPMul(a6)
	move.l	#Halb,d1
	jsr	SPAdd(a6)
	bsr	FixIt
	move.w	(a7)+,d2	; Lg
	move.w	(a7)+,d1	; Ziffernanzahl
	move.l	(a7)+,a2
	move.w	d2,-(a7)
	bsr.b	PutInt
	move.w	(a7)+,d1
	move.l	a2,a0
	move.l	(a7)+,a2	; gewünschtes Ende
	clr.b	(a2)
	sub.l	a2,a0
	add.w	a0,d1
	rts

PutInt:	; d0 nach (a2)+
	; d2 = Ziffernanzahl
	moveq	#0,d2
.1	move.w	d2,-(a7)
	moveq	#10,d1
	jsr	uintdiv
	move.w	(a7)+,d2
	move.w	d1,-(a7)
	addq.w	#1,d2
	tst.l	d0
	bne.b	.1
	move.w	d2,d1
.2	move.w	(a7)+,d0
	add.b	#'0',d0
	move.b	d0,(a2)+
	subq.w	#1,d1
	bne.b	.2
	rts

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

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

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

FixIt:	; SPFix-Ersatz
	tst.l	d0
	beq.b	.0	; Null ist Null
	bpl.b	.1
	bclr	#31,d0	; negativ
	bsr.b	.1
	neg.l	d0
	rts
.1	cmp.l	#Eins,d0
	blo.b	.0
	move.l	d0,d1
	and.l	#$007FFFFF,d0	; Mantisse
	bset	#23,d0		; Hidden Bit setzen
	swap	d1
	lsr.w	#23-16,d1	; nackter Exponent
	sub.w	#$7E+24,d1	; Shift-Stellen
	bhs.b	.links
	neg.w	d1
	lsr.l	d1,d0
	rts
.links	lsl.l	d1,d0
	rts
.0	moveq #0,d0
	rts

Exponent:
	; von Float d0>=0 nach d1, d0 nicht verändern
	tst.l	d0
	bne.b	.null
	moveq	#0,d1		; Null hat Exponent 0 (na ja...)
	rts
.null	jsr	GetMathbase
	cmp.l	#Eins,d0
	bhs.b	.greater
	; d0 < 1
	moveq	#0,d1
	move.l	d0,-(a7)
.1	subq.l	#1,d1
	move.l	d1,-(a7)
	move.l	d1,d0
	bsr	power
	move.l	(a7)+,d1
	move.l	(a7),d2
	cmp.l	d0,d2		; Floats vergleichen
	blo.b	.1
	bra.b	.5
.greater	; d0 >= 1
	moveq	#-1,d1
	move.l	d0,-(a7)
.3	addq.l	#1,d1
	cmp.w	#20,d1
	bhs.b	.4
	move.l	d1,-(a7)
	move.l	d1,d0
	bsr	power
	move.l	(a7)+,d1
	move.l	(a7),d2
	cmp.l	d0,d2
	bhi.b	.3
.4	; gefunden
	subq.w	#1,d1
.5	move.l	(a7)+,d0
	rts


_fpwr10:
	move.l	4(a7),d0
	movem.l	d2-d3/a6,-(a7)
	jsr	GetMathbase
	bsr.b	power
	movem.l	(a7)+,d2-d3/a6
	rts

power:	; 10^d0 berechnen (Math-Base schon in a6!)
	cmp.w	#19,d0
	bgt.b	.large
	tst.w	d0
	bpl.b	.a
	neg.w	d0
	cmp.w	#19,d0
	bhi.b	.e
	bsr.b	.a
	move.l	d0,d1
	move.l	#Eins,d0
	jmp	SPDiv(a6)
.a	cmp.w	#9,d0
	bls.b	.b
	sub.w	#9,d0
	bsr.b	.b
	move.l	.data+9*4(pc),d1
	jmp	SPMul(a6)
.b	asl.w	#2,d0
	move.l	.data(pc,d0.w),d0
	rts
.data	dc.l	Eins,Zehn,$42C80000,$447A0000,$461C4000
	dc.l	$47C35000,$49742400,$4B189680,$4CBEBC20,$4E6E6B28
.e	moveq #0,d0
	rts

.large	; Überlauf:
	move.l #$7FFFFFFF,d0
	rts

	end
