Advertisement
Toliak

lab8_3

Nov 27th, 2018
369
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 10.64 KB | None | 0 0
  1. #include <iostream>
  2. #include <iomanip>
  3. #include <cstring>
  4. #include <vector>
  5. #include <cassert>
  6. #include <unordered_map>
  7. #include <functional>
  8.  
  9. #define MAX(x, y) ((x) > (y) ? (x) : (y))
  10.  
  11. struct BigUInt192
  12. {
  13.     using baseType = uint16_t;
  14.     using oversizedType = uint32_t;
  15.  
  16.     static_assert(sizeof(baseType) < sizeof(oversizedType), "");
  17.  
  18.     BigUInt192()
  19.     {
  20.         parts = new baseType[arraySize];
  21.         this->erase();
  22.     }
  23.     BigUInt192(const BigUInt192 &original)
  24.         : BigUInt192()
  25.     {
  26.         std::memcpy(parts, original.parts, sizeof(baseType) * arraySize);
  27.     }
  28.     template<int T>
  29.     void fromString(const std::string &str)
  30.     {
  31.         // something went wrong
  32.     }
  33.  
  34.     void erase()
  35.     {
  36.         std::memset(parts, 0, sizeof(baseType) * arraySize);
  37.     }
  38.     template<template<class> class F, class T>
  39.     BigUInt192 applyBlock(F<T> functor) const
  40.     {
  41.         BigUInt192 result;
  42.         for (size_t i = 0; i < BigUInt192::arraySize; i++) {
  43.             result.parts[i] = functor(parts[i]);
  44.         }
  45.         return result;
  46.     }
  47.     template<template<class> class F, class T>
  48.     BigUInt192 applyBlock(const BigUInt192 &right, F<T> functor) const
  49.     {
  50.         BigUInt192 result;
  51.         for (size_t i = 0; i < BigUInt192::arraySize; i++) {
  52.             result.parts[i] = functor(parts[i], right.parts[i]);
  53.         }
  54.         return result;
  55.     }
  56.     BigUInt192 shift(char way, size_t amount, bool circled) const
  57.     {
  58.         BigUInt192::baseType mask = 0x0;
  59.         for (size_t i = 0; i < amount; i++) {
  60.             mask = static_cast<BigUInt192::baseType>(mask << 1 | 1);
  61.         }
  62.  
  63.         BigUInt192 result;
  64.         BigUInt192::baseType last = 0;
  65.         if (way == 0) {                     // <<
  66.             for (size_t i = 0; i < BigUInt192::arraySize; i++) {
  67.                 result.parts[i] = (parts[i] << amount) | last;
  68.                 last = (parts[i] >> (8 * sizeof(BigUInt192::baseType) - amount)) & mask;
  69.             }
  70.         } else {                            // >>
  71.             for (size_t i = 0; i < BigUInt192::arraySize; i++) {
  72.                 const size_t index = BigUInt192::arraySize - i - 1;
  73.                 result.parts[index] = (parts[index] >> amount);
  74.                 result.parts[index] |= last << (8 * sizeof(BigUInt192::baseType) - amount);
  75.                 last = parts[index] & mask;
  76.             }
  77.         }
  78.  
  79.         if (circled) {
  80.             if (way == 0)                   // <<
  81.                 result.parts[0] |= last;
  82.             else                            // >>
  83.                 result.parts[BigUInt192::arraySize - 1] |= last << (8 * sizeof(BigUInt192::baseType) - amount);
  84.         }
  85.  
  86.         return result;
  87.     }
  88.     template<int T>
  89.     std::string toString() const
  90.     {
  91.         // something went wrong
  92.     }
  93.  
  94.     ~BigUInt192()
  95.     {
  96.         delete[] parts;
  97.     }
  98.  
  99.     static const size_t bytes = 24;
  100.     static const size_t arraySize = bytes / sizeof(baseType) + (bytes % sizeof(baseType) > 0);
  101.  
  102.     baseType *parts;
  103. };
  104.  
  105. template<>
  106. void BigUInt192::fromString<2>(const std::string &str)
  107. {
  108.     erase();
  109.     for (auto it = str.crbegin(); it != str.crend(); it++) {
  110.         const size_t i = static_cast<size_t>(it - str.crbegin());
  111.         assert(*it == '0' || *it == '1');
  112.         if (*it == '0')
  113.             continue;
  114.  
  115.         const size_t index = i / (sizeof(BigUInt192::baseType) * 8);
  116.         const size_t shift = i % (sizeof(BigUInt192::baseType) * 8);
  117.         parts[index] |= (*it - '0') << shift;
  118.     }
  119. }
  120.  
  121. template<>
  122. void BigUInt192::fromString<16>(const std::string &str)
  123. {
  124.     erase();
  125.     for (auto it = str.crbegin(); it != str.crend(); it++) {
  126.         if (*it == '0')
  127.             continue;
  128.  
  129.         const size_t i = static_cast<size_t>(it - str.crbegin());
  130.         BigUInt192::baseType numeral;
  131.         std::stringstream stream;
  132.         stream << std::nouppercase << *it;
  133.         stream >> std::hex >> numeral;
  134.  
  135.         const size_t index = i / (sizeof(BigUInt192::baseType) * 8);
  136.         const size_t shift = (i % (sizeof(BigUInt192::baseType) * 2)) * 4;
  137.         parts[index] |= numeral << shift;
  138.     }
  139. }
  140.  
  141. template<>
  142. std::string BigUInt192::toString<2>() const
  143. {
  144.     std::stringstream stream;
  145.     bool numberStarted = false;
  146.     for (size_t i = 0; i < BigUInt192::arraySize; i++) {
  147.         const size_t index = BigUInt192::arraySize - i - 1;
  148.         const size_t bits = sizeof(BigUInt192::baseType) * 8;
  149.         for (int j = 0; j < bits; j++) {
  150.             const size_t shift = bits - j - 1;
  151.             const auto numeral = static_cast<uint16_t>((parts[index] >> shift) & 0b1);
  152.             if ((numeral == 0 && numberStarted) || numeral == 1)
  153.                 stream << numeral;
  154.             if (numeral == 1 && !numberStarted)
  155.                 numberStarted = true;
  156.         }
  157.     }
  158.     return stream.str();
  159. }
  160.  
  161. template<>
  162. std::string BigUInt192::toString<16>() const
  163. {
  164.     std::stringstream stream;
  165.     bool numberStarted = false;
  166.     for (size_t i = 0; i < BigUInt192::arraySize; i++) {
  167.         const size_t index = BigUInt192::arraySize - i - 1;
  168.         const size_t steps = sizeof(BigUInt192::baseType) * 2;
  169.         for (int j = 0; j < steps; j++) {
  170.             const size_t shift = (steps - j - 1) * 4;
  171.             const auto numeral = static_cast<uint16_t>((parts[index] >> shift) & 0b1111);
  172.             if ((numeral == 0 && numberStarted) || numeral != 0)
  173.                 stream << std::hex << std::uppercase << numeral;
  174.             if (numeral != 0 && !numberStarted)
  175.                 numberStarted = true;
  176.         }
  177.     }
  178.     return stream.str();
  179. }
  180.  
  181. BigUInt192 operator+(const BigUInt192 &left, const BigUInt192 &right)
  182. {
  183.     BigUInt192 result;
  184.     BigUInt192::oversizedType last = 0;
  185.     for (size_t i = 0; i < BigUInt192::arraySize; i++) {
  186.         BigUInt192::oversizedType partSum = left.parts[i] + right.parts[i] + last;
  187.         if (partSum >> 16 != 0) {
  188.             last = 1;           // Переносим бит из последнего разряда (17й)
  189.         } else {
  190.             last = 0;
  191.         }
  192.         result.parts[i] = static_cast<BigUInt192::baseType>(partSum);
  193.     }
  194.     return result;
  195. }
  196.  
  197. BigUInt192 operator-(const BigUInt192 &left, const BigUInt192 &right)
  198. {
  199.     BigUInt192 result;
  200.     bool last = false;
  201.     for (size_t i = 0; i < BigUInt192::arraySize; i++) {
  202.         const BigUInt192::oversizedType toSub = right.parts[i] + last;
  203.         BigUInt192::oversizedType partSub;
  204.         if (left.parts[i] >= toSub) {
  205.             partSub = left.parts[i] - toSub;
  206.             last = false;
  207.         } else {
  208.             partSub = (1 << 8 * sizeof(BigUInt192::baseType)) + left.parts[i];
  209.             partSub -= right.parts[i];
  210.             last = true;
  211.         }
  212.         result.parts[i] = static_cast<BigUInt192::baseType>(partSub);
  213.     }
  214.     return result;
  215. }
  216.  
  217. bool operator>(const BigUInt192 &left, const BigUInt192 &right)
  218. {
  219.     for (size_t i = 0; i < BigUInt192::arraySize; i++) {
  220.         const size_t index = BigUInt192::arraySize - i - 1;
  221.         if (left.parts[index] == right.parts[index])
  222.             continue;
  223.         return left.parts[index] > right.parts[index];
  224.     }
  225.     return false;
  226. }
  227.  
  228. bool operator==(const BigUInt192 &left, const BigUInt192 &right)
  229. {
  230.     for (size_t i = 0; i < BigUInt192::arraySize; i++) {
  231.         if (left.parts[i] != right.parts[i])
  232.             return false;
  233.     }
  234.     return true;
  235. }
  236.  
  237. bool operator!=(const BigUInt192 &left, const BigUInt192 &right)
  238. {
  239.     return !(left == right);
  240. }
  241.  
  242. bool operator<(const BigUInt192 &left, const BigUInt192 &right)
  243. {
  244.     return !(left > right) && left != right;
  245. }
  246.  
  247. bool operator<=(const BigUInt192 &left, const BigUInt192 &right)
  248. {
  249.     return left < right || left == right;
  250. }
  251.  
  252. bool operator>=(const BigUInt192 &left, const BigUInt192 &right)
  253. {
  254.     return left > right || left == right;
  255. }
  256.  
  257. BigUInt192 operator&(const BigUInt192 &left, const BigUInt192 &right)
  258. {
  259.     return left.applyBlock(right, std::bit_and<>());
  260. }
  261.  
  262. BigUInt192 operator|(const BigUInt192 &left, const BigUInt192 &right)
  263. {
  264.     return left.applyBlock(right, std::bit_or<>());
  265. }
  266.  
  267. BigUInt192 operator^(const BigUInt192 &left, const BigUInt192 &right)
  268. {
  269.     return left.applyBlock(right, std::bit_xor<>());
  270. }
  271.  
  272. BigUInt192 operator~(const BigUInt192 &left)
  273. {
  274.     return left.applyBlock(std::bit_not<>());
  275. }
  276.  
  277. BigUInt192 operator<<(const BigUInt192 &left, size_t shift)
  278. {
  279.     return left.shift(0, shift, false);
  280. }
  281.  
  282. BigUInt192 operator>>(const BigUInt192 &left, size_t shift)
  283. {
  284.     return left.shift(1, shift, false);
  285. }
  286.  
  287. BigUInt192 circledShiftL(const BigUInt192 &left, size_t shift)
  288. {
  289.     return left.shift(0, shift, true);
  290. }
  291.  
  292. BigUInt192 circledShiftR(const BigUInt192 &left, size_t shift)
  293. {
  294.     return left.shift(1, shift, true);
  295. }
  296.  
  297. std::istream &operator>>(std::istream &istream, BigUInt192 &value)
  298. {
  299.  
  300.     std::string s;
  301.     istream >> s;
  302.  
  303.     std::ios_base::fmtflags base = istream.flags() & std::istream::basefield;
  304.     switch (base) {
  305.         case std::ios_base::dec: {
  306.             value.fromString<2>(s);
  307.             break;
  308.         }
  309.         case std::ios_base::hex: {
  310.             value.fromString<16>(s);
  311.             break;
  312.         }
  313.         default: {
  314.             value.fromString<2>(s);
  315.             break;
  316.         }
  317.     }
  318.  
  319.     return istream;
  320. }
  321.  
  322. std::ostream &operator<<(std::ostream &ostream, const BigUInt192 &value)
  323. {
  324.     auto temp = ostream.flags();
  325.  
  326.     std::ios_base::fmtflags base = ostream.flags() & std::istream::basefield;
  327.     switch (base) {
  328.         case std::ios_base::dec: {
  329.             ostream << value.toString<2>();
  330.             break;
  331.         }
  332.         case std::ios_base::hex: {
  333.             ostream << value.toString<16>();
  334.             break;
  335.         }
  336.         default: {
  337.             ostream << value.toString<2>();
  338.             break;
  339.         }
  340.     }
  341.  
  342.     return ostream;
  343. }
  344.  
  345. int main()
  346. {
  347.  
  348.     BigUInt192 test1L;
  349.     BigUInt192 test1R;
  350.     test1L.fromString<16>("FF");
  351.     test1R.fromString<16>("AA");
  352.     BigUInt192 test1Result1;
  353.     // test1Result1.fromString("")
  354.     // std::cout << BigUInt192("FF") +  << std::endl;
  355.  
  356.     BigUInt192 a;
  357.     BigUInt192 b;
  358.  
  359.     std::cin >> std::hex >> a;
  360.     std::cin >> std::hex >> b;
  361.  
  362.     std::cout << std::hex << circledShiftR(a, 5) << std::endl;
  363.     std::cout << std::hex << circledShiftL(b, 5) << std::endl;
  364.     std::cout << std::hex << a + b << std::endl;
  365.     std::cout << std::hex << a - b << std::endl;
  366.     std::cout << std::hex << (a & b) << std::endl;
  367.     std::cout << std::hex << (a | b) << std::endl;
  368.     std::cout << std::hex << (a > b) << std::endl;
  369.  
  370.     std::cout << "Hello, World!" << std::endl;
  371.     return 0;
  372. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement