jsoncons 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (155) hide show
  1. checksums.yaml +7 -0
  2. data/ext/jsoncons/extconf.rb +43 -0
  3. data/ext/jsoncons/jsoncons.cpp +161 -0
  4. data/ext/jsoncons/jsoncons.h +10 -0
  5. data/jsoncons.gemspec +44 -0
  6. data/lib/jsoncons/jsoncons/examples/input/address-book.json +13 -0
  7. data/lib/jsoncons/jsoncons/examples/input/books.json +28 -0
  8. data/lib/jsoncons/jsoncons/examples/input/countries.json +7 -0
  9. data/lib/jsoncons/jsoncons/examples/input/employees.json +30 -0
  10. data/lib/jsoncons/jsoncons/examples/input/jsonschema/name.json +15 -0
  11. data/lib/jsoncons/jsoncons/examples/input/multiple-json-objects.json +3 -0
  12. data/lib/jsoncons/jsoncons/examples/input/sales.csv +6 -0
  13. data/lib/jsoncons/jsoncons/examples/input/store.json +28 -0
  14. data/lib/jsoncons/jsoncons/examples/input/tasks.csv +6 -0
  15. data/lib/jsoncons/jsoncons/include/jsoncons/allocator_holder.hpp +38 -0
  16. data/lib/jsoncons/jsoncons/include/jsoncons/basic_json.hpp +5905 -0
  17. data/lib/jsoncons/jsoncons/include/jsoncons/bigint.hpp +1611 -0
  18. data/lib/jsoncons/jsoncons/include/jsoncons/byte_string.hpp +820 -0
  19. data/lib/jsoncons/jsoncons/include/jsoncons/config/binary_config.hpp +226 -0
  20. data/lib/jsoncons/jsoncons/include/jsoncons/config/compiler_support.hpp +375 -0
  21. data/lib/jsoncons/jsoncons/include/jsoncons/config/jsoncons_config.hpp +309 -0
  22. data/lib/jsoncons/jsoncons/include/jsoncons/config/version.hpp +40 -0
  23. data/lib/jsoncons/jsoncons/include/jsoncons/conv_error.hpp +218 -0
  24. data/lib/jsoncons/jsoncons/include/jsoncons/decode_json.hpp +209 -0
  25. data/lib/jsoncons/jsoncons/include/jsoncons/decode_traits.hpp +651 -0
  26. data/lib/jsoncons/jsoncons/include/jsoncons/detail/endian.hpp +44 -0
  27. data/lib/jsoncons/jsoncons/include/jsoncons/detail/grisu3.hpp +312 -0
  28. data/lib/jsoncons/jsoncons/include/jsoncons/detail/optional.hpp +483 -0
  29. data/lib/jsoncons/jsoncons/include/jsoncons/detail/parse_number.hpp +1133 -0
  30. data/lib/jsoncons/jsoncons/include/jsoncons/detail/span.hpp +188 -0
  31. data/lib/jsoncons/jsoncons/include/jsoncons/detail/string_view.hpp +537 -0
  32. data/lib/jsoncons/jsoncons/include/jsoncons/detail/string_wrapper.hpp +370 -0
  33. data/lib/jsoncons/jsoncons/include/jsoncons/detail/write_number.hpp +567 -0
  34. data/lib/jsoncons/jsoncons/include/jsoncons/encode_json.hpp +315 -0
  35. data/lib/jsoncons/jsoncons/include/jsoncons/encode_traits.hpp +378 -0
  36. data/lib/jsoncons/jsoncons/include/jsoncons/json.hpp +18 -0
  37. data/lib/jsoncons/jsoncons/include/jsoncons/json_array.hpp +324 -0
  38. data/lib/jsoncons/jsoncons/include/jsoncons/json_content_handler.hpp +12 -0
  39. data/lib/jsoncons/jsoncons/include/jsoncons/json_cursor.hpp +448 -0
  40. data/lib/jsoncons/jsoncons/include/jsoncons/json_decoder.hpp +420 -0
  41. data/lib/jsoncons/jsoncons/include/jsoncons/json_encoder.hpp +1587 -0
  42. data/lib/jsoncons/jsoncons/include/jsoncons/json_error.hpp +156 -0
  43. data/lib/jsoncons/jsoncons/include/jsoncons/json_exception.hpp +241 -0
  44. data/lib/jsoncons/jsoncons/include/jsoncons/json_filter.hpp +653 -0
  45. data/lib/jsoncons/jsoncons/include/jsoncons/json_fwd.hpp +23 -0
  46. data/lib/jsoncons/jsoncons/include/jsoncons/json_object.hpp +1772 -0
  47. data/lib/jsoncons/jsoncons/include/jsoncons/json_options.hpp +862 -0
  48. data/lib/jsoncons/jsoncons/include/jsoncons/json_parser.hpp +2900 -0
  49. data/lib/jsoncons/jsoncons/include/jsoncons/json_reader.hpp +731 -0
  50. data/lib/jsoncons/jsoncons/include/jsoncons/json_traits_macros.hpp +1072 -0
  51. data/lib/jsoncons/jsoncons/include/jsoncons/json_traits_macros_deprecated.hpp +144 -0
  52. data/lib/jsoncons/jsoncons/include/jsoncons/json_type.hpp +206 -0
  53. data/lib/jsoncons/jsoncons/include/jsoncons/json_type_traits.hpp +1830 -0
  54. data/lib/jsoncons/jsoncons/include/jsoncons/json_visitor.hpp +1560 -0
  55. data/lib/jsoncons/jsoncons/include/jsoncons/json_visitor2.hpp +2079 -0
  56. data/lib/jsoncons/jsoncons/include/jsoncons/pretty_print.hpp +89 -0
  57. data/lib/jsoncons/jsoncons/include/jsoncons/ser_context.hpp +62 -0
  58. data/lib/jsoncons/jsoncons/include/jsoncons/sink.hpp +289 -0
  59. data/lib/jsoncons/jsoncons/include/jsoncons/source.hpp +777 -0
  60. data/lib/jsoncons/jsoncons/include/jsoncons/source_adaptor.hpp +148 -0
  61. data/lib/jsoncons/jsoncons/include/jsoncons/staj2_cursor.hpp +1189 -0
  62. data/lib/jsoncons/jsoncons/include/jsoncons/staj_cursor.hpp +1254 -0
  63. data/lib/jsoncons/jsoncons/include/jsoncons/staj_iterator.hpp +449 -0
  64. data/lib/jsoncons/jsoncons/include/jsoncons/tag_type.hpp +245 -0
  65. data/lib/jsoncons/jsoncons/include/jsoncons/text_source_adaptor.hpp +144 -0
  66. data/lib/jsoncons/jsoncons/include/jsoncons/traits_extension.hpp +884 -0
  67. data/lib/jsoncons/jsoncons/include/jsoncons/typed_array_view.hpp +250 -0
  68. data/lib/jsoncons/jsoncons/include/jsoncons/unicode_traits.hpp +1330 -0
  69. data/lib/jsoncons/jsoncons/include/jsoncons/uri.hpp +635 -0
  70. data/lib/jsoncons/jsoncons/include/jsoncons/value_converter.hpp +340 -0
  71. data/lib/jsoncons/jsoncons/include/jsoncons_ext/bson/bson.hpp +23 -0
  72. data/lib/jsoncons/jsoncons/include/jsoncons_ext/bson/bson_cursor.hpp +320 -0
  73. data/lib/jsoncons/jsoncons/include/jsoncons_ext/bson/bson_decimal128.hpp +865 -0
  74. data/lib/jsoncons/jsoncons/include/jsoncons_ext/bson/bson_encoder.hpp +585 -0
  75. data/lib/jsoncons/jsoncons/include/jsoncons_ext/bson/bson_error.hpp +103 -0
  76. data/lib/jsoncons/jsoncons/include/jsoncons_ext/bson/bson_oid.hpp +245 -0
  77. data/lib/jsoncons/jsoncons/include/jsoncons_ext/bson/bson_options.hpp +75 -0
  78. data/lib/jsoncons/jsoncons/include/jsoncons_ext/bson/bson_parser.hpp +645 -0
  79. data/lib/jsoncons/jsoncons/include/jsoncons_ext/bson/bson_reader.hpp +92 -0
  80. data/lib/jsoncons/jsoncons/include/jsoncons_ext/bson/bson_type.hpp +44 -0
  81. data/lib/jsoncons/jsoncons/include/jsoncons_ext/bson/decode_bson.hpp +201 -0
  82. data/lib/jsoncons/jsoncons/include/jsoncons_ext/bson/encode_bson.hpp +144 -0
  83. data/lib/jsoncons/jsoncons/include/jsoncons_ext/cbor/cbor.hpp +26 -0
  84. data/lib/jsoncons/jsoncons/include/jsoncons_ext/cbor/cbor_cursor.hpp +351 -0
  85. data/lib/jsoncons/jsoncons/include/jsoncons_ext/cbor/cbor_cursor2.hpp +265 -0
  86. data/lib/jsoncons/jsoncons/include/jsoncons_ext/cbor/cbor_detail.hpp +93 -0
  87. data/lib/jsoncons/jsoncons/include/jsoncons_ext/cbor/cbor_encoder.hpp +1766 -0
  88. data/lib/jsoncons/jsoncons/include/jsoncons_ext/cbor/cbor_error.hpp +105 -0
  89. data/lib/jsoncons/jsoncons/include/jsoncons_ext/cbor/cbor_options.hpp +113 -0
  90. data/lib/jsoncons/jsoncons/include/jsoncons_ext/cbor/cbor_parser.hpp +1942 -0
  91. data/lib/jsoncons/jsoncons/include/jsoncons_ext/cbor/cbor_reader.hpp +116 -0
  92. data/lib/jsoncons/jsoncons/include/jsoncons_ext/cbor/decode_cbor.hpp +203 -0
  93. data/lib/jsoncons/jsoncons/include/jsoncons_ext/cbor/encode_cbor.hpp +151 -0
  94. data/lib/jsoncons/jsoncons/include/jsoncons_ext/csv/csv.hpp +17 -0
  95. data/lib/jsoncons/jsoncons/include/jsoncons_ext/csv/csv_cursor.hpp +358 -0
  96. data/lib/jsoncons/jsoncons/include/jsoncons_ext/csv/csv_encoder.hpp +954 -0
  97. data/lib/jsoncons/jsoncons/include/jsoncons_ext/csv/csv_error.hpp +85 -0
  98. data/lib/jsoncons/jsoncons/include/jsoncons_ext/csv/csv_options.hpp +973 -0
  99. data/lib/jsoncons/jsoncons/include/jsoncons_ext/csv/csv_parser.hpp +2099 -0
  100. data/lib/jsoncons/jsoncons/include/jsoncons_ext/csv/csv_reader.hpp +348 -0
  101. data/lib/jsoncons/jsoncons/include/jsoncons_ext/csv/csv_serializer.hpp +12 -0
  102. data/lib/jsoncons/jsoncons/include/jsoncons_ext/csv/decode_csv.hpp +208 -0
  103. data/lib/jsoncons/jsoncons/include/jsoncons_ext/csv/encode_csv.hpp +122 -0
  104. data/lib/jsoncons/jsoncons/include/jsoncons_ext/jmespath/jmespath.hpp +5215 -0
  105. data/lib/jsoncons/jsoncons/include/jsoncons_ext/jmespath/jmespath_error.hpp +215 -0
  106. data/lib/jsoncons/jsoncons/include/jsoncons_ext/jsonpatch/jsonpatch.hpp +579 -0
  107. data/lib/jsoncons/jsoncons/include/jsoncons_ext/jsonpatch/jsonpatch_error.hpp +121 -0
  108. data/lib/jsoncons/jsoncons/include/jsoncons_ext/jsonpath/expression.hpp +3329 -0
  109. data/lib/jsoncons/jsoncons/include/jsoncons_ext/jsonpath/flatten.hpp +432 -0
  110. data/lib/jsoncons/jsoncons/include/jsoncons_ext/jsonpath/json_location.hpp +445 -0
  111. data/lib/jsoncons/jsoncons/include/jsoncons_ext/jsonpath/json_query.hpp +115 -0
  112. data/lib/jsoncons/jsoncons/include/jsoncons_ext/jsonpath/jsonpath.hpp +13 -0
  113. data/lib/jsoncons/jsoncons/include/jsoncons_ext/jsonpath/jsonpath_error.hpp +240 -0
  114. data/lib/jsoncons/jsoncons/include/jsoncons_ext/jsonpath/jsonpath_expression.hpp +2612 -0
  115. data/lib/jsoncons/jsoncons/include/jsoncons_ext/jsonpath/jsonpath_selector.hpp +1322 -0
  116. data/lib/jsoncons/jsoncons/include/jsoncons_ext/jsonpointer/jsonpointer.hpp +1577 -0
  117. data/lib/jsoncons/jsoncons/include/jsoncons_ext/jsonpointer/jsonpointer_error.hpp +119 -0
  118. data/lib/jsoncons/jsoncons/include/jsoncons_ext/jsonschema/format_validator.hpp +968 -0
  119. data/lib/jsoncons/jsoncons/include/jsoncons_ext/jsonschema/json_validator.hpp +120 -0
  120. data/lib/jsoncons/jsoncons/include/jsoncons_ext/jsonschema/jsonschema.hpp +13 -0
  121. data/lib/jsoncons/jsoncons/include/jsoncons_ext/jsonschema/jsonschema_error.hpp +105 -0
  122. data/lib/jsoncons/jsoncons/include/jsoncons_ext/jsonschema/jsonschema_version.hpp +18 -0
  123. data/lib/jsoncons/jsoncons/include/jsoncons_ext/jsonschema/keyword_validator.hpp +1745 -0
  124. data/lib/jsoncons/jsoncons/include/jsoncons_ext/jsonschema/keyword_validator_factory.hpp +556 -0
  125. data/lib/jsoncons/jsoncons/include/jsoncons_ext/jsonschema/schema_draft7.hpp +198 -0
  126. data/lib/jsoncons/jsoncons/include/jsoncons_ext/jsonschema/schema_location.hpp +200 -0
  127. data/lib/jsoncons/jsoncons/include/jsoncons_ext/jsonschema/schema_version.hpp +35 -0
  128. data/lib/jsoncons/jsoncons/include/jsoncons_ext/jsonschema/subschema.hpp +144 -0
  129. data/lib/jsoncons/jsoncons/include/jsoncons_ext/mergepatch/mergepatch.hpp +103 -0
  130. data/lib/jsoncons/jsoncons/include/jsoncons_ext/msgpack/decode_msgpack.hpp +202 -0
  131. data/lib/jsoncons/jsoncons/include/jsoncons_ext/msgpack/encode_msgpack.hpp +142 -0
  132. data/lib/jsoncons/jsoncons/include/jsoncons_ext/msgpack/msgpack.hpp +24 -0
  133. data/lib/jsoncons/jsoncons/include/jsoncons_ext/msgpack/msgpack_cursor.hpp +343 -0
  134. data/lib/jsoncons/jsoncons/include/jsoncons_ext/msgpack/msgpack_cursor2.hpp +259 -0
  135. data/lib/jsoncons/jsoncons/include/jsoncons_ext/msgpack/msgpack_encoder.hpp +753 -0
  136. data/lib/jsoncons/jsoncons/include/jsoncons_ext/msgpack/msgpack_error.hpp +94 -0
  137. data/lib/jsoncons/jsoncons/include/jsoncons_ext/msgpack/msgpack_options.hpp +74 -0
  138. data/lib/jsoncons/jsoncons/include/jsoncons_ext/msgpack/msgpack_parser.hpp +748 -0
  139. data/lib/jsoncons/jsoncons/include/jsoncons_ext/msgpack/msgpack_reader.hpp +116 -0
  140. data/lib/jsoncons/jsoncons/include/jsoncons_ext/msgpack/msgpack_type.hpp +63 -0
  141. data/lib/jsoncons/jsoncons/include/jsoncons_ext/ubjson/decode_ubjson.hpp +201 -0
  142. data/lib/jsoncons/jsoncons/include/jsoncons_ext/ubjson/encode_ubjson.hpp +142 -0
  143. data/lib/jsoncons/jsoncons/include/jsoncons_ext/ubjson/ubjson.hpp +23 -0
  144. data/lib/jsoncons/jsoncons/include/jsoncons_ext/ubjson/ubjson_cursor.hpp +307 -0
  145. data/lib/jsoncons/jsoncons/include/jsoncons_ext/ubjson/ubjson_encoder.hpp +502 -0
  146. data/lib/jsoncons/jsoncons/include/jsoncons_ext/ubjson/ubjson_error.hpp +100 -0
  147. data/lib/jsoncons/jsoncons/include/jsoncons_ext/ubjson/ubjson_options.hpp +87 -0
  148. data/lib/jsoncons/jsoncons/include/jsoncons_ext/ubjson/ubjson_parser.hpp +880 -0
  149. data/lib/jsoncons/jsoncons/include/jsoncons_ext/ubjson/ubjson_reader.hpp +92 -0
  150. data/lib/jsoncons/jsoncons/include/jsoncons_ext/ubjson/ubjson_type.hpp +43 -0
  151. data/lib/jsoncons/version.rb +5 -0
  152. data/lib/jsoncons.rb +33 -0
  153. data/test/jsoncons_test.rb +108 -0
  154. data/test/test_helper.rb +7 -0
  155. metadata +268 -0
