Dukales

stoi using x87 packed BCD format load instruction

Nov 6th, 2015
205
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 3.67 KB | None | 0 0
  1. #include <type_traits>
  2. #include <cstdint>
  3.  
  4. template< typename C >
  5. bool
  6. is_valid(C const & c)
  7. {
  8.     return (!(c < '0') && !('9' < c));
  9. }
  10.  
  11. using u8 = unsigned char;
  12. using BCD = u8 [10];
  13.  
  14. inline
  15. void
  16. convert(BCD const & bcd, std::int16_t & attrib)
  17. {
  18.     asm("fbld %1\n" "fistps %0" : "=m"(attrib) : "m"(bcd) : "memory");
  19. }
  20.  
  21. inline
  22. void
  23. convert(BCD const & bcd, std::int32_t & attrib)
  24. {
  25.     asm("fbld %1\n" "fistpl %0" : "=m"(attrib) : "m"(bcd) : "memory");
  26. }
  27.  
  28. inline
  29. void
  30. convert(BCD const & bcd, std::int64_t & attrib)
  31. {
  32.     asm("fbld %1\n" "fistpq %0" : "=m"(attrib) : "m"(bcd) : "memory");
  33. }
  34.  
  35. template< typename F >
  36. std::enable_if_t< (std::is_floating_point< F >{}) >
  37. convert(BCD const & bcd, F & attrib)
  38. {
  39.     asm("fbld %1\n" : "=t"(attrib) : "m"(bcd) : "memory");
  40. }
  41.  
  42. template< typename iterator, typename T >
  43. void
  44. extract_int(iterator & beg, iterator const & end, T const & attrib) = delete;
  45.  
  46. template< typename iterator, typename T >
  47. bool
  48. extract_int(iterator & beg, iterator const & end, T & attrib)
  49. {
  50.     if (beg == end) {
  51.         return false;
  52.     }
  53.     BCD bcd;
  54.     auto sbeg = beg;
  55.     auto & sign = *sbeg;
  56.     if (sign == '-') {
  57.         bcd[9] = u8(0x80);
  58.         ++sbeg;
  59.     } else {
  60.         bcd[9] = u8(0x00);
  61.         if (sign == '+') {
  62.             ++sbeg;
  63.         }
  64.     }
  65.     auto length = 0;
  66.     auto it = sbeg;
  67.     while ((it != end) && is_valid(*it)) {
  68.         ++length;
  69.         ++it;
  70.     }
  71.     if (length == 0) {
  72.         return false;
  73.     }
  74.     if (18 < length) {
  75.         return false;
  76.     }
  77.     --length;
  78.     beg = sbeg;
  79.     char i = 17;
  80.     while (length < i) {
  81.         --i;
  82.         if (length == i) {
  83.             bcd[i / 2] = u8(*beg - '0');
  84.             ++beg;
  85.             --i;
  86.             break;
  87.         } else {
  88.             bcd[i / 2] = u8(0x00);
  89.             --i;
  90.         }
  91.     }
  92.     ++i;
  93.     do {
  94.         i -= 2;
  95.         auto & ch = bcd[i / 2];
  96.         ch = u8((*beg - '0') << 4);
  97.         ++beg;
  98.         ch |= u8(*beg - '0');
  99.         ++beg;
  100.     } while (0 < i);
  101.     convert(bcd, attrib);
  102.     return true;
  103. }
  104.  
  105. #include <iomanip>
  106. #include <iostream>
  107.  
  108. #include <cstdlib>
  109. #ifdef NDEBUG
  110. #undef NDEBUG
  111. #endif
  112. #include <cassert>
  113.  
  114. template< typename T = long double >
  115. bool
  116. print(std::string const & s)
  117. {
  118.    
  119.     auto beg = std::cbegin(s);
  120.     T val{};
  121.     if (extract_int(beg, std::cend(s), val)) {
  122.         std::cout << std::fixed << std::setprecision(0) << val << std::endl;
  123.         return true;
  124.     }
  125.     std::cout << "can't convert" << std::endl;
  126.     return false;
  127. }
  128.  
  129. template< typename T = long double >
  130. void
  131. check()
  132. {
  133.     std::cout << __PRETTY_FUNCTION__ << std::endl;
  134.    
  135.     assert(print< T >("+135792468135792468"));
  136.     assert(print< T >( "123456789123456789"));
  137.     assert(print< T >("-987654321987654321"));
  138.     assert(print< T >( "1"));
  139.     assert(print< T >("-1"));
  140.     assert(print< T >("+1"));
  141.     assert(print< T >( "0"));
  142.     assert(print< T >("-0"));
  143.     assert(print< T >("+0"));
  144.    
  145.     assert(!print< T >("+1357924681357924680")); // 19 digits
  146.     assert(!print< T >( "1234567891234567890")); // 19 digits
  147.     assert(!print< T >("-9876543219876543210")); // 19 digits
  148.     assert(!print< T >(""));
  149.     assert(!print< T >("+"));
  150.     assert(!print< T >("-"));
  151.     assert(!print< T >( "A"));
  152.     assert(!print< T >("+A"));
  153.     assert(!print< T >("-A"));
  154.    
  155.     std::cout << std::endl;
  156. }
  157.  
  158. int
  159. main()
  160. {    
  161.     // full-scale precision
  162.     check< long double >();
  163.     check< std::int64_t >();
  164.    
  165.     // partial precision
  166.     check< float >();
  167.     check< double >();
  168.     check< std::int16_t >();
  169.     check< std::int32_t >();
  170.     return EXIT_SUCCESS;
  171. }
Advertisement
Add Comment
Please, Sign In to add comment