Понадобилась функция, выделяющая мантиссу и экспоненту по основанию 10, но нигде не нашёл. Решил сделать сам. Вот она: Code (Text): namespace fpu_cw { WORD _stdcw, _cwup, _cwdown, _cwtrunc; } static void GetCWValues(void) { using namespace fpu_cw; asm { FNINIT FNSTCW word ptr _stdcw mov AX, word ptr _stdcw bts AX, 11 btr AX, 10 mov word ptr _cwup, AX bts AX, 10 btr AX, 11 mov word ptr _cwdown, AX bts AX, 10 bts AX, 11 mov word ptr _cwtrunc, AX } } #pragma startup GetCWValues 64 static const long double ten = 10.0; double _stdcall XTRACT10(const double value, int * pe) { using namespace fpu_cw; double XTRACT10; unsigned short cw; int e; asm { FNSTCW cw FLD value // v FTST FSTSW AX sahf jz @zero FXTRACT // m2 e2 FLDLG2 // lg2 m2 e2 FMUL ST(2), ST // lg2 m2 lg2*e2 FLD ST(2) // lg2*e2 lg2 m2 lg2*e2 FLDCW word ptr _cwdown FRNDINT // [lg2*e2] lg2 m2 lg2*e2 FSUB ST(3), ST // e10? lg2 m2 {lg2*e2} FISTP e // lg2 m2 {lg2*e2} FDIVP ST(2), ST // m2 {lg2*e2}/lg2 FXCH // {lg2*e2}/lg2 m2 FLD1 // 1 {lg2*e2}/lg2 m2 FCOMIP ST, ST(1) // {lg2*e2}/lg2 m2 ja @rempwr FLD ST(0) // {lg2*e2}/lg2 {lg2*e2}/lg2 m2 FLDCW word ptr _stdcw FRNDINT // [{lg2*e2}/lg2] {lg2*e2}/lg2 m2 FSUB ST(1), ST // [{lg2*e2}/lg2] {{lg2*e2}/lg2} m2 FXCH // {{lg2*e2}/lg2} [{lg2*e2}/lg2] m2 F2XM1 // (2^{{lg2*e2}/lg2} - 1) [{lg2*e2}/lg2] m2 FLD1 // 1 (2^{{lg2*e2}/lg2} - 1) [{lg2*e2}/lg2] m2 FADD // 2^{{lg2*e2}/lg2} [{lg2*e2}/lg2] m2 FSCALE // 10^{lg2*e2} [{lg2*e2}/lg2] m2 FMULP ST(2), ST // [{lg2*e2}/lg2] 10^{lg2*e2}*m2 FSTP ST // m10? jmp @revise @rempwr: F2XM1 // (2^{lg2*e2}/lg2 - 1) m2 FLD1 // 1 (2^{lg2*e2}/lg2 - 1) m2 FADD // 2^({lg2*e2}/lg2) m2 FMUL // m10? @revise: FLD ten // 10.0 m10? FCOMI ST, ST(1) jb @change FSTP ST // m10 jmp @end @change: FDIV // m10 inc e jmp @end @zero: mov e, 0 @end: FSTP XTRACT10 // FLDCW cw } if (pe != NULL) *pe = e; return XTRACT10; } Вместо констант lg2 и ten можно вписать произвольные и тогда можно брать по любому основанию. Очень не хотелось изобретать велосипед. Можно ли проще? Дайте пожалуйста ссылки. Что не так?
Code (Text): static const long double ten = 10.0; double _stdcall XTRACT10(const double value, int * pexponent) { double XTRACT10; unsigned short cw, cwdown, cwround; int exponent; asm { FNSTCW cw FLD value // v FTST FSTSW AX sahf jz @zero FXTRACT // m2 e2 FLDLG2 // lg2 m2 e2 FMULP ST(2), ST // m2 lg2*e2 FLD ST(1) // lg2*e2 m2 lg2*e2 mov AX, cw bts AX, 10 btr AX, 11 mov cwdown, AX FLDCW cwdown FRNDINT // [lg2*e2] m2 lg2*e2 FLDCW cw FSUB ST(2), ST // e10? m2 {lg2*e2} FISTP exponent // m2 {lg2*e2} FLDL2T // l2t m2 {lg2*e2} // 10 FMULP ST(2), ST // m2 {lg2*e2}*l2t FXCH // {lg2*e2}*l2t m2 FLD1 // 1 {lg2*e2}*l2t m2 FCOMIP ST, ST(1) // {lg2*e2}*l2t m2 jae @rempwr FLD ST(0) // {lg2*e2}*l2t {lg2*e2}*l2t m2 mov AX, cw btr AX, 10 btr AX, 11 mov cwround, AX FLDCW cwround FRNDINT // [{lg2*e2}*l2t] {lg2*e2}*l2t m2 FLDCW cw FSUB ST(1), ST // [{lg2*e2}*l2t] {{lg2*e2}*l2t} m2 FXCH // {{lg2*e2}*l2t} [{lg2*e2}*l2t] m2 F2XM1 // (2^{{lg2*e2}*l2t} - 1) [{lg2*e2}*l2t] m2 FLD1 // 1 (2^{{lg2*e2}*l2t} - 1) [{lg2*e2}*l2t] m2 FADD // 2^{{lg2*e2}*l2t} [{lg2*e2}*l2t] m2 FSCALE // 10^{lg2*e2} [{lg2*e2}*l2t] m2 FMULP ST(2), ST // [{lg2*e2}*l2t] 10^{lg2*e2}*m2 FSTP ST // m10? jmp @revise @rempwr: F2XM1 // (2^{lg2*e2}*l2t - 1) m2 FLD1 // 1 (2^{lg2*e2}*l2t - 1) m2 FADD // 2^({lg2*e2}*l2t) m2 FMUL // m10? @revise: FLD ten // 10.0 m10? // 10 FCOMI ST, ST(1) jbe @reduce FSTP ST // m10 jmp @end @reduce: FDIV // m10 inc exponent jmp @end @zero: mov exponent, 0 @end: FSTP XTRACT10 // FLDCW cw } if (pexponent != NULL) *pexponent = exponent; return XTRACT10; }
Вот и всё. Мб кому-нибудь будет полезно Code (Text): double _stdcall XTRACTR(const double value, const double radix, int * pexponent) { double XTRACTR; unsigned short cw, cwdown; int exponent; bool msigned; asm { FNSTCW cw FLD value // v FTST FSTSW AX sahf jz @zero // m2 == 0 setb msigned FABS FXTRACT // m2 e2 FLD1 // 1 m2 e2 FLD ST // 1 1 m2 e2 FLD radix // r 1 1 m2 e2 FYL2X // l2r 1 m2 e2 FDIV ST(1), ST // l2r lr2 m2 e2 FXCH // lr2 l2r m2 e2 FMULP ST(3), ST // l2r m2 lr2*e2 FLD ST(2) // lr2*e2 l2r m2 lr2*e2 mov AX, cw bts AX, 10 btr AX, 11 mov cwdown, AX FLDCW cwdown FRNDINT // [lr2*e2] l2r m2 lr2*e2 FLDCW cw FSUB ST(3), ST // er? l2r m2 {lr2*e2} FISTP exponent // l2r m2 {lr2*e2} FMULP ST(2), ST // m2 {lr2*e2}*l2r FXCH // {lr2*e2}*l2r m2 FLD1 // 1 {lr2*e2}*l2r m2 FCOMI ST, ST(1) // 1 {lr2*e2}*l2r m2 jae @rempwr // {lr2*e2}*l2r <= 1 FLD ST(1) // {lr2*e2}*l2r 1 {lr2*e2}*l2r m2 FRNDINT // [{lr2*e2}*l2r] 1 {lr2*e2}*l2r m2 FSUB ST(2), ST // [{lr2*e2}*l2r] 1 {{lr2*e2}*l2r} m2 FXCH ST(2) // {{lr2*e2}*l2r} 1 [{lr2*e2}*l2r] m2 F2XM1 // (2^{{lr2*e2}*l2r} - 1) 1 [{lr2*e2}*l2r] m2 FADD // 2^{{lr2*e2}*l2r} [{lr2*e2}*l2r] m2 FSCALE // r^{lr2*e2} [{lr2*e2}*l2r] m2 FMULP ST(2), ST // [{lr2*e2}*l2r] r^{lr2*e2}*m2 FSTP ST // mr? jmp @revise @rempwr: FXCH // 1 {lr2*e2}*l2r m2 F2XM1 // (2^{lr2*e2}*l2r - 1) 1 m2 FADD // 2^({lr2*e2}*l2r) m2 FMUL // mr? @revise: // mr? in [radix, 2*radix) FLD radix // r mr? FCOMI ST, ST(1) jbe @reduce // r <= mr? FLD1 // 1 r mr? FCOMIP ST, ST(2) // r mr? ja @raise // 1 > mr? FSTP ST // mr? jmp @check @reduce: // r mr? FDIV // r*mr? inc exponent // er++ jmp @check // mr @raise: // r mr? FMUL // r*mr? dec exponent // er-- jmp @check // mr @zero: // mr mov exponent, 0 // mr = 0 // er = 0 jmp @end @check: cmp msigned, 1 jne @end FCHS @end: FSTP XTRACTR // } if (pexponent != NULL) *pexponent = exponent; return XTRACTR; }
И ведь никто не сказал, что я глупость сделал =) Code (Text): long double _stdcall XTRACTR(const long double value, const long double radix, int * pexponent) { long double XTRACTR; int exponent; unsigned short cw, cwdown; bool sign; asm { FLD value // val FTST FSTSW AX sahf setb sign jz @end FABS // |val| FLD1 // 1 v FLD radix // r 1 v FYL2X // l2r v FLD ST // l2r l2r v FLD1 // 1 l2r l2r v FLD ST(3) // v 1 l2r l2r v FYL2X // l2v l2r l2r v FDIVR // lrv l2r v FNSTCW cw mov AX, cw bts AX, 10 btr AX, 11 mov cwdown, AX FLDCW cwdown FRNDINT // e l2r v FIST exponent // [lrv) l2r v FLDCW cw FCHS // -[lrv) l2r v FMUL // -[lrv)*l2r v FLD ST // -[lrv)*l2r -[lrv)*l2r v FRNDINT // [-[lrv)*l2r] -[lrv)*l2r v FSUB ST(1), ST // [-[lrv)*l2r] {-[lrv)*l2r} v FXCH // {-[lrv)*l2r} [-[lrv)*l2r] v F2XM1 // (2^{-[lrv)*l2r} - 1) [-[lrv)*l2r] v FLD1 // 1 (2^{-[lrv)*l2r} - 1) [-[lrv)*l2r] v FADD // 2^{-[lrv)*l2r} [-[lrv)*l2r] v FSCALE // r^(-e) [-[lrv)*l2r] v FMULP ST(2), ST // [-[lrv)*l2r] v*r^(-e) FSTP ST // v*r^(-e) test sign, 1 jz @end FCHS @end: FSTP XTRACTR // } if (pexponent != NULL) *pexponent = exponent; return XTRACTR; }