@@ -0,0 +1,1611 @@
1
+ // Copyright 2018 vDaniel Parker
2
+ // Distributed under the Boost license, Version 1.0.
3
+ // (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
4
+
5
+ // See https://github.com/danielaparker/jsoncons for latest version
6
+
7
+ #ifndef JSONCONS_BIGINT_HPP
8
+ #define JSONCONS_BIGINT_HPP
9
+
10
+ #include <cstdint>
11
+ #include <vector> // std::vector
12
+ #include <iostream>
13
+ #include <climits>
14
+ #include <cassert> // assert
15
+ #include <limits> // std::numeric_limits
16
+ #include <algorithm> // std::max, std::min, std::reverse
17
+ #include <string> // std::string
18
+ #include <cstring> // std::memcpy
19
+ #include <cmath> // std::fmod
20
+ #include <memory> // std::allocator
21
+ #include <initializer_list> // std::initializer_list
22
+ #include <type_traits> // std::enable_if
23
+ #include <jsoncons/config/jsoncons_config.hpp>
24
+
25
+ namespace jsoncons {
26
+
27
+ /*
28
+ This implementation is based on Chapter 2 and Appendix A of
29
+ Ammeraal, L. (1996) Algorithms and Data Structures in C++,
30
+ Chichester: John Wiley.
31
+
32
+ */
33
+
34
+
35
+ namespace detail {
36
+
37
+ template <class Allocator>
38
+ class basic_bigint_base
39
+ {
40
+ public:
41
+ using allocator_type = Allocator;
42
+ using basic_type_allocator_type = typename std::allocator_traits<allocator_type>:: template rebind_alloc<uint64_t>;
43
+
44
+ private:
45
+ basic_type_allocator_type alloc_;
46
+ public:
47
+ using allocator_traits_type = std::allocator_traits<allocator_type>;
48
+ using stored_allocator_type = allocator_type;
49
+ using pointer = typename allocator_traits_type::pointer;
50
+ using value_type = typename allocator_traits_type::value_type;
51
+ using size_type = typename allocator_traits_type::size_type;
52
+ using pointer_traits = std::pointer_traits<pointer>;
53
+
54
+ basic_bigint_base()
55
+ : alloc_()
56
+ {
57
+ }
58
+ explicit basic_bigint_base(const allocator_type& alloc)
59
+ : alloc_(basic_type_allocator_type(alloc))
60
+ {
61
+ }
62
+
63
+ basic_type_allocator_type get_allocator() const
64
+ {
65
+ return alloc_;
66
+ }
67
+ };
68
+
69
+ } // namespace detail
70
+
71
+ template <class Allocator = std::allocator<uint64_t>>
72
+ class basic_bigint : protected detail::basic_bigint_base<Allocator>
73
+ {
74
+ using base_t = detail::basic_bigint_base<Allocator>;
75
+
76
+ public:
77
+
78
+ using size_type = typename base_t::size_type;
79
+ using value_type = typename base_t::value_type;
80
+ using base_t::get_allocator;
81
+ using bigint_type = basic_bigint<Allocator>;
82
+
83
+ static constexpr uint64_t max_basic_type = (std::numeric_limits<uint64_t>::max)();
84
+ static constexpr uint64_t basic_type_bits = sizeof(uint64_t) * 8; // Number of bits
85
+ static constexpr uint64_t basic_type_halfBits = basic_type_bits/2;
86
+
87
+ static constexpr uint16_t word_length = 4; // Use multiples of word_length words
88
+ static constexpr uint64_t r_mask = (uint64_t(1) << basic_type_halfBits) - 1;
89
+ static constexpr uint64_t l_mask = max_basic_type - r_mask;
90
+ static constexpr uint64_t l_bit = max_basic_type - (max_basic_type >> 1);
91
+
92
+ private:
93
+
94
+ struct common_storage
95
+ {
96
+ uint8_t is_dynamic_:1;
97
+ uint8_t is_negative_:1;
98
+ size_type length_;
99
+ };
100
+
101
+ struct short_storage
102
+ {
103
+ uint8_t is_dynamic_:1;
104
+ uint8_t is_negative_:1;
105
+ size_type length_;
106
+ uint64_t values_[2];
107
+
108
+ short_storage()
109
+ : is_dynamic_(false),
110
+ is_negative_(false),
111
+ length_(0),
112
+ values_{0,0}
113
+ {
114
+ }
115
+
116
+ template <class T>
117
+ short_storage(T n,
118
+ typename std::enable_if<std::is_integral<T>::value &&
119
+ sizeof(T) <= sizeof(int64_t) &&
120
+ std::is_signed<T>::value>::type* = 0)
121
+ : is_dynamic_(false),
122
+ is_negative_(n < 0),
123
+ length_(n == 0 ? 0 : 1)
124
+ {
125
+ values_[0] = n < 0 ? (uint64_t(0)-static_cast<uint64_t>(n)) : static_cast<uint64_t>(n);
126
+ values_[1] = 0;
127
+ }
128
+
129
+ template <class T>
130
+ short_storage(T n,
131
+ typename std::enable_if<std::is_integral<T>::value &&
132
+ sizeof(T) <= sizeof(int64_t) &&
133
+ !std::is_signed<T>::value>::type* = 0)
134
+ : is_dynamic_(false),
135
+ is_negative_(false),
136
+ length_(n == 0 ? 0 : 1)
137
+ {
138
+ values_[0] = n;
139
+ values_[1] = 0;
140
+ }
141
+
142
+ template <class T>
143
+ short_storage(T n,
144
+ typename std::enable_if<std::is_integral<T>::value &&
145
+ sizeof(int64_t) < sizeof(T) &&
146
+ std::is_signed<T>::value>::type* = 0)
147
+ : is_dynamic_(false),
148
+ is_negative_(n < 0),
149
+ length_(n == 0 ? 0 : 2)
150
+ {
151
+ using unsigned_type = typename std::make_unsigned<T>::type;
152
+
153
+ auto u = n < 0 ? (unsigned_type(0)-static_cast<unsigned_type>(n)) : static_cast<unsigned_type>(n);
154
+ values_[0] = uint64_t(u & max_basic_type);;
155
+ u >>= basic_type_bits;
156
+ values_[1] = uint64_t(u & max_basic_type);;
157
+ }
158
+
159
+ template <class T>
160
+ short_storage(T n,
161
+ typename std::enable_if<std::is_integral<T>::value &&
162
+ sizeof(int64_t) < sizeof(T) &&
163
+ !std::is_signed<T>::value>::type* = 0)
164
+ : is_dynamic_(false),
165
+ is_negative_(false),
166
+ length_(n == 0 ? 0 : 2)
167
+ {
168
+ values_[0] = uint64_t(n & max_basic_type);;
169
+ n >>= basic_type_bits;
170
+ values_[1] = uint64_t(n & max_basic_type);;
171
+ }
172
+
173
+ short_storage(const short_storage& stor)
174
+ : is_dynamic_(false),
175
+ is_negative_(stor.is_negative_),
176
+ length_(stor.length_)
177
+ {
178
+ values_[0] = stor.values_[0];
179
+ values_[1] = stor.values_[1];
180
+ }
181
+
182
+ short_storage& operator=(const short_storage& stor) = delete;
183
+ };
184
+
185
+ struct dynamic_storage
186
+ {
187
+ using real_allocator_type = typename std::allocator_traits<Allocator>:: template rebind_alloc<uint64_t>;
188
+ using pointer = typename std::allocator_traits<real_allocator_type>::pointer;
189
+
190
+ uint8_t is_dynamic_:1;
191
+ uint8_t is_negative_:1;
192
+ size_type length_;
193
+ size_type capacity_;
194
+ pointer data_;
195
+
196
+ dynamic_storage()
197
+ : is_dynamic_(true),
198
+ is_negative_(false),
199
+ length_(0),
200
+ capacity_(0),
201
+ data_(nullptr)
202
+ {
203
+ }
204
+
205
+ dynamic_storage(const dynamic_storage& stor, const real_allocator_type& alloc)
206
+ : is_dynamic_(true),
207
+ is_negative_(stor.is_negative_),
208
+ length_(stor.length_),
209
+ capacity_(0),
210
+ data_(nullptr)
211
+ {
212
+ create(stor.length_, alloc);
213
+ std::memcpy(data_, stor.data_, stor.length_*sizeof(uint64_t));
214
+ }
215
+
216
+ dynamic_storage(dynamic_storage&& stor) noexcept
217
+ : is_dynamic_(true),
218
+ is_negative_(stor.is_negative_),
219
+ length_(stor.length_),
220
+ capacity_(stor.capacity_),
221
+ data_(stor.data_)
222
+ {
223
+ stor.length_ = 0;
224
+ stor.capacity_ = 0;
225
+ stor.data_ = nullptr;
226
+ }
227
+
228
+ void create(size_type length, real_allocator_type alloc)
229
+ {
230
+ capacity_ = round_up(length);
231
+ data_ = std::allocator_traits<real_allocator_type>::allocate(alloc, capacity_);
232
+ JSONCONS_TRY
233
+ {
234
+ std::allocator_traits<real_allocator_type>::construct(alloc, traits_extension::to_plain_pointer(data_));
235
+ }
236
+ JSONCONS_CATCH(...)
237
+ {
238
+ std::allocator_traits<real_allocator_type>::deallocate(alloc, data_, capacity_);
239
+ JSONCONS_RETHROW;
240
+ }
241
+ }
242
+
243
+ void destroy(const real_allocator_type& a) noexcept
244
+ {
245
+ if (data_ != nullptr)
246
+ {
247
+ real_allocator_type alloc(a);
248
+
249
+ std::allocator_traits<real_allocator_type>::destroy(alloc, traits_extension::to_plain_pointer(data_));
250
+ std::allocator_traits<real_allocator_type>::deallocate(alloc, data_,capacity_);
251
+ }
252
+ }
253
+
254
+ void reserve(size_type n, const real_allocator_type& a)
255
+ {
256
+ real_allocator_type alloc(a);
257
+
258
+ size_type capacity_new = round_up(n);
259
+ uint64_t* data_old = data_;
260
+ data_ = std::allocator_traits<real_allocator_type>::allocate(alloc, capacity_new);
261
+ if (length_ > 0)
262
+ {
263
+ std::memcpy( data_, data_old, length_*sizeof(uint64_t));
264
+ }
265
+ if (capacity_ > 0 && data_ != nullptr)
266
+ {
267
+ std::allocator_traits<real_allocator_type>::deallocate(alloc, data_old, capacity_);
268
+ }
269
+ capacity_ = capacity_new;
270
+ }
271
+
272
+ // Find suitable new block size
273
+ constexpr size_type round_up(size_type i) const
274
+ {
275
+ return (i/word_length + 1) * word_length;
276
+ }
277
+ };
278
+
279
+ union
280
+ {
281
+ common_storage common_stor_;
282
+ short_storage short_stor_;
283
+ dynamic_storage dynamic_stor_;
284
+ };
285
+
286
+ public:
287
+ basic_bigint()
288
+ {
289
+ ::new (&short_stor_) short_storage();
290
+ }
291
+
292
+ explicit basic_bigint(const Allocator& alloc)
293
+ : base_t(alloc)
294
+ {
295
+ ::new (&short_stor_) short_storage();
296
+ }
297
+
298
+
299
+ basic_bigint(const basic_bigint<Allocator>& n)
300
+ : base_t(n.get_allocator())
301
+ {
302
+ if (!n.is_dynamic())
303
+ {
304
+ ::new (&short_stor_) short_storage(n.short_stor_);
305
+ }
306
+ else
307
+ {
308
+ ::new (&dynamic_stor_) dynamic_storage(n.dynamic_stor_, get_allocator());
309
+ }
310
+ }
311
+
312
+ basic_bigint(basic_bigint<Allocator>&& other) noexcept
313
+ : base_t(other.get_allocator())
314
+ {
315
+ if (!other.is_dynamic())
316
+ {
317
+ ::new (&short_stor_) short_storage(other.short_stor_);
318
+ }
319
+ else
320
+ {
321
+ ::new (&dynamic_stor_) dynamic_storage(std::move(other.dynamic_stor_));
322
+ }
323
+ }
324
+
325
+ template <class Integer>
326
+ basic_bigint(Integer n,
327
+ typename std::enable_if<std::is_integral<Integer>::value>::type* = 0)
328
+ {
329
+ ::new (&short_stor_) short_storage(n);
330
+ }
331
+
332
+ ~basic_bigint() noexcept
333
+ {
334
+ destroy();
335
+ }
336
+
337
+ constexpr bool is_dynamic() const
338
+ {
339
+ return common_stor_.is_dynamic_;
340
+ }
341
+
342
+ constexpr size_type length() const
343
+ {
344
+ return common_stor_.length_;
345
+ }
346
+
347
+ constexpr size_type capacity() const
348
+ {
349
+ return is_dynamic() ? dynamic_stor_.capacity_ : 2;
350
+ }
351
+
352
+ bool is_negative() const
353
+ {
354
+ return common_stor_.is_negative_;
355
+ }
356
+
357
+ void is_negative(bool value)
358
+ {
359
+ common_stor_.is_negative_ = value;
360
+ }
361
+
362
+ constexpr const uint64_t* data() const
363
+ {
364
+ return is_dynamic() ? dynamic_stor_.data_ : short_stor_.values_;
365
+ }
366
+
367
+ uint64_t* data()
368
+ {
369
+ return is_dynamic() ? dynamic_stor_.data_ : short_stor_.values_;
370
+ }
371
+
372
+ template <class CharT>
373
+ static basic_bigint<Allocator> from_string(const std::basic_string<CharT>& s)
374
+ {
375
+ return from_string(s.data(), s.length());
376
+ }
377
+
378
+ template <class CharT>
379
+ static basic_bigint<Allocator> from_string(const CharT* s)
380
+ {
381
+ return from_string(s, std::char_traits<CharT>::length(s));
382
+ }
383
+
384
+ template <class CharT>
385
+ static basic_bigint<Allocator> from_string(const CharT* data, size_type length)
386
+ {
387
+ bool neg;
388
+ if (*data == '-')
389
+ {
390
+ neg = true;
391
+ data++;
392
+ --length;
393
+ }
394
+ else
395
+ {
396
+ neg = false;
397
+ }
398
+
399
+ basic_bigint<Allocator> v = 0;
400
+ for (size_type i = 0; i < length; i++)
401
+ {
402
+ CharT c = data[i];
403
+ switch (c)
404
+ {
405
+ case '0':case '1':case '2':case '3':case '4':case '5':case '6':case '7':case '8': case '9':
406
+ v = (v * 10) + (uint64_t)(c - '0');
407
+ break;
408
+ default:
409
+ JSONCONS_THROW(std::runtime_error(std::string("Invalid digit ") + "\'" + (char)c + "\'"));
410
+ }
411
+ }
412
+
413
+ if (neg)
414
+ {
415
+ v.common_stor_.is_negative_ = true;
416
+ }
417
+
418
+ return v;
419
+ }
420
+
421
+ template <class CharT>
422
+ static basic_bigint<Allocator> from_string_radix(const CharT* data, size_type length, uint8_t radix)
423
+ {
424
+ if (!(radix >= 2 && radix <= 16))
425
+ {
426
+ JSONCONS_THROW(std::runtime_error("Unsupported radix"));
427
+ }
428
+
429
+ bool neg;
430
+ if (*data == '-')
431
+ {
432
+ neg = true;
433
+ data++;
434
+ --length;
435
+ }
436
+ else
437
+ {
438
+ neg = false;
439
+ }
440
+
441
+ basic_bigint<Allocator> v = 0;
442
+ for (size_type i = 0; i < length; i++)
443
+ {
444
+ CharT c = data[i];
445
+ uint64_t d;
446
+ switch (c)
447
+ {
448
+ case '0':case '1':case '2':case '3':case '4':case '5':case '6':case '7':case '8': case '9':
449
+ d = (uint64_t)(c - '0');
450
+ break;
451
+ case 'a':case 'b':case 'c':case 'd':case 'e':case 'f':
452
+ d = (uint64_t)(c - ('a' - 10));
453
+ break;
454
+ case 'A':case 'B':case 'C':case 'D':case 'E':case 'F':
455
+ d = (uint64_t)(c - ('A' - 10));
456
+ break;
457
+ default:
458
+ JSONCONS_THROW(std::runtime_error(std::string("Invalid digit in radix ") + std::to_string(radix) + ": \'" + (char)c + "\'"));
459
+ }
460
+ if (d >= radix)
461
+ {
462
+ JSONCONS_THROW(std::runtime_error(std::string("Invalid digit in radix ") + std::to_string(radix) + ": \'" + (char)c + "\'"));
463
+ }
464
+ v = (v * radix) + d;
465
+ }
466
+
467
+ if ( neg )
468
+ {
469
+ v.common_stor_.is_negative_ = true;
470
+ }
471
+ return v;
472
+ }
473
+
474
+ static basic_bigint from_bytes_be(int signum, const uint8_t* str, std::size_t n)
475
+ {
476
+ static const double radix_log2 = std::log2(next_power_of_two(256));
477
+ // Estimate how big the result will be, so we can pre-allocate it.
478
+ double bits = radix_log2 * n;
479
+ double big_digits = std::ceil(bits / 64.0);
480
+ //std::cout << "ESTIMATED: " << big_digits << "\n";
481
+
482
+ bigint_type v = 0;
483
+ v.reserve(static_cast<std::size_t>(big_digits));
484
+
485
+ if (n > 0)
486
+ {
487
+ for (std::size_t i = 0; i < n; i++)
488
+ {
489
+ v = (v * 256) + (uint64_t)(str[i]);
490
+ }
491
+ }
492
+ //std::cout << "ACTUAL: " << v.length() << "\n";
493
+
494
+ if (signum < 0)
495
+ {
496
+ v.common_stor_.is_negative_ = true;
497
+ }
498
+
499
+ return v;
500
+ }
501
+
502
+ uint64_t* begin() { return is_dynamic() ? dynamic_stor_.data_ : short_stor_.values_; }
503
+ const uint64_t* begin() const { return is_dynamic() ? dynamic_stor_.data_ : short_stor_.values_; }
504
+ uint64_t* end() { return begin() + length(); }
505
+ const uint64_t* end() const { return begin() + length(); }
506
+
507
+ void resize(size_type n)
508
+ {
509
+ size_type len_old = common_stor_.length_;
510
+ reserve(n);
511
+ common_stor_.length_ = n;
512
+ if ( common_stor_.length_ > len_old )
513
+ {
514
+ memset( data()+len_old, 0, (common_stor_.length_ - len_old)*sizeof(uint64_t) );
515
+ }
516
+ }
517
+
518
+ void reserve(size_type n)
519
+ {
520
+ if (capacity() < n)
521
+ {
522
+ if (!is_dynamic())
523
+ {
524
+ size_type size = short_stor_.length_;
525
+ size_type is_neg = short_stor_.is_negative_;
526
+ uint64_t values[2] = {short_stor_.values_[0], short_stor_.values_[1]};
527
+
528
+ ::new (&dynamic_stor_) dynamic_storage();
529
+ dynamic_stor_.reserve(n, get_allocator());
530
+ dynamic_stor_.length_ = size;
531
+ dynamic_stor_.is_negative_ = is_neg;
532
+ dynamic_stor_.data_[0] = values[0];
533
+ dynamic_stor_.data_[1] = values[1];
534
+ }
535
+ else
536
+ {
537
+ dynamic_stor_.reserve(n, get_allocator());
538
+ }
539
+ }
540
+ }
541
+
542
+ // operators
543
+
544
+ bool operator!() const
545
+ {
546
+ return length() == 0 ? true : false;
547
+ }
548
+
549
+ basic_bigint operator-() const
550
+ {
551
+ basic_bigint<Allocator> v(*this);
552
+ v.common_stor_.is_negative_ = !v.is_negative();
553
+ return v;
554
+ }
555
+
556
+ basic_bigint& operator=( const basic_bigint<Allocator>& y )
557
+ {
558
+ if ( this != &y )
559
+ {
560
+ resize( y.length() );
561
+ common_stor_.is_negative_ = y.is_negative();
562
+ if ( y.length() > 0 )
563
+ {
564
+ std::memcpy( data(), y.data(), y.length()*sizeof(uint64_t) );
565
+ }
566
+ }
567
+ return *this;
568
+ }
569
+
570
+ basic_bigint& operator+=( const basic_bigint<Allocator>& y )
571
+ {
572
+ if ( is_negative() != y.is_negative() )
573
+ return *this -= -y;
574
+ uint64_t d;
575
+ uint64_t carry = 0;
576
+
577
+ resize( (std::max)(y.length(), length()) + 1 );
578
+
579
+ for (size_type i = 0; i < length(); i++ )
580
+ {
581
+ if ( i >= y.length() && carry == 0 )
582
+ break;
583
+ d = data()[i] + carry;
584
+ carry = d < carry;
585
+ if ( i < y.length() )
586
+ {
587
+ data()[i] = d + y.data()[i];
588
+ if ( data()[i] < d )
589
+ carry = 1;
590
+ }
591
+ else
592
+ data()[i] = d;
593
+ }
594
+ reduce();
595
+ return *this;
596
+ }
597
+
598
+ basic_bigint& operator-=( const basic_bigint<Allocator>& y )
599
+ {
600
+ if ( is_negative() != y.is_negative() )
601
+ return *this += -y;
602
+ if ( (!is_negative() && y > *this) || (is_negative() && y < *this) )
603
+ return *this = -(y - *this);
604
+ uint64_t borrow = 0;
605
+ uint64_t d;
606
+ for (size_type i = 0; i < length(); i++ )
607
+ {
608
+ if ( i >= y.length() && borrow == 0 )
609
+ break;
610
+ d = data()[i] - borrow;
611
+ borrow = d > data()[i];
612
+ if ( i < y.length())
613
+ {
614
+ data()[i] = d - y.data()[i];
615
+ if ( data()[i] > d )
616
+ borrow = 1;
617
+ }
618
+ else
619
+ data()[i] = d;
620
+ }
621
+ reduce();
622
+ return *this;
623
+ }
624
+
625
+ basic_bigint& operator*=( int64_t y )
626
+ {
627
+ *this *= uint64_t(y < 0 ? -y : y);
628
+ if ( y < 0 )
629
+ common_stor_.is_negative_ = !is_negative();
630
+ return *this;
631
+ }
632
+
633
+ basic_bigint& operator*=( uint64_t y )
634
+ {
635
+ size_type len0 = length();
636
+ uint64_t hi;
637
+ uint64_t lo;
638
+ uint64_t dig = data()[0];
639
+ uint64_t carry = 0;
640
+
641
+ resize( length() + 1 );
642
+
643
+ size_type i = 0;
644
+ for (i = 0; i < len0; i++ )
645
+ {
646
+ DDproduct( dig, y, hi, lo );
647
+ data()[i] = lo + carry;
648
+ dig = data()[i+1];
649
+ carry = hi + (data()[i] < lo);
650
+ }
651
+ data()[i] = carry;
652
+ reduce();
653
+ return *this;
654
+ }
655
+
656
+ basic_bigint& operator*=( basic_bigint<Allocator> y )
657
+ {
658
+ if ( length() == 0 || y.length() == 0 )
659
+ return *this = 0;
660
+ bool difSigns = is_negative() != y.is_negative();
661
+ if ( length() + y.length() == 2 ) // length() = y.length() = 1
662
+ {
663
+ uint64_t a = data()[0], b = y.data()[0];
664
+ data()[0] = a * b;
665
+ if ( data()[0] / a != b )
666
+ {
667
+ resize( 2 );
668
+ DDproduct( a, b, data()[1], data()[0] );
669
+ }
670
+ common_stor_.is_negative_ = difSigns;
671
+ return *this;
672
+ }
673
+ if ( length() == 1 ) // && y.length() > 1
674
+ {
675
+ uint64_t digit = data()[0];
676
+ *this = y;
677
+ *this *= digit;
678
+ }
679
+ else
680
+ {
681
+ if ( y.length() == 1 )
682
+ *this *= y.data()[0];
683
+ else
684
+ {
685
+ size_type lenProd = length() + y.length(), jA, jB;
686
+ uint64_t sumHi = 0, sumLo, hi, lo,
687
+ sumLo_old, sumHi_old, carry=0;
688
+ basic_bigint<Allocator> x = *this;
689
+ resize( lenProd ); // Give *this length lenProd
690
+
691
+ for (size_type i = 0; i < lenProd; i++ )
692
+ {
693
+ sumLo = sumHi;
694
+ sumHi = carry;
695
+ carry = 0;
696
+ for ( jA=0; jA < x.length(); jA++ )
697
+ {
698
+ jB = i - jA;
699
+ if ( jB >= 0 && jB < y.length() )
700
+ {
701
+ DDproduct( x.data()[jA], y.data()[jB], hi, lo );
702
+ sumLo_old = sumLo;
703
+ sumHi_old = sumHi;
704
+ sumLo += lo;
705
+ if ( sumLo < sumLo_old )
706
+ sumHi++;
707
+ sumHi += hi;
708
+ carry += (sumHi < sumHi_old);
709
+ }
710
+ }
711
+ data()[i] = sumLo;
712
+ }
713
+ }
714
+ }
715
+ reduce();
716
+ common_stor_.is_negative_ = difSigns;
717
+ return *this;
718
+ }
719
+
720
+ basic_bigint& operator/=( const basic_bigint<Allocator>& divisor )
721
+ {
722
+ basic_bigint<Allocator> r;
723
+ divide( divisor, *this, r, false );
724
+ return *this;
725
+ }
726
+
727
+ basic_bigint& operator%=( const basic_bigint<Allocator>& divisor )
728
+ {
729
+ basic_bigint<Allocator> q;
730
+ divide( divisor, q, *this, true );
731
+ return *this;
732
+ }
733
+
734
+ basic_bigint& operator<<=( uint64_t k )
735
+ {
736
+ size_type q = (size_type)(k / basic_type_bits);
737
+ if ( q ) // Increase common_stor_.length_ by q:
738
+ {
739
+ resize(length() + q);
740
+ for (size_type i = length(); i-- > 0; )
741
+ data()[i] = ( i < q ? 0 : data()[i - q]);
742
+ k %= basic_type_bits;
743
+ }
744
+ if ( k ) // 0 < k < basic_type_bits:
745
+ {
746
+ uint64_t k1 = basic_type_bits - k;
747
+ uint64_t mask = (uint64_t(1) << k) - uint64_t(1);
748
+ resize( length() + 1 );
749
+ for (size_type i = length(); i-- > 0; )
750
+ {
751
+ data()[i] <<= k;
752
+ if ( i > 0 )
753
+ data()[i] |= (data()[i-1] >> k1) & mask;
754
+ }
755
+ }
756
+ reduce();
757
+ return *this;
758
+ }
759
+
760
+ basic_bigint& operator>>=(uint64_t k)
761
+ {
762
+ size_type q = (size_type)(k / basic_type_bits);
763
+ if ( q >= length() )
764
+ {
765
+ resize( 0 );
766
+ return *this;
767
+ }
768
+ if (q > 0)
769
+ {
770
+ memmove( data(), data()+q, (size_type)((length() - q)*sizeof(uint64_t)) );
771
+ resize( length() - q );
772
+ k %= basic_type_bits;
773
+ if ( k == 0 )
774
+ {
775
+ reduce();
776
+ return *this;
777
+ }
778
+ }
779
+
780
+ size_type n = (size_type)(length() - 1);
781
+ int64_t k1 = basic_type_bits - k;
782
+ uint64_t mask = (uint64_t(1) << k) - 1;
783
+ for (size_type i = 0; i <= n; i++)
784
+ {
785
+ data()[i] >>= k;
786
+ if ( i < n )
787
+ data()[i] |= ((data()[i+1] & mask) << k1);
788
+ }
789
+ reduce();
790
+ return *this;
791
+ }
792
+
793
+ basic_bigint& operator++()
794
+ {
795
+ *this += 1;
796
+ return *this;
797
+ }
798
+
799
+ basic_bigint<Allocator> operator++(int)
800
+ {
801
+ basic_bigint<Allocator> old = *this;
802
+ ++(*this);
803
+ return old;
804
+ }
805
+
806
+ basic_bigint<Allocator>& operator--()
807
+ {
808
+ *this -= 1;
809
+ return *this;
810
+ }
811
+
812
+ basic_bigint<Allocator> operator--(int)
813
+ {
814
+ basic_bigint<Allocator> old = *this;
815
+ --(*this);
816
+ return old;
817
+ }
818
+
819
+ basic_bigint& operator|=( const basic_bigint<Allocator>& a )
820
+ {
821
+ if ( length() < a.length() )
822
+ {
823
+ resize( a.length() );
824
+ }
825
+
826
+ const uint64_t* qBegin = a.begin();
827
+ const uint64_t* q = a.end() - 1;
828
+ uint64_t* p = begin() + a.length() - 1;
829
+
830
+ while ( q >= qBegin )
831
+ {
832
+ *p-- |= *q--;
833
+ }
834
+
835
+ reduce();
836
+
837
+ return *this;
838
+ }
839
+
840
+ basic_bigint& operator^=( const basic_bigint<Allocator>& a )
841
+ {
842
+ if ( length() < a.length() )
843
+ {
844
+ resize( a.length() );
845
+ }
846
+
847
+ const uint64_t* qBegin = a.begin();
848
+ const uint64_t* q = a.end() - 1;
849
+ uint64_t* p = begin() + a.length() - 1;
850
+
851
+ while ( q >= qBegin )
852
+ {
853
+ *p-- ^= *q--;
854
+ }
855
+
856
+ reduce();
857
+
858
+ return *this;
859
+ }
860
+
861
+ basic_bigint& operator&=( const basic_bigint<Allocator>& a )
862
+ {
863
+ size_type old_length = length();
864
+
865
+ resize( (std::min)( length(), a.length() ) );
866
+
867
+ const uint64_t* pBegin = begin();
868
+ uint64_t* p = end() - 1;
869
+ const uint64_t* q = a.begin() + length() - 1;
870
+
871
+ while ( p >= pBegin )
872
+ {
873
+ *p-- &= *q--;
874
+ }
875
+
876
+ if ( old_length > length() )
877
+ {
878
+ memset( data() + length(), 0, old_length - length() );
879
+ }
880
+
881
+ reduce();
882
+
883
+ return *this;
884
+ }
885
+
886
+ explicit operator bool() const
887
+ {
888
+ return length() != 0 ? true : false;
889
+ }
890
+
891
+ explicit operator int64_t() const
892
+ {
893
+ int64_t x = 0;
894
+ if ( length() > 0 )
895
+ {
896
+ x = data() [0];
897
+ }
898
+
899
+ return is_negative() ? -x : x;
900
+ }
901
+
902
+ explicit operator uint64_t() const
903
+ {
904
+ uint64_t u = 0;
905
+ if ( length() > 0 )
906
+ {
907
+ u = data() [0];
908
+ }
909
+
910
+ return u;
911
+ }
912
+
913
+ explicit operator double() const
914
+ {
915
+ double x = 0.0;
916
+ double factor = 1.0;
917
+ double values = (double)max_basic_type + 1.0;
918
+
919
+ const uint64_t* p = begin();
920
+ const uint64_t* pEnd = end();
921
+ while ( p < pEnd )
922
+ {
923
+ x += *p*factor;
924
+ factor *= values;
925
+ ++p;
926
+ }
927
+
928
+ return is_negative() ? -x : x;
929
+ }
930
+
931
+ explicit operator long double() const
932
+ {
933
+ long double x = 0.0;
934
+ long double factor = 1.0;
935
+ long double values = (long double)max_basic_type + 1.0;
936
+
937
+ const uint64_t* p = begin();
938
+ const uint64_t* pEnd = end();
939
+ while ( p < pEnd )
940
+ {
941
+ x += *p*factor;
942
+ factor *= values;
943
+ ++p;
944
+ }
945
+
946
+ return is_negative() ? -x : x;
947
+ }
948
+
949
+ template <typename Alloc>
950
+ void write_bytes_be(int& signum, std::vector<uint8_t,Alloc>& data) const
951
+ {
952
+ basic_bigint<Allocator> n(*this);
953
+ signum = (n < 0) ? -1 : (n > 0 ? 1 : 0);
954
+
955
+ basic_bigint<Allocator> divisor(256);
956
+
957
+ while (n >= 256)
958
+ {
959
+ basic_bigint<Allocator> q;
960
+ basic_bigint<Allocator> r;
961
+ n.divide(divisor, q, r, true);
962
+ n = q;
963
+ data.push_back((uint8_t)(uint64_t)r);
964
+ }
965
+ if (n >= 0)
966
+ {
967
+ data.push_back((uint8_t)(uint64_t)n);
968
+ }
969
+ std::reverse(data.begin(),data.end());
970
+ }
971
+
972
+ std::string to_string() const
973
+ {
974
+ std::string s;
975
+ write_string(s);
976
+ return s;
977
+ }
978
+
979
+ template <typename Ch, typename Traits, typename Alloc>
980
+ void write_string(std::basic_string<Ch,Traits,Alloc>& data) const
981
+ {
982
+ basic_bigint<Allocator> v(*this);
983
+
984
+ size_t len = (v.length() * basic_type_bits / 3) + 2;
985
+ data.reserve(len);
986
+
987
+ static uint64_t p10 = 1;
988
+ static uint64_t ip10 = 0;
989
+
990
+ if ( v.length() == 0 )
991
+ {
992
+ data.push_back('0');
993
+ }
994
+ else
995
+ {
996
+ uint64_t r;
997
+ if ( p10 == 1 )
998
+ {
999
+ while ( p10 <= (std::numeric_limits<uint64_t>::max)()/10 )
1000
+ {
1001
+ p10 *= 10;
1002
+ ip10++;
1003
+ }
1004
+ }
1005
+ // p10 is max unsigned power of 10
1006
+ basic_bigint<Allocator> R;
1007
+ basic_bigint<Allocator> LP10 = p10; // LP10 = p10 = ::pow(10, ip10)
1008
+
1009
+ do
1010
+ {
1011
+ v.divide( LP10, v, R, true );
1012
+ r = (R.length() ? R.data()[0] : 0);
1013
+ for ( size_type j=0; j < ip10; j++ )
1014
+ {
1015
+ data.push_back(char(r % 10 + '0'));
1016
+ r /= 10;
1017
+ if ( r + v.length() == 0 )
1018
+ break;
1019
+ }
1020
+ }
1021
+ while ( v.length() );
1022
+ if (is_negative())
1023
+ {
1024
+ data.push_back('-');
1025
+ }
1026
+ std::reverse(data.begin(),data.end());
1027
+ }
1028
+ }
1029
+
1030
+ std::string to_string_hex() const
1031
+ {
1032
+ std::string s;
1033
+ write_string_hex(s);
1034
+ return s;
1035
+ }
1036
+
1037
+ template <typename Ch, typename Traits, typename Alloc>
1038
+ void write_string_hex(std::basic_string<Ch,Traits,Alloc>& data) const
1039
+ {
1040
+ basic_bigint<Allocator> v(*this);
1041
+
1042
+ std::size_t len = (v.length() * basic_bigint<Allocator>::basic_type_bits / 3) + 2;
1043
+ data.reserve(len);
1044
+ // 1/3 > ln(2)/ln(10)
1045
+ static uint64_t p10 = 1;
1046
+ static uint64_t ip10 = 0;
1047
+
1048
+ if ( v.length() == 0 )
1049
+ {
1050
+ data.push_back('0');
1051
+ }
1052
+ else
1053
+ {
1054
+ uint64_t r;
1055
+ if ( p10 == 1 )
1056
+ {
1057
+ while ( p10 <= (std::numeric_limits<uint64_t>::max)()/16 )
1058
+ {
1059
+ p10 *= 16;
1060
+ ip10++;
1061
+ }
1062
+ } // p10 is max unsigned power of 16
1063
+ basic_bigint<Allocator> R;
1064
+ basic_bigint<Allocator> LP10 = p10; // LP10 = p10 = ::pow(16, ip10)
1065
+ do
1066
+ {
1067
+ v.divide( LP10, v, R, true );
1068
+ r = (R.length() ? R.data()[0] : 0);
1069
+ for ( size_type j=0; j < ip10; j++ )
1070
+ {
1071
+ uint8_t c = r % 16;
1072
+ data.push_back((c < 10) ? ('0' + c) : ('A' - 10 + c));
1073
+ r /= 16;
1074
+ if ( r + v.length() == 0 )
1075
+ break;
1076
+ }
1077
+ }
1078
+ while (v.length());
1079
+
1080
+ if (is_negative())
1081
+ {
1082
+ data.push_back('-');
1083
+ }
1084
+ std::reverse(data.begin(),data.end());
1085
+ }
1086
+ }
1087
+
1088
+ // Global Operators
1089
+
1090
+ friend bool operator==( const basic_bigint<Allocator>& x, const basic_bigint<Allocator>& y ) noexcept
1091
+ {
1092
+ return x.compare(y) == 0 ? true : false;
1093
+ }
1094
+
1095
+ friend bool operator==( const basic_bigint<Allocator>& x, int y ) noexcept
1096
+ {
1097
+ return x.compare(y) == 0 ? true : false;
1098
+ }
1099
+
1100
+ friend bool operator!=( const basic_bigint<Allocator>& x, const basic_bigint<Allocator>& y ) noexcept
1101
+ {
1102
+ return x.compare(y) != 0 ? true : false;
1103
+ }
1104
+
1105
+ friend bool operator!=( const basic_bigint<Allocator>& x, int y ) noexcept
1106
+ {
1107
+ return x.compare(basic_bigint<Allocator>(y)) != 0 ? true : false;
1108
+ }
1109
+
1110
+ friend bool operator<( const basic_bigint<Allocator>& x, const basic_bigint<Allocator>& y ) noexcept
1111
+ {
1112
+ return x.compare(y) < 0 ? true : false;
1113
+ }
1114
+
1115
+ friend bool operator<( const basic_bigint<Allocator>& x, int64_t y ) noexcept
1116
+ {
1117
+ return x.compare(y) < 0 ? true : false;
1118
+ }
1119
+
1120
+ friend bool operator>( const basic_bigint<Allocator>& x, const basic_bigint<Allocator>& y ) noexcept
1121
+ {
1122
+ return x.compare(y) > 0 ? true : false;
1123
+ }
1124
+
1125
+ friend bool operator>( const basic_bigint<Allocator>& x, int y ) noexcept
1126
+ {
1127
+ return x.compare(basic_bigint<Allocator>(y)) > 0 ? true : false;
1128
+ }
1129
+
1130
+ friend bool operator<=( const basic_bigint<Allocator>& x, const basic_bigint<Allocator>& y ) noexcept
1131
+ {
1132
+ return x.compare(y) <= 0 ? true : false;
1133
+ }
1134
+
1135
+ friend bool operator<=( const basic_bigint<Allocator>& x, int y ) noexcept
1136
+ {
1137
+ return x.compare(y) <= 0 ? true : false;
1138
+ }
1139
+
1140
+ friend bool operator>=( const basic_bigint<Allocator>& x, const basic_bigint<Allocator>& y ) noexcept
1141
+ {
1142
+ return x.compare(y) >= 0 ? true : false;
1143
+ }
1144
+
1145
+ friend bool operator>=( const basic_bigint<Allocator>& x, int y ) noexcept
1146
+ {
1147
+ return x.compare(y) >= 0 ? true : false;
1148
+ }
1149
+
1150
+ friend basic_bigint<Allocator> operator+( basic_bigint<Allocator> x, const basic_bigint<Allocator>& y )
1151
+ {
1152
+ return x += y;
1153
+ }
1154
+
1155
+ friend basic_bigint<Allocator> operator+( basic_bigint<Allocator> x, int64_t y )
1156
+ {
1157
+ return x += y;
1158
+ }
1159
+
1160
+ friend basic_bigint<Allocator> operator-( basic_bigint<Allocator> x, const basic_bigint<Allocator>& y )
1161
+ {
1162
+ return x -= y;
1163
+ }
1164
+
1165
+ friend basic_bigint<Allocator> operator-( basic_bigint<Allocator> x, int64_t y )
1166
+ {
1167
+ return x -= y;
1168
+ }
1169
+
1170
+ friend basic_bigint<Allocator> operator*( int64_t x, const basic_bigint<Allocator>& y )
1171
+ {
1172
+ return basic_bigint<Allocator>(y) *= x;
1173
+ }
1174
+
1175
+ friend basic_bigint<Allocator> operator*( basic_bigint<Allocator> x, const basic_bigint<Allocator>& y )
1176
+ {
1177
+ return x *= y;
1178
+ }
1179
+
1180
+ friend basic_bigint<Allocator> operator*( basic_bigint<Allocator> x, int64_t y )
1181
+ {
1182
+ return x *= y;
1183
+ }
1184
+
1185
+ friend basic_bigint<Allocator> operator/( basic_bigint<Allocator> x, const basic_bigint<Allocator>& y )
1186
+ {
1187
+ return x /= y;
1188
+ }
1189
+
1190
+ friend basic_bigint<Allocator> operator/( basic_bigint<Allocator> x, int y )
1191
+ {
1192
+ return x /= y;
1193
+ }
1194
+
1195
+ friend basic_bigint<Allocator> operator%( basic_bigint<Allocator> x, const basic_bigint<Allocator>& y )
1196
+ {
1197
+ return x %= y;
1198
+ }
1199
+
1200
+ friend basic_bigint<Allocator> operator<<( basic_bigint<Allocator> u, unsigned k )
1201
+ {
1202
+ return u <<= k;
1203
+ }
1204
+
1205
+ friend basic_bigint<Allocator> operator<<( basic_bigint<Allocator> u, int k )
1206
+ {
1207
+ return u <<= k;
1208
+ }
1209
+
1210
+ friend basic_bigint<Allocator> operator>>( basic_bigint<Allocator> u, unsigned k )
1211
+ {
1212
+ return u >>= k;
1213
+ }
1214
+
1215
+ friend basic_bigint<Allocator> operator>>( basic_bigint<Allocator> u, int k )
1216
+ {
1217
+ return u >>= k;
1218
+ }
1219
+
1220
+ friend basic_bigint<Allocator> operator|( basic_bigint<Allocator> x, const basic_bigint<Allocator>& y )
1221
+ {
1222
+ return x |= y;
1223
+ }
1224
+
1225
+ friend basic_bigint<Allocator> operator|( basic_bigint<Allocator> x, int y )
1226
+ {
1227
+ return x |= y;
1228
+ }
1229
+
1230
+ friend basic_bigint<Allocator> operator|( basic_bigint<Allocator> x, unsigned y )
1231
+ {
1232
+ return x |= y;
1233
+ }
1234
+
1235
+ friend basic_bigint<Allocator> operator^( basic_bigint<Allocator> x, const basic_bigint<Allocator>& y )
1236
+ {
1237
+ return x ^= y;
1238
+ }
1239
+
1240
+ friend basic_bigint<Allocator> operator^( basic_bigint<Allocator> x, int y )
1241
+ {
1242
+ return x ^= y;
1243
+ }
1244
+
1245
+ friend basic_bigint<Allocator> operator^( basic_bigint<Allocator> x, unsigned y )
1246
+ {
1247
+ return x ^= y;
1248
+ }
1249
+
1250
+ friend basic_bigint<Allocator> operator&( basic_bigint<Allocator> x, const basic_bigint<Allocator>& y )
1251
+ {
1252
+ return x &= y;
1253
+ }
1254
+
1255
+ friend basic_bigint<Allocator> operator&( basic_bigint<Allocator> x, int y )
1256
+ {
1257
+ return x &= y;
1258
+ }
1259
+
1260
+ friend basic_bigint<Allocator> operator&( basic_bigint<Allocator> x, unsigned y )
1261
+ {
1262
+ return x &= y;
1263
+ }
1264
+
1265
+ friend basic_bigint<Allocator> abs( const basic_bigint<Allocator>& a )
1266
+ {
1267
+ if ( a.is_negative() )
1268
+ {
1269
+ return -a;
1270
+ }
1271
+ return a;
1272
+ }
1273
+
1274
+ friend basic_bigint<Allocator> power( basic_bigint<Allocator> x, unsigned n )
1275
+ {
1276
+ basic_bigint<Allocator> y = 1;
1277
+
1278
+ while ( n )
1279
+ {
1280
+ if ( n & 1 )
1281
+ {
1282
+ y *= x;
1283
+ }
1284
+ x *= x;
1285
+ n >>= 1;
1286
+ }
1287
+
1288
+ return y;
1289
+ }
1290
+
1291
+ friend basic_bigint<Allocator> sqrt( const basic_bigint<Allocator>& a )
1292
+ {
1293
+ basic_bigint<Allocator> x = a;
1294
+ basic_bigint<Allocator> b = a;
1295
+ basic_bigint<Allocator> q;
1296
+
1297
+ b <<= 1;
1298
+ while ( b >>= 2, b > 0 )
1299
+ {
1300
+ x >>= 1;
1301
+ }
1302
+ while ( x > (q = a/x) + 1 || x < q - 1 )
1303
+ {
1304
+ x += q;
1305
+ x >>= 1;
1306
+ }
1307
+ return x < q ? x : q;
1308
+ }
1309
+
1310
+ template <class CharT>
1311
+ friend std::basic_ostream<CharT>& operator<<(std::basic_ostream<CharT>& os, const basic_bigint<Allocator>& v)
1312
+ {
1313
+ std::basic_string<CharT> s;
1314
+ v.write_string(s);
1315
+ os << s;
1316
+
1317
+ return os;
1318
+ }
1319
+
1320
+ int compare( const basic_bigint<Allocator>& y ) const noexcept
1321
+ {
1322
+ if ( is_negative() != y.is_negative() )
1323
+ return y.is_negative() - is_negative();
1324
+ int code = 0;
1325
+ if ( length() == 0 && y.length() == 0 )
1326
+ code = 0;
1327
+ else if ( length() < y.length() )
1328
+ code = -1;
1329
+ else if ( length() > y.length() )
1330
+ code = +1;
1331
+ else
1332
+ {
1333
+ for (size_type i = length(); i-- > 0; )
1334
+ {
1335
+ if (data()[i] > y.data()[i])
1336
+ {
1337
+ code = 1;
1338
+ break;
1339
+ }
1340
+ else if (data()[i] < y.data()[i])
1341
+ {
1342
+ code = -1;
1343
+ break;
1344
+ }
1345
+ }
1346
+ }
1347
+ return is_negative() ? -code : code;
1348
+ }
1349
+
1350
+ void divide( basic_bigint<Allocator> denom, basic_bigint<Allocator>& quot, basic_bigint<Allocator>& rem, bool remDesired ) const
1351
+ {
1352
+ if ( denom.length() == 0 )
1353
+ {
1354
+ JSONCONS_THROW(std::runtime_error( "Zero divide." ));
1355
+ }
1356
+ bool quot_neg = is_negative() ^ denom.is_negative();
1357
+ bool rem_neg = is_negative();
1358
+ int x = 0;
1359
+ basic_bigint<Allocator> num = *this;
1360
+ num.common_stor_.is_negative_ = denom.common_stor_.is_negative_ = false;
1361
+ if ( num < denom )
1362
+ {
1363
+ quot = uint64_t(0);
1364
+ rem = num;
1365
+ rem.common_stor_.is_negative_ = rem_neg;
1366
+ return;
1367
+ }
1368
+ if ( denom.length() == 1 && num.length() == 1 )
1369
+ {
1370
+ quot = uint64_t( num.data()[0]/denom.data()[0] );
1371
+ rem = uint64_t( num.data()[0]%denom.data()[0] );
1372
+ quot.common_stor_.is_negative_ = quot_neg;
1373
+ rem.common_stor_.is_negative_ = rem_neg;
1374
+ return;
1375
+ }
1376
+ else if (denom.length() == 1 && (denom.data()[0] & l_mask) == 0 )
1377
+ {
1378
+ // Denominator fits into a half word
1379
+ uint64_t divisor = denom.data()[0], dHi = 0,
1380
+ q1, r, q2, dividend;
1381
+ quot.resize(length());
1382
+ for (size_type i=length(); i-- > 0; )
1383
+ {
1384
+ dividend = (dHi << basic_type_halfBits) | (data()[i] >> basic_type_halfBits);
1385
+ q1 = dividend/divisor;
1386
+ r = dividend % divisor;
1387
+ dividend = (r << basic_type_halfBits) | (data()[i] & r_mask);
1388
+ q2 = dividend/divisor;
1389
+ dHi = dividend % divisor;
1390
+ quot.data()[i] = (q1 << basic_type_halfBits) | q2;
1391
+ }
1392
+ quot.reduce();
1393
+ rem = dHi;
1394
+ quot.common_stor_.is_negative_ = quot_neg;
1395
+ rem.common_stor_.is_negative_ = rem_neg;
1396
+ return;
1397
+ }
1398
+ basic_bigint<Allocator> num0 = num, denom0 = denom;
1399
+ int second_done = normalize(denom, num, x);
1400
+ size_type l = denom.length() - 1;
1401
+ size_type n = num.length() - 1;
1402
+ quot.resize(n - l);
1403
+ for (size_type i=quot.length(); i-- > 0; )
1404
+ quot.data()[i] = 0;
1405
+ rem = num;
1406
+ if ( rem.data()[n] >= denom.data()[l] )
1407
+ {
1408
+ rem.resize(rem.length() + 1);
1409
+ n++;
1410
+ quot.resize(quot.length() + 1);
1411
+ }
1412
+ uint64_t d = denom.data()[l];
1413
+ for ( size_type k = n; k > l; k-- )
1414
+ {
1415
+ uint64_t q = DDquotient(rem.data()[k], rem.data()[k-1], d);
1416
+ subtractmul( rem.data() + k - l - 1, denom.data(), l + 1, q );
1417
+ quot.data()[k - l - 1] = q;
1418
+ }
1419
+ quot.reduce();
1420
+ quot.common_stor_.is_negative_ = quot_neg;
1421
+ if ( remDesired )
1422
+ {
1423
+ unnormalize(rem, x, second_done);
1424
+ rem.common_stor_.is_negative_ = rem_neg;
1425
+ }
1426
+ }
1427
+ private:
1428
+ void destroy() noexcept
1429
+ {
1430
+ if (is_dynamic())
1431
+ {
1432
+ dynamic_stor_.destroy(get_allocator());
1433
+ }
1434
+ }
1435
+ void DDproduct( uint64_t A, uint64_t B,
1436
+ uint64_t& hi, uint64_t& lo ) const
1437
+ // Multiplying two digits: (hi, lo) = A * B
1438
+ {
1439
+ uint64_t hiA = A >> basic_type_halfBits, loA = A & r_mask,
1440
+ hiB = B >> basic_type_halfBits, loB = B & r_mask,
1441
+ mid1, mid2, old;
1442
+
1443
+ lo = loA * loB;
1444
+ hi = hiA * hiB;
1445
+ mid1 = loA * hiB;
1446
+ mid2 = hiA * loB;
1447
+ old = lo;
1448
+ lo += mid1 << basic_type_halfBits;
1449
+ hi += (lo < old) + (mid1 >> basic_type_halfBits);
1450
+ old = lo;
1451
+ lo += mid2 << basic_type_halfBits;
1452
+ hi += (lo < old) + (mid2 >> basic_type_halfBits);
1453
+ }
1454
+
1455
+ uint64_t DDquotient( uint64_t A, uint64_t B, uint64_t d ) const
1456
+ // Divide double word (A, B) by d. Quotient = (qHi, qLo)
1457
+ {
1458
+ uint64_t left, middle, right, qHi, qLo, x, dLo1,
1459
+ dHi = d >> basic_type_halfBits, dLo = d & r_mask;
1460
+ qHi = A/(dHi + 1);
1461
+ // This initial guess of qHi may be too small.
1462
+ middle = qHi * dLo;
1463
+ left = qHi * dHi;
1464
+ x = B - (middle << basic_type_halfBits);
1465
+ A -= (middle >> basic_type_halfBits) + left + (x > B);
1466
+ B = x;
1467
+ dLo1 = dLo << basic_type_halfBits;
1468
+ // Increase qHi if necessary:
1469
+ while ( A > dHi || (A == dHi && B >= dLo1) )
1470
+ {
1471
+ x = B - dLo1;
1472
+ A -= dHi + (x > B);
1473
+ B = x;
1474
+ qHi++;
1475
+ }
1476
+ qLo = ((A << basic_type_halfBits) | (B >> basic_type_halfBits))/(dHi + 1);
1477
+ // This initial guess of qLo may be too small.
1478
+ right = qLo * dLo;
1479
+ middle = qLo * dHi;
1480
+ x = B - right;
1481
+ A -= (x > B);
1482
+ B = x;
1483
+ x = B - (middle << basic_type_halfBits);
1484
+ A -= (middle >> basic_type_halfBits) + (x > B);
1485
+ B = x;
1486
+ // Increase qLo if necessary:
1487
+ while ( A || B >= d )
1488
+ {
1489
+ x = B - d;
1490
+ A -= (x > B);
1491
+ B = x;
1492
+ qLo++;
1493
+ }
1494
+ return (qHi << basic_type_halfBits) + qLo;
1495
+ }
1496
+
1497
+ void subtractmul( uint64_t* a, uint64_t* b, size_type n, uint64_t& q ) const
1498
+ // a -= q * b: b in n positions; correct q if necessary
1499
+ {
1500
+ uint64_t hi, lo, d, carry = 0;
1501
+ size_type i;
1502
+ for ( i = 0; i < n; i++ )
1503
+ {
1504
+ DDproduct( b[i], q, hi, lo );
1505
+ d = a[i];
1506
+ a[i] -= lo;
1507
+ if ( a[i] > d )
1508
+ carry++;
1509
+ d = a[i + 1];
1510
+ a[i + 1] -= hi + carry;
1511
+ carry = a[i + 1] > d;
1512
+ }
1513
+ if ( carry ) // q was too large
1514
+ {
1515
+ q--;
1516
+ carry = 0;
1517
+ for ( i = 0; i < n; i++ )
1518
+ {
1519
+ d = a[i] + carry;
1520
+ carry = d < carry;
1521
+ a[i] = d + b[i];
1522
+ if ( a[i] < d )
1523
+ carry = 1;
1524
+ }
1525
+ a[n] = 0;
1526
+ }
1527
+ }
1528
+
1529
+ int normalize( basic_bigint<Allocator>& denom, basic_bigint<Allocator>& num, int& x ) const
1530
+ {
1531
+ size_type r = denom.length() - 1;
1532
+ uint64_t y = denom.data()[r];
1533
+
1534
+ x = 0;
1535
+ while ( (y & l_bit) == 0 )
1536
+ {
1537
+ y <<= 1;
1538
+ x++;
1539
+ }
1540
+ denom <<= x;
1541
+ num <<= x;
1542
+ if ( r > 0 && denom.data()[r] < denom.data()[r-1] )
1543
+ {
1544
+ denom *= max_basic_type;
1545
+ num *= max_basic_type;
1546
+ return 1;
1547
+ }
1548
+ return 0;
1549
+ }
1550
+
1551
+ void unnormalize( basic_bigint<Allocator>& rem, int x, int secondDone ) const
1552
+ {
1553
+ if ( secondDone )
1554
+ {
1555
+ rem /= max_basic_type;
1556
+ }
1557
+ if ( x > 0 )
1558
+ {
1559
+ rem >>= x;
1560
+ }
1561
+ else
1562
+ {
1563
+ rem.reduce();
1564
+ }
1565
+ }
1566
+
1567
+ size_type round_up(size_type i) const // Find suitable new block size
1568
+ {
1569
+ return (i/word_length + 1) * word_length;
1570
+ }
1571
+
1572
+ void reduce()
1573
+ {
1574
+ uint64_t* p = end() - 1;
1575
+ uint64_t* pBegin = begin();
1576
+ while ( p >= pBegin )
1577
+ {
1578
+ if ( *p )
1579
+ {
1580
+ break;
1581
+ }
1582
+ --common_stor_.length_;
1583
+ --p;
1584
+ }
1585
+ if ( length() == 0 )
1586
+ {
1587
+ common_stor_.is_negative_ = false;
1588
+ }
1589
+ }
1590
+
1591
+ static uint64_t next_power_of_two(uint64_t n) {
1592
+ n = n - 1;
1593
+ n |= n >> 1;
1594
+ n |= n >> 2;
1595
+ n |= n >> 4;
1596
+ n |= n >> 8;
1597
+ n |= n >> 16;
1598
+ n |= n >> 32;
1599
+ return n + 1;
1600
+ }
1601
+ };
1602
+
1603
+ using bigint = basic_bigint<std::allocator<uint8_t>>;
1604
+
1605
+ #if !defined(JSONCONS_NO_DEPRECATED)
1606
+ JSONCONS_DEPRECATED_MSG("Instead, use bigint") typedef bigint bignum;
1607
+ #endif
1608
+
1609
+ }
1610
+
1611
+ #endif