Tvůrce webu je i pro tebe! Postav třeba web. Bez grafika. Bez kodéra. Hned.
wz

Obsah / Utility / TEXTFORM / MixSToTextBuf, MixCToTextBuf, MixToTextBufN

Zdrojový kód: INCLUDE\UTIL\TEXTFORM.INC, UTIL\TEXTFORM.ASM

Související:

FltToTextBuf   Zformátování desetinného čísla do bufferu
FltToTextBufN   Délka textu formátovaného desetinného čísla
ExpSToTextBuf   Zformátování čísla s exponentem do bufferu, malé "e"
ExpCToTextBuf   Zformátování čísla s exponentem do bufferu, velké "E"
ExpToTextBufN   Délka textu formátovaného čísla s exponentem
FormToTextBuf   Zformátování textu do bufferu
FormToTextBufN   Délka formátovaného textu

MixSToTextBuf, MixCToTextBuf - Zformátování smíšeného desetinného čísla do bufferu

Funkce MixSToTextBuf a MixCToTextBuf zkonvertují desetinné číslo na text ve smíšeném formátovaném tvaru - tj. buď s exponentem nebo bez exponentu. Formát s exponentem se zvolí v případě, že exponent je menší než -4 nebo větší nebo roven zadané přesnosti. MixSToTextBuf použije malé písmeno exponentu "e", MixCToTextBuf velké písmeno "E". Velikost písmene exponentu přitom nemusí odpovídat formátovacímu příznaku FORMTYPE_Cap_b, který vypne zaokrouhlování poslední číslice.


; -----------------------------------------------------------------------------
;             Convert float number into text buffer in mixed form
; -----------------------------------------------------------------------------
; INPUT:	ST0 = float number (it does not pop it from the FPU stack)
;		EBX = formatting parameters FORMPAR
;		ECX = pointer to nationality descriptor NATIONAL
;		ESI = remaining free space in buffer
;		EDI = destination buffer
; OUTPUT:	ESI = next remaining free space in buffer
;		EDI = next destination buffer
; NOTES:	It uses float point form in range 1e-4 to 1e+precision,
;			else uses exponential form.
;		It uses 2 more registers from FPU stack.
;		FPU should be in default state - 64 bits, round to nearest.
;		To destroy FPU register you can use "ffreep st0" instruction.
;		On AMD 1.6 GHz it takes approx. "10*decimal places+200" nsec.
; -----------------------------------------------------------------------------

MixSToTextBuf:	MIXTOTEXTBUF FltToTextBuf, ExpSToTextBuf ; use small "e"

MixCToTextBuf:	MIXTOTEXTBUF FltToTextBuf, ExpCToTextBuf ; use capital "E"

Na vstupu každé z funkcí obsahuje registr ST0 desetinné číslo ke konverzi, registr EBX obsahuje formátovací parametry FORMPAR (ne ukazatel), registr ECX ukazatel na popisovač národnostních informací NATIONAL, registr ESI čítač zbylého místa v cílovém bufferu a registr EDI ukazatel do cílového bufferu. Na výstupu z funkce jsou registry ESI a EDI posunuty na novou ukládací pozici. Funkce používá další 2 registry koprocesoru. Vstupní číslo v registru ST0 zůstává zachováno, neuvolňuje se ze zásobníku koprocesoru. K uvolnění čísla z registru ST0 lze použít instrukci "ffreep st0" volanou po ukončení funkce. Funkce předpokládá, že koprocesor je v implicitním nastavení - přesnost 64 bitů, zaokrouhlení k nejbližšímu.

Obě funkce používají makro MIXTOTEXTBUF (podrobněji rozepsáno dále), parametry jsou jména funkcí pro zformátování čísla bez exponentu nebo s exponentem.

MixToTextBufN - Délka textu formátovaného smíšeného desetinného čísla

