jsoncons 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
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