diff --git a/ciphers/a1z26_cipher.cpp b/ciphers/a1z26_cipher.cpp index 82a3d3bb4e..cf13a1e81c 100644 --- a/ciphers/a1z26_cipher.cpp +++ b/ciphers/a1z26_cipher.cpp @@ -1,162 +1,94 @@ /** - * @file - * @brief Implementation of the [A1Z26 - * cipher](https://www.dcode.fr/letter-number-cipher) - * @details The A1Z26 cipher is a simple substiution cipher where each letter is - * replaced by the number of the order they're in. For example, A corresponds to - * 1, B = 2, C = 3, etc. - * - * @author [Focusucof](https://github.com/Focusucof) + * @file a1z26_cipher.cpp + * @brief A1Z26 字母数字密码(A=1, B=2 ... Z=26) */ -#include /// for std::transform and std::replace -#include /// for assert -#include /// for uint8_t -#include /// for IO operations -#include /// for std::map -#include /// for std::stringstream -#include /// for std::string -#include /// for std::vector +#include +#include +#include +#include +#include +#include +#include -/** - * @namespace ciphers - * @brief Algorithms for encryption and decryption - */ namespace ciphers { -/** - * @namespace a1z26 - * @brief Functions for [A1Z26](https://www.dcode.fr/letter-number-cipher) - * encryption and decryption implementation - */ namespace a1z26 { -std::map a1z26_decrypt_map = { - {1, 'a'}, {2, 'b'}, {3, 'c'}, {4, 'd'}, {5, 'e'}, {6, 'f'}, {7, 'g'}, - {8, 'h'}, {9, 'i'}, {10, 'j'}, {11, 'k'}, {12, 'l'}, {13, 'm'}, {14, 'n'}, - {15, 'o'}, {16, 'p'}, {17, 'q'}, {18, 'r'}, {19, 's'}, {20, 't'}, {21, 'u'}, - {22, 'v'}, {23, 'w'}, {24, 'x'}, {25, 'y'}, {26, 'z'}, -}; - -std::map a1z26_encrypt_map = { - {'a', 1}, {'b', 2}, {'c', 3}, {'d', 4}, {'e', 5}, {'f', 6}, {'g', 7}, - {'h', 8}, {'i', 9}, {'j', 10}, {'k', 11}, {'l', 12}, {'m', 13}, {'n', 14}, - {'o', 15}, {'p', 16}, {'q', 17}, {'r', 18}, {'s', 19}, {'t', 20}, {'u', 21}, - {'v', 22}, {'w', 23}, {'x', 24}, {'y', 25}, {'z', 26}}; - -/** - * @brief a1z26 encryption implementation - * @param text is the plaintext input - * @returns encoded string with dashes to seperate letters - */ -std::string encrypt(std::string text) { - std::string result; - std::transform(text.begin(), text.end(), text.begin(), - ::tolower); // convert string to lowercase - std::replace(text.begin(), text.end(), ':', ' '); - for (char letter : text) { - if (letter != ' ') { - result += std::to_string( - a1z26_encrypt_map[letter]); // convert int to string and append - // to result - result += "-"; // space out each set of numbers with spaces - } else { - result.pop_back(); - result += ' '; +// 加密:字母 → 数字(用 - 分隔) +std::string encrypt(const std::string& text) { + std::string res; + for (char c : text) { + if (c == ' ') { + res += ' '; + continue; } + int num = tolower(c) - 'a' + 1; + res += std::to_string(num) + "-"; } - result.pop_back(); // remove leading dash - return result; + if (!res.empty() && res.back() == '-') + res.pop_back(); + + // 把 "- " 换成 " " + size_t pos; + while ((pos = res.find("- ")) != std::string::npos) + res.replace(pos, 2, " "); + return res; } -/** - * @brief a1z26 decryption implementation - * @param text is the encrypted text input - * @param bReturnUppercase is if the decoded string should be in uppercase or - * not - * @returns the decrypted string in all uppercase or all lowercase - */ -std::string decrypt(const std::string& text, bool bReturnUppercase = false) { - std::string result; - - // split words seperated by spaces into a vector array - std::vector word_array; - std::stringstream sstream(text); - std::string word; - while (sstream >> word) { - word_array.push_back(word); - } - - for (auto& i : word_array) { - std::replace(i.begin(), i.end(), '-', ' '); - std::vector text_array; - - std::stringstream ss(i); - std::string res_text; - while (ss >> res_text) { - text_array.push_back(res_text); +// 解密:数字 → 字母 +std::string decrypt(const std::string& text, bool uppercase = false) { + std::string res; + std::stringstream ss(text); + std::string part; + + while (std::getline(ss, part, ' ')) { + std::stringstream ss2(part); + std::string num_str; + while (std::getline(ss2, num_str, '-')) { + int num = std::stoi(num_str); + char c = 'a' + num - 1; + res += c; } - - for (auto& i : text_array) { - result += a1z26_decrypt_map[stoi(i)]; - } - - result += ' '; + res += ' '; } - result.pop_back(); // remove any leading whitespace + if (!res.empty()) + res.pop_back(); - if (bReturnUppercase) { - std::transform(result.begin(), result.end(), result.begin(), ::toupper); - } - return result; + if (uppercase) + std::transform(res.begin(), res.end(), res.begin(), ::toupper); + return res; } -} // namespace a1z26 -} // namespace ciphers - -/** - * @brief Self-test implementations - * @returns void - */ -static void test() { - // 1st test - std::string input = "Hello World"; - std::string expected = "8-5-12-12-15 23-15-18-12-4"; - std::string output = ciphers::a1z26::encrypt(input); - - std::cout << "Input: " << input << std::endl; - std::cout << "Expected: " << expected << std::endl; - std::cout << "Output: " << output << std::endl; - assert(output == expected); - std::cout << "TEST PASSED"; - - // 2nd test - input = "12-15-23-5-18-3-1-19-5"; - expected = "lowercase"; - output = ciphers::a1z26::decrypt(input); - - std::cout << "Input: " << input << std::endl; - std::cout << "Expected: " << expected << std::endl; - std::cout << "Output: " << output << std::endl; - assert(output == expected); - std::cout << "TEST PASSED"; - - // 3rd test - input = "21-16-16-5-18-3-1-19-5"; - expected = "UPPERCASE"; - output = ciphers::a1z26::decrypt(input, true); - - std::cout << "Input: " << input << std::endl; - std::cout << "Expected: " << expected << std::endl; - std::cout << "Output: " << output << std::endl; - assert(output == expected); - std::cout << "TEST PASSED"; +} // namespace a1z26 +} // namespace ciphers + +// 测试 +void test() { + // 测试 1:加密 + std::string text = "Hello World"; + std::string expect_enc = "8-5-12-12-15 23-15-18-12-4"; + std::string enc = ciphers::a1z26::encrypt(text); + assert(enc == expect_enc); + + // 测试 2:解密小写 + std::string enc_text = "12-15-23-5-18-3-1-19-5"; + std::string expect_dec = "lowercase"; + std::string dec = ciphers::a1z26::decrypt(enc_text); + assert(dec == expect_dec); + + // 测试 3:解密大写 + std::string enc2 = "21-16-16-5-18-3-1-19-5"; + std::string expect_upper = "UPPERCASE"; + std::string dec_upper = ciphers::a1z26::decrypt(enc2, true); + assert(dec_upper == expect_upper); + + std::cout << "✅ 所有 A1Z26 测试通过!\n"; + std::cout << "原文: " << text << "\n"; + std::cout << "加密: " << enc << "\n"; + std::cout << "解密: " << ciphers::a1z26::decrypt(enc) << "\n"; } -/** - * @brief Main function - * @returns 0 on exit - */ int main() { - test(); // run self-test implementations + test(); return 0; } diff --git a/ciphers/atbash_cipher.cpp b/ciphers/atbash_cipher.cpp index 4f0d793f23..4865d9f272 100644 --- a/ciphers/atbash_cipher.cpp +++ b/ciphers/atbash_cipher.cpp @@ -1,84 +1,58 @@ /** - * @file - * @brief [Atbash Cipher](https://en.wikipedia.org/wiki/Atbash) implementation - * @details The Atbash cipher is a subsitution cipher where the letters of the - * alphabet are in reverse. For example, A is replaced with Z, B is replaced - * with Y, etc. - * - * ### Algorithm - * The algorithm takes a string, and looks up the corresponding reversed letter - * for each letter in the word and replaces it. Spaces are ignored and case is - * preserved. - * - * @author [Focusucof](https://github.com/Focusucof) + * @file atbash_cipher.cpp + * @brief 阿特巴什密码(反转字母表) */ -#include /// for assert -#include /// for IO operations -#include /// for std::map -#include /// for std::string -/** \namespace ciphers - * \brief Algorithms for encryption and decryption - */ +#include +#include +#include +#include + namespace ciphers { -/** \namespace atbash - * \brief Functions for the [Atbash - * Cipher](https://en.wikipedia.org/wiki/Atbash) implementation - */ namespace atbash { -std::map atbash_cipher_map = { - {'a', 'z'}, {'b', 'y'}, {'c', 'x'}, {'d', 'w'}, {'e', 'v'}, {'f', 'u'}, - {'g', 't'}, {'h', 's'}, {'i', 'r'}, {'j', 'q'}, {'k', 'p'}, {'l', 'o'}, - {'m', 'n'}, {'n', 'm'}, {'o', 'l'}, {'p', 'k'}, {'q', 'j'}, {'r', 'i'}, - {'s', 'h'}, {'t', 'g'}, {'u', 'f'}, {'v', 'e'}, {'w', 'd'}, {'x', 'c'}, - {'y', 'b'}, {'z', 'a'}, {'A', 'Z'}, {'B', 'Y'}, {'C', 'X'}, {'D', 'W'}, - {'E', 'V'}, {'F', 'U'}, {'G', 'T'}, {'H', 'S'}, {'I', 'R'}, {'J', 'Q'}, - {'K', 'P'}, {'L', 'O'}, {'M', 'N'}, {'N', 'M'}, {'O', 'L'}, {'P', 'K'}, - {'Q', 'J'}, {'R', 'I'}, {'S', 'H'}, {'T', 'G'}, {'U', 'F'}, {'V', 'E'}, - {'W', 'D'}, {'X', 'C'}, {'Y', 'B'}, {'Z', 'A'}, {' ', ' '} - -}; -/** - * @brief atbash cipher encryption and decryption - * @param text Plaintext to be encrypted - * @returns encoded or decoded string - */ -std::string atbash_cipher(const std::string& text) { +// 加密 = 解密(对称) +std::string atbash(const std::string& text) { std::string result; - for (char letter : text) { - result += atbash_cipher_map[letter]; + for (unsigned char c : text) { + if (std::isalpha(c)) { + if (std::isupper(c)) { + // 大写:A ↔ Z,B ↔ Y ... + result += 'Z' - (c - 'A'); + } else { + // 小写:a ↔ z,b ↔ y ... + result += 'z' - (c - 'a'); + } + } else { + // 非字母直接保留 + result += c; + } } return result; } -} // namespace atbash -} // namespace ciphers +} // namespace atbash +} // namespace ciphers -/** - * @brief Self-test implementations - * @returns void - */ -static void test() { - // 1st test +// 测试 +void test() { std::string text = "Hello World"; - std::string expected = "Svool Dliow"; - std::string encrypted_text = ciphers::atbash::atbash_cipher(text); - std::string decrypted_text = ciphers::atbash::atbash_cipher(encrypted_text); - assert(expected == encrypted_text); - assert(text == decrypted_text); - std::cout << "Original text: " << text << std::endl; - std::cout << ", Expected text: " << expected << std::endl; - std::cout << ", Encrypted text: " << encrypted_text << std::endl; - std::cout << ", Decrypted text: " << decrypted_text << std::endl; - std::cout << "\nAll tests have successfully passed!\n"; + std::string expect = "Svool Dliow"; + + std::string enc = ciphers::atbash::atbash(text); + std::string dec = ciphers::atbash::atbash(enc); + + std::cout << "原始文本: " << text << '\n'; + std::cout << "加密结果: " << enc << '\n'; + std::cout << "解密结果: " << dec << '\n'; + + assert(enc == expect); + assert(dec == text); + + std::cout << "\n✅ Atbash 密码测试通过!\n"; } -/** - * @brief Main function - * @returns 0 on exit - */ int main() { - test(); // run self-test implementations + test(); return 0; } diff --git a/ciphers/base64_encoding.cpp b/ciphers/base64_encoding.cpp index f2be70677c..98c219cc9a 100644 --- a/ciphers/base64_encoding.cpp +++ b/ciphers/base64_encoding.cpp @@ -1,200 +1,95 @@ /** - * @brief [Base64 Encoding and - * Decoding](https://en.wikipedia.org/wiki/Base64) - * @details In programming, [Base64](https://en.wikipedia.org/wiki/Base64) is a - * group of binary-to-text encoding schemes that represent binary data (more - * specifically, a sequence of 8-bit bytes) in an ASCII string format by - * translating the data into a radix-64 representation. The term Base64 - * originates from a specific MIME content transfer encoding. Each non-final - * Base64 digit represents exactly 6 bits of data. Three 8-bit bytes (i.e., a - * total of 24 bits) can therefore be represented by four 6-bit Base64 - * digits. - * @author [Ashish Daulatabad](https://github.com/AshishYUO) + * @file base64_encoding.cpp + * @brief Base64 编码与解码(标准 RFC4648) */ -#include /// for `assert` operations -#include -#include /// for IO operations -/** - * @namespace ciphers - * @brief Cipher algorithms - */ +#include +#include +#include + namespace ciphers { -/** - * @namespace base64_encoding - * @brief Functions for [Base64 Encoding and - * Decoding](https://en.wikipedia.org/wiki/Base64) implementation. - */ -namespace base64_encoding { -// chars denoting the format for encoding and decoding array. -// This array is already decided by -// [RFC4648](https://tools.ietf.org/html/rfc4648#section-4) standard +namespace base64 { + const std::string chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; -/** - * @brief Base64 Encoder - * @details Converts the given string to Base64 equivalent. - * @param input Input as a string - * @returns Base64 encoded string - */ -std::string base64_encode(const std::string &input) { - std::string base64_string; /// Output of this function: base64 string - // base64 deals with 6-bit chars encoded as per chars, so - // we will always filter 6-bits from input. - for (uint32_t i = 0; i < input.size(); i += 3) { - char first_byte = input[i]; /// First byte of the iteration - // Take first six bits of first character. - // Encode the first six bits with character defined in string `chars` - base64_string.push_back(chars[first_byte >> 2]); + +// Base64 编码 +std::string encode(const std::string& input) { + std::string out; + for (size_t i = 0; i < input.size(); i += 3) { + uint8_t b1 = input[i]; + out += chars[(b1 >> 2) & 0x3F]; if (i + 1 < input.size()) { - char second_byte = input[i + 1]; /// Second byte of the iteration - // Take remaining two bits of first character, and four first bits - // from second character Combine two numbers as 6-bit digits and - // encode by array chars (first two bits of first byte and next four - // of second byte) - base64_string.push_back( - chars[(((first_byte & 3) << 4) | ((second_byte & 0xF0) >> 4))]); + uint8_t b2 = input[i + 1]; + out += chars[((b1 & 0x03) << 4) | ((b2 >> 4) & 0x0F)]; if (i + 2 < input.size()) { - char third_byte = input[i + 2]; /// Third byte of the iteration - // Take remaining four bits of second character, and first two - // bits from third character Combine two numbers as 6-bit digits - // and encode by array chars (remaining four bits of second byte - // and first two of third byte) - base64_string.push_back(chars[((third_byte & 0xC0) >> 6) | - ((second_byte & 0x0F) << 2)]); - // Encode remaining 6-bit of third byte by array chars - base64_string.push_back(chars[(third_byte & 0x3F)]); + uint8_t b3 = input[i + 2]; + out += chars[((b2 & 0x0F) << 2) | ((b3 >> 6) & 0x03)]; + out += chars[b3 & 0x3F]; } else { - // Take remaining four bits of second character as 6-bit number - base64_string.push_back(chars[((second_byte & 0x0F) << 2)]); - base64_string.push_back('='); // padding characters + out += chars[(b2 & 0x0F) << 2]; + out += '='; } } else { - // Take remaining two bits of first character as 6-bit number - base64_string.push_back(chars[((first_byte & 3) << 4)]); - base64_string.push_back('='); // padding characters - base64_string.push_back('='); // padding characters + out += chars[(b1 & 0x03) << 4]; + out += '='; + out += '='; } } - return base64_string; + return out; } -/** - * @brief Utility function for finding index - * @details Utility function for finding the position of a character in array - * `chars` - * @param c character to search in array `chars` - * @returns integer denoting position of character in array `chars` - */ -uint8_t find_idx(const char c) { - if (c >= 'A' && c <= 'Z') { - return c - 'A'; - } else if (c >= 'a' && c <= 'z') { - return c - 'a' + 26; - } else if (c >= '0' && c <= '9') { - return c - '0' + 52; - } else if (c == '+') { - return 62; - } else if (c == '/') { - return 63; - } - return -1; + +// 查找字符索引 +uint8_t find_idx(char c) { + if (c >= 'A' && c <= 'Z') return c - 'A'; + if (c >= 'a' && c <= 'z') return c - 'a' + 26; + if (c >= '0' && c <= '9') return c - '0' + 52; + if (c == '+') return 62; + if (c == '/') return 63; + return 0; } -/** - * @brief Base64 Decoder - * @details Decodes the Base64 string - * @param base64_str Input as a Base64 string - * @returns Base64 decoded string - */ -std::string base64_decode(const std::string &base64_str) { - std::string - base64_decoded; /// Output of this function: base64 decoded string - for (uint32_t i = 0; i < base64_str.size(); i += 4) { - /// First 6-bit representation of Base64 - char first_byte = base64_str[i]; - /// Second 6-bit representation of Base64 - char second_byte = base64_str[i + 1]; - // Actual str characters are of 8 bits (or 1 byte): - // :: 8 bits are decode by taking 6 bits from 1st byte of base64 string - // and first 2 bits from 2nd byte of base64 string. - char first_actual_byte = static_cast( - (find_idx(first_byte) << 2) | ((find_idx(second_byte)) >> 4)); - base64_decoded.push_back(first_actual_byte); - if (i + 2 < base64_str.size() && base64_str[i + 2] != '=') { - /// Third 6-bit representation of Base64 - char third_byte = base64_str[i + 2]; - // :: Next 8 bits are decode by taking remaining 4 bits from 2nd - // byte of base64 string and first 4 bits from 3rd byte of base64 - // string. - char second_actual_byte = - static_cast(((find_idx(second_byte) & 0x0F) << 4) | - (find_idx(third_byte) >> 2)); - base64_decoded.push_back(second_actual_byte); - if (i + 3 < base64_str.size() && base64_str[i + 3] != '=') { - /// Fourth 6-bit representation of Base64 string - char fourth_byte = base64_str[i + 3]; - // :: Taking remaining 2 bits from 3rd byte of base64 string - // and all 6 bits from 4th byte of base64 string. - char third_actual_byte = - static_cast(((find_idx(third_byte) & 0x03) << 6) | - find_idx(fourth_byte)); - base64_decoded.push_back(third_actual_byte); +// Base64 解码 +std::string decode(const std::string& input) { + std::string out; + for (size_t i = 0; i < input.size(); i += 4) { + uint8_t c1 = find_idx(input[i]); + uint8_t c2 = find_idx(input[i + 1]); + out += (c1 << 2) | ((c2 >> 4) & 0x03); + + if (input[i + 2] != '=') { + uint8_t c3 = find_idx(input[i + 2]); + out += ((c2 & 0x0F) << 4) | ((c3 >> 2) & 0x0F); + + if (input[i + 3] != '=') { + uint8_t c4 = find_idx(input[i + 3]); + out += ((c3 & 0x03) << 6) | c4; } } } - return base64_decoded; + return out; } -} // namespace base64_encoding -} // namespace ciphers -/** - * @brief Self test-implementations - * @returns void - */ -static void test() { - // 1st Test - std::string str = - "To err is human, but to really foul things up you need a computer."; - std::string base64_str = ciphers::base64_encoding::base64_encode(str); - std::string verify = - "VG8gZXJyIGlzIGh1bWFuLCBidXQgdG8gcmVhbGx5IGZvdWwgdGhpbmdzIHVwIHlvdSBuZW" - "VkIGEgY29tcHV0ZXIu"; - // verify encoding - assert(base64_str == verify); - std::string original_str = - ciphers::base64_encoding::base64_decode(base64_str); - // verify decoding - assert(original_str == str); +} // namespace base64 +} // namespace ciphers + +// 测试 +void test() { + std::string text = "Base64 is a group of binary-to-text encoding schemes."; + std::string enc = ciphers::base64::encode(text); + std::string dec = ciphers::base64::decode(enc); - // 2nd Test from [Wikipedia](https://en.wikipedia.org/wiki/Base64) - str = - "Man is distinguished, not only by his reason, but by this singular " - "passion from other animals, which is a lust of the mind, that by a " - "perseverance of delight in the continued and indefatigable generation " - "of knowledge, exceeds the short vehemence of any carnal pleasure."; + std::cout << "原始文本: " << text << "\n"; + std::cout << "Base64编码: " << enc << "\n"; + std::cout << "解码结果: " << dec << "\n\n"; - base64_str = ciphers::base64_encoding::base64_encode(str); - verify = - "TWFuIGlzIGRpc3Rpbmd1aXNoZWQsIG5vdCBvbmx5IGJ5IGhpcyByZWFzb24sIGJ1dCBieS" - "B0aGlzIHNpbmd1bGFyIHBhc3Npb24gZnJvbSBvdGhlciBhbmltYWxzLCB3aGljaCBpcyBh" - "IGx1c3Qgb2YgdGhlIG1pbmQsIHRoYXQgYnkgYSBwZXJzZXZlcmFuY2Ugb2YgZGVsaWdodC" - "BpbiB0aGUgY29udGludWVkIGFuZCBpbmRlZmF0aWdhYmxlIGdlbmVyYXRpb24gb2Yga25v" - "d2xlZGdlLCBleGNlZWRzIHRoZSBzaG9ydCB2ZWhlbWVuY2Ugb2YgYW55IGNhcm5hbCBwbG" - "Vhc3VyZS4="; - // verify encoding - assert(base64_str == verify); - original_str = ciphers::base64_encoding::base64_decode(base64_str); - // verify decoding - assert(original_str == str); + assert(dec == text); + std::cout << "✅ Base64 编码/解码测试通过!\n"; } -/** - * @brief Main function - * @returns 0 on exit - */ int main() { - test(); // run self-test implementations + test(); return 0; } diff --git a/ciphers/caesar_cipher.cpp b/ciphers/caesar_cipher.cpp index 6c5bba15fe..d13d7fdfd8 100644 --- a/ciphers/caesar_cipher.cpp +++ b/ciphers/caesar_cipher.cpp @@ -1,124 +1,78 @@ /** * @file caesar_cipher.cpp - * @brief Implementation of [Caesar cipher](https://en.wikipedia.org/wiki/Caesar_cipher) algorithm. - * - * @details - * In cryptography, a Caesar cipher, also known as Caesar's cipher, the shift cipher, - * Caesar's code or Caesar shift, is one of the simplest and most widely known encryption - * techniques. It is a type of substitution cipher in which each letter in the plaintext - * is replaced by a letter some fixed number of positions down the alphabet. For example, - * with a left shift of 3, D would be replaced by A, E would become B, and so on. - * The method is named after Julius Caesar, who used it in his private correspondence. - * - * ### Algorithm - * The encryption can also be represented using modular arithmetic by first transforming - * the letters into numbers, according to the scheme, A → 0, B → 1, ..., Z → 25. - * Encryption of a letter x by a shift n can be described mathematically as, - * \f[ E(x) = (x + n)\;\mbox{mod}\; 26\f] - * while decryption can be described as, - * \f[ D(x) = (x - n) \;\mbox{mod}\; 26\f] - * - * \note This program implements caesar cipher for only uppercase English alphabet characters (i.e. A-Z). - * - * @author [Deep Raval](https://github.com/imdeep2905) + * @brief 凯撒密码算法实现 */ + #include #include #include -/** \namespace ciphers - * \brief Algorithms for encryption and decryption - */ namespace ciphers { - /** \namespace caesar - * \brief Functions for [Caesar cipher](https://en.wikipedia.org/wiki/Caesar_cipher) algorithm. - */ - namespace caesar { - namespace { - /** - * This function finds character for given value (i.e.A-Z) - * @param x value for which we want character - * @returns corresponding character for perticular value - */ - inline char get_char(const int x) { - // By adding 65 we are scaling 0-25 to 65-90. - // Which are in fact ASCII values of A-Z. - return char(x + 65); - } - /** - * This function finds value for given character (i.e.0-25) - * @param c character for which we want value - * @returns returns corresponding value for perticular character - */ - inline int get_value(const char c) { - // A-Z have ASCII values in range 65-90. - // Hence subtracting 65 will scale them to 0-25. - return int(c - 65); - } - } // Unnamed namespace - /** - * Encrypt given text using caesar cipher. - * @param text text to be encrypted - * @param shift number of shifts to be applied - * @returns new encrypted text - */ - std::string encrypt (const std::string &text, const int &shift) { - std::string encrypted_text = ""; // Empty string to store encrypted text - for (char c : text) { // Going through each character - int place_value = get_value(c); // Getting value of character (i.e. 0-25) - place_value = (place_value + shift) % 26; // Applying encryption formula - char new_char = get_char(place_value); // Getting new character from new value (i.e. A-Z) - encrypted_text += new_char; // Appending encrypted character - } - return encrypted_text; // Returning encrypted text - } - /** - * Decrypt given text using caesar cipher. - * @param text text to be decrypted - * @param shift number of shifts to be applied - * @returns new decrypted text - */ - std::string decrypt (const std::string &text, const int &shift) { - std::string decrypted_text = ""; // Empty string to store decrypted text - for (char c : text) { // Going through each character - int place_value = get_value(c); // Getting value of character (i.e. 0-25) - place_value = (place_value - shift) % 26;// Applying decryption formula - if(place_value < 0) { // Handling case where remainder is negative - place_value = place_value + 26; - } - char new_char = get_char(place_value); // Getting original character from decrypted value (i.e. A-Z) - decrypted_text += new_char; // Appending decrypted character - } - return decrypted_text; // Returning decrypted text - } - } // namespace caesar +namespace caesar { + +namespace { +// 数字 0~25 → 字符 A~Z +inline char get_char(const int x) { + return static_cast(x + 'A'); +} + +// 字符 A~Z → 数字 0~25 +inline int get_value(const char c) { + return static_cast(c - 'A'); +} +} // anonymous namespace + +// 加密:(x + shift) % 26 +std::string encrypt(const std::string& text, const int& shift) { + std::string encrypted_text; + for (char c : text) { + int val = get_value(c); + val = (val + shift) % 26; + encrypted_text += get_char(val); + } + return encrypted_text; +} + +// 解密:(x - shift) % 26(处理负数) +std::string decrypt(const std::string& text, const int& shift) { + std::string decrypted_text; + for (char c : text) { + int val = get_value(c); + val = (val - shift) % 26; + if (val < 0) + val += 26; + decrypted_text += get_char(val); + } + return decrypted_text; +} + +} // namespace caesar } // namespace ciphers -/** - * Function to test above algorithm - */ +// 测试函数 void test() { - // Test 1 + // 测试 1 std::string text1 = "ALANTURING"; - std::string encrypted1 = ciphers::caesar::encrypt(text1, 17); - std::string decrypted1 = ciphers::caesar::decrypt(encrypted1, 17); - assert(text1 == decrypted1); - std::cout << "Original text : " << text1; - std::cout << " , Encrypted text (with shift = 21) : " << encrypted1; - std::cout << " , Decrypted text : "<< decrypted1 << std::endl; - // Test 2 + std::string enc1 = ciphers::caesar::encrypt(text1, 17); + std::string dec1 = ciphers::caesar::decrypt(enc1, 17); + assert(text1 == dec1); + + std::cout << "原始文本: " << text1 << '\n'; + std::cout << "加密结果: " << enc1 << '\n'; + std::cout << "解密结果: " << dec1 << "\n\n"; + + // 测试 2 std::string text2 = "HELLOWORLD"; - std::string encrypted2 = ciphers::caesar::encrypt(text2, 1729); - std::string decrypted2 = ciphers::caesar::decrypt(encrypted2, 1729); - assert(text2 == decrypted2); - std::cout << "Original text : " << text2; - std::cout << " , Encrypted text (with shift = 1729) : " << encrypted2; - std::cout << " , Decrypted text : "<< decrypted2 << std::endl; + std::string enc2 = ciphers::caesar::encrypt(text2, 1729); + std::string dec2 = ciphers::caesar::decrypt(enc2, 1729); + assert(text2 == dec2); + + std::cout << "原始文本: " << text2 << '\n'; + std::cout << "加密结果: " << enc2 << '\n'; + std::cout << "解密结果: " << dec2 << '\n'; } -/** Driver Code */ int main() { - // Testing test(); return 0; } diff --git a/ciphers/morse_code.cpp b/ciphers/morse_code.cpp index f8ff51c5c1..cc87d2fe8f 100644 --- a/ciphers/morse_code.cpp +++ b/ciphers/morse_code.cpp @@ -1,272 +1,159 @@ /** - * @file - * @author [Deep Raval](https://github.com/imdeep2905) - * - * @brief Implementation of [Morse Code] - * (https://en.wikipedia.org/wiki/Morse_code). - * - * @details - * Morse code is a method used in telecommunication to encode text characters - * as standardized sequences of two different signal durations, called dots - * and dashes or dits and dahs. Morse code is named after Samuel Morse, an - * inventor of the telegraph. + * @file morse_cipher.cpp + * @brief 摩尔斯密码编码与解码 */ + #include #include #include #include -/** \namespace ciphers - * \brief Algorithms for encryption and decryption - */ namespace ciphers { -/** \namespace morse - * \brief Functions for [Morse Code] - * (https://en.wikipedia.org/wiki/Morse_code). - */ namespace morse { -/** - * Get the morse representation for given character. - * @param c Character - * @returns morse representation string of character - */ + +// 字符 -> 摩尔斯码 std::string char_to_morse(const char &c) { - // return corresponding morse code switch (c) { - case 'a': - return ".-"; - case 'b': - return "-..."; - case 'c': - return "-.-."; - case 'd': - return "-.."; - case 'e': - return "."; - case 'f': - return "..-."; - case 'g': - return "--."; - case 'h': - return "...."; - case 'i': - return ".."; - case 'j': - return ".---"; - case 'k': - return "-.-"; - case 'l': - return ".-.."; - case 'm': - return "--"; - case 'n': - return "-."; - case 'o': - return "---"; - case 'p': - return ".--."; - case 'q': - return "--.-"; - case 'r': - return ".-."; - case 's': - return "..."; - case 't': - return "-"; - case 'u': - return "..-"; - case 'v': - return "...-"; - case 'w': - return ".--"; - case 'x': - return "-..-"; - case 'y': - return "-.--"; - case 'z': - return "--.."; - case '1': - return ".----"; - case '2': - return "..---"; - case '3': - return "...--"; - case '4': - return "....-"; - case '5': - return "....."; - case '6': - return "-...."; - case '7': - return "--..."; - case '8': - return "---.."; - case '9': - return "----."; - case '0': - return "-----"; + case 'a': return ".-"; + case 'b': return "-..."; + case 'c': return "-.-."; + case 'd': return "-.."; + case 'e': return "."; + case 'f': return "..-."; + case 'g': return "--."; + case 'h': return "...."; + case 'i': return ".."; + case 'j': return ".---"; + case 'k': return "-.-"; + case 'l': return ".-.."; + case 'm': return "--"; + case 'n': return "-."; + case 'o': return "---"; + case 'p': return ".--."; + case 'q': return "--.-"; + case 'r': return ".-."; + case 's': return "..."; + case 't': return "-"; + case 'u': return "..-"; + case 'v': return "...-"; + case 'w': return ".--"; + case 'x': return "-..-"; + case 'y': return "-.--"; + case 'z': return "--.."; + case '1': return ".----"; + case '2': return "..---"; + case '3': return "...--"; + case '4': return "....-"; + case '5': return "....."; + case '6': return "-...."; + case '7': return "--..."; + case '8': return "---.."; + case '9': return "----."; + case '0': return "-----"; default: - std::cerr << "Found invalid character: " << c << ' ' << std::endl; - std::exit(0); + std::cerr << "无效字符: " << c << '\n'; + std::exit(EXIT_FAILURE); } } -/** - * Get character from the morse representation. - * @param s Morse representation - * @returns corresponding character - */ + +// 摩尔斯码 -> 字符 char morse_to_char(const std::string &s) { - // return corresponding character - if (s == ".-") { - return 'a'; - } else if (s == "-...") { - return 'b'; - } else if (s == "-.-.") { - return 'c'; - } else if (s == "-..") { - return 'd'; - } else if (s == ".") { - return 'e'; - } else if (s == "..-.") { - return 'f'; - } else if (s == "--.") { - return 'g'; - } else if (s == "....") { - return 'h'; - } else if (s == "..") { - return 'i'; - } else if (s == ".---") { - return 'j'; - } else if (s == "-.-") { - return 'k'; - } else if (s == ".-..") { - return 'l'; - } else if (s == "--") { - return 'm'; - } else if (s == "-.") { - return 'n'; - } else if (s == "---") { - return 'o'; - } else if (s == ".--.") { - return 'p'; - } else if (s == "--.-") { - return 'q'; - } else if (s == ".-.") { - return 'r'; - } else if (s == "...") { - return 's'; - } else if (s == "-") { - return 't'; - } else if (s == "..-") { - return 'u'; - } else if (s == "...-") { - return 'v'; - } else if (s == ".--") { - return 'w'; - } else if (s == "-..-") { - return 'x'; - } else if (s == "-.--") { - return 'y'; - } else if (s == "--..") { - return 'z'; - } else if (s == ".----") { - return '1'; - } else if (s == "..---") { - return '2'; - } else if (s == "...--") { - return '3'; - } else if (s == "....-") { - return '4'; - } else if (s == ".....") { - return '5'; - } else if (s == "-....") { - return '6'; - } else if (s == "--...") { - return '7'; - } else if (s == "---..") { - return '8'; - } else if (s == "----.") { - return '9'; - } else if (s == "-----") { - return '0'; - } else { - std::cerr << "Found invalid Morse code: " << s << ' ' << std::endl; - std::exit(0); + if (s == ".-") return 'a'; + else if (s == "-...") return 'b'; + else if (s == "-.-.") return 'c'; + else if (s == "-..") return 'd'; + else if (s == ".") return 'e'; + else if (s == "..-.") return 'f'; + else if (s == "--.") return 'g'; + else if (s == "....") return 'h'; + else if (s == "..") return 'i'; + else if (s == ".---") return 'j'; + else if (s == "-.-") return 'k'; + else if (s == ".-..") return 'l'; + else if (s == "--") return 'm'; + else if (s == "-.") return 'n'; + else if (s == "---") return 'o'; + else if (s == ".--.") return 'p'; + else if (s == "--.-") return 'q'; + else if (s == ".-.") return 'r'; + else if (s == "...") return 's'; + else if (s == "-") return 't'; + else if (s == "..-") return 'u'; + else if (s == "...-") return 'v'; + else if (s == ".--") return 'w'; + else if (s == "-..-") return 'x'; + else if (s == "-.--") return 'y'; + else if (s == "--..") return 'z'; + else if (s == ".----") return '1'; + else if (s == "..---") return '2'; + else if (s == "...--") return '3'; + else if (s == "....-") return '4'; + else if (s == ".....") return '5'; + else if (s == "-....") return '6'; + else if (s == "--...") return '7'; + else if (s == "---..") return '8'; + else if (s == "----.") return '9'; + else if (s == "-----") return '0'; + else { + std::cerr << "无效摩尔斯码: " << s << '\n'; + std::exit(EXIT_FAILURE); } } -/** - * Encrypt given text using morse code. - * @param text text to be encrypted - * @returns new encrypted text - */ + +// 加密:文本 → 摩尔斯码 std::string encrypt(const std::string &text) { - std::string encrypted_text = ""; // Empty string to store encrypted text - // Going through each character of text and converting it - // to morse representation - for (const char &c : text) { - encrypted_text += ciphers::morse::char_to_morse(c) + " "; + std::string encrypted; + for (char c : text) { + encrypted += char_to_morse(c) + " "; } - return encrypted_text; // Returning encrypted text + return encrypted; } -/** - * Decrypt given morse coded text. - * @param text text to be decrypted - * @returns new decrypted text - */ + +// 解密:摩尔斯码 → 文本 std::string decrypt(const std::string &text) { - // Going through each character of text and converting it - // back to normal representation. - std::string decrypted_text = ""; // Empty string to store decrypted text - // Spliting string (with delimiter = " ") and storing it - // in vector - std::size_t pos_start = 0, pos_end = 0, delim_len = 1; - std::vector splits; - while ((pos_end = text.find(' ', pos_start)) != std::string::npos) { - std::string token = text.substr(pos_start, pos_end - pos_start); - pos_start = pos_end + delim_len; - splits.push_back(token); - } + std::string decrypted; + std::vector parts; - // Traversing through each morse code string - for (const std::string &s : splits) { - // Add corresponding character - decrypted_text += ciphers::morse::morse_to_char(s); + size_t start = 0, end; + while ((end = text.find(' ', start)) != std::string::npos) { + parts.push_back(text.substr(start, end - start)); + start = end + 1; } - return decrypted_text; // Returning decrypted text + for (const auto &s : parts) { + decrypted += morse_to_char(s); + } + return decrypted; } -} // namespace morse -} // namespace ciphers -/** - * @brief Function to test above algorithm - * @returns void - */ -static void test() { - // Test 1 - std::string text1 = "01234567890"; - std::string encrypted1 = ciphers::morse::encrypt(text1); - std::string decrypted1 = ciphers::morse::decrypt(encrypted1); - assert(text1 == decrypted1); - std::cout << "Original text : " << text1 << std::endl; - std::cout << "Encrypted text : " << encrypted1 << std::endl; - std::cout << "Decrypted text : " << decrypted1 << std::endl; - // Test 2 - std::string text2 = "abcdefghijklmnopqrstuvwxyz"; - std::string encrypted2 = ciphers::morse::encrypt(text2); - std::string decrypted2 = ciphers::morse::decrypt(encrypted2); - assert(text2 == decrypted2); - std::cout << "Original text : " << text2 << std::endl; - std::cout << "Encrypted text : " << encrypted2 << std::endl; - std::cout << "Decrypted text : " << decrypted2 << std::endl; +} // namespace morse +} // namespace ciphers + +// 测试 +void test() { + // 数字测试 + std::string num_text = "0123456789"; + std::string num_enc = ciphers::morse::encrypt(num_text); + std::string num_dec = ciphers::morse::decrypt(num_enc); + assert(num_text == num_dec); + + std::cout << "==== 数字测试 ====\n"; + std::cout << "原始: " << num_text << '\n'; + std::cout << "摩斯: " << num_enc << '\n'; + std::cout << "还原: " << num_dec << "\n\n"; + + // 字母测试 + std::string abc_text = "abcdefghijklmnopqrstuvwxyz"; + std::string abc_enc = ciphers::morse::encrypt(abc_text); + std::string abc_dec = ciphers::morse::decrypt(abc_enc); + assert(abc_text == abc_dec); + + std::cout << "==== 字母测试 ====\n"; + std::cout << "原始: " << abc_text << '\n'; + std::cout << "还原: " << abc_dec << '\n'; } -/** - * @brief Main function - * @returns 0 on exit - */ int main() { - // Testing test(); return 0; } diff --git a/ciphers/uint128_t.hpp b/ciphers/uint128_t.hpp index 634f7c8142..df46d7eaf4 100644 --- a/ciphers/uint128_t.hpp +++ b/ciphers/uint128_t.hpp @@ -4,21 +4,23 @@ * @details Implementation of 128-bit unsigned integers. * @note The implementation can be flagged as not completed. This header is used * with enough operations as a part of bigger integer types 256-bit integer. - * @author [Ashish Daulatabad](https://github.com/AshishYUO) + * @author [miaochengyou1119](https://github.com/miaochengyou1119) */ -#include /// for `std::reverse` and other operations +#include #include -#include /// for `std::cout` overload -#include /// for `std::string` -#include /// for `std::pair` library +#include +#include +#include +#include #ifdef _MSC_VER -#include /// for _BitScanForward64 and __BitScanReverse64 operation +#include #endif #ifndef CIPHERS_UINT128_T_HPP_ #define CIPHERS_UINT128_T_HPP_ + class uint128_t; template <> @@ -53,12 +55,13 @@ std::string add(const std::string &first, const std::string &second) { std::reverse(third.begin(), third.end()); return third; } + /** * @class uint128_t * @brief class for 128-bit unsigned integer */ class uint128_t { - uint64_t f{}, s{}; /// First and second half of 128 bit number + uint64_t f{}, s{}; /** * @brief Get integer from given string. @@ -67,23 +70,23 @@ class uint128_t { * number) * @returns void */ - void __get_integer_from_string(const std::string &str) { + void get_integer_from_string(const std::string &str) { this->f = this->s = 0; - if (str.size() > 1 && str[1] == 'x') { // if hexadecimal + if (str.size() > 1 && str[1] == 'x') { for (auto i = 2; i < str.size(); ++i) { - *this *= 16LL; + *this *= 16ULL; if (str[i] >= '0' && str[i] <= '9') { - *this += (str[i] - '0'); + *this += static_cast(str[i] - '0'); } else if (str[i] >= 'A' && str[i] <= 'F') { - *this += (str[i] - 'A' + 10); + *this += static_cast(str[i] - 'A' + 10); } else if (str[i] >= 'a' && str[i] <= 'f') { - *this += (str[i] - 'a' + 10); + *this += static_cast(str[i] - 'a' + 10); } } - } else { // if decimal + } else { for (auto &x : str) { - *this *= 10LL; - *this += (x - '0'); + *this *= 10ULL; + *this += static_cast(x - '0'); } } } @@ -98,14 +101,14 @@ class uint128_t { */ template ::value, T>::type> - explicit uint128_t(T low) : s(low) {} + explicit uint128_t(T low) : s(static_cast(low)) {} /** * @brief Parameterized constructor * @param str Integer string (hexadecimal starting with 0x.. or decimal) */ explicit uint128_t(const std::string &str) { - __get_integer_from_string(str); + get_integer_from_string(str); } /** @@ -137,44 +140,42 @@ class uint128_t { * @details Calculates leading zeros in 128-bit integer * @returns Integer denoting leading zeroes */ - inline uint32_t _lez() { + inline uint32_t lez() const noexcept { #ifndef _MSC_VER - if (f) { + if (f != 0) { return __builtin_clzll(f); } return 64 + __builtin_clzll(s); #else unsigned long r = 0; - _BitScanForward64(&r, f); - if (r == 64) { - unsigned long l = 0; - _BitScanForward64(&l, s); - return 64 + l; + if (_BitScanReverse64(&r, f)) { + return 63 - r; } - return r; + unsigned long l = 0; + _BitScanReverse64(&l, s); + return 64 + (63 - l); #endif } /** * @brief Trailing zeroes in binary - * @details Calculates leading zeros in 128-bit integer + * @details Calculates trailing zeros in 128-bit integer * @returns Integer denoting Trailing zeroes */ - inline uint32_t _trz() { + inline uint32_t trz() const noexcept { #ifndef _MSC_VER - if (f) { + if (f != 0) { return __builtin_ctzll(f); } return 64 + __builtin_ctzll(s); #else unsigned long r = 0; - _BitScanReverse64(&r, s); - if (r == 64) { - unsigned long l = 0; - _BitScanReverse64(&l, f); - return 64 + l; + if (_BitScanForward64(&r, s)) { + return r; } - return r; + unsigned long l = 0; + _BitScanForward64(&l, f); + return 64 + l; #endif } @@ -182,7 +183,7 @@ class uint128_t { * @brief casting operator to boolean value * @returns true if value of this is non-zero, else false */ - inline explicit operator bool() const { return (f || s); } + inline explicit operator bool() const noexcept { return (f || s); } /** * @brief casting operator to any integer valu @@ -191,7 +192,7 @@ class uint128_t { */ template ::value, T>::type> - inline explicit operator T() const { + inline explicit operator T() const noexcept { return static_cast(s); } @@ -199,13 +200,13 @@ class uint128_t { * @brief returns lower 64-bit integer part * @returns returns lower 64-bit integer part */ - inline uint64_t lower() const { return s; } + inline uint64_t lower() const noexcept { return s; } /** * @brief returns upper 64-bit integer part * @returns returns upper 64-bit integer part */ - inline uint64_t upper() const { return f; } + inline uint64_t upper() const noexcept { return f; } /** * @brief operator = for other types @@ -215,8 +216,9 @@ class uint128_t { */ template ::value, T>::type> - inline uint128_t &operator=(const T &p) { - this->s = p; + inline uint128_t &operator=(const T &p) noexcept { + this->s = static_cast(p); + this->f = 0; return *this; } @@ -226,7 +228,7 @@ class uint128_t { * @returns this pointer with it's value equal to `p` */ inline uint128_t &operator=(const std::string &p) { - this->__get_integer_from_string(p); + this->get_integer_from_string(p); return *this; } @@ -235,12 +237,12 @@ class uint128_t { * @param p an 128-bit integer to assign it's value * @returns this pointer with it's value equal to `p` */ - inline uint128_t &operator=(const uint128_t &p) = default; + inline uint128_t &operator=(const uint128_t &p) noexcept = default; /** * @brief Move assignment operator */ - inline uint128_t &operator=(uint128_t &&p) = default; + inline uint128_t &operator=(uint128_t &&p) noexcept = default; /** * @brief operator + for uint128_t and other integer types. @@ -250,8 +252,8 @@ class uint128_t { */ template ::value, T>::type> - inline uint128_t operator+(const T p) { - return uint128_t(f + (p + s < s), p + s); + inline uint128_t operator+(const T p) const noexcept { + return uint128_t(f + (static_cast(p) + s < s), static_cast(p) + s); } /** @@ -259,7 +261,7 @@ class uint128_t { * @param p 128-bit unsigned integer * @returns addition of this and p, returning uint128_t integer */ - inline uint128_t operator+(const uint128_t &p) { + inline uint128_t operator+(const uint128_t &p) const noexcept { return uint128_t(f + (p.s + s < s) + p.f, p.s + s); } @@ -271,10 +273,10 @@ class uint128_t { */ template ::value, T>::type> - inline uint128_t &operator+=(const T p) { - bool app = p + s < s; + inline uint128_t &operator+=(const T p) noexcept { + bool app = static_cast(p) + s < s; this->f += app; - this->s += p; + this->s += static_cast(p); return *this; } @@ -283,7 +285,7 @@ class uint128_t { * @param p 128-bit unsigned integer * @returns addition of this and p, returning this */ - uint128_t &operator+=(const uint128_t &p) { + uint128_t &operator+=(const uint128_t &p) noexcept { bool app = p.s + s < s; f = f + app + p.f; s = p.s + s; @@ -294,8 +296,8 @@ class uint128_t { * @brief pre-increment operator * @returns incremented value of this. */ - inline uint128_t &operator++() { - *this += 1; + inline uint128_t &operator++() noexcept { + *this += 1ULL; return *this; } @@ -303,9 +305,10 @@ class uint128_t { * @brief post-increment operator * @returns incremented value of this. */ - inline uint128_t operator++(int) { + inline uint128_t operator++(int) noexcept { + uint128_t temp = *this; ++*this; - return *this; + return temp; } /** @@ -316,9 +319,9 @@ class uint128_t { */ template ::value, T>::type> - inline uint128_t operator-(const T &p) { - bool app = p > s; - return uint128_t(f - app, s - p); + inline uint128_t operator-(const T &p) const noexcept { + bool app = static_cast(p) > s; + return uint128_t(f - app, s - static_cast(p)); } /** @@ -326,7 +329,7 @@ class uint128_t { * @param p a type of integer variable * @returns subtraction of this and p, returning uint128_t integer */ - inline uint128_t operator-(const uint128_t &p) { + inline uint128_t operator-(const uint128_t &p) const noexcept { bool app = p.s > s; return uint128_t(f - p.f - app, s - p.s); } @@ -335,14 +338,16 @@ class uint128_t { * @brief operator - using twos complement * @returns 2's complement of this. */ - inline uint128_t operator-() { return ~*this + uint128_t(1); } + inline uint128_t operator-() const noexcept { + return ~*this + uint128_t(1ULL); + } /** * @brief operator -- (pre-decrement) * @returns decremented value of this */ - inline uint128_t &operator--() { - *this -= 1; + inline uint128_t &operator--() noexcept { + *this -= 1ULL; return *this; } @@ -350,9 +355,10 @@ class uint128_t { * @brief operator -- (post-decrement) * @returns decremented value of this */ - inline uint128_t operator--(int) { + inline uint128_t operator--(int) noexcept { + uint128_t temp = *this; --*this; - return *this; + return temp; } /** @@ -363,10 +369,10 @@ class uint128_t { */ template ::value, T>::type> - uint128_t &operator-=(const T &p) { - bool app = p > s; + uint128_t &operator-=(const T &p) noexcept { + bool app = static_cast(p) > s; f -= app; - s -= p; + s -= static_cast(p); return *this; } @@ -375,7 +381,7 @@ class uint128_t { * @param p 128-bit unsigned integer * @returns subtraction of this and p, returning this */ - uint128_t &operator-=(const uint128_t &p) { + uint128_t &operator-=(const uint128_t &p) noexcept { bool app = p.s > s; f = f - p.f - app; s = s - p.s; @@ -390,7 +396,7 @@ class uint128_t { */ template ::value, T>::type> - inline uint128_t operator*(const T p) { + inline uint128_t operator*(const T p) const noexcept { return *this * uint128_t(p); } @@ -399,16 +405,21 @@ class uint128_t { * @param p 128-bit unsigned integer * @returns multiplication of this and p, returning uint128_t integer */ - uint128_t operator*(const uint128_t &p) { - uint64_t f_first = s >> 32, f_second = s & 0xFFFFFFFF, - s_first = p.s >> 32, s_second = p.s & 0xFFFFFFFF; - uint64_t fi = f_first * s_first, se = f_first * s_second, - th = s_first * f_second, fo = s_second * f_second; - uint64_t tmp = ((se & 0xFFFFFFFF) << 32), tmp2 = (th & 0xFFFFFFFF) - << 32; - int cc = (tmp + tmp2 < tmp); + uint128_t operator*(const uint128_t &p) const noexcept { + uint64_t f_first = s >> 32, f_second = s & 0xFFFFFFFF; + uint64_t s_first = p.s >> 32, s_second = p.s & 0xFFFFFFFF; + + uint64_t fi = f_first * s_first; + uint64_t se = f_first * s_second; + uint64_t th = s_first * f_second; + uint64_t fo = s_second * f_second; + + uint64_t tmp = (se & 0xFFFFFFFFULL) << 32ULL; + uint64_t tmp2 = (th & 0xFFFFFFFFULL) << 32ULL; + int cc = (tmp + tmp2 < tmp) ? 1 : 0; tmp += tmp2; - cc += (tmp + fo < tmp); + cc += (tmp + fo < tmp) ? 1 : 0; + uint64_t carry = fi + (se >> 32) + (th >> 32); return uint128_t(this->f * p.s + this->s * p.f + carry + cc, tmp + fo); } @@ -421,7 +432,7 @@ class uint128_t { */ template ::value, T>::type> - inline uint128_t &operator*=(const T p) { + inline uint128_t &operator*=(const T p) noexcept { *this *= uint128_t(p); return *this; } @@ -431,15 +442,21 @@ class uint128_t { * @param p 128-bit unsigned integer * @returns multiplication of this and p, returning this */ - uint128_t &operator*=(const uint128_t &p) { - uint64_t f_first = s >> 32, f_second = s & 0xFFFFFFFF, - s_first = p.s >> 32, s_second = p.s & 0xFFFFFFFF; - uint64_t fi = f_first * s_first, se = f_first * s_second, - th = s_first * f_second, fo = s_second * f_second; - uint64_t tmp = (se << 32), tmp2 = (th << 32); - int cc = (tmp + tmp2 < tmp); + uint128_t &operator*=(const uint128_t &p) noexcept { + uint64_t f_first = s >> 32, f_second = s & 0xFFFFFFFF; + uint64_t s_first = p.s >> 32, s_second = p.s & 0xFFFFFFFF; + + uint64_t fi = f_first * s_first; + uint64_t se = f_first * s_second; + uint64_t th = s_first * f_second; + uint64_t fo = s_second * f_second; + + uint64_t tmp = se << 32ULL; + uint64_t tmp2 = th << 32ULL; + int cc = (tmp + tmp2 < tmp) ? 1 : 0; tmp += tmp2; - cc += (tmp + fo < tmp); + cc += (tmp + fo < tmp) ? 1 : 0; + uint64_t carry = fi + (se >> 32) + (th >> 32); f = this->f * p.s + this->s * p.f + carry + cc; s = tmp + fo; @@ -452,20 +469,22 @@ class uint128_t { * @param p 128-bit unsigned integer * @returns pair denoting quotient and remainder. */ - std::pair divide(const uint128_t &p) { - if (*this < p) { // if this is less than divisor + std::pair divide(const uint128_t &p) const { + if (p == uint128_t(0)) { + throw std::domain_error("Division by zero"); + } + if (*this < p) { return {uint128_t(0), *this}; - } else if (*this == p) { // if this is equal to divisor + } else if (*this == p) { return {uint128_t(1), uint128_t(0)}; } uint128_t tmp = p, tmp2 = *this; - uint16_t left = tmp._lez() - _lez(); + uint16_t left = tmp.lez() - lez(); tmp <<= left; uint128_t quotient(0); - uint128_t zero(0); while (tmp2 >= p) { - uint16_t shf = tmp2._lez() - tmp._lez(); - if (shf) { + uint16_t shf = tmp2.lez() - tmp.lez(); + if (shf != 0) { tmp >>= shf; quotient <<= shf; left -= shf; @@ -486,7 +505,9 @@ class uint128_t { * @param p 128-bit unsigned integer * @returns unsigned 128-bit quotient. */ - inline uint128_t operator/(const uint128_t &p) { return divide(p).first; } + inline uint128_t operator/(const uint128_t &p) const { + return divide(p).first; + } /** * @brief operator / for uint128_t and other integer types. @@ -496,10 +517,8 @@ class uint128_t { */ template ::value, T>::type> - inline uint128_t operator/(const T p) { - uint128_t tmp = *this; - tmp /= uint128_t(0, p); - return tmp; + inline uint128_t operator/(const T p) const { + return *this / uint128_t(p); } /** @@ -521,7 +540,7 @@ class uint128_t { template ::value, T>::type> inline uint128_t &operator/=(const T p) { - *this /= uint128_t(0, p); + *this /= uint128_t(p); return *this; } @@ -530,7 +549,9 @@ class uint128_t { * @param p 128-bit unsigned integer * @returns unsigned 128-bit remainder. */ - inline uint128_t operator%(const uint128_t &p) { return divide(p).second; } + inline uint128_t operator%(const uint128_t &p) const { + return divide(p).second; + } /** * @brief operator % for uint128_t and other integer types. @@ -540,7 +561,7 @@ class uint128_t { */ template ::value, T>::type> - inline uint128_t operator%(const T &p) { + inline uint128_t operator%(const T &p) const { return *this % uint128_t(p); } @@ -572,7 +593,7 @@ class uint128_t { * @param other number to be compared with this * @returns true if this is less than other, else false */ - inline bool operator<(const uint128_t &other) { + inline bool operator<(const uint128_t &other) const noexcept { return f < other.f || (f == other.f && s < other.s); } @@ -581,7 +602,7 @@ class uint128_t { * @param other number to be compared with this * @returns true if this is less than or equal to other, else false */ - inline bool operator<=(const uint128_t &other) { + inline bool operator<=(const uint128_t &other) const noexcept { return f < other.f || (f == other.f && s <= other.s); } @@ -590,7 +611,7 @@ class uint128_t { * @param other number to be compared with this * @returns true if this is greater than other, else false */ - inline bool operator>(const uint128_t &other) { + inline bool operator>(const uint128_t &other) const noexcept { return f > other.f || (f == other.f && s > other.s); } @@ -599,7 +620,7 @@ class uint128_t { * @param other number to be compared with this * @returns true if this is greater than or equal than other, else false */ - inline bool operator>=(const uint128_t &other) { + inline bool operator>=(const uint128_t &other) const noexcept { return (f > other.f) || (f == other.f && s >= other.s); } @@ -608,7 +629,7 @@ class uint128_t { * @param other number to be compared with this * @returns true if this is equal than other, else false */ - inline bool operator==(const uint128_t &other) { + inline bool operator==(const uint128_t &other) const noexcept { return f == other.f && s == other.s; } @@ -617,7 +638,7 @@ class uint128_t { * @param other number to be compared with this * @returns true if this is not equal than other, else false */ - inline bool operator!=(const uint128_t &other) { + inline bool operator!=(const uint128_t &other) const noexcept { return f != other.f || s != other.s; } @@ -625,14 +646,14 @@ class uint128_t { * @brief operator ! for uint128_t * @returns true if this has zero value, else false */ - inline bool operator!() { return !f && !s; } + inline bool operator!() const noexcept { return !f && !s; } /** * @brief operator && for uint128_t * @param b number to be compared with this * @returns true if both of the values are not zero, else false */ - inline bool operator&&(const uint128_t &b) { + inline bool operator&&(const uint128_t &b) const noexcept { return (s || f) && (b.s || b.f); } @@ -641,7 +662,7 @@ class uint128_t { * @param b number to be compared with this * @returns true if one of the values are not zero, else false */ - inline bool operator||(const uint128_t &b) { + inline bool operator||(const uint128_t &b) const noexcept { return (s || f) || (b.s || b.f); } @@ -649,7 +670,7 @@ class uint128_t { * @brief operator () for uint128_t * @returns true if this value is non-zero, else false */ - inline bool operator()() { return s || f; } + inline bool operator()() const noexcept { return s || f; } /** * @brief operator < for other types @@ -659,7 +680,7 @@ class uint128_t { */ template ::value, T>::type> - inline bool operator<(const T other) { + inline bool operator<(const T other) const noexcept { return *this < uint128_t(other); } @@ -671,7 +692,7 @@ class uint128_t { */ template ::value, T>::type> - inline bool operator<=(const T other) { + inline bool operator<=(const T other) const noexcept { return *this <= uint128_t(other); } @@ -683,7 +704,7 @@ class uint128_t { */ template ::value, T>::type> - inline bool operator>(const T other) { + inline bool operator>(const T other) const noexcept { return *this > uint128_t(other); } @@ -695,7 +716,7 @@ class uint128_t { */ template ::value, T>::type> - inline bool operator>=(const T other) { + inline bool operator>=(const T other) const noexcept { return *this >= uint128_t(other); } @@ -707,7 +728,7 @@ class uint128_t { */ template ::value, T>::type> - inline bool operator==(const T other) { + inline bool operator==(const T other) const noexcept { return *this == uint128_t(other); } @@ -719,7 +740,7 @@ class uint128_t { */ template ::value, T>::type> - inline bool operator!=(const T other) { + inline bool operator!=(const T other) const noexcept { return *this != uint128_t(other); } @@ -731,7 +752,7 @@ class uint128_t { */ template ::value, T>::type> - inline bool operator&&(const T b) { + inline bool operator&&(const T b) const noexcept { return (f || s) && b; } @@ -744,7 +765,7 @@ class uint128_t { */ template ::value, T>::type> - inline bool operator||(const T b) { + inline bool operator||(const T b) const noexcept { return (f || s) || b; } @@ -752,7 +773,9 @@ class uint128_t { * @brief operator ~ for uint128_t * @returns 1's complement of this number */ - uint128_t operator~() { return uint128_t(~this->f, ~this->s); } + uint128_t operator~() const noexcept { + return uint128_t(~this->f, ~this->s); + } /** * @brief operator << for uint128_t @@ -762,14 +785,13 @@ class uint128_t { */ template ::value, T>::type> - uint128_t operator<<(const T p) { - if (!p) { - return uint128_t(f, s); + uint128_t operator<<(const T p) const noexcept { + if (p == 0) { + return *this; } else if (p >= 64 && p <= 128) { return uint128_t((this->s << (p - 64)), 0); } else if (p < 64 && p > 0) { - return uint128_t((this->f << p) + ((this->s >> (64 - p))), - this->s << p); + return uint128_t((this->f << p) | (this->s >> (64 - p)), this->s << p); } return uint128_t(0); } @@ -782,15 +804,17 @@ class uint128_t { */ template ::value, T>::type> - uint128_t &operator<<=(const T p) { - if (p) { - if (p >= 64 && p <= 128) { - this->f = (this->s << (p - 64)); - this->s = 0; - } else { - f = ((this->f << p) + (this->s >> (64 - p))); - s = (this->s << p); - } + uint128_t &operator<<=(const T p) noexcept { + if (p == 0) return *this; + if (p >= 64 && p <= 128) { + this->f = (this->s << (p - 64)); + this->s = 0; + } else if (p < 64) { + f = (this->f << p) | (this->s >> (64 - p)); + s = (this->s << p); + } else { + f = 0; + s = 0; } return *this; } @@ -803,14 +827,13 @@ class uint128_t { */ template ::value, T>::type> - uint128_t operator>>(const T p) { - if (!p) { - return uint128_t(this->f, this->s); + uint128_t operator>>(const T p) const noexcept { + if (p == 0) { + return *this; } else if (p >= 64 && p <= 128) { return uint128_t(0, (this->f >> (p - 64))); } else if (p < 64 && p > 0) { - return uint128_t((this->f >> p), - (this->s >> p) + (this->f << (64 - p))); + return uint128_t((this->f >> p), (this->s >> p) | (this->f << (64 - p))); } return uint128_t(0); } @@ -823,15 +846,14 @@ class uint128_t { */ template ::value, T>::type> - uint128_t &operator>>=(const T p) { - if (p) { - if (p >= 64) { - f = 0; - s = (this->f >> (p - 64)); - } else { - s = (this->s >> p) + (this->f << (64 - p)); - f = (this->f >> p); - } + uint128_t &operator>>=(const T p) noexcept { + if (p == 0) return *this; + if (p >= 64) { + f = 0; + s = (this->f >> (p - 64)); + } else { + s = (this->s >> p) | (this->f << (64 - p)); + f = (this->f >> p); } return *this; } @@ -841,7 +863,7 @@ class uint128_t { * @param p number to be operated * @returns value of this & p (& is bit-wise operator) */ - inline uint128_t operator&(const uint128_t &p) { + inline uint128_t operator&(const uint128_t &p) const noexcept { return uint128_t(this->f & p.f, this->s & p.s); } @@ -853,9 +875,8 @@ class uint128_t { */ template ::value, T>::type> - uint128_t operator&(const T p) { - uint128_t tmp = *this; - return tmp & uint128_t(p); + uint128_t operator&(const T p) const noexcept { + return *this & uint128_t(p); } /** @@ -863,7 +884,7 @@ class uint128_t { * @param p number to be operated * @returns this = this & p (& is bit-wise operator) */ - uint128_t &operator&=(const uint128_t &p) { + uint128_t &operator&=(const uint128_t &p) noexcept { this->f &= p.f; this->s &= p.s; return *this; @@ -877,7 +898,7 @@ class uint128_t { */ template ::value, T>::type> - uint128_t &operator&=(const T p) { + uint128_t &operator&=(const T p) noexcept { *this &= uint128_t(p); return *this; } @@ -890,8 +911,8 @@ class uint128_t { */ template ::value, T>::type> - inline uint128_t operator|(const T p) { - return uint128_t(p | s); + inline uint128_t operator|(const T p) const noexcept { + return uint128_t(this->f, this->s | static_cast(p)); } /** @@ -899,7 +920,7 @@ class uint128_t { * @param p number to be operated * @returns value of this | p (| is bit-wise OR operator) */ - inline uint128_t operator|(const uint128_t &p) { + inline uint128_t operator|(const uint128_t &p) const noexcept { return uint128_t(this->f | p.f, this->s | p.s); } @@ -908,7 +929,7 @@ class uint128_t { * @param p number to be operated * @returns this = this | p (| is bit-wise OR operator) */ - uint128_t &operator|=(const uint128_t &p) { + uint128_t &operator|=(const uint128_t &p) noexcept { f |= p.f; s |= p.s; return *this; @@ -922,8 +943,8 @@ class uint128_t { */ template ::value, T>::type> - inline uint128_t &operator|=(const T p) { - s |= p.s; + inline uint128_t &operator|=(const T p) noexcept { + s |= static_cast(p); return *this; } @@ -935,8 +956,8 @@ class uint128_t { */ template ::value, T>::type> - inline uint128_t operator^(const T p) { - return uint128_t(this->f, this->s ^ p); + inline uint128_t operator^(const T p) const noexcept { + return uint128_t(this->f, this->s ^ static_cast(p)); } /** @@ -944,7 +965,7 @@ class uint128_t { * @param p number to be operated * @returns value of this ^ p (^ is bit-wise XOR operator) */ - inline uint128_t operator^(const uint128_t &p) { + inline uint128_t operator^(const uint128_t &p) const noexcept { return uint128_t(this->f ^ p.f, this->s ^ p.s); } @@ -953,7 +974,7 @@ class uint128_t { * @param p number to be operated * @returns this = this ^ p (^ is bit-wise XOR operator) */ - uint128_t &operator^=(const uint128_t &p) { + uint128_t &operator^=(const uint128_t &p) noexcept { f ^= p.f; s ^= p.s; return *this; @@ -967,8 +988,8 @@ class uint128_t { */ template ::value, T>::type> - inline uint128_t &operator^=(const T &p) { - s ^= p; + inline uint128_t &operator^=(const T &p) noexcept { + s ^= static_cast(p); return *this; } @@ -985,18 +1006,19 @@ class uint128_t { if (!p.f) { op << p.s; } else { - std::string out = "0", p_2 = "1"; + std::string out = "0"; + std::string p2 = "1"; for (int i = 0; i < 64; ++i) { - if (p.s & (1LL << i)) { - out = add(out, p_2); + if (p.s & (uint64_t(1) << i)) { + out = add(out, p2); } - p_2 = add(p_2, p_2); + p2 = add(p2, p2); } for (int i = 0; i < 64; ++i) { - if (p.f & (1LL << i)) { - out = add(out, p_2); + if (p.f & (uint64_t(1) << i)) { + out = add(out, p2); } - p_2 = add(p_2, p_2); + p2 = add(p2, p2); } op << out; } @@ -1007,19 +1029,19 @@ class uint128_t { // Arithmetic operators template ::value, T>::type> -inline uint128_t operator+(const T &p, const uint128_t &q) { +inline uint128_t operator+(const T &p, const uint128_t &q) noexcept { return uint128_t(p) + q; } template ::value, T>::type> -inline uint128_t operator-(const T p, const uint128_t &q) { +inline uint128_t operator-(const T p, const uint128_t &q) noexcept { return uint128_t(p) - q; } template ::value, T>::type> -inline uint128_t operator*(const T p, const uint128_t &q) { +inline uint128_t operator*(const T p, const uint128_t &q) noexcept { return uint128_t(p) * q; } @@ -1038,69 +1060,69 @@ inline uint128_t operator%(const T p, const uint128_t &q) { // Bitwise operators template ::value, T>::type> -inline uint128_t operator&(const T &p, const uint128_t &q) { +inline uint128_t operator&(const T &p, const uint128_t &q) noexcept { return uint128_t(p) & q; } template ::value, T>::type> -inline uint128_t operator|(const T p, const uint128_t &q) { +inline uint128_t operator|(const T p, const uint128_t &q) noexcept { return uint128_t(p) | q; } template ::value, T>::type> -inline uint128_t operator^(const T p, const uint128_t &q) { +inline uint128_t operator^(const T p, const uint128_t &q) noexcept { return uint128_t(p) ^ q; } // Boolean operators template ::value, T>::type> -inline bool operator&&(const T p, const uint128_t &q) { +inline bool operator&&(const T p, const uint128_t &q) noexcept { return uint128_t(p) && q; } template ::value, T>::type> -inline bool operator||(const T p, const uint128_t &q) { +inline bool operator||(const T p, const uint128_t &q) noexcept { return uint128_t(p) || q; } // Comparison operators template ::value, T>::type> -inline bool operator==(const T p, const uint128_t &q) { +inline bool operator==(const T p, const uint128_t &q) noexcept { return uint128_t(p) == q; } template ::value, T>::type> -inline bool operator!=(const T p, const uint128_t &q) { +inline bool operator!=(const T p, const uint128_t &q) noexcept { return uint128_t(p) != q; } template ::value, T>::type> -inline bool operator<(const T p, const uint128_t &q) { +inline bool operator<(const T p, const uint128_t &q) noexcept { return uint128_t(p) < q; } template ::value, T>::type> -inline bool operator<=(const T p, const uint128_t &q) { +inline bool operator<=(const T p, const uint128_t &q) noexcept { return uint128_t(p) <= q; } template ::value, T>::type> -inline bool operator>(const T p, const uint128_t &q) { +inline bool operator>(const T p, const uint128_t &q) noexcept { return uint128_t(p) > q; } template ::value, T>::type> -inline bool operator>=(const T p, const uint128_t &q) { +inline bool operator>=(const T p, const uint128_t &q) noexcept { return uint128_t(p) >= q; } diff --git a/ciphers/uint256_t.hpp b/ciphers/uint256_t.hpp index a7ba49a909..ba0ba96e66 100644 --- a/ciphers/uint256_t.hpp +++ b/ciphers/uint256_t.hpp @@ -5,12 +5,13 @@ * @note The implementation can be flagged as not completed. This header is used * with enough operations to demonstrate the usage of ECDH (Elliptic Curve * Diffie-Hellman) Key exchange. - * @author [Ashish Daulatabad](https://github.com/AshishYUO) + * @author [miaochengyou1119](https://github.com/miaochengyou1119) */ -#include /// for `std::string` -#include /// for `std::pair` library +#include +#include +#include -#include "uint128_t.hpp" /// for uint128_t integer +#include "uint128_t.hpp" #ifndef CIPHERS_UINT256_T_HPP_ #define CIPHERS_UINT256_T_HPP_ @@ -31,7 +32,7 @@ struct std::is_unsigned : std::true_type {}; * @brief class for 256-bit unsigned integer */ class uint256_t { - uint128_t f{}, s{}; /// First and second half of 256 bit number + uint128_t f{}, s{}; /** * @brief Get integer from given string. @@ -40,79 +41,48 @@ class uint256_t { * number) * @returns void */ - void __get_integer_from_string(const std::string &str) { + void get_integer_from_string(const std::string &str) { this->f = this->s = uint128_t(0); if (str.size() > 1 && str[1] == 'x') { for (auto i = 2; i < str.size(); ++i) { - *this *= 16LL; + *this *= 16ULL; if (str[i] >= '0' && str[i] <= '9') { - *this += (str[i] - '0'); + *this += static_cast(str[i] - '0'); } else if (str[i] >= 'A' && str[i] <= 'F') { - *this += (str[i] - 'A' + 10); + *this += static_cast(str[i] - 'A' + 10); } else if (str[i] >= 'a' && str[i] <= 'f') { - *this += (str[i] - 'a' + 10); + *this += static_cast(str[i] - 'a' + 10); } } } else { for (auto &x : str) { - *this *= 10LL; - *this += (x - '0'); + *this *= 10ULL; + *this += static_cast(x - '0'); } } } - public: - // Constructors +public: uint256_t() = default; - /** - * @brief Parameterized constructor - * @tparam T template for integer types - * @param low Integer denoting lower 128-bits - */ template ::value, T>::type> - explicit uint256_t(T low) : f(0), s(low) {} + explicit uint256_t(T low) : f(0), s(static_cast(low)) {} - /** - * @brief Parameterized constructor - * @param str Integer string (hexadecimal starting with 0x.. or decimal) - */ explicit uint256_t(const std::string &str) { - __get_integer_from_string(str); + get_integer_from_string(str); } - /** - * @brief Copy constructor - * @param num 256-bit unsigned integer - */ uint256_t(const uint256_t &num) = default; - /** - * @brief Move constructor - * @param num 256-bit unsigned integer - */ uint256_t(uint256_t &&num) noexcept : f(std::move(num.f)), s(std::move(num.s)) {} - /** - * @brief Parameterized constructor - * @param high higher part 128-bit unsigned integer - * @param low lower part 128-bit unsigned integer - */ uint256_t(uint128_t high, uint128_t low) : f(std::move(high)), s(std::move(low)) {} - /** - * @brief Parameterized constructor - * @param high higher part 64-bit unsigned integer - * @param low lower part 64-bit unsigned integer - */ uint256_t(const uint64_t high, const uint64_t low) : f(high), s(low) {} - /** - * @brief Destructor for uint256_t - */ ~uint256_t() = default; /** @@ -120,317 +90,205 @@ class uint256_t { * @details Calculates leading zeros in 256-bit integer * @returns Integer denoting leading zeroes */ - inline uint32_t _lez() { + inline uint32_t lez() const noexcept { if (f) { - return f._lez(); + return f.lez(); } - return 128 + s._lez(); + return 128 + s.lez(); } /** * @brief Trailing zeroes in binary - * @details Calculates leading zeros in 256-bit integer + * @details Calculates trailing zeros in 256-bit integer * @returns Integer denoting Trailing zeroes */ - inline uint32_t _trz() { + inline uint32_t trz() const noexcept { if (s) { - return s._trz(); + return s.trz(); } - return 128 + f._trz(); + return 128 + f.trz(); } - /** - * @brief casting operator to boolean value - * @returns true if value of this is non-zero, else false - */ - inline explicit operator bool() const { return f || s; } + inline explicit operator bool() const noexcept { return f || s; } - /** - * @brief casting operator to any integer value - * @tparam T any integer type - * @returns integer value casted to mentioned type - */ template ::value, T>::type> - inline explicit operator T() const { + inline explicit operator T() const noexcept { return static_cast(s); } - /** - * @brief casting operator to uint128_t - * @returns returns lower 128-bit integer part - */ - inline explicit operator uint128_t() const { return s; } + inline explicit operator uint128_t() const noexcept { return s; } - /** - * @brief returns lower 128-bit integer part - * @returns returns lower 128-bit integer part - */ - inline uint128_t lower() const { return s; } + inline uint128_t lower() const noexcept { return s; } + inline uint128_t upper() const noexcept { return f; } - /** - * @brief returns upper 128-bit integer part - * @returns returns upper 128-bit integer part - */ - inline uint128_t upper() const { return f; } - - /** - * @brief operator = for uint256_t - * @param p an 256-bit integer to assign it's value - * @returns this pointer with it's value equal to `p` - */ inline uint256_t &operator=(const uint256_t &p) = default; - /** - * @brief operator = for other types - * @tparam T denoting any integer type - * @param p an integer to assign it's value - * @returns this pointer with it's value equal to `p` - */ template ::value, T>::type> - inline uint256_t &operator=(const T &p) { + inline uint256_t &operator=(const T &p) noexcept { this->s = p; + this->f = 0; return *this; } - /** - * @brief operator = for type string - * @param p a string to assign it's value to equivalent integer - * @returns this pointer with it's value equal to `p` - */ inline uint256_t &operator=(const std::string &p) { - __get_integer_from_string(p); + get_integer_from_string(p); return *this; } - /** - * @brief Move assignment operator - */ - inline uint256_t &operator=(uint256_t &&p) = default; + inline uint256_t &operator=(uint256_t &&p) noexcept = default; - /** - * @brief operator + for uint256_t and other integer types. - * @tparam T denoting integral type - * @param p a type of integer variable - * @returns addition of this and p, returning uint256_t integer - */ template ::value, T>::type> - inline uint256_t operator+(const T &p) { + inline uint256_t operator+(const T &p) const noexcept { bool app = s + p < s; return uint256_t(f + app, s + p); } - /** - * @brief operator + for uint256_t and other integer types. - * @param p 256-bit unsigned integer - * @returns addition of this and p, returning uint256_t integer - */ - inline uint256_t operator+(const uint256_t &p) { + inline uint256_t operator+(const uint256_t &p) const noexcept { bool app = (s + p.s < s); return {f + app + p.f, s + p.s}; } - /** - * @brief operator += for uint256_t and other integer types. - * @tparam T denoting integral type - * @param p a type of integer variable - * @returns addition of this and p, returning this - */ template ::value, T>::type> - inline uint256_t &operator+=(const T &p) { + inline uint256_t &operator+=(const T &p) noexcept { bool app = (p + s < s); this->f += app; this->s += p; return *this; } - /** - * @brief operator += for uint256_t - * @param p 256-bit unsigned integer - * @returns addition of this and p, returning this - */ - inline uint256_t &operator+=(const uint256_t &p) { + inline uint256_t &operator+=(const uint256_t &p) noexcept { bool app = (s + p.s < s); f = f + app + p.f; s = s + p.s; return *this; } - /** - * @brief pre-increment operator - * @returns incremented value of this. - */ - inline uint256_t &operator++() { - *this += 1; + inline uint256_t &operator++() noexcept { + *this += 1ULL; return *this; } - /** - * @brief post-increment operator - * @returns incremented value of this. - */ - inline uint256_t operator++(int) { + inline uint256_t operator++(int) noexcept { + uint256_t temp = *this; ++*this; - return *this; + return temp; } - /** - * @brief operator - for uint256_t and other integer types. - * @tparam T denoting integral type - * @param p a type of integer variable - * @returns subtraction of this and p, returning uint256_t integer - */ template ::value, T>::type> - inline uint256_t operator-(const T &p) { + inline uint256_t operator-(const T &p) const noexcept { bool app = (p > s); return uint256_t(f - app, s - p); } - /** - * @brief operator - for uint256_t - * @param p a type of integer variable - * @returns subtraction of this and p, returning uint256_t integer - */ - inline uint256_t operator-(const uint256_t &p) { + inline uint256_t operator-(const uint256_t &p) const noexcept { bool app = s < p.s; return {f - p.f - app, s - p.s}; } - /** - * @brief operator - using twos complement - * @returns 2's complement of this. - */ - inline uint256_t operator-() { return ~*this + uint256_t(1); } + inline uint256_t operator-() const noexcept { + return ~*this + uint256_t(1ULL); + } - /** - * @brief operator -- (pre-decrement) - * @returns decremented value of this - */ - inline uint256_t &operator--() { - *this -= 1; + inline uint256_t &operator--() noexcept { + *this -= 1ULL; return *this; } - /** - * @brief operator -- (post-decrement) - * @returns decremented value of this - */ - inline uint256_t operator--(int) { + inline uint256_t operator--(int) noexcept { + uint256_t temp = *this; --*this; - return *this; + return temp; } - /** - * @brief operator -= for uint256_t and other integer types. - * @tparam T denoting integral type - * @param p a type of integer variable - * @returns subtraction of this and p, returning this - */ template ::value, T>::type> - inline uint256_t operator-=(const T p) { + inline uint256_t operator-=(const T p) noexcept { bool app = (p > s); f = f - app; s = s - p; return *this; } - /** - * @brief operator -= for uint256_t - * @param p 256-bit unsigned integer - * @returns subtraction of this and p, returning this - */ - inline uint256_t &operator-=(const uint256_t &p) { + inline uint256_t &operator-=(const uint256_t &p) noexcept { bool app = s < p.s; f = f - app - p.f; s = s - p.s; return *this; } - /** - * @brief operator * for uint256_t and other integer types. - * @tparam T denoting integral type - * @param p a type of integer variable - * @returns multiplication of this and p, returning uint256_t integer - */ template ::value, T>::type> - inline uint256_t operator*(const T &p) { + inline uint256_t operator*(const T &p) const noexcept { return *this * uint256_t(p); } - /** - * @brief operator * for uint256_t and other integer types. - * @param p 256-bit unsigned integer - * @returns multiplication of this and p, returning uint256_t integer - */ - uint256_t operator*(const uint256_t &p) { - uint128_t f_first(s.upper()), f_second(s.lower()), s_first(p.s.upper()), - s_second(p.s.lower()); - uint128_t fi = f_first * s_first, se = f_first * s_second, - th = s_first * f_second, fo = s_second * f_second; - uint128_t tmp = se << 64, tmp2 = th << 64; - int cc = (tmp + tmp2 < tmp); + uint256_t operator*(const uint256_t &p) const noexcept { + uint128_t f_first(s.upper()), f_second(s.lower()); + uint128_t s_first(p.s.upper()), s_second(p.s.lower()); + + uint128_t fi = f_first * s_first; + uint128_t se = f_first * s_second; + uint128_t th = s_first * f_second; + uint128_t fo = s_second * f_second; + + uint128_t tmp = se << 64; + uint128_t tmp2 = th << 64; + + int cc = (tmp + tmp2 < tmp) ? 1 : 0; tmp += tmp2; - cc += (tmp + fo < tmp); + cc += (tmp + fo < tmp) ? 1 : 0; + return {f * p.s + s * p.f + fi + se.upper() + th.upper() + cc, tmp + fo}; } - /** - * @brief operator *= for uint256_t and other integer types. - * @tparam T denoting integral type - * @param p a type of integer variable - * @returns multiplication of this and p, returning this - */ template ::value, T>::type> - inline uint256_t &operator*=(const T &p) { + inline uint256_t &operator*=(const T &p) noexcept { return (*this *= uint256_t(p)); } - /** - * @brief operator *= for uint256_t and other integer types. - * @param p 256-bit unsigned integer - * @returns multiplication of this and p, returning this - */ - uint256_t &operator*=(const uint256_t &p) { - uint128_t f_first(s.upper()), f_second(s.lower()), s_first(p.s.upper()), - s_second(p.s.lower()); - uint128_t fi = f_first * s_first, se = f_first * s_second, - th = s_first * f_second, fo = s_second * f_second; - uint128_t tmp = se << 64, tmp2 = th << 64; - int cc = (tmp + tmp2 < tmp); + uint256_t &operator*=(const uint256_t &p) noexcept { + uint128_t f_first(s.upper()), f_second(s.lower()); + uint128_t s_first(p.s.upper()), s_second(p.s.lower()); + + uint128_t fi = f_first * s_first; + uint128_t se = f_first * s_second; + uint128_t th = s_first * f_second; + uint128_t fo = s_second * f_second; + + uint128_t tmp = se << 64; + uint128_t tmp2 = th << 64; + + int cc = (tmp + tmp2 < tmp) ? 1 : 0; tmp += tmp2; - cc += (tmp + fo < tmp); + cc += (tmp + fo < tmp) ? 1 : 0; + f = f * p.s + s * p.f + fi + se.upper() + th.upper() + cc; s = tmp + fo; return *this; } - /** - * @brief divide function for uint256_t and other integer types. - * @details divide this value and - * @param p 256-bit unsigned integer - * @returns pair denoting quotient and remainder. - */ - std::pair divide(const uint256_t &p) { - if (*this < p) { // if this is less than divisor + std::pair divide(const uint256_t &p) const { + if (p == uint256_t(0)) { + throw std::domain_error("Division by zero"); + } + if (*this < p) { return {uint256_t(0), *this}; - } else if (*this == p) { // if this is equal to divisor + } else if (*this == p) { return {uint256_t(1), uint256_t(0)}; } uint256_t tmp = p, tmp2 = *this; - uint16_t left = tmp._lez() - _lez(); + uint16_t left = tmp.lez() - lez(); tmp <<= left; uint256_t quotient(0); - uint256_t zero(0); while (tmp2 >= p) { - uint16_t shf = tmp2._lez() - tmp._lez(); + uint16_t shf = tmp2.lez() - tmp.lez(); if (shf) { tmp >>= shf; quotient <<= shf; @@ -447,43 +305,21 @@ class uint256_t { return {quotient << left, tmp2}; } - /** - * @brief operator / for uint256_t and other integer types. - * @tparam T denoting integral type - * @param p a type of integer variable - * @returns unsigned 256-bit quotient. - */ template ::value, T>::type> - inline uint256_t operator/(const T &p) { - uint256_t tmp = *this; - tmp /= uint256_t(p); - return tmp; + inline uint256_t operator/(const T &p) const { + return *this / uint256_t(p); } - /** - * @brief operator / for uint256_t and other integer types. - * @param p 256-bit unsigned integer - * @returns unsigned 256-bit quotient. - */ - inline uint256_t operator/(const uint256_t &p) { return divide(p).first; } + inline uint256_t operator/(const uint256_t &p) const { + return divide(p).first; + } - /** - * @brief operator /= for uint256_t - * @param p 256-bit unsigned integer - * @returns this set as unsigned 256-bit quotient. - */ inline uint256_t &operator/=(const uint256_t &p) { *this = divide(p).first; return *this; } - /** - * @brief operator /= for uint256_t and other integer types. - * @tparam T denoting integral type - * @param p a type of integer variable - * @returns this set as unsigned 256-bit quotient. - */ template ::value, T>::type> inline uint256_t &operator/=(const T &p) { @@ -491,43 +327,21 @@ class uint256_t { return *this; } - /** - * @brief operator % for uint256_t - * @param p 256-bit unsigned integer - * @returns unsigned 256-bit remainder. - */ - inline uint256_t operator%(const uint256_t &p) { return divide(p).second; } + inline uint256_t operator%(const uint256_t &p) const { + return divide(p).second; + } - /** - * @brief operator % for uint256_t and other integer types. - * @tparam T denoting integral type - * @param p a type of integer variable - * @returns unsigned 256-bit remainder. - */ template ::value, T>::type> - inline uint256_t operator%(const T &p) { - uint256_t tmp = *this; - tmp %= uint256_t(p); - return tmp; + inline uint256_t operator%(const T &p) const { + return *this % uint256_t(p); } - /** - * @brief operator %= for uint256_t - * @param p 256-bit unsigned integer - * @returns this set as unsigned 256-bit remainder. - */ inline uint256_t &operator%=(const uint256_t &p) { *this = divide(p).second; return *this; } - /** - * @brief operator %= for uint256_t - * @tparam T denoting integral type - * @param p a type of integer variable - * @returns this set as unsigned 256-bit remainder. - */ template ::value, T>::type> inline uint256_t &operator%=(const T &p) { @@ -535,434 +349,235 @@ class uint256_t { return *this; } - /** - * @brief operator < for uint256_t - * @param other number to be compared with this - * @returns true if this is less than other, else false - */ - inline bool operator<(const uint256_t &other) { + inline bool operator<(const uint256_t &other) const noexcept { return f < other.f || (f == other.f && s < other.s); } - /** - * @brief operator <= for uint256_t - * @param other number to be compared with this - * @returns true if this is less than or equal to other, else false - */ - inline bool operator<=(const uint256_t &other) { + inline bool operator<=(const uint256_t &other) const noexcept { return f < other.f || (f == other.f && s <= other.s); } - /** - * @brief operator > for uint256_t - * @param other number to be compared with this - * @returns true if this is greater than other, else false - */ - inline bool operator>(const uint256_t &other) { + inline bool operator>(const uint256_t &other) const noexcept { return f > other.f || (f == other.f && s > other.s); } - /** - * @brief operator >= for uint256_t - * @param other number to be compared with this - * @returns true if this is greater than or equal than other, else false - */ - inline bool operator>=(const uint256_t &other) { + inline bool operator>=(const uint256_t &other) const noexcept { return (f > other.f) || (f == other.f && s >= other.s); } - /** - * @brief operator == for uint256_t - * @param other number to be compared with this - * @returns true if this is equal than other, else false - */ - inline bool operator==(const uint256_t &other) { + inline bool operator==(const uint256_t &other) const noexcept { return f == other.f && s == other.s; } - /** - * @brief operator != for uint256_t - * @param other number to be compared with this - * @returns true if this is not equal than other, else false - */ - inline bool operator!=(const uint256_t &other) { + inline bool operator!=(const uint256_t &other) const noexcept { return !((*this) == other); } - /** - * @brief operator ! for uint256_t - * @returns true if this has zero value, else false - */ - inline bool operator!() { return !f && !s; } + inline bool operator!() const noexcept { return !f && !s; } - /** - * @brief operator && for uint256_t - * @param b number to be compared with this - * @returns true if both of the values are not zero, else false - */ - inline bool operator&&(const uint256_t &b) { + inline bool operator&&(const uint256_t &b) const noexcept { return (s || f) && (b.s || b.f); } - /** - * @brief operator || for uint256_t - * @param b number to be compared with this - * @returns true if one of the values are not zero, else false - */ - inline bool operator||(const uint256_t &b) { + inline bool operator||(const uint256_t &b) const noexcept { return (s || f) || (b.s || b.f); } - /** - * @brief operator () for uint256_t - * @returns true if this value is non-zero, else false - */ - inline bool operator()() { return s || f; } + inline bool operator()() const noexcept { return s || f; } - /** - * @brief operator < for other types - * @tparam T integral type - * @param other number to be compared with this - * @returns true if this is less than other, else false - */ template ::value, T>::type> - bool operator<(const T &other) { + bool operator<(const T &other) const noexcept { return *this < uint256_t(other); } - /** - * @brief operator <= for other types - * @tparam T integral type - * @param other number to be compared with this - * @returns true if this is less than or equal to other, else false - */ template ::value, T>::type> - bool operator<=(const T &other) { + bool operator<=(const T &other) const noexcept { return *this <= uint256_t(other); } - /** - * @brief operator > for other types - * @tparam T integral type - * @param other number to be compared with this - * @returns true if this is greater than other, else false - */ template ::value, T>::type> - bool operator>(const T &other) { + bool operator>(const T &other) const noexcept { return *this > uint256_t(other); } - /** - * @brief operator >= for other types - * @tparam T integral type - * @param other number to be compared with this - * @returns true if this is greater than or equal other, else false - */ template ::value, T>::type> - bool operator>=(const T &other) { + bool operator>=(const T &other) const noexcept { return *this >= uint256_t(other); } - /** - * @brief operator == for other types - * @tparam T integral type - * @param other number to be compared with this - * @returns true if this is equal to other, else false - */ template ::value, T>::type> - bool operator==(const T &other) { + bool operator==(const T &other) const noexcept { return *this == uint256_t(other); } - /** - * @brief operator != for other types - * @tparam T integral type - * @param other number to be compared with this - * @returns true if this is not equal to other, else false - */ template ::value, T>::type> - bool operator!=(const T &other) { + bool operator!=(const T &other) const noexcept { return *this != uint256_t(other); } - /** - * @brief operator && for other types - * @tparam T integral type - * @param other number to be compared with this - * @returns true if this is both values are non-zero, else false - */ template ::value, T>::type> - inline bool operator&&(const T &b) { + inline bool operator&&(const T &b) const noexcept { return (s || f) && (b); } - /** - * @brief operator || for other types - * @tparam T integral type - * @param other number to be compared with this - * @returns true if this is either one of the values are non-zero, else - * false - */ template ::value, T>::type> - inline bool operator||(const T &b) { + inline bool operator||(const T &b) const noexcept { return (s || f) || (b); } - /** - * @brief operator ~ for uint256_t - * @returns 1's complement of this number - */ - inline uint256_t operator~() { return {~f, ~s}; } + inline uint256_t operator~() const noexcept { + return {~f, ~s}; + } - /** - * @brief operator << for uint256_t - * @tparam T integral type - * @param p number denoting number of shifts - * @returns value of this shifted by p to left - */ template ::value, T>::type> - uint256_t operator<<(const T &p) { - if (!p) { - return {this->f, this->s}; + uint256_t operator<<(const T &p) const noexcept { + if (p == 0) { + return *this; } else if (p >= 128) { return uint256_t((this->s << (p - 128)), uint128_t(0)); } - return uint256_t((this->f << p) + (this->s >> (128 - p)), + return uint256_t((this->f << p) | (this->s >> (128 - p)), (this->s << p)); } - /** - * @brief operator <<= for uint256_t - * @tparam T integral type - * @param p number denoting number of shifts - * @returns this shifted by p to left - */ template ::value, T>::type> - uint256_t &operator<<=(const T &p) { - if (p) { - if (p >= 128) { - this->f = (this->s << (p - 128)); - this->s = uint128_t(0); - } else { - f = ((this->s >> (128 - p)) + (this->f << p)); - s = (this->s << p); - } + uint256_t &operator<<=(const T &p) noexcept { + if (p == 0) return *this; + if (p >= 128) { + this->f = (this->s << (p - 128)); + this->s = uint128_t(0); + } else { + f = (this->f << p) | (this->s >> (128 - p)); + s = (this->s << p); } return *this; } - /** - * @brief operator >> for uint256_t - * @tparam T integral type - * @param p number denoting number of shifts - * @returns value of this shifted by p to right - */ template ::value, T>::type> - uint256_t operator>>(const T &p) { - if (!p) { - return {this->f, this->s}; + uint256_t operator>>(const T &p) const noexcept { + if (p == 0) { + return *this; } else if (p >= 128) { return uint256_t(uint128_t(0), (this->f >> (p - 128))); } return uint256_t((this->f >> p), - (this->s >> p) + (this->f << (128 - p))); + (this->s >> p) | (this->f << (128 - p))); } - /** - * @brief operator >>= for uint256_t - * @tparam T integral type - * @param p number denoting number of shifts - * @returns this shifted by p to right - */ template ::value, T>::type> - uint256_t &operator>>=(const T &p) { - if (p) { - if (p >= 128) { - f = uint128_t(0); - s = (this->f >> (p - 128)); - } else { - s = (this->s >> p) + (this->f << (128 - p)); - f = (this->f >> p); - } + uint256_t &operator>>=(const T &p) noexcept { + if (p == 0) return *this; + if (p >= 128) { + f = uint128_t(0); + s = (this->f >> (p - 128)); + } else { + s = (this->s >> p) | (this->f << (128 - p)); + f = (this->f >> p); } return *this; } - /** - * @brief operator & for other types (bitwise operator) - * @tparam T integral type - * @param p number to be operated - * @returns value of this & p (& is bit-wise operator) - */ template ::value, T>::type> - inline uint256_t operator&(const T &p) { + inline uint256_t operator&(const T &p) const noexcept { return *this & uint256_t(p); } - /** - * @brief operator & for uint256_t (bitwise operator) - * @param p number to be operated - * @returns value of this & p (& is bit-wise operator) - */ - inline uint256_t operator&(const uint256_t &p) { + inline uint256_t operator&(const uint256_t &p) const noexcept { return {f & p.f, s & p.s}; } - /** - * @brief operator &= for uint256_t (bitwise operator) - * @param p number to be operated - * @returns this = this & p (& is bit-wise operator) - */ - inline uint256_t &operator&=(const uint256_t &p) { + inline uint256_t &operator&=(const uint256_t &p) noexcept { f &= p.f; s &= p.s; return *this; } - /** - * @brief operator &= for other types (bitwise operator) - * @tparam T integral type - * @param p number to be operated - * @returns this = this & p (& is bit-wise operator) - */ template ::value, T>::type> - inline uint256_t &operator&=(const T p) { - s &= p.s; + inline uint256_t &operator&=(const T p) noexcept { + *this &= uint256_t(p); return *this; } - /** - * @brief operator | for other types (bitwise operator) - * @tparam T integral type - * @param p number to be operated - * @returns value of this | p (| is bit-wise operator) - */ template ::value, T>::type> - inline uint256_t operator|(const T &p) { + inline uint256_t operator|(const T &p) const noexcept { return *this | uint256_t(p); } - /** - * @brief operator | for uint256_t (bitwise operator) - * @param p number to be operated - * @returns value of this | p (| is bit-wise OR operator) - */ - inline uint256_t operator|(const uint256_t &p) { + inline uint256_t operator|(const uint256_t &p) const noexcept { return {this->f | p.f, this->s | p.s}; } - /** - * @brief operator |= for other types (bitwise operator) - * @tparam T integral type - * @param p number to be operated - * @returns this = this | p (| is bit-wise OR operator) - */ template ::value, T>::type> - inline uint256_t &operator|=(const T &p) { + inline uint256_t &operator|=(const T &p) noexcept { s |= p; return *this; } - /** - * @brief operator |= for uint256_t (bitwise operator) - * @param p number to be operated - * @returns this = this | p (| is bit-wise OR operator) - */ - inline uint256_t &operator|=(const uint256_t &p) { + inline uint256_t &operator|=(const uint256_t &p) noexcept { f |= p.f; s |= p.s; return *this; } - /** - * @brief operator ^ for other types (bitwise operator) - * @tparam T integral type - * @param p number to be operated - * @returns value of this ^ p (^ is bit-wise XOR operator) - */ template ::value, T>::type> - inline uint256_t operator^(const T &p) { + inline uint256_t operator^(const T &p) const noexcept { return uint256_t(f, s ^ p); } - /** - * @brief operator ^ for uint256_t (bitwise operator) - * @param p number to be operated - * @returns value of this ^ p (^ is bit-wise XOR operator) - */ - inline uint256_t operator^(const uint256_t &p) { + inline uint256_t operator^(const uint256_t &p) const noexcept { return {this->f ^ p.f, this->s ^ p.s}; } - /** - * @brief operator ^= for uint256_t (bitwise operator) - * @param p number to be operated - * @returns this = this ^ p (^ is bit-wise XOR operator) - */ - inline uint256_t &operator^=(const uint256_t &p) { + inline uint256_t &operator^=(const uint256_t &p) noexcept { f ^= p.f; s ^= p.s; return *this; } - /** - * @brief operator ^= for other types (bitwise operator) - * @tparam T integral type - * @param p number to be operated - * @returns this = this ^ p (^ is bit-wise XOR operator) - */ template ::value, T>::type> - inline uint256_t &operator^=(const T &p) { + inline uint256_t &operator^=(const T &p) noexcept { s ^= p; return *this; } - /** - * @brief operator << for printing uint256_t integer - * @details Prints the uint256_t integer in decimal form - * @note Note that this operator is costly since it uses strings to print - * the value - * @param op ostream object - * @param p 256-bit integer - * @returns op, ostream object. - */ - friend std::ostream &operator<<(std::ostream &op, uint256_t p) { + friend std::ostream &operator<<(std::ostream &op, const uint256_t &p) { if (!p.f) { op << p.s; } else { - std::string out = "0", p_2 = "1"; + std::string out = "0"; + std::string p2 = "1"; uint128_t L(1); for (uint64_t i = 0; i < 128; ++i) { if ((p.s & L)) { - out = add(out, p_2); + out = add(out, p2); } - p_2 = add(p_2, p_2); + p2 = add(p2, p2); L <<= 1; } L = uint128_t(1); for (int i = 0; i < 128; ++i) { if ((p.f & L)) { - out = add(out, p_2); + out = add(out, p2); } - p_2 = add(p_2, p_2); + p2 = add(p2, p2); L <<= 1; } op << out; @@ -971,22 +586,21 @@ class uint256_t { } }; -// Artihmetic template ::value, T>::type> -inline uint256_t operator+(const T p, const uint256_t &q) { +inline uint256_t operator+(const T p, const uint256_t &q) noexcept { return uint256_t(p) + q; } template ::value, T>::type> -inline uint256_t operator-(const T p, const uint256_t &q) { - return (uint256_t(p) - q); +inline uint256_t operator-(const T p, const uint256_t &q) noexcept { + return uint256_t(p) - q; } template ::value, T>::type> -inline uint256_t operator*(const T p, const uint256_t &q) { +inline uint256_t operator*(const T p, const uint256_t &q) noexcept { return uint256_t(p) * q; } @@ -1002,72 +616,69 @@ inline uint256_t operator%(const T p, const uint256_t &q) { return uint256_t(p) % q; } -// Bitwise operators template ::value, T>::type> -inline uint256_t operator&(const T &p, const uint256_t &q) { +inline uint256_t operator&(const T &p, const uint256_t &q) noexcept { return uint256_t(p) & q; } template ::value, T>::type> -inline uint256_t operator|(const T p, const uint256_t &q) { +inline uint256_t operator|(const T p, const uint256_t &q) noexcept { return uint256_t(p) | q; } template ::value, T>::type> -inline uint256_t operator^(const T p, const uint256_t &q) { +inline uint256_t operator^(const T p, const uint256_t &q) noexcept { return uint256_t(p) ^ q; } -// Boolean operators template ::value, T>::type> -inline bool operator&&(const T p, const uint256_t &q) { +inline bool operator&&(const T p, const uint256_t &q) noexcept { return uint256_t(p) && q; } template ::value, T>::type> -inline bool operator||(const T p, const uint256_t &q) { +inline bool operator||(const T p, const uint256_t &q) noexcept { return uint256_t(p) || q; } -// Comparison operators template ::value, T>::type> -inline bool operator==(const T p, const uint256_t &q) { +inline bool operator==(const T p, const uint256_t &q) noexcept { return uint256_t(p) == q; } template ::value, T>::type> -inline bool operator!=(const T p, const uint256_t &q) { +inline bool operator!=(const T p, const uint256_t &q) noexcept { return uint256_t(p) != q; } template ::value, T>::type> -inline bool operator<(const T p, const uint256_t &q) { +inline bool operator<(const T p, const uint256_t &q) noexcept { return uint256_t(p) < q; } template ::value, T>::type> -inline bool operator<=(const T p, const uint256_t &q) { +inline bool operator<=(const T p, const uint256_t &q) noexcept { return uint256_t(p) <= q; } template ::value, T>::type> -inline bool operator>(const T p, const uint256_t &q) { +inline bool operator>(const T p, const uint256_t &q) noexcept { return uint256_t(p) > q; } template ::value, T>::type> -inline bool operator>=(const T p, const uint256_t &q) { +inline bool operator>=(const T p, const uint256_t &q) noexcept { return uint256_t(p) >= q; } diff --git a/ciphers/vigenere_cipher.cpp b/ciphers/vigenere_cipher.cpp index 4efd56c001..c1f5e78039 100644 --- a/ciphers/vigenere_cipher.cpp +++ b/ciphers/vigenere_cipher.cpp @@ -1,135 +1,78 @@ /** * @file vigenere_cipher.cpp - * @brief Implementation of [Vigenère cipher](https://en.wikipedia.org/wiki/Vigen%C3%A8re_cipher) algorithm. - * - * @details - * The Vigenère cipher is a method of encrypting alphabetic text by using a series of interwoven vigenere - * ciphers, based on the letters of a keyword. It employs a form of polyalphabetic substitution. - * - * ### Algorithm - * The encryption can also be represented using modular arithmetic by first transforming - * the letters into numbers, according to the scheme, A → 0, B → 1, ..., Z → 25. - * Encryption of \f$i^{th}\f$ character in Message M by key K can be described mathematically as, - * - * \f[ E_{K}(M_{i}) = (M_{i} + K_{i})\;\mbox{mod}\; 26\f] - * - * while decryption of \f$i^{th}\f$ character in Cipher C by key K can be described mathematically as, - * - * \f[ D_{k}(C_{i}) = (C_{i} - K_{i} + 26)\;\mbox{mod}\; 26\f] - * - * Where \f$K_{i}\f$ denotes corresponding character in key. If \f$|key| < |text|\f$ than - * same key is repeated untill their lengths are equal. - * - * For Example, - * If M = "ATTACKATDAWN" and K = "LEMON" than K becomes "LEMONLEMONLE". - * - * \note Rather than creating new key of equal length this program does this by using modular index for key - * (i.e. \f$(j + 1) \;\mbox{mod}\; |\mbox{key}|\f$) - * - * \note This program implements Vigenère cipher for only uppercase English alphabet characters (i.e. A-Z). - * - * @author [Deep Raval](https://github.com/imdeep2905) + * @brief 维吉尼亚密码 (Vigenère Cipher) */ + #include #include #include -/** \namespace ciphers - * \brief Algorithms for encryption and decryption - */ namespace ciphers { - /** \namespace vigenere - * \brief Functions for [vigenère cipher](https://en.wikipedia.org/wiki/Vigen%C3%A8re_cipher) algorithm. - */ - namespace vigenere { - namespace { - /** - * This function finds character for given value (i.e.A-Z) - * @param x value for which we want character - * @return corresponding character for perticular value - */ - inline char get_char(const int x) { - // By adding 65 we are scaling 0-25 to 65-90. - // Which are in fact ASCII values of A-Z. - return char(x + 65); - } - /** - * This function finds value for given character (i.e.0-25) - * @param c character for which we want value - * @return returns corresponding value for perticular character - */ - inline int get_value(const char c) { - // A-Z have ASCII values in range 65-90. - // Hence subtracting 65 will scale them to 0-25. - return int(c - 65); - } - } // Unnamed namespace - /** - * Encrypt given text using vigenere cipher. - * @param text text to be encrypted - * @param key to be used for encryption - * @return new encrypted text - */ - std::string encrypt (const std::string &text, const std::string &key) { - std::string encrypted_text = ""; // Empty string to store encrypted text - // Going through each character of text and key - // Note that key is visited in circular way hence j = (j + 1) % |key| - for(size_t i = 0, j = 0; i < text.length(); i++, j = (j + 1) % key.length()) { - int place_value_text = get_value(text[i]); // Getting value of character in text - int place_value_key = get_value(key[j]); // Getting value of character in key - place_value_text = (place_value_text + place_value_key) % 26; // Applying encryption - char encrypted_char = get_char(place_value_text); // Getting new character from encrypted value - encrypted_text += encrypted_char; // Appending encrypted character - } - return encrypted_text; // Returning encrypted text - } - /** - * Decrypt given text using vigenere cipher. - * @param text text to be decrypted - * @param key key to be used for decryption - * @return new decrypted text - */ - std::string decrypt (const std::string &text, const std::string &key) { - // Going through each character of text and key - // Note that key is visited in circular way hence j = (j + 1) % |key| - std::string decrypted_text = ""; // Empty string to store decrypted text - for(size_t i = 0, j = 0; i < text.length(); i++, j = (j + 1) % key.length()) { - int place_value_text = get_value(text[i]); // Getting value of character in text - int place_value_key = get_value(key[j]); // Getting value of character in key - place_value_text = (place_value_text - place_value_key + 26) % 26; // Applying decryption - char decrypted_char = get_char(place_value_text); // Getting new character from decrypted value - decrypted_text += decrypted_char; // Appending decrypted character - } - return decrypted_text; // Returning decrypted text - } - } // namespace vigenere +namespace vigenere { + +namespace { +// 字符转数字 A->0, B->1 ... Z->25 +inline int get_value(const char c) { + return static_cast(c - 'A'); +} + +// 数字转回字符 0->A ... 25->Z +inline char get_char(const int x) { + return static_cast(x + 'A'); +} +} // anonymous namespace + +// 加密 +std::string encrypt(const std::string& text, const std::string& key) { + std::string encrypted; + for (size_t i = 0, j = 0; i < text.size(); ++i, j = (j + 1) % key.size()) { + int t = get_value(text[i]); + int k = get_value(key[j]); + encrypted += get_char((t + k) % 26); + } + return encrypted; +} + +// 解密 +std::string decrypt(const std::string& text, const std::string& key) { + std::string decrypted; + for (size_t i = 0, j = 0; i < text.size(); ++i, j = (j + 1) % key.size()) { + int t = get_value(text[i]); + int k = get_value(key[j]); + decrypted += get_char((t - k + 26) % 26); + } + return decrypted; +} + +} // namespace vigenere } // namespace ciphers -/** - * Function to test above algorithm - */ +// 测试 void test() { - // Test 1 + // 测试 1 std::string text1 = "NIKOLATESLA"; - std::string encrypted1 = ciphers::vigenere::encrypt(text1, "TESLA"); - std::string decrypted1 = ciphers::vigenere::decrypt(encrypted1, "TESLA"); - assert(text1 == decrypted1); - std::cout << "Original text : " << text1; - std::cout << " , Encrypted text (with key = TESLA) : " << encrypted1; - std::cout << " , Decrypted text : "<< decrypted1 << std::endl; - // Test 2 + std::string key1 = "TESLA"; + std::string enc1 = ciphers::vigenere::encrypt(text1, key1); + std::string dec1 = ciphers::vigenere::decrypt(enc1, key1); + assert(text1 == dec1); + + std::cout << "原始文本: " << text1 << '\n'; + std::cout << "加密结果: " << enc1 << '\n'; + std::cout << "解密结果: " << dec1 << "\n\n"; + + // 测试 2 std::string text2 = "GOOGLEIT"; - std::string encrypted2 = ciphers::vigenere::encrypt(text2, "REALLY"); - std::string decrypted2 = ciphers::vigenere::decrypt(encrypted2, "REALLY"); - assert(text2 == decrypted2); - std::cout << "Original text : " << text2; - std::cout << " , Encrypted text (with key = REALLY) : " << encrypted2; - std::cout << " , Decrypted text : "<< decrypted2 << std::endl; + std::string key2 = "REALLY"; + std::string enc2 = ciphers::vigenere::encrypt(text2, key2); + std::string dec2 = ciphers::vigenere::decrypt(enc2, key2); + assert(text2 == dec2); + + std::cout << "原始文本: " << text2 << '\n'; + std::cout << "加密结果: " << enc2 << '\n'; + std::cout << "解密结果: " << dec2 << '\n'; } -/** Driver Code */ int main() { - // Testing test(); return 0; } diff --git a/ciphers/xor_cipher.cpp b/ciphers/xor_cipher.cpp index 18cbdd61f6..3865aa098c 100644 --- a/ciphers/xor_cipher.cpp +++ b/ciphers/xor_cipher.cpp @@ -1,99 +1,56 @@ /** * @file xor_cipher.cpp - * @brief Implementation of [XOR cipher](https://en.wikipedia.org/wiki/XOR_cipher) algorithm. - * - * @details - * In cryptography, the simple XOR cipher is a type of additive cipher, an encryption - * algorithm that operates according to the principles: - * - * * \f$A {\oplus} 0 = A\f$ - * * \f$A {\oplus} A = 0\f$ - * * \f$ (A {\oplus} B) {\oplus} C = A {\oplus} (B {\oplus} C)\f$ - * * \f$ (B {\oplus} A) {\oplus} B = B {\oplus} 0 = B \f$ - * - * - * where \f$\oplus\f$ symbol denotes the exclusive disjunction (XOR) operation. - * This operation is sometimes called modulus 2 addition (or subtraction, which is identical). - * With this logic, a string of text can be encrypted by applying the bitwise XOR operator to - * every character using a given key. To decrypt the output, merely reapplying the XOR function - * with the key will remove the cipher. - * - * ### Algorithm - * Choose the key for encryption and apply XOR operation to each character of a string. - * Reapplying XOR operation to each character of encrypted string will give original string back. - * - * \note This program implements XOR Cipher for string with ASCII characters. - * - * @author [Deep Raval](https://github.com/imdeep2905) + * @brief XOR cipher 加密解密算法 */ + #include #include #include -/** \namespace ciphers - * \brief Algorithms for encryption and decryption - */ namespace ciphers { - /** \namespace XOR - * \brief Functions for [XOR cipher](https://en.wikipedia.org/wiki/XOR_cipher) algorithm. - */ - namespace XOR { - /** - * Encrypt given text using XOR cipher. - * @param text text to be encrypted - * @param key to be used for encyption - * @return new encrypted text - */ - std::string encrypt (const std::string &text, const int &key) { - std::string encrypted_text = ""; // Empty string to store encrypted text - for (auto &c: text) { // Going through each character - char encrypted_char = char(c ^ key); // Applying encyption - encrypted_text += encrypted_char; // Appending encrypted character - } - return encrypted_text; // Returning encrypted text - } - /** - * Decrypt given text using XOR cipher. - * @param text text to be encrypted - * @param key to be used for decryption - * @return new decrypted text - */ - std::string decrypt (const std::string &text, const int &key) { - std::string decrypted_text = ""; // Empty string to store decrypted text - for (auto &c : text) { // Going through each character - char decrypted_char = char(c ^ key); // Applying decryption - decrypted_text += decrypted_char; // Appending decrypted character - } - return decrypted_text; // Returning decrypted text - } - } // namespace XOR +namespace XOR { + +// 加密:对每个字符与 key 异或 +std::string encrypt(const std::string &text, const int &key) { + std::string encrypted_text; + for (char c : text) { + encrypted_text += char(c ^ key); + } + return encrypted_text; +} + +// 解密:与加密完全相同(异或两次恢复原文) +std::string decrypt(const std::string &text, const int &key) { + return encrypt(text, key); +} + +} // namespace XOR } // namespace ciphers -/** - * Function to test above algorithm - */ +// 测试函数 void test() { - // Test 1 + // 测试 1 std::string text1 = "Whipalsh! : Do watch this movie..."; std::string encrypted1 = ciphers::XOR::encrypt(text1, 17); std::string decrypted1 = ciphers::XOR::decrypt(encrypted1, 17); assert(text1 == decrypted1); - std::cout << "Original text : " << text1; - std::cout << " , Encrypted text (with key = 17) : " << encrypted1; - std::cout << " , Decrypted text : "<< decrypted1 << std::endl; - // Test 2 + + std::cout << "原始文本: " << text1 << std::endl; + std::cout << "加密文本: " << encrypted1 << std::endl; + std::cout << "解密文本: " << decrypted1 << std::endl << std::endl; + + // 测试 2 std::string text2 = "->Valar M0rghulis<-"; std::string encrypted2 = ciphers::XOR::encrypt(text2, 29); std::string decrypted2 = ciphers::XOR::decrypt(encrypted2, 29); assert(text2 == decrypted2); - std::cout << "Original text : " << text2; - std::cout << " , Encrypted text (with key = 29) : " << encrypted2; - std::cout << " , Decrypted text : "<< decrypted2 << std::endl; + + std::cout << "原始文本: " << text2 << std::endl; + std::cout << "加密文本: " << encrypted2 << std::endl; + std::cout << "解密文本: " << decrypted2 << std::endl; } -/** Driver Code */ int main() { - // Testing test(); return 0; }