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.
- checksums.yaml +7 -0
- data/ext/jsoncons/extconf.rb +43 -0
- data/ext/jsoncons/jsoncons.cpp +161 -0
- data/ext/jsoncons/jsoncons.h +10 -0
- data/jsoncons.gemspec +44 -0
- data/lib/jsoncons/jsoncons/examples/input/address-book.json +13 -0
- data/lib/jsoncons/jsoncons/examples/input/books.json +28 -0
- data/lib/jsoncons/jsoncons/examples/input/countries.json +7 -0
- data/lib/jsoncons/jsoncons/examples/input/employees.json +30 -0
- data/lib/jsoncons/jsoncons/examples/input/jsonschema/name.json +15 -0
- data/lib/jsoncons/jsoncons/examples/input/multiple-json-objects.json +3 -0
- data/lib/jsoncons/jsoncons/examples/input/sales.csv +6 -0
- data/lib/jsoncons/jsoncons/examples/input/store.json +28 -0
- data/lib/jsoncons/jsoncons/examples/input/tasks.csv +6 -0
- data/lib/jsoncons/jsoncons/include/jsoncons/allocator_holder.hpp +38 -0
- data/lib/jsoncons/jsoncons/include/jsoncons/basic_json.hpp +5905 -0
- data/lib/jsoncons/jsoncons/include/jsoncons/bigint.hpp +1611 -0
- data/lib/jsoncons/jsoncons/include/jsoncons/byte_string.hpp +820 -0
- data/lib/jsoncons/jsoncons/include/jsoncons/config/binary_config.hpp +226 -0
- data/lib/jsoncons/jsoncons/include/jsoncons/config/compiler_support.hpp +375 -0
- data/lib/jsoncons/jsoncons/include/jsoncons/config/jsoncons_config.hpp +309 -0
- data/lib/jsoncons/jsoncons/include/jsoncons/config/version.hpp +40 -0
- data/lib/jsoncons/jsoncons/include/jsoncons/conv_error.hpp +218 -0
- data/lib/jsoncons/jsoncons/include/jsoncons/decode_json.hpp +209 -0
- data/lib/jsoncons/jsoncons/include/jsoncons/decode_traits.hpp +651 -0
- data/lib/jsoncons/jsoncons/include/jsoncons/detail/endian.hpp +44 -0
- data/lib/jsoncons/jsoncons/include/jsoncons/detail/grisu3.hpp +312 -0
- data/lib/jsoncons/jsoncons/include/jsoncons/detail/optional.hpp +483 -0
- data/lib/jsoncons/jsoncons/include/jsoncons/detail/parse_number.hpp +1133 -0
- data/lib/jsoncons/jsoncons/include/jsoncons/detail/span.hpp +188 -0
- data/lib/jsoncons/jsoncons/include/jsoncons/detail/string_view.hpp +537 -0
- data/lib/jsoncons/jsoncons/include/jsoncons/detail/string_wrapper.hpp +370 -0
- data/lib/jsoncons/jsoncons/include/jsoncons/detail/write_number.hpp +567 -0
- data/lib/jsoncons/jsoncons/include/jsoncons/encode_json.hpp +315 -0
- data/lib/jsoncons/jsoncons/include/jsoncons/encode_traits.hpp +378 -0
- data/lib/jsoncons/jsoncons/include/jsoncons/json.hpp +18 -0
- data/lib/jsoncons/jsoncons/include/jsoncons/json_array.hpp +324 -0
- data/lib/jsoncons/jsoncons/include/jsoncons/json_content_handler.hpp +12 -0
- data/lib/jsoncons/jsoncons/include/jsoncons/json_cursor.hpp +448 -0
- data/lib/jsoncons/jsoncons/include/jsoncons/json_decoder.hpp +420 -0
- data/lib/jsoncons/jsoncons/include/jsoncons/json_encoder.hpp +1587 -0
- data/lib/jsoncons/jsoncons/include/jsoncons/json_error.hpp +156 -0
- data/lib/jsoncons/jsoncons/include/jsoncons/json_exception.hpp +241 -0
- data/lib/jsoncons/jsoncons/include/jsoncons/json_filter.hpp +653 -0
- data/lib/jsoncons/jsoncons/include/jsoncons/json_fwd.hpp +23 -0
- data/lib/jsoncons/jsoncons/include/jsoncons/json_object.hpp +1772 -0
- data/lib/jsoncons/jsoncons/include/jsoncons/json_options.hpp +862 -0
- data/lib/jsoncons/jsoncons/include/jsoncons/json_parser.hpp +2900 -0
- data/lib/jsoncons/jsoncons/include/jsoncons/json_reader.hpp +731 -0
- data/lib/jsoncons/jsoncons/include/jsoncons/json_traits_macros.hpp +1072 -0
- data/lib/jsoncons/jsoncons/include/jsoncons/json_traits_macros_deprecated.hpp +144 -0
- data/lib/jsoncons/jsoncons/include/jsoncons/json_type.hpp +206 -0
- data/lib/jsoncons/jsoncons/include/jsoncons/json_type_traits.hpp +1830 -0
- data/lib/jsoncons/jsoncons/include/jsoncons/json_visitor.hpp +1560 -0
- data/lib/jsoncons/jsoncons/include/jsoncons/json_visitor2.hpp +2079 -0
- data/lib/jsoncons/jsoncons/include/jsoncons/pretty_print.hpp +89 -0
- data/lib/jsoncons/jsoncons/include/jsoncons/ser_context.hpp +62 -0
- data/lib/jsoncons/jsoncons/include/jsoncons/sink.hpp +289 -0
- data/lib/jsoncons/jsoncons/include/jsoncons/source.hpp +777 -0
- data/lib/jsoncons/jsoncons/include/jsoncons/source_adaptor.hpp +148 -0
- data/lib/jsoncons/jsoncons/include/jsoncons/staj2_cursor.hpp +1189 -0
- data/lib/jsoncons/jsoncons/include/jsoncons/staj_cursor.hpp +1254 -0
- data/lib/jsoncons/jsoncons/include/jsoncons/staj_iterator.hpp +449 -0
- data/lib/jsoncons/jsoncons/include/jsoncons/tag_type.hpp +245 -0
- data/lib/jsoncons/jsoncons/include/jsoncons/text_source_adaptor.hpp +144 -0
- data/lib/jsoncons/jsoncons/include/jsoncons/traits_extension.hpp +884 -0
- data/lib/jsoncons/jsoncons/include/jsoncons/typed_array_view.hpp +250 -0
- data/lib/jsoncons/jsoncons/include/jsoncons/unicode_traits.hpp +1330 -0
- data/lib/jsoncons/jsoncons/include/jsoncons/uri.hpp +635 -0
- data/lib/jsoncons/jsoncons/include/jsoncons/value_converter.hpp +340 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/bson/bson.hpp +23 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/bson/bson_cursor.hpp +320 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/bson/bson_decimal128.hpp +865 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/bson/bson_encoder.hpp +585 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/bson/bson_error.hpp +103 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/bson/bson_oid.hpp +245 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/bson/bson_options.hpp +75 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/bson/bson_parser.hpp +645 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/bson/bson_reader.hpp +92 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/bson/bson_type.hpp +44 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/bson/decode_bson.hpp +201 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/bson/encode_bson.hpp +144 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/cbor/cbor.hpp +26 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/cbor/cbor_cursor.hpp +351 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/cbor/cbor_cursor2.hpp +265 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/cbor/cbor_detail.hpp +93 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/cbor/cbor_encoder.hpp +1766 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/cbor/cbor_error.hpp +105 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/cbor/cbor_options.hpp +113 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/cbor/cbor_parser.hpp +1942 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/cbor/cbor_reader.hpp +116 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/cbor/decode_cbor.hpp +203 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/cbor/encode_cbor.hpp +151 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/csv/csv.hpp +17 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/csv/csv_cursor.hpp +358 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/csv/csv_encoder.hpp +954 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/csv/csv_error.hpp +85 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/csv/csv_options.hpp +973 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/csv/csv_parser.hpp +2099 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/csv/csv_reader.hpp +348 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/csv/csv_serializer.hpp +12 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/csv/decode_csv.hpp +208 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/csv/encode_csv.hpp +122 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/jmespath/jmespath.hpp +5215 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/jmespath/jmespath_error.hpp +215 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/jsonpatch/jsonpatch.hpp +579 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/jsonpatch/jsonpatch_error.hpp +121 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/jsonpath/expression.hpp +3329 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/jsonpath/flatten.hpp +432 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/jsonpath/json_location.hpp +445 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/jsonpath/json_query.hpp +115 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/jsonpath/jsonpath.hpp +13 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/jsonpath/jsonpath_error.hpp +240 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/jsonpath/jsonpath_expression.hpp +2612 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/jsonpath/jsonpath_selector.hpp +1322 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/jsonpointer/jsonpointer.hpp +1577 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/jsonpointer/jsonpointer_error.hpp +119 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/jsonschema/format_validator.hpp +968 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/jsonschema/json_validator.hpp +120 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/jsonschema/jsonschema.hpp +13 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/jsonschema/jsonschema_error.hpp +105 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/jsonschema/jsonschema_version.hpp +18 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/jsonschema/keyword_validator.hpp +1745 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/jsonschema/keyword_validator_factory.hpp +556 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/jsonschema/schema_draft7.hpp +198 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/jsonschema/schema_location.hpp +200 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/jsonschema/schema_version.hpp +35 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/jsonschema/subschema.hpp +144 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/mergepatch/mergepatch.hpp +103 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/msgpack/decode_msgpack.hpp +202 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/msgpack/encode_msgpack.hpp +142 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/msgpack/msgpack.hpp +24 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/msgpack/msgpack_cursor.hpp +343 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/msgpack/msgpack_cursor2.hpp +259 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/msgpack/msgpack_encoder.hpp +753 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/msgpack/msgpack_error.hpp +94 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/msgpack/msgpack_options.hpp +74 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/msgpack/msgpack_parser.hpp +748 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/msgpack/msgpack_reader.hpp +116 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/msgpack/msgpack_type.hpp +63 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/ubjson/decode_ubjson.hpp +201 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/ubjson/encode_ubjson.hpp +142 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/ubjson/ubjson.hpp +23 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/ubjson/ubjson_cursor.hpp +307 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/ubjson/ubjson_encoder.hpp +502 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/ubjson/ubjson_error.hpp +100 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/ubjson/ubjson_options.hpp +87 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/ubjson/ubjson_parser.hpp +880 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/ubjson/ubjson_reader.hpp +92 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/ubjson/ubjson_type.hpp +43 -0
- data/lib/jsoncons/version.rb +5 -0
- data/lib/jsoncons.rb +33 -0
- data/test/jsoncons_test.rb +108 -0
- data/test/test_helper.rb +7 -0
- 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
|