|
|
| Посл.отвђт | Сообщенiе |
|
|
Дата: Май 22, 2004 20:55:56 · Поправил: Quantum Black_mirror Ого! Бум пробовать. Благодарю!!! ЗЫ: Вот это Дзен! || \||/ \/ |
|
|
Дата: Май 23, 2004 00:30:39 · Поправил: Black_mirror Устранены баги с округлением: ;destroy: edx,ecx and two floating-point register
;return: eax - end of string
float_to_str:;(str +4,float +8)
xchg edi,[esp+4]
mov edx,[esp+8]
shl edx,1
fld dword [esp+8]
mov al,'+'
jnc .positive
mov al,'-'
fchs
.positive:
stosb
cmp edx,0ff000000h
mov eax,'INF'
jz .special
mov eax,'NAN'
ja .special
mov eax,4D104D43h ;lg(2)
shr edx,24
mul edx
sub eax,0EE0606B8h ;126*lg(2) = 25.EE0606B9
sbb edx,25h+1
fmul qword [.pw2+edx*8+8]
fcom [.f2in31]
fnstsw ax
sahf
jb .noscale
inc edx
fmul [.f01]
.noscale:
fistp dword [esp+8]
push edx
mov edx,[esp+8]
lea edx,[edx*4+edx]
mov eax,edx
and eax,0f0000000h
sub edx,eax
shr eax,28
add eax,'0.'
stosw
mov ecx,6
.outfraq:
shl edx,1
lea edx,[edx*4+edx]
mov eax,edx
and eax,0f0000000h
sub edx,eax
shr eax,28
add al,'0'
stosb
loop .outfraq
pop edx
test edx,edx
mov al,'+'
jns .epositive
mov al,'-'
neg edx
.epositive:
stosb
xchg eax,edx
aam 10
xchg al,ah
or ax,'00'
stosw
mov byte [edi],0
.exit:
mov eax,edi
mov edi,[esp+4]
ret 8
.special:
fstp st0 ;<- добавлено для исправления злого бага
stosd
dec edi
jmp .exit
.i10 dd 10
.i31 dd 31
.f01 dd 0.1
.f2in31 dd 2147483648.0
;10^(-n)*2^28 n=[-38..+38]
dd 02A16A1B1h,49A2CED3h , 04357691Ch,496E17B8h
dd 0CF7920E3h,493812F9h , 072C74D82h,49034261h
dd 0EAD87C04h,48CED09Bh , 02246C99Dh,4898A6E3h
dd 0B5056E17h,4863B8B5h , 08808B024h,482F8DEFh
dd 039A08CEAh,47F93E59h , 0FAE6D721h,47C431E0h
dd 02F1F1281h,479027E7h , 0E4FE8402h,4759D971h
dd 0B7320335h,4724ADF4h , 02C280291h,46F08B2Ah
dd 079D99DB4h,46BA7843h , 0C7E14AF6h,46852D02h
dd 0064DD592h,4650F0CFh , 0D6E2EF50h,461B1AE4h
dd 078B58C40h,45E5AF1Dh , 060913D00h,45B158E4h
dd 0674EC800h,457BC16Dh , 085D8A000h,45463457h
dd 037E08000h,4511C379h , 026340000h,44DC6BF5h
dd 01E900000h,44A6BCC4h , 0E5400000h,4472309Ch
dd 0A2000000h,443D1A94h , 0E8000000h,44074876h
dd 020000000h,43D2A05Fh , 000000000h,439DCD65h
dd 000000000h,4367D784h , 000000000h,433312D0h
dd 000000000h,42FE8480h , 000000000h,42C86A00h
dd 000000000h,42938800h , 000000000h,425F4000h
dd 000000000h,42290000h , 000000000h,41F40000h
.pw2 dd 000000000h,41C00000h , 09999999Ah,41899999h
dd 047AE147Ch,41547AE1h , 0D2F1A9FDh,4120624Dh
dd 0EB1C4330h,40EA36E2h , 088E368F4h,40B4F8B5h
dd 0A0B5ED90h,4080C6F7h , 09ABCAF4Eh,404AD7F2h
dd 0E2308C3Fh,4015798Eh , 0E826D699h,3FE12E0Bh
dd 0D9D7BDC3h,3FAB7CDFh , 0E179649Ch,3F75FD7Fh
dd 0812DEA18h,3F419799h , 06849768Dh,3F0C25C2h
dd 086A12BA4h,3ED6849Bh , 09EE7561Eh,3EA203AFh
dd 097D889CAh,3E6CD2B2h , 04646D4A2h,3E370EF5h
dd 0D1D243B5h,3E02725Dh , 04FB6D2BCh,3DCD83C9h
dd 00C924232h,3D979CA1h , 00A0E9B5Ch,3D62E3B4h
dd 010175EF9h,3D2E3920h , 04012B262h,3CF82DB3h
dd 099A88EB5h,3CC357C2h , 0F5DA7DEFh,3C8EF2D0h
dd 0C4AECB27h,3C58C240h , 036F23C1Fh,3C23CE9Ah
dd 0BE506035h,3BEFB0F6h , 0FEA6B35Eh,3BB95A5Eh
dd 0FEEBC2B1h,3B84484Bh , 06589688Fh,3B5039D6h
dd 0D5A8A74Ch,3B19F623h , 077BA1F70h,3AE4C4E9h
dd 092FB4C5Bh,3AB09D87h , 0B7F87A2Bh,3A7A95A5h
dd 0932D2E8Ah,3A454484h , 0428A8BA2h,3A11039Dh
dd 09DAA7903h,39DB38FBh |
|
|
Дата: Июн 2, 2004 23:20:17 · Поправил: Black_mirror;переводит число расширенной точности в символьный вид
;при возврате eax указывает на байт сразу за числом
long_double_to_str:;(str +4, long double +8(12 байт))
fnstcw [esp+18]
push edi ;+4
mov edi,[4+esp+4] ;указатель на стороку
mov edx,[4+esp+16] ;порядок и знак числа
fldcw [.cwnear] ;расширеная точность, округление к ближайшему
fld tword [4+esp+8] ;загружаем число
mov al,'+'
shl edx,17 ;в cf - знак числа
jnc .positive
mov al,'-' ;меняем знак числа
fchs
.positive:
stosb ;выводим знак числа
shr edx,17 ;порядок числа
cmp edx,7FFFh ;проверяем на особое значение
jz .special
;вычисляем десятичный порядок
mov eax,4D104D43h ;lg(2)
mul edx ;p(двоичный)*lg(2)
lea ecx,[esp] ;align
sub eax,46405238h ;16383*lg(2)-1/2=1343.4640523781h
sbb edx,1343h ;десятичный порядок
lea ecx,[esp] ;align
;возведение 10 в степень -p
mov eax,.p1-12 ;таблицуа 10^(2^n)
mov ecx,edx
fld1
neg ecx ;-p(десятичный)
jz .endpw ;p=0
jns .power ;-p>0
neg ecx ;меняем знак
mov eax,.m1-12 ;таблицуа 10^-(2^n)
.power:
add eax,12
shr ecx,1 ;тестируем бит порядка
ja .power
fld tword [eax] ;умножаем на соответствующую степень 10
fmulp
jnz .power
.endpw:
fmulp ;умножаем число на 10^-p
fld1 ;сравниваем получившееся число с 1
fcomp st1
fnstsw ax
sahf
jbe .great1
fmul [.ten] ;если меньше, домножаем на 10
dec edx ;корректируем порядок
.great1:
fldcw [.cwdown] ;округление вниз
fist word [edi] ;сохраняем первую цифру
fisub word [edi] ;вычисляем остаток
inc edi
inc edi
;st0 - дробная часть числа, выводим с точностью 18 цифр
push edx ;+8
fmul qword [.c1e18]
fistp qword [8+esp+8]
mov eax,[8+esp+8]
lea ecx,[esp+1234] ;align
nop ;align
mov edx,[8+esp+12]
div [.i1e9] ;num=eax*1e-9+edx*1e-18
push edx
stc
rcl eax,2 ;умножаем старшую часть на 2^64/1e9
mul [.cc]
shrd eax,edx,31 ;eax - число формата 0.32
mov ecx,9
.l0: ;находим старшие 9 цифр
mul [.i10]
mov [edi],dl
inc edi
loop .l0
pop eax
stc
nop ;align
rcl eax,2 ;умножаем младшую часть на 2^64/1e9
mul [.cc]
shrd eax,edx,31
mov ecx,9
.l1: ;находим младшие 9 цифр
mul [.i10]
mov [edi],dl
inc edi
loop .l1
pop edx
;старая версия цикла
; mov ecx,18
; .outdigit:
; fmul [.ten]
; fist word [edi]
; fisub word [edi]
; inc edi
; loop .outdigit
; fstp st0
;преобразуем в ASCII
mov eax,'0000'
add dword [edi-20],'0.00'
add [edi-16],eax
add [edi-12],eax
add [edi-8],eax
add [edi-4],eax
;выводим символ и знак порядка
mov ax,'E+'
test edx,edx
jns .epositive
mov ah,'-'
neg edx
.epositive:
stosw
;выводим порядок
mov al,100
xchg eax,edx
div dl
ror eax,8
aam 10
bswap eax
aam 10
xchg al,ah
or eax,'0000'
stosd
mov byte [edi],0 ;записываем завершающий нуль
xchg eax,edi
pop edi
fldcw [esp+18]
ret 16
;обрабатываем специальные значения
.special:
fstp st0
mov eax,'NAN'
mov edx,[4+esp+12] ;если мантиста = 80000000 00000000, то это INF
shl edx,1 ;иначе это не число
jnc .nan
or edx,[4+esp+8]
jnz .nan
mov eax,'INF'
.nan:
stosd
dec edi
xchg eax,edi
pop edi
fldcw [esp+18]
ret 16
align 4
.cc dd 2305843009 ;2^61/10^9
.i10 dd 10
.i1e9 dd 1000000000
.c1e18 dq 1e18
.ten dd 10.0
.cwnear dw 033Fh
.cwdown dw 073Fh
.p1 dd $00000000,$A0000000,$4002;$00000000
.p2 dd $00000000,$C8000000,$4005;$00000000
.p4 dd $00000000,$9C400000,$400C;$00000000
.p8 dd $00000000,$BEBC2000,$4019;$00000000
.p16 dd $04000000,$8E1BC9BF,$4034;$00000000
.p32 dd $2B70B59E,$9DC5ADA8,$4069;$F0200000;^ округлено в большую сторону
.p64 dd $FFCFA6D5,$C2781F49,$40D3;$3CBF6B71;v округлено в меньшую сторону
.p128 dd $80E98CE0,$93BA47C9,$41A8;$C66F336C;^
.p256 dd $9DF9DE8E,$AA7EEBFB,$4351;$DDBB901B;^
.p512 dd $A60E91C7,$E319A0AE,$46A3;$CC655C54;^
.p1024 dd $81750C17,$C9767586,$4D48;$650D3D28;v
.p2048 dd $C53D5DE5,$9E8B3B5D,$5A92;$A74D28CE;^
.p4096 dd $8A20979B,$C4605202,$7525;$C94C153F;^
.m1 dd $CCCCCCCD,$CCCCCCCC,$3FFB;$CCCCCCCC;^
.m2 dd $70A3D70B,$A3D70A3D,$3FF8;$3D70A3D7;v^ дополнительно увеличено на 1
.m4 dd $E219652D,$D1B71758,$3FF1;$D3C36113;^^
.m8 dd $8461CEFE,$ABCC7711,$3FE4;$FDC20D2B;^^
.m16 dd $C44DE15C,$E69594BE,$3FC9;$4C2EBE68;v^
.m32 dd $453994BA,$CFB11EAD,$3F94;$67DE18ED;v
.m64 dd $A539E9A5,$A87FEA27,$3F2A;$3F2398D7;v
.m128 dd $64BCE4A1,$DDD0467C,$3E55;$AC7CB3F6;^
.m256 dd $637A193A,$C0314325,$3CAC;$FA911155;^
.m512 dd $DB23D21C,$9049EE32,$395A;$7132D332;v
.m1024 dd $DA57C0BE,$A2A682A5,$32B5;$87A60158;^
.m2048 dd $34362DE4,$CEAE534F,$256B;$492512D4;v
.m4096 dd $D2CE9FDE,$A6DD04C8,$0AD8;$2DE38123;v
На данный момент одно преобразование на атлоне выполняется за 500 тактов. Может у кого есть идеи для оптимизации по скорости и/или точности вычислений? (таблицу на 90К не предлагать) |
|
|
Дата: Июн 2, 2004 23:37:34 А вот тестирующая програмка(перенаправив вывод в файл можно посмотреть на результаты преобразований). 1459977548__ld2s.zip |
|
Powered by miniBB 1.6 © 2001-2002
Время загрузки страницы (сек.): 0.069 |