Funkce MixToTextBufN zjistí délku formátovaného čísla ve smíšeném tvaru (tj. buď s exponentem nebo bez exponentu) v bufferu. Formát s exponentem se zvolí v případě, že exponent je menší než -4 nebo větší nebo roven zadané přesnosti.


; -----------------------------------------------------------------------------
;     Convert float number into text buffer in mixed form - get text length
; -----------------------------------------------------------------------------
; INPUT:	ST0 = float number (it does not pop it from the FPU stack)
;		EBX = formatting parameters FORMPAR
; OUTPUT:	EAX = text length
; NOTES:	It uses float point form in range 1e-4 to 1e+precision,
;			else uses exponential form.
;		It uses 2 more registers from FPU stack.
;		FPU should be in default state - 64 bits, round to nearest.
;		To destroy FPU register you can use "ffreep st0" instruction.
; -----------------------------------------------------------------------------

MixToTextBufN:	MIXTOTEXTBUF FltToTextBufN, ExpToTextBufN ; get text length

Na vstupu funkce obsahuje registr ST0 desetinné číslo ke konverzi a registr EBX formátovací parametry FORMPAR (ne ukazatel). Na výstupu je navrácena v registru EAX délka textu. Funkce používá další 2 registry koprocesoru. Vstupní číslo v registru ST0 zůstává zachováno, neuvolňuje se ze zásobníku koprocesoru. K uvolnění čísla z registru ST0 lze použít instrukci "ffreep st0" volanou po ukončení funkce. Funkce předpokládá, že koprocesor je v implicitním nastavení - přesnost 64 bitů, zaokrouhlení k nejbližšímu.

Funkce používá makro MIXTOTEXTBUF (podrobněji rozepsáno dále), parametry jsou jména funkcí pro zjištění délky textu čísla bez exponentu nebo s exponentem.

MIXTOTEXTBUF - Interní makro, formátované smíšené desetinné číslo

Makro MIXTOTEXTBUF je použito interně funkcemi MixSToTextBuf, MixCToTextBuf a MixToTextBufN.


; -----------------------------------------------------------------------------
;                   Macro - convert float number in mixed form
; -----------------------------------------------------------------------------

%macro		MIXTOTEXTBUF 2
; parameter %1 = floating point function, %2 = exponential function

; ------------- Push registers

		push	ebx		; push EBX
		push	eax		; push EAX

Makro má dva vstupní parametry. Prvním parametrem je jméno funkce, která bude použita v případě formátu čísla bez exponentu. Druhým parametrem je jméno funkce, která bude použita v případě formátu čísla s exponentem.


; ------------- Convert flags

		btc	ebx,FORMFLAG_Prec_b ; invert precision flag
		mov	eax,ebx		; EAX <- flags
		shr	eax,FORMFLAG_Alt_b ; EAX <- alternate bits
		and	eax,B0+B1	; EAX <- alternate bits
		mov	eax,[MixFormFlag+eax] ; EAX <- new bits
		and	ebx,~((FORMFLAG2_Alt+FORMFLAG2_Alt2)*256*256) ; clear
		shl	eax,FORMFLAG_Alt_b ; EAX <- new bits
		or	ebx,eax		; set new flags

Jednou ze základní odlišností funkcí se smíšeným formátem oproti jiným formátům je odlišná interpretace některých příznaků, proto jsou příznaky v registru EBX zkonvertovány na tvar používaný volanými funkcemi.

První odchylkou je opačná interpetace údaje přesnosti. Funkce pro smíšený tvar interpretuje implicitně přesnost jako počet významných číslic, zatímco ostatní funkce jako počet číslic za desetinnou tečkou. Proto je invertován příznak FORMFLAG_Prec_b.

označení B0 (alt) B1 (alt2) float, exp mix
  0 0 ruší oddělovač, neořezává nuly rušší oddělovač, ořezává nuly
# 1 0 oddělovač vždy, neořezává nuly oddělovač vždy, neořezává nuly
## 0 1 ruší oddělovač, ořezává nuly oddělovač vždy, ořezává nuly
### 1 1 oddělovač vždy, ořezává nuly ruší oddělovač, neořezává nuly

Další podstatnou odchylkou je jiná interpretace příznaků alternativního formátu, jak je patrné z uvedené tabulky. Do registru EAX, bity 0 a 1, jsou načteny příznaky alternativního formátu. Volané funkce interpretují přepínače alternativních formátů tak, že příznak FORMFLAG_Alt_b (bit 0 v registru EAX) zajistí doplnění oddělovače desetinných míst i v případě, že nenásleduje žádná číslice. Příznak FORMFLAG_Alt2_b zajistí odstranění koncových nevýznamných nul.


; ------------- Mixed float alternate flags

MixFormFlag:	db	B1		; 0 (default): no decimal, truncate 0
		db	B0		; Alt1: always decimal, don't truncate
		db	B0+B1		; Alt2: always decimal, truncate 0
		db	0		; Alt1+Alt2: no decimal, don't truncate

Konverze přepínačů je provedena tabulkou MixFormFlag, nové přepínače jsou doplněny do registru EBX.


; ------------- Check minimal value 1.0e-4

		fld	st0		; duplicate number
		fabs			; absolute value
		fld	tword [MixFormMin] ; load minimal value 1.0e-4
		fcomp	st1		; check minimal value
		fstsw	ax		; AX <- FPU flags
		sahf			; get FPU flags
		ja	%%L4		; use exponential form

Nyní je třeba rozlišit, zda se použije funkce bez exponentu nebo s exponentem. Nejdříve je provedeno porovnání s hodnotou 1.0e-4. Je-li číslo menší než tato hodnota, použije se tvar funkce s exponentem.


; ------------- Check maximal value 1.0e+precision

		xor	eax,eax		; EAX <- 0
		mov	al,10		; EAX <- default exponent 1e10
		bt	ebx,FORMFLAG_Prec_b ; alternate precision?
		jnc	%%L2		; use alternate precision (=fractional)
		cmp	bl,20		; maximal precision
		jae	%%L4		; use exponential form
		movzx	eax,bl		; EAX <- precision
%%L2:		ficomp	dword [MixFormMax+eax*4] ; check maximal value
		fstsw	ax		; AX <- FPU flags
		sahf			; get FPU flags
		jae	%%L6		; use exponential form
		
; ------------- Use float point form

		pop	eax		; pop EAX
		call	%1		; use float point form
		pop	ebx		; pop EBX
		ret

; ------------- Use exponential form

%%L4:		ffreep	st0		; free number
%%L6:		pop	eax		; pop EAX
		call	%2		; use exponential form
		pop	ebx		; pop EBX
		ret
%endmacro

Dále je provedeno rozlišení podle maximální hodnoty čísla. Není-li nastaven příznak alternativní přesnosti FORMFLAG_Prec_b, má přesnost význam počtu číslic za desetinnou tečkou - v tom případě se číslo porovná s hodnotou 1.0e+10 a je-li větší nebo rovno, použije se formát s exponentem.


MixFormMin:	dt	1.0e-4		; minimal value for mixed float

MixFormMax:				; maximal value for mixed float
		%assign	INTMUL10 10
		%rep	20
		dd	INTMUL10
		%assign	INTMUL10 INTMUL10*10
		%endrep

Je-li příznak FORMFLAG_Prec_b nastaven, má přesnost význam počtu významných číslic. Přesnost se omezí na maximální hodnotu 20 a porovná se s hodnotou podle tabulky MixFormMax závisející na přesnosti tak, že exponenciální tvar se použije, je-li exponent čísla větší nebo roven požadované přesnosti.


Obsah / Utility / TEXTFORM / MixSToTextBuf, MixCToTextBuf, MixToTextBufN