fxtract radix 10

Тема в разделе "WASM.ASSEMBLER", создана пользователем Dukales, 19 янв 2010.

  1. Dukales

    Dukales New Member

    Публикаций:
    0
    Регистрация:
    5 июл 2009
    Сообщения:
    199
    Понадобилась функция, выделяющая мантиссу и экспоненту по основанию 10, но нигде не нашёл. Решил сделать сам. Вот она:
    Код (Text):
    1. namespace fpu_cw
    2. {
    3.  WORD _stdcw,
    4.       _cwup,
    5.       _cwdown,
    6.       _cwtrunc;
    7. }
    8.  
    9. static void GetCWValues(void)
    10. {
    11.  using namespace fpu_cw;
    12.  
    13.  asm
    14.  {
    15.   FNINIT
    16.   FNSTCW word ptr _stdcw
    17.  
    18.   mov AX, word ptr _stdcw
    19.  
    20.   bts AX, 11
    21.   btr AX, 10
    22.   mov word ptr _cwup, AX
    23.  
    24.   bts AX, 10
    25.   btr AX, 11
    26.   mov word ptr _cwdown, AX
    27.  
    28.   bts AX, 10
    29.   bts AX, 11
    30.   mov word ptr _cwtrunc, AX
    31.  }
    32. }
    33.  
    34. #pragma startup GetCWValues 64
    35.  
    36. static const long double ten = 10.0;
    37.  
    38. double _stdcall XTRACT10(const double value, int * pe)
    39. {        
    40.  using namespace fpu_cw;
    41.  
    42.  double XTRACT10;
    43.  
    44.  unsigned short cw;
    45.  int e;
    46.  asm
    47.  {
    48.   FNSTCW cw
    49.   FLD value                     // v
    50.   FTST
    51.   FSTSW AX
    52.   sahf
    53.   jz @zero
    54.   FXTRACT                       // m2 e2
    55.   FLDLG2                        // lg2 m2 e2
    56.   FMUL ST(2), ST                // lg2 m2 lg2*e2
    57.   FLD ST(2)                     // lg2*e2 lg2 m2 lg2*e2
    58.   FLDCW word ptr _cwdown
    59.   FRNDINT                       // [lg2*e2] lg2 m2 lg2*e2
    60.   FSUB ST(3), ST                // e10? lg2 m2 {lg2*e2}
    61.   FISTP e                       // lg2 m2 {lg2*e2}
    62.   FDIVP ST(2), ST               // m2 {lg2*e2}/lg2
    63.   FXCH                          // {lg2*e2}/lg2 m2
    64.   FLD1                          // 1 {lg2*e2}/lg2 m2
    65.   FCOMIP ST, ST(1)              // {lg2*e2}/lg2 m2
    66.   ja @rempwr
    67.   FLD ST(0)                     // {lg2*e2}/lg2 {lg2*e2}/lg2 m2
    68.   FLDCW word ptr _stdcw
    69.   FRNDINT                       // [{lg2*e2}/lg2] {lg2*e2}/lg2 m2
    70.   FSUB ST(1), ST                // [{lg2*e2}/lg2] {{lg2*e2}/lg2} m2
    71.   FXCH                          // {{lg2*e2}/lg2} [{lg2*e2}/lg2] m2
    72.   F2XM1                         // (2^{{lg2*e2}/lg2} - 1) [{lg2*e2}/lg2] m2
    73.   FLD1                          // 1 (2^{{lg2*e2}/lg2} - 1) [{lg2*e2}/lg2] m2
    74.   FADD                          // 2^{{lg2*e2}/lg2} [{lg2*e2}/lg2] m2
    75.   FSCALE                        // 10^{lg2*e2} [{lg2*e2}/lg2] m2
    76.   FMULP ST(2), ST               // [{lg2*e2}/lg2] 10^{lg2*e2}*m2
    77.   FSTP ST                       // m10?
    78.   jmp @revise
    79.  
    80.   @rempwr:
    81.   F2XM1                         // (2^{lg2*e2}/lg2 - 1) m2
    82.   FLD1                          // 1 (2^{lg2*e2}/lg2 - 1) m2
    83.   FADD                          // 2^({lg2*e2}/lg2) m2
    84.   FMUL                          // m10?
    85.  
    86.   @revise:
    87.   FLD ten                       // 10.0 m10?
    88.   FCOMI ST, ST(1)
    89.   jb @change
    90.   FSTP ST                       // m10
    91.   jmp @end
    92.  
    93.   @change:
    94.   FDIV                          // m10
    95.   inc e
    96.   jmp @end
    97.  
    98.   @zero:
    99.   mov e, 0
    100.  
    101.   @end:
    102.   FSTP XTRACT10                 //
    103.   FLDCW cw
    104.  }
    105.  
    106.  if (pe != NULL) *pe = e;
    107.  
    108.  return XTRACT10;
    109. }
    Вместо констант lg2 и ten можно вписать произвольные и тогда можно брать по любому основанию.
    Очень не хотелось изобретать велосипед. Можно ли проще? Дайте пожалуйста ссылки. Что не так?
     
  2. Dukales

    Dukales New Member

    Публикаций:
    0
    Регистрация:
    5 июл 2009
    Сообщения:
    199
    *в обоих сравнениях or equal следовало написать
     
  3. Dukales

    Dukales New Member

    Публикаций:
    0
    Регистрация:
    5 июл 2009
    Сообщения:
    199
    Код (Text):
    1. static const long double ten = 10.0;
    2.  
    3. double _stdcall XTRACT10(const double value, int * pexponent)
    4. {
    5.  double XTRACT10;
    6.  
    7.  unsigned short cw, cwdown, cwround;
    8.  int exponent;
    9.  asm
    10.  {
    11.   FNSTCW cw
    12.   FLD value                     // v
    13.   FTST
    14.   FSTSW AX
    15.   sahf
    16.   jz @zero
    17.   FXTRACT                       // m2 e2
    18.   FLDLG2                        // lg2 m2 e2
    19.   FMULP ST(2), ST               // m2 lg2*e2
    20.   FLD ST(1)                     // lg2*e2 m2 lg2*e2
    21.  
    22.   mov AX, cw
    23.   bts AX, 10
    24.   btr AX, 11
    25.   mov cwdown, AX
    26.   FLDCW cwdown
    27.   FRNDINT                       // [lg2*e2] m2 lg2*e2
    28.   FLDCW cw
    29.  
    30.   FSUB ST(2), ST                // e10? m2 {lg2*e2}
    31.   FISTP exponent                // m2 {lg2*e2}
    32.   FLDL2T                        // l2t m2 {lg2*e2}                              // 10
    33.   FMULP ST(2), ST               // m2 {lg2*e2}*l2t
    34.   FXCH                          // {lg2*e2}*l2t m2
    35.   FLD1                          // 1 {lg2*e2}*l2t m2
    36.   FCOMIP ST, ST(1)              // {lg2*e2}*l2t m2
    37.   jae @rempwr
    38.   FLD ST(0)                     // {lg2*e2}*l2t {lg2*e2}*l2t m2
    39.  
    40.   mov AX, cw
    41.   btr AX, 10
    42.   btr AX, 11
    43.   mov cwround, AX
    44.   FLDCW cwround
    45.   FRNDINT                       // [{lg2*e2}*l2t] {lg2*e2}*l2t m2
    46.   FLDCW cw
    47.  
    48.   FSUB ST(1), ST                // [{lg2*e2}*l2t] {{lg2*e2}*l2t} m2
    49.   FXCH                          // {{lg2*e2}*l2t} [{lg2*e2}*l2t] m2
    50.   F2XM1                         // (2^{{lg2*e2}*l2t} - 1) [{lg2*e2}*l2t] m2
    51.   FLD1                          // 1 (2^{{lg2*e2}*l2t} - 1) [{lg2*e2}*l2t] m2
    52.   FADD                          // 2^{{lg2*e2}*l2t} [{lg2*e2}*l2t] m2
    53.   FSCALE                        // 10^{lg2*e2} [{lg2*e2}*l2t] m2
    54.   FMULP ST(2), ST               // [{lg2*e2}*l2t] 10^{lg2*e2}*m2
    55.   FSTP ST                       // m10?
    56.   jmp @revise
    57.  
    58.   @rempwr:
    59.   F2XM1                         // (2^{lg2*e2}*l2t - 1) m2
    60.   FLD1                          // 1 (2^{lg2*e2}*l2t - 1) m2
    61.   FADD                          // 2^({lg2*e2}*l2t) m2
    62.   FMUL                          // m10?
    63.  
    64.   @revise:
    65.   FLD ten                       // 10.0 m10?                                    // 10
    66.   FCOMI ST, ST(1)
    67.   jbe @reduce
    68.   FSTP ST                       // m10
    69.   jmp @end
    70.  
    71.   @reduce:
    72.   FDIV                          // m10
    73.   inc exponent
    74.   jmp @end
    75.  
    76.   @zero:
    77.   mov exponent, 0
    78.  
    79.   @end:
    80.   FSTP XTRACT10                 //
    81.   FLDCW cw
    82.  }
    83.  
    84.  if (pexponent != NULL) *pexponent = exponent;
    85.  
    86.  return XTRACT10;
    87. }
     
  4. Dukales

    Dukales New Member

    Публикаций:
    0
    Регистрация:
    5 июл 2009
    Сообщения:
    199
    Вот и всё. Мб кому-нибудь будет полезно
    Код (Text):
    1. double _stdcall XTRACTR(const double value, const double radix, int * pexponent)
    2. {
    3.  double XTRACTR;
    4.  
    5.  unsigned short cw, cwdown;
    6.  int exponent;
    7.  bool msigned;
    8.  asm
    9.  {
    10.   FNSTCW cw
    11.  
    12.   FLD value                     // v
    13.   FTST
    14.   FSTSW AX
    15.   sahf
    16.   jz @zero                      // m2 == 0
    17.   setb msigned
    18.   FABS
    19.   FXTRACT                       // m2 e2
    20.   FLD1                          // 1 m2 e2
    21.   FLD ST                        // 1 1 m2 e2
    22.   FLD radix                     // r 1 1 m2 e2
    23.   FYL2X                         // l2r 1 m2 e2
    24.   FDIV ST(1), ST                // l2r lr2 m2 e2
    25.   FXCH                          // lr2 l2r m2 e2
    26.   FMULP ST(3), ST               // l2r m2 lr2*e2
    27.   FLD ST(2)                     // lr2*e2 l2r m2 lr2*e2
    28.  
    29.   mov AX, cw
    30.   bts AX, 10
    31.   btr AX, 11
    32.   mov cwdown, AX
    33.   FLDCW cwdown
    34.   FRNDINT                       // [lr2*e2] l2r m2 lr2*e2
    35.   FLDCW cw
    36.  
    37.   FSUB ST(3), ST                // er? l2r m2 {lr2*e2}
    38.   FISTP exponent                // l2r m2 {lr2*e2}  
    39.   FMULP ST(2), ST               // m2 {lr2*e2}*l2r
    40.   FXCH                          // {lr2*e2}*l2r m2
    41.   FLD1                          // 1 {lr2*e2}*l2r m2
    42.   FCOMI ST, ST(1)               // 1 {lr2*e2}*l2r m2
    43.   jae @rempwr                   // {lr2*e2}*l2r <= 1
    44.   FLD ST(1)                     // {lr2*e2}*l2r 1 {lr2*e2}*l2r m2
    45.   FRNDINT                       // [{lr2*e2}*l2r] 1 {lr2*e2}*l2r m2
    46.   FSUB ST(2), ST                // [{lr2*e2}*l2r] 1 {{lr2*e2}*l2r} m2
    47.   FXCH ST(2)                    // {{lr2*e2}*l2r} 1 [{lr2*e2}*l2r] m2
    48.   F2XM1                         // (2^{{lr2*e2}*l2r} - 1) 1 [{lr2*e2}*l2r] m2
    49.   FADD                          // 2^{{lr2*e2}*l2r} [{lr2*e2}*l2r] m2
    50.   FSCALE                        // r^{lr2*e2} [{lr2*e2}*l2r] m2
    51.   FMULP ST(2), ST               // [{lr2*e2}*l2r] r^{lr2*e2}*m2
    52.   FSTP ST                       // mr?
    53.   jmp @revise
    54.  
    55.   @rempwr:
    56.   FXCH                          // 1 {lr2*e2}*l2r m2
    57.   F2XM1                         // (2^{lr2*e2}*l2r - 1) 1 m2
    58.   FADD                          // 2^({lr2*e2}*l2r) m2
    59.   FMUL                          // mr?
    60.  
    61.   @revise:                      // mr? in [radix, 2*radix)
    62.   FLD radix                     // r mr?
    63.   FCOMI ST, ST(1)
    64.   jbe @reduce                   // r <= mr?
    65.   FLD1                          // 1 r mr?
    66.   FCOMIP ST, ST(2)              // r mr?
    67.   ja @raise                     // 1 > mr?
    68.   FSTP ST                       // mr?
    69.   jmp @check
    70.  
    71.   @reduce:                      // r mr?
    72.   FDIV                          // r*mr?
    73.   inc exponent                  // er++
    74.   jmp @check                     // mr
    75.  
    76.   @raise:                       // r mr?
    77.   FMUL                          // r*mr?
    78.   dec exponent                  // er--
    79.   jmp @check                    // mr
    80.  
    81.   @zero:                        // mr
    82.   mov exponent, 0               // mr = 0 // er = 0
    83.   jmp @end
    84.  
    85.   @check:
    86.   cmp msigned, 1
    87.   jne @end                      
    88.   FCHS
    89.  
    90.   @end:
    91.   FSTP XTRACTR                  //
    92.  }
    93.  
    94.  if (pexponent != NULL) *pexponent = exponent;
    95.  
    96.  return XTRACTR;
    97. }
     
  5. Dukales

    Dukales New Member

    Публикаций:
    0
    Регистрация:
    5 июл 2009
    Сообщения:
    199
    И ведь никто не сказал, что я глупость сделал =)
    Код (Text):
    1. long double _stdcall XTRACTR(const long double value, const long double radix, int * pexponent)
    2. {
    3.  long double XTRACTR;
    4.  int exponent;
    5.  
    6.  unsigned short cw, cwdown;
    7.  bool sign;
    8.  asm
    9.  {
    10.   FLD value             // val
    11.   FTST
    12.   FSTSW AX
    13.   sahf
    14.   setb sign
    15.   jz @end
    16.   FABS                  // |val|
    17.   FLD1                  // 1 v
    18.   FLD radix             // r 1 v
    19.   FYL2X                 // l2r v
    20.   FLD ST                // l2r l2r v
    21.   FLD1                  // 1 l2r l2r v
    22.   FLD ST(3)             // v 1 l2r l2r v
    23.   FYL2X                 // l2v l2r l2r v
    24.   FDIVR                 // lrv l2r v
    25.  
    26.   FNSTCW cw
    27.   mov AX, cw
    28.   bts AX, 10
    29.   btr AX, 11
    30.   mov cwdown, AX
    31.   FLDCW cwdown
    32.   FRNDINT               // e l2r v
    33.   FIST exponent         // [lrv) l2r v
    34.   FLDCW cw
    35.  
    36.   FCHS                  // -[lrv) l2r v
    37.   FMUL                  // -[lrv)*l2r v
    38.   FLD ST                // -[lrv)*l2r -[lrv)*l2r v
    39.  
    40.   FRNDINT               // [-[lrv)*l2r] -[lrv)*l2r v
    41.   FSUB ST(1), ST        // [-[lrv)*l2r] {-[lrv)*l2r} v
    42.   FXCH                  // {-[lrv)*l2r} [-[lrv)*l2r] v
    43.   F2XM1                 // (2^{-[lrv)*l2r} - 1) [-[lrv)*l2r] v
    44.   FLD1                  // 1 (2^{-[lrv)*l2r} - 1) [-[lrv)*l2r] v
    45.   FADD                  // 2^{-[lrv)*l2r} [-[lrv)*l2r] v
    46.   FSCALE                // r^(-e) [-[lrv)*l2r] v
    47.   FMULP ST(2), ST       // [-[lrv)*l2r] v*r^(-e)
    48.   FSTP ST               // v*r^(-e)
    49.   test sign, 1
    50.   jz @end
    51.   FCHS
    52.   @end:
    53.   FSTP XTRACTR          //
    54.  }
    55.  
    56.  if (pexponent != NULL) *pexponent = exponent;
    57.  
    58.  return XTRACTR;
    59. }
     
  6. tex32

    tex32 New Member

    Публикаций:
    0
    Регистрация:
    24 окт 2009
    Сообщения:
    202
    Поздравляю с решением задачи.
     
  7. Dukales

    Dukales New Member

    Публикаций:
    0
    Регистрация:
    5 июл 2009
    Сообщения:
    199
    наблюдал издалека?)
     
  8. Dukales

    Dukales New Member

    Публикаций:
    0
    Регистрация:
    5 июл 2009
    Сообщения:
    199
    tex32
    спасибо