Bug 1890689 apply drift correction to input rate instead of output rate r=pehrsons
[gecko.git] / js / public / BigInt.h
blob4cf1a10140ac6170f94dd72ea2b3212bec4a4eb1
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* This Source Code Form is subject to the terms of the Mozilla Public
3 * License, v. 2.0. If a copy of the MPL was not distributed with this
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 /* BigInt. */
8 #ifndef js_BigInt_h
9 #define js_BigInt_h
11 #include "mozilla/Span.h" // mozilla::Span
13 #include <limits> // std::numeric_limits
14 #include <stdint.h> // int64_t, uint64_t
15 #include <type_traits> // std::enable_if_t, std::{true,false}_type, std::is_{integral,signed,unsigned}_v
17 #include "jstypes.h" // JS_PUBLIC_API
18 #include "js/TypeDecls.h"
20 namespace mozilla {
21 template <typename T>
22 class Range;
25 namespace JS {
27 class JS_PUBLIC_API BigInt;
29 namespace detail {
31 using Int64Limits = std::numeric_limits<int64_t>;
32 using Uint64Limits = std::numeric_limits<uint64_t>;
34 extern JS_PUBLIC_API BigInt* BigIntFromInt64(JSContext* cx, int64_t num);
35 extern JS_PUBLIC_API BigInt* BigIntFromUint64(JSContext* cx, uint64_t num);
36 extern JS_PUBLIC_API BigInt* BigIntFromBool(JSContext* cx, bool b);
38 template <typename T, typename = void>
39 struct NumberToBigIntConverter;
41 template <typename SignedIntT>
42 struct NumberToBigIntConverter<
43 SignedIntT,
44 std::enable_if_t<
45 std::is_integral_v<SignedIntT> && std::is_signed_v<SignedIntT> &&
46 Int64Limits::min() <= std::numeric_limits<SignedIntT>::min() &&
47 std::numeric_limits<SignedIntT>::max() <= Int64Limits::max()>> {
48 static BigInt* convert(JSContext* cx, SignedIntT num) {
49 return BigIntFromInt64(cx, num);
53 template <typename UnsignedIntT>
54 struct NumberToBigIntConverter<
55 UnsignedIntT,
56 std::enable_if_t<
57 std::is_integral_v<UnsignedIntT> && std::is_unsigned_v<UnsignedIntT> &&
58 std::numeric_limits<UnsignedIntT>::max() <= Uint64Limits::max()>> {
59 static BigInt* convert(JSContext* cx, UnsignedIntT num) {
60 return BigIntFromUint64(cx, num);
64 template <>
65 struct NumberToBigIntConverter<bool> {
66 static BigInt* convert(JSContext* cx, bool b) {
67 return BigIntFromBool(cx, b);
71 extern JS_PUBLIC_API bool BigIntIsInt64(const BigInt* bi, int64_t* result);
72 extern JS_PUBLIC_API bool BigIntIsUint64(const BigInt* bi, uint64_t* result);
74 template <typename T, typename = void>
75 struct BigIntToNumberChecker;
77 template <typename SignedIntT>
78 struct BigIntToNumberChecker<
79 SignedIntT,
80 std::enable_if_t<
81 std::is_integral_v<SignedIntT> && std::is_signed_v<SignedIntT> &&
82 Int64Limits::min() <= std::numeric_limits<SignedIntT>::min() &&
83 std::numeric_limits<SignedIntT>::max() <= Int64Limits::max()>> {
84 using TypeLimits = std::numeric_limits<SignedIntT>;
86 static bool fits(const BigInt* bi, SignedIntT* result) {
87 int64_t innerResult;
88 if (!BigIntIsInt64(bi, &innerResult)) {
89 return false;
91 if (TypeLimits::min() <= innerResult && innerResult <= TypeLimits::max()) {
92 *result = SignedIntT(innerResult);
93 return true;
95 return false;
99 template <typename UnsignedIntT>
100 struct BigIntToNumberChecker<
101 UnsignedIntT,
102 std::enable_if_t<
103 std::is_integral_v<UnsignedIntT> && std::is_unsigned_v<UnsignedIntT> &&
104 std::numeric_limits<UnsignedIntT>::max() <= Uint64Limits::max()>> {
105 static bool fits(const BigInt* bi, UnsignedIntT* result) {
106 uint64_t innerResult;
107 if (!BigIntIsUint64(bi, &innerResult)) {
108 return false;
110 if (innerResult <= std::numeric_limits<UnsignedIntT>::max()) {
111 *result = UnsignedIntT(innerResult);
112 return true;
114 return false;
118 } // namespace detail
121 * Create a BigInt from an integer value. All integral types not larger than 64
122 * bits in size are supported.
124 template <typename NumericT>
125 static inline BigInt* NumberToBigInt(JSContext* cx, NumericT val) {
126 return detail::NumberToBigIntConverter<NumericT>::convert(cx, val);
130 * Create a BigInt from a floating-point value. If the number isn't integral
131 * (that is, if it's NaN, an infinity, or contains a fractional component),
132 * this function returns null and throws an exception.
134 * Passing -0.0 will produce the bigint 0n.
136 extern JS_PUBLIC_API BigInt* NumberToBigInt(JSContext* cx, double num);
139 * Create a BigInt by parsing a string using the ECMAScript StringToBigInt
140 * algorithm (https://tc39.es/ecma262/#sec-stringtobigint). Latin1 and two-byte
141 * character ranges are supported. It may be convenient to use
142 * JS::ConstLatin1Chars or JS::ConstTwoByteChars.
144 * (StringToBigInt performs parsing similar to that performed by the |Number|
145 * global function when passed a string, but it doesn't allow infinities,
146 * decimal points, or exponential notation, and neither algorithm allows numeric
147 * separators or an 'n' suffix character. This fast-and-loose description is
148 * offered purely as a convenience to the reader: see the specification
149 * algorithm for exact behavior.)
151 * If parsing fails, this function returns null and throws an exception.
153 extern JS_PUBLIC_API BigInt* StringToBigInt(
154 JSContext* cx, const mozilla::Range<const Latin1Char>& chars);
156 extern JS_PUBLIC_API BigInt* StringToBigInt(
157 JSContext* cx, const mozilla::Range<const char16_t>& chars);
160 * Create a BigInt by parsing a string consisting of an optional sign character
161 * followed by one or more alphanumeric ASCII digits in the provided radix.
163 * If the radix is not in the range [2, 36], or the string fails to parse, this
164 * function returns null and throws an exception.
166 extern JS_PUBLIC_API BigInt* SimpleStringToBigInt(
167 JSContext* cx, mozilla::Span<const char> chars, uint8_t radix);
170 * Convert a JS::Value to a BigInt using the ECMAScript ToBigInt algorithm
171 * (https://tc39.es/ecma262/#sec-tobigint).
173 * (Note in particular that this will throw if passed a value whose type is
174 * 'number'. To convert a number to a BigInt, use one of the overloads of
175 * JS::NumberToBigInt().)
177 extern JS_PUBLIC_API BigInt* ToBigInt(JSContext* cx, Handle<Value> val);
180 * Convert the given BigInt, modulo 2**64, to a signed 64-bit integer.
182 extern JS_PUBLIC_API int64_t ToBigInt64(const BigInt* bi);
185 * Convert the given BigInt, modulo 2**64, to an unsigned 64-bit integer.
187 extern JS_PUBLIC_API uint64_t ToBigUint64(const BigInt* bi);
190 * Convert the given BigInt to a Number value as if calling the Number
191 * constructor on it
192 * (https://tc39.es/ecma262/#sec-number-constructor-number-value). The value
193 * may be rounded if it doesn't fit without loss of precision.
195 extern JS_PUBLIC_API double BigIntToNumber(const BigInt* bi);
198 * Return true if the given BigInt is negative.
200 extern JS_PUBLIC_API bool BigIntIsNegative(const BigInt* bi);
203 * Return true if the given BigInt fits inside the given NumericT type without
204 * loss of precision, and store the value in the out parameter. Otherwise return
205 * false and leave the value of the out parameter unspecified.
207 template <typename NumericT>
208 static inline bool BigIntFits(const BigInt* bi, NumericT* out) {
209 return detail::BigIntToNumberChecker<NumericT>::fits(bi, out);
213 * Same as BigIntFits(), but checks if the value fits inside a JS Number value.
215 extern JS_PUBLIC_API bool BigIntFitsNumber(const BigInt* bi, double* out);
218 * Convert the given BigInt to a String value as if toString() were called on
219 * it.
221 * If the radix is not in the range [2, 36], then this function returns null and
222 * throws an exception.
224 extern JS_PUBLIC_API JSString* BigIntToString(JSContext* cx, Handle<BigInt*> bi,
225 uint8_t radix);
227 } // namespace JS
229 #endif /* js_BigInt_h */