summaryrefslogtreecommitdiffstats
path: root/third_party/rust/dtoa
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--third_party/rust/dtoa-short/.cargo-checksum.json1
-rw-r--r--third_party/rust/dtoa-short/Cargo.toml31
-rw-r--r--third_party/rust/dtoa-short/LICENSE373
-rw-r--r--third_party/rust/dtoa-short/src/lib.rs197
-rw-r--r--third_party/rust/dtoa/.cargo-checksum.json1
-rw-r--r--third_party/rust/dtoa/Cargo.toml25
-rw-r--r--third_party/rust/dtoa/LICENSE-APACHE201
-rw-r--r--third_party/rust/dtoa/LICENSE-MIT23
-rw-r--r--third_party/rust/dtoa/README.md80
-rw-r--r--third_party/rust/dtoa/benches/bench.rs54
-rw-r--r--third_party/rust/dtoa/src/diyfp.rs253
-rw-r--r--third_party/rust/dtoa/src/dtoa.rs509
-rw-r--r--third_party/rust/dtoa/src/lib.rs205
-rw-r--r--third_party/rust/dtoa/tests/test.rs38
14 files changed, 1991 insertions, 0 deletions
diff --git a/third_party/rust/dtoa-short/.cargo-checksum.json b/third_party/rust/dtoa-short/.cargo-checksum.json
new file mode 100644
index 0000000000..7e152e8d78
--- /dev/null
+++ b/third_party/rust/dtoa-short/.cargo-checksum.json
@@ -0,0 +1 @@
+{"files":{"Cargo.toml":"77739c7541e1db4a011846d4bcaf39709cbe1e118dd269c9718e5cc0c7320548","LICENSE":"1f256ecad192880510e84ad60474eab7589218784b9a50bc7ceee34c2b91f1d5","src/lib.rs":"5c0c6cdc9ff4716f2ec9807f12bcf3c155e70a5d916eb0829bd0bab80eb65529"},"package":"bde03329ae10e79ede66c9ce4dc930aa8599043b0743008548680f25b91502d6"} \ No newline at end of file
diff --git a/third_party/rust/dtoa-short/Cargo.toml b/third_party/rust/dtoa-short/Cargo.toml
new file mode 100644
index 0000000000..b926972b1a
--- /dev/null
+++ b/third_party/rust/dtoa-short/Cargo.toml
@@ -0,0 +1,31 @@
+# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO
+#
+# When uploading crates to the registry Cargo will automatically
+# "normalize" Cargo.toml files for maximal compatibility
+# with all versions of Cargo and also rewrite `path` dependencies
+# to registry (e.g., crates.io) dependencies
+#
+# If you believe there's an error in this file please file an
+# issue against the rust-lang/cargo repository. If you're
+# editing this file be aware that the upstream Cargo.toml
+# will likely look very different (and much more reasonable)
+
+[package]
+name = "dtoa-short"
+version = "0.3.3"
+authors = ["Xidorn Quan <me@upsuper.org>"]
+include = ["src/*.rs", "Cargo.toml", "LICENSE"]
+description = "Serialize float number and truncate to certain precision"
+keywords = ["float"]
+categories = ["value-formatting"]
+license = "MPL-2.0"
+repository = "https://github.com/upsuper/dtoa-short"
+[dependencies.dtoa]
+version = "0.4.1"
+[dev-dependencies.float-cmp]
+version = "0.4"
+[badges.codecov]
+repository = "upsuper/dtoa-short"
+
+[badges.travis-ci]
+repository = "upsuper/dtoa-short"
diff --git a/third_party/rust/dtoa-short/LICENSE b/third_party/rust/dtoa-short/LICENSE
new file mode 100644
index 0000000000..a612ad9813
--- /dev/null
+++ b/third_party/rust/dtoa-short/LICENSE
@@ -0,0 +1,373 @@
+Mozilla Public License Version 2.0
+==================================
+
+1. Definitions
+--------------
+
+1.1. "Contributor"
+ means each individual or legal entity that creates, contributes to
+ the creation of, or owns Covered Software.
+
+1.2. "Contributor Version"
+ means the combination of the Contributions of others (if any) used
+ by a Contributor and that particular Contributor's Contribution.
+
+1.3. "Contribution"
+ means Covered Software of a particular Contributor.
+
+1.4. "Covered Software"
+ means Source Code Form to which the initial Contributor has attached
+ the notice in Exhibit A, the Executable Form of such Source Code
+ Form, and Modifications of such Source Code Form, in each case
+ including portions thereof.
+
+1.5. "Incompatible With Secondary Licenses"
+ means
+
+ (a) that the initial Contributor has attached the notice described
+ in Exhibit B to the Covered Software; or
+
+ (b) that the Covered Software was made available under the terms of
+ version 1.1 or earlier of the License, but not also under the
+ terms of a Secondary License.
+
+1.6. "Executable Form"
+ means any form of the work other than Source Code Form.
+
+1.7. "Larger Work"
+ means a work that combines Covered Software with other material, in
+ a separate file or files, that is not Covered Software.
+
+1.8. "License"
+ means this document.
+
+1.9. "Licensable"
+ means having the right to grant, to the maximum extent possible,
+ whether at the time of the initial grant or subsequently, any and
+ all of the rights conveyed by this License.
+
+1.10. "Modifications"
+ means any of the following:
+
+ (a) any file in Source Code Form that results from an addition to,
+ deletion from, or modification of the contents of Covered
+ Software; or
+
+ (b) any new file in Source Code Form that contains any Covered
+ Software.
+
+1.11. "Patent Claims" of a Contributor
+ means any patent claim(s), including without limitation, method,
+ process, and apparatus claims, in any patent Licensable by such
+ Contributor that would be infringed, but for the grant of the
+ License, by the making, using, selling, offering for sale, having
+ made, import, or transfer of either its Contributions or its
+ Contributor Version.
+
+1.12. "Secondary License"
+ means either the GNU General Public License, Version 2.0, the GNU
+ Lesser General Public License, Version 2.1, the GNU Affero General
+ Public License, Version 3.0, or any later versions of those
+ licenses.
+
+1.13. "Source Code Form"
+ means the form of the work preferred for making modifications.
+
+1.14. "You" (or "Your")
+ means an individual or a legal entity exercising rights under this
+ License. For legal entities, "You" includes any entity that
+ controls, is controlled by, or is under common control with You. For
+ purposes of this definition, "control" means (a) the power, direct
+ or indirect, to cause the direction or management of such entity,
+ whether by contract or otherwise, or (b) ownership of more than
+ fifty percent (50%) of the outstanding shares or beneficial
+ ownership of such entity.
+
+2. License Grants and Conditions
+--------------------------------
+
+2.1. Grants
+
+Each Contributor hereby grants You a world-wide, royalty-free,
+non-exclusive license:
+
+(a) under intellectual property rights (other than patent or trademark)
+ Licensable by such Contributor to use, reproduce, make available,
+ modify, display, perform, distribute, and otherwise exploit its
+ Contributions, either on an unmodified basis, with Modifications, or
+ as part of a Larger Work; and
+
+(b) under Patent Claims of such Contributor to make, use, sell, offer
+ for sale, have made, import, and otherwise transfer either its
+ Contributions or its Contributor Version.
+
+2.2. Effective Date
+
+The licenses granted in Section 2.1 with respect to any Contribution
+become effective for each Contribution on the date the Contributor first
+distributes such Contribution.
+
+2.3. Limitations on Grant Scope
+
+The licenses granted in this Section 2 are the only rights granted under
+this License. No additional rights or licenses will be implied from the
+distribution or licensing of Covered Software under this License.
+Notwithstanding Section 2.1(b) above, no patent license is granted by a
+Contributor:
+
+(a) for any code that a Contributor has removed from Covered Software;
+ or
+
+(b) for infringements caused by: (i) Your and any other third party's
+ modifications of Covered Software, or (ii) the combination of its
+ Contributions with other software (except as part of its Contributor
+ Version); or
+
+(c) under Patent Claims infringed by Covered Software in the absence of
+ its Contributions.
+
+This License does not grant any rights in the trademarks, service marks,
+or logos of any Contributor (except as may be necessary to comply with
+the notice requirements in Section 3.4).
+
+2.4. Subsequent Licenses
+
+No Contributor makes additional grants as a result of Your choice to
+distribute the Covered Software under a subsequent version of this
+License (see Section 10.2) or under the terms of a Secondary License (if
+permitted under the terms of Section 3.3).
+
+2.5. Representation
+
+Each Contributor represents that the Contributor believes its
+Contributions are its original creation(s) or it has sufficient rights
+to grant the rights to its Contributions conveyed by this License.
+
+2.6. Fair Use
+
+This License is not intended to limit any rights You have under
+applicable copyright doctrines of fair use, fair dealing, or other
+equivalents.
+
+2.7. Conditions
+
+Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted
+in Section 2.1.
+
+3. Responsibilities
+-------------------
+
+3.1. Distribution of Source Form
+
+All distribution of Covered Software in Source Code Form, including any
+Modifications that You create or to which You contribute, must be under
+the terms of this License. You must inform recipients that the Source
+Code Form of the Covered Software is governed by the terms of this
+License, and how they can obtain a copy of this License. You may not
+attempt to alter or restrict the recipients' rights in the Source Code
+Form.
+
+3.2. Distribution of Executable Form
+
+If You distribute Covered Software in Executable Form then:
+
+(a) such Covered Software must also be made available in Source Code
+ Form, as described in Section 3.1, and You must inform recipients of
+ the Executable Form how they can obtain a copy of such Source Code
+ Form by reasonable means in a timely manner, at a charge no more
+ than the cost of distribution to the recipient; and
+
+(b) You may distribute such Executable Form under the terms of this
+ License, or sublicense it under different terms, provided that the
+ license for the Executable Form does not attempt to limit or alter
+ the recipients' rights in the Source Code Form under this License.
+
+3.3. Distribution of a Larger Work
+
+You may create and distribute a Larger Work under terms of Your choice,
+provided that You also comply with the requirements of this License for
+the Covered Software. If the Larger Work is a combination of Covered
+Software with a work governed by one or more Secondary Licenses, and the
+Covered Software is not Incompatible With Secondary Licenses, this
+License permits You to additionally distribute such Covered Software
+under the terms of such Secondary License(s), so that the recipient of
+the Larger Work may, at their option, further distribute the Covered
+Software under the terms of either this License or such Secondary
+License(s).
+
+3.4. Notices
+
+You may not remove or alter the substance of any license notices
+(including copyright notices, patent notices, disclaimers of warranty,
+or limitations of liability) contained within the Source Code Form of
+the Covered Software, except that You may alter any license notices to
+the extent required to remedy known factual inaccuracies.
+
+3.5. Application of Additional Terms
+
+You may choose to offer, and to charge a fee for, warranty, support,
+indemnity or liability obligations to one or more recipients of Covered
+Software. However, You may do so only on Your own behalf, and not on
+behalf of any Contributor. You must make it absolutely clear that any
+such warranty, support, indemnity, or liability obligation is offered by
+You alone, and You hereby agree to indemnify every Contributor for any
+liability incurred by such Contributor as a result of warranty, support,
+indemnity or liability terms You offer. You may include additional
+disclaimers of warranty and limitations of liability specific to any
+jurisdiction.
+
+4. Inability to Comply Due to Statute or Regulation
+---------------------------------------------------
+
+If it is impossible for You to comply with any of the terms of this
+License with respect to some or all of the Covered Software due to
+statute, judicial order, or regulation then You must: (a) comply with
+the terms of this License to the maximum extent possible; and (b)
+describe the limitations and the code they affect. Such description must
+be placed in a text file included with all distributions of the Covered
+Software under this License. Except to the extent prohibited by statute
+or regulation, such description must be sufficiently detailed for a
+recipient of ordinary skill to be able to understand it.
+
+5. Termination
+--------------
+
+5.1. The rights granted under this License will terminate automatically
+if You fail to comply with any of its terms. However, if You become
+compliant, then the rights granted under this License from a particular
+Contributor are reinstated (a) provisionally, unless and until such
+Contributor explicitly and finally terminates Your grants, and (b) on an
+ongoing basis, if such Contributor fails to notify You of the
+non-compliance by some reasonable means prior to 60 days after You have
+come back into compliance. Moreover, Your grants from a particular
+Contributor are reinstated on an ongoing basis if such Contributor
+notifies You of the non-compliance by some reasonable means, this is the
+first time You have received notice of non-compliance with this License
+from such Contributor, and You become compliant prior to 30 days after
+Your receipt of the notice.
+
+5.2. If You initiate litigation against any entity by asserting a patent
+infringement claim (excluding declaratory judgment actions,
+counter-claims, and cross-claims) alleging that a Contributor Version
+directly or indirectly infringes any patent, then the rights granted to
+You by any and all Contributors for the Covered Software under Section
+2.1 of this License shall terminate.
+
+5.3. In the event of termination under Sections 5.1 or 5.2 above, all
+end user license agreements (excluding distributors and resellers) which
+have been validly granted by You or Your distributors under this License
+prior to termination shall survive termination.
+
+************************************************************************
+* *
+* 6. Disclaimer of Warranty *
+* ------------------------- *
+* *
+* Covered Software is provided under this License on an "as is" *
+* basis, without warranty of any kind, either expressed, implied, or *
+* statutory, including, without limitation, warranties that the *
+* Covered Software is free of defects, merchantable, fit for a *
+* particular purpose or non-infringing. The entire risk as to the *
+* quality and performance of the Covered Software is with You. *
+* Should any Covered Software prove defective in any respect, You *
+* (not any Contributor) assume the cost of any necessary servicing, *
+* repair, or correction. This disclaimer of warranty constitutes an *
+* essential part of this License. No use of any Covered Software is *
+* authorized under this License except under this disclaimer. *
+* *
+************************************************************************
+
+************************************************************************
+* *
+* 7. Limitation of Liability *
+* -------------------------- *
+* *
+* Under no circumstances and under no legal theory, whether tort *
+* (including negligence), contract, or otherwise, shall any *
+* Contributor, or anyone who distributes Covered Software as *
+* permitted above, be liable to You for any direct, indirect, *
+* special, incidental, or consequential damages of any character *
+* including, without limitation, damages for lost profits, loss of *
+* goodwill, work stoppage, computer failure or malfunction, or any *
+* and all other commercial damages or losses, even if such party *
+* shall have been informed of the possibility of such damages. This *
+* limitation of liability shall not apply to liability for death or *
+* personal injury resulting from such party's negligence to the *
+* extent applicable law prohibits such limitation. Some *
+* jurisdictions do not allow the exclusion or limitation of *
+* incidental or consequential damages, so this exclusion and *
+* limitation may not apply to You. *
+* *
+************************************************************************
+
+8. Litigation
+-------------
+
+Any litigation relating to this License may be brought only in the
+courts of a jurisdiction where the defendant maintains its principal
+place of business and such litigation shall be governed by laws of that
+jurisdiction, without reference to its conflict-of-law provisions.
+Nothing in this Section shall prevent a party's ability to bring
+cross-claims or counter-claims.
+
+9. Miscellaneous
+----------------
+
+This License represents the complete agreement concerning the subject
+matter hereof. If any provision of this License is held to be
+unenforceable, such provision shall be reformed only to the extent
+necessary to make it enforceable. Any law or regulation which provides
+that the language of a contract shall be construed against the drafter
+shall not be used to construe this License against a Contributor.
+
+10. Versions of the License
+---------------------------
+
+10.1. New Versions
+
+Mozilla Foundation is the license steward. Except as provided in Section
+10.3, no one other than the license steward has the right to modify or
+publish new versions of this License. Each version will be given a
+distinguishing version number.
+
+10.2. Effect of New Versions
+
+You may distribute the Covered Software under the terms of the version
+of the License under which You originally received the Covered Software,
+or under the terms of any subsequent version published by the license
+steward.
+
+10.3. Modified Versions
+
+If you create software not governed by this License, and you want to
+create a new license for such software, you may create and use a
+modified version of this License if you rename the license and remove
+any references to the name of the license steward (except to note that
+such modified license differs from this License).
+
+10.4. Distributing Source Code Form that is Incompatible With Secondary
+Licenses
+
+If You choose to distribute Source Code Form that is Incompatible With
+Secondary Licenses under the terms of this version of the License, the
+notice described in Exhibit B of this License must be attached.
+
+Exhibit A - Source Code Form License Notice
+-------------------------------------------
+
+ This Source Code Form is subject to the terms of the Mozilla Public
+ License, v. 2.0. If a copy of the MPL was not distributed with this
+ file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+If it is not possible or desirable to put the notice in a particular
+file, then You may include the notice in a location (such as a LICENSE
+file in a relevant directory) where a recipient would be likely to look
+for such a notice.
+
+You may add additional accurate notices of copyright ownership.
+
+Exhibit B - "Incompatible With Secondary Licenses" Notice
+---------------------------------------------------------
+
+ This Source Code Form is "Incompatible With Secondary Licenses", as
+ defined by the Mozilla Public License, v. 2.0.
diff --git a/third_party/rust/dtoa-short/src/lib.rs b/third_party/rust/dtoa-short/src/lib.rs
new file mode 100644
index 0000000000..c5c23eeade
--- /dev/null
+++ b/third_party/rust/dtoa-short/src/lib.rs
@@ -0,0 +1,197 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+extern crate dtoa;
+
+use std::fmt::Write;
+use std::{fmt, str};
+
+/// Format the given `value` into `dest` and return the notation it uses.
+#[inline]
+pub fn write<W: Write, V: Floating>(dest: &mut W, value: V) -> DtoaResult {
+ Floating::write(value, dest)
+}
+
+/// Form of the formatted floating-point number.
+#[derive(Debug, PartialEq, Eq, Clone, Copy)]
+pub struct Notation {
+ /// Whether it contains a decimal point.
+ pub decimal_point: bool,
+ /// Whether it uses E-notation.
+ pub scientific: bool,
+}
+
+impl Notation {
+ fn integer() -> Self {
+ Notation {
+ decimal_point: false,
+ scientific: false,
+ }
+ }
+}
+
+/// Result of formatting the number.
+pub type DtoaResult = Result<Notation, fmt::Error>;
+
+pub trait Floating : dtoa::Floating {
+ fn write<W: Write>(self, dest: &mut W) -> DtoaResult;
+}
+
+impl Floating for f32 {
+ fn write<W: Write>(self, dest: &mut W) -> DtoaResult {
+ write_with_prec(dest, self, 6)
+ }
+}
+
+impl Floating for f64 {
+ fn write<W: Write>(self, dest: &mut W) -> DtoaResult {
+ write_with_prec(dest, self, 15)
+ }
+}
+
+// dtoa's buffer is 24 bytes, so we use the same length here. We may
+// need to update if dtoa changes its number in the future. See
+// https://github.com/dtolnay/dtoa/blob/
+// 584674a70af74521ce40350dba776ea67cfcbaa7/src/dtoa.rs#L465
+const BUFFER_SIZE: usize = 24;
+
+fn write_with_prec<W, V>(dest: &mut W, value: V, prec: usize)
+ -> DtoaResult where W: Write, V: dtoa::Floating
+{
+ let mut buf = [b'\0'; BUFFER_SIZE + 8];
+ let len = dtoa::write(&mut buf[1..], value).map_err(|_| fmt::Error)?;
+ let (result, notation) = restrict_prec(&mut buf[0..len + 1], prec);
+ dest.write_str(if cfg!(debug_assertions) {
+ str::from_utf8(result).unwrap()
+ } else {
+ // safety: dtoa only generates ascii.
+ unsafe { str::from_utf8_unchecked(result) }
+ })?;
+ Ok(notation)
+}
+
+fn restrict_prec(buf: &mut [u8], prec: usize) -> (&[u8], Notation) {
+ let len = buf.len();
+ debug_assert!(len <= BUFFER_SIZE + 1, "dtoa may have changed its buffer size");
+ // Put a leading zero to capture any carry.
+ debug_assert!(buf[0] == b'\0', "Caller must prepare an empty byte for us");
+ buf[0] = b'0';
+ // Remove the sign for now. We will put it back at the end.
+ let sign = match buf[1] {
+ s @ b'+' | s @ b'-' => {
+ buf[1] = b'0';
+ Some(s)
+ }
+ _ => None,
+ };
+ // Locate dot, exponent, and the first significant digit.
+ let mut pos_dot = None;
+ let mut pos_exp = None;
+ let mut prec_start = None;
+ for i in 1..len {
+ if buf[i] == b'.' {
+ debug_assert!(pos_dot.is_none());
+ pos_dot = Some(i);
+ } else if buf[i] == b'e' {
+ pos_exp = Some(i);
+ // We don't change exponent part, so stop here.
+ break;
+ } else if prec_start.is_none() && buf[i] != b'0' {
+ debug_assert!(buf[i] >= b'1' && buf[i] <= b'9');
+ prec_start = Some(i);
+ }
+ }
+ let prec_start = match prec_start {
+ Some(i) => i,
+ // If there is no non-zero digit at all, it is just zero.
+ None => return (&buf[0..1], Notation::integer()),
+ };
+ // Coefficient part ends at 'e' or the length.
+ let coeff_end = pos_exp.unwrap_or(len);
+ // Decimal dot is effectively at the end of coefficient part if no
+ // dot presents before that.
+ let pos_dot = pos_dot.unwrap_or(coeff_end);
+ // Find the end position of the number within the given precision.
+ let prec_end = {
+ let end = prec_start + prec;
+ if pos_dot > prec_start && pos_dot <= end {
+ end + 1
+ } else {
+ end
+ }
+ };
+ let mut new_coeff_end = coeff_end;
+ if prec_end < coeff_end {
+ // Round to the given precision.
+ let next_char = buf[prec_end];
+ new_coeff_end = prec_end;
+ if next_char >= b'5' {
+ for i in (0..prec_end).rev() {
+ if buf[i] == b'.' {
+ continue;
+ }
+ if buf[i] != b'9' {
+ buf[i] += 1;
+ new_coeff_end = i + 1;
+ break;
+ }
+ buf[i] = b'0';
+ }
+ }
+ }
+ if new_coeff_end < pos_dot {
+ // If the precision isn't enough to reach the dot, set all digits
+ // in-between to zero and keep the number until the dot.
+ for i in new_coeff_end..pos_dot {
+ buf[i] = b'0';
+ }
+ new_coeff_end = pos_dot;
+ } else {
+ // Strip any trailing zeros.
+ for i in (0..new_coeff_end).rev() {
+ if buf[i] != b'0' {
+ if buf[i] == b'.' {
+ new_coeff_end = i;
+ }
+ break;
+ }
+ new_coeff_end = i;
+ }
+ }
+ // Move exponent part if necessary.
+ let real_end = if let Some(pos_exp) = pos_exp {
+ let exp_len = len - pos_exp;
+ if new_coeff_end != pos_exp {
+ for i in 0..exp_len {
+ buf[new_coeff_end + i] = buf[pos_exp + i];
+ }
+ }
+ new_coeff_end + exp_len
+ } else {
+ new_coeff_end
+ };
+ // Add back the sign and strip the leading zero.
+ let result = if let Some(sign) = sign {
+ if buf[1] == b'0' && buf[2] != b'.' {
+ buf[1] = sign;
+ &buf[1..real_end]
+ } else {
+ debug_assert!(buf[0] == b'0');
+ buf[0] = sign;
+ &buf[0..real_end]
+ }
+ } else {
+ if buf[0] == b'0' && buf[1] != b'.' {
+ &buf[1..real_end]
+ } else {
+ &buf[0..real_end]
+ }
+ };
+ // Generate the notation info.
+ let notation = Notation {
+ decimal_point: pos_dot < new_coeff_end,
+ scientific: pos_exp.is_some(),
+ };
+ (result, notation)
+}
diff --git a/third_party/rust/dtoa/.cargo-checksum.json b/third_party/rust/dtoa/.cargo-checksum.json
new file mode 100644
index 0000000000..550d130236
--- /dev/null
+++ b/third_party/rust/dtoa/.cargo-checksum.json
@@ -0,0 +1 @@
+{"files":{"Cargo.toml":"657b9f00844e4f422237ebd26991476b160da598894d98d1d0be57e4e553c986","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"23f18e03dc49df91622fe2a76176497404e46ced8a715d9d2b67a7446571cca3","README.md":"3416361ff0af6647a1616cc020766df798d683b8645f0d9270512277ee6cb47e","benches/bench.rs":"ac713ab4e1c668dea70416504955563fcd6bd2982ae1cfa3a1c0043e09dd893f","src/diyfp.rs":"89f685b3beb13dff8d4c2e28e16c4891013f7b387e625c5151267b2cd077df1d","src/dtoa.rs":"c70bb76acde7b749dfc9273fd556c73960027b3534c1f56a32768bf8f25985ff","src/lib.rs":"43eb71b7e5d5f802ad3c49148db4e27f9d911aa69ea77777f95feefc2e1f1e93","tests/test.rs":"296f3c322e08508fd372e436434fdd209bb911cab2124ea654d5f78d90f3eeea"},"package":"56899898ce76aaf4a0f24d914c97ea6ed976d42fec6ad33fcbb0a1103e07b2b0"} \ No newline at end of file
diff --git a/third_party/rust/dtoa/Cargo.toml b/third_party/rust/dtoa/Cargo.toml
new file mode 100644
index 0000000000..6382cea1e4
--- /dev/null
+++ b/third_party/rust/dtoa/Cargo.toml
@@ -0,0 +1,25 @@
+# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO
+#
+# When uploading crates to the registry Cargo will automatically
+# "normalize" Cargo.toml files for maximal compatibility
+# with all versions of Cargo and also rewrite `path` dependencies
+# to registry (e.g., crates.io) dependencies
+#
+# If you believe there's an error in this file please file an
+# issue against the rust-lang/cargo repository. If you're
+# editing this file be aware that the upstream Cargo.toml
+# will likely look very different (and much more reasonable)
+
+[package]
+name = "dtoa"
+version = "0.4.8"
+authors = ["David Tolnay <dtolnay@gmail.com>"]
+exclude = ["performance.png"]
+description = "Fast functions for printing floating-point primitives to an io::Write"
+documentation = "https://docs.rs/dtoa"
+readme = "README.md"
+categories = ["value-formatting"]
+license = "MIT OR Apache-2.0"
+repository = "https://github.com/dtolnay/dtoa"
+[package.metadata.docs.rs]
+targets = ["x86_64-unknown-linux-gnu"]
diff --git a/third_party/rust/dtoa/LICENSE-APACHE b/third_party/rust/dtoa/LICENSE-APACHE
new file mode 100644
index 0000000000..16fe87b06e
--- /dev/null
+++ b/third_party/rust/dtoa/LICENSE-APACHE
@@ -0,0 +1,201 @@
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+END OF TERMS AND CONDITIONS
+
+APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "[]"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+Copyright [yyyy] [name of copyright owner]
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
diff --git a/third_party/rust/dtoa/LICENSE-MIT b/third_party/rust/dtoa/LICENSE-MIT
new file mode 100644
index 0000000000..31aa79387f
--- /dev/null
+++ b/third_party/rust/dtoa/LICENSE-MIT
@@ -0,0 +1,23 @@
+Permission is hereby granted, free of charge, to any
+person obtaining a copy of this software and associated
+documentation files (the "Software"), to deal in the
+Software without restriction, including without
+limitation the rights to use, copy, modify, merge,
+publish, distribute, sublicense, and/or sell copies of
+the Software, and to permit persons to whom the Software
+is furnished to do so, subject to the following
+conditions:
+
+The above copyright notice and this permission notice
+shall be included in all copies or substantial portions
+of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
+ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
+TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
+PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
+SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
+IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE.
diff --git a/third_party/rust/dtoa/README.md b/third_party/rust/dtoa/README.md
new file mode 100644
index 0000000000..210d516475
--- /dev/null
+++ b/third_party/rust/dtoa/README.md
@@ -0,0 +1,80 @@
+dtoa
+====
+
+[<img alt="github" src="https://img.shields.io/badge/github-dtolnay/dtoa-8da0cb?style=for-the-badge&labelColor=555555&logo=github" height="20">](https://github.com/dtolnay/dtoa)
+[<img alt="crates.io" src="https://img.shields.io/crates/v/dtoa.svg?style=for-the-badge&color=fc8d62&logo=rust" height="20">](https://crates.io/crates/dtoa)
+[<img alt="docs.rs" src="https://img.shields.io/badge/docs.rs-dtoa-66c2a5?style=for-the-badge&labelColor=555555&logoColor=white&logo=data:image/svg+xml;base64,PHN2ZyByb2xlPSJpbWciIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgdmlld0JveD0iMCAwIDUxMiA1MTIiPjxwYXRoIGZpbGw9IiNmNWY1ZjUiIGQ9Ik00ODguNiAyNTAuMkwzOTIgMjE0VjEwNS41YzAtMTUtOS4zLTI4LjQtMjMuNC0zMy43bC0xMDAtMzcuNWMtOC4xLTMuMS0xNy4xLTMuMS0yNS4zIDBsLTEwMCAzNy41Yy0xNC4xIDUuMy0yMy40IDE4LjctMjMuNCAzMy43VjIxNGwtOTYuNiAzNi4yQzkuMyAyNTUuNSAwIDI2OC45IDAgMjgzLjlWMzk0YzAgMTMuNiA3LjcgMjYuMSAxOS45IDMyLjJsMTAwIDUwYzEwLjEgNS4xIDIyLjEgNS4xIDMyLjIgMGwxMDMuOS01MiAxMDMuOSA1MmMxMC4xIDUuMSAyMi4xIDUuMSAzMi4yIDBsMTAwLTUwYzEyLjItNi4xIDE5LjktMTguNiAxOS45LTMyLjJWMjgzLjljMC0xNS05LjMtMjguNC0yMy40LTMzLjd6TTM1OCAyMTQuOGwtODUgMzEuOXYtNjguMmw4NS0zN3Y3My4zek0xNTQgMTA0LjFsMTAyLTM4LjIgMTAyIDM4LjJ2LjZsLTEwMiA0MS40LTEwMi00MS40di0uNnptODQgMjkxLjFsLTg1IDQyLjV2LTc5LjFsODUtMzguOHY3NS40em0wLTExMmwtMTAyIDQxLjQtMTAyLTQxLjR2LS42bDEwMi0zOC4yIDEwMiAzOC4ydi42em0yNDAgMTEybC04NSA0Mi41di03OS4xbDg1LTM4Ljh2NzUuNHptMC0xMTJsLTEwMiA0MS40LTEwMi00MS40di0uNmwxMDItMzguMiAxMDIgMzguMnYuNnoiPjwvcGF0aD48L3N2Zz4K" height="20">](https://docs.rs/dtoa)
+[<img alt="build status" src="https://img.shields.io/github/workflow/status/dtolnay/dtoa/CI/master?style=for-the-badge" height="20">](https://github.com/dtolnay/dtoa/actions?query=branch%3Amaster)
+
+This crate provides fast functions for printing floating-point primitives to an
+[`io::Write`]. The implementation is a straightforward Rust port of [Milo Yip]'s
+C++ implementation [dtoa.h]. The original C++ code of each function is included
+in comments.
+
+See also [`itoa`] for printing integer primitives.
+
+*Version requirement: rustc 1.0+*
+
+[`io::Write`]: https://doc.rust-lang.org/std/io/trait.Write.html
+[Milo Yip]: https://github.com/miloyip
+[dtoa.h]: https://github.com/miloyip/rapidjson/blob/master/include/rapidjson/internal/dtoa.h
+[`itoa`]: https://github.com/dtolnay/itoa
+
+```toml
+[dependencies]
+dtoa = "0.4"
+```
+
+<br>
+
+## Performance (lower is better)
+
+![performance](https://raw.githubusercontent.com/dtolnay/dtoa/master/performance.png)
+
+<br>
+
+## Examples
+
+```rust
+use std::io;
+
+fn main() -> io::Result<()> {
+ // Write to a vector or other io::Write.
+ let mut buf = Vec::new();
+ dtoa::write(&mut buf, 2.71828f64)?;
+ println!("{:?}", buf);
+
+ // Write to a stack buffer.
+ let mut bytes = [b'\0'; 20];
+ let n = dtoa::write(&mut bytes[..], 2.71828f64)?;
+ println!("{:?}", &bytes[..n]);
+
+ Ok(())
+}
+```
+
+The function signature is:
+
+```rust
+fn write<W: io::Write, V: dtoa::Floating>(writer: W, value: V) -> io::Result<()>;
+```
+
+where `dtoa::Floating` is implemented for f32 and f64. The return value gives
+the number of bytes written.
+
+<br>
+
+#### License
+
+<sup>
+Licensed under either of <a href="LICENSE-APACHE">Apache License, Version
+2.0</a> or <a href="LICENSE-MIT">MIT license</a> at your option.
+</sup>
+
+<br>
+
+<sub>
+Unless you explicitly state otherwise, any contribution intentionally submitted
+for inclusion in this crate by you, as defined in the Apache-2.0 license, shall
+be dual licensed as above, without any additional terms or conditions.
+</sub>
diff --git a/third_party/rust/dtoa/benches/bench.rs b/third_party/rust/dtoa/benches/bench.rs
new file mode 100644
index 0000000000..ec57953563
--- /dev/null
+++ b/third_party/rust/dtoa/benches/bench.rs
@@ -0,0 +1,54 @@
+#![feature(test)]
+
+extern crate dtoa;
+extern crate test;
+
+macro_rules! benches {
+ ($($name:ident($value:expr),)*) => {
+ mod bench_dtoa {
+ use test::{Bencher, black_box};
+ $(
+ #[bench]
+ fn $name(b: &mut Bencher) {
+ use dtoa;
+
+ let mut buf = Vec::with_capacity(20);
+
+ b.iter(|| {
+ buf.clear();
+ dtoa::write(&mut buf, black_box($value)).unwrap()
+ });
+ }
+ )*
+ }
+
+ mod bench_fmt {
+ use test::{Bencher, black_box};
+ $(
+ #[bench]
+ fn $name(b: &mut Bencher) {
+ use std::io::Write;
+
+ let mut buf = Vec::with_capacity(20);
+
+ b.iter(|| {
+ buf.clear();
+ write!(&mut buf, "{}", black_box($value)).unwrap()
+ });
+ }
+ )*
+ }
+ }
+}
+
+benches!(
+ bench_0_f64(0f64),
+ bench_short_f64(0.1234f64),
+ bench_e_f64(2.718281828459045f64),
+ bench_max_f64(::std::f64::MAX),
+
+ bench_0_f32(0f32),
+ bench_short_f32(0.1234f32),
+ bench_e_f32(2.718281828459045f32),
+ bench_max_f32(::std::f32::MAX),
+);
diff --git a/third_party/rust/dtoa/src/diyfp.rs b/third_party/rust/dtoa/src/diyfp.rs
new file mode 100644
index 0000000000..9d797657d6
--- /dev/null
+++ b/third_party/rust/dtoa/src/diyfp.rs
@@ -0,0 +1,253 @@
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+//
+// ---
+//
+// The C++ implementation preserved here in comments is licensed as follows:
+//
+// Tencent is pleased to support the open source community by making RapidJSON
+// available.
+//
+// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All
+// rights reserved.
+//
+// Licensed under the MIT License (the "License"); you may not use this file
+// except in compliance with the License. You may obtain a copy of the License
+// at
+//
+// http://opensource.org/licenses/MIT
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+// License for the specific language governing permissions and limitations under
+// the License.
+
+use std::ops;
+
+#[derive(Copy, Clone, Debug)]
+pub struct DiyFp<F, E> {
+ pub f: F,
+ pub e: E,
+}
+
+impl<F, E> DiyFp<F, E> {
+ pub fn new(f: F, e: E) -> Self {
+ DiyFp { f: f, e: e }
+ }
+}
+
+impl ops::Mul for DiyFp<u32, i32> {
+ type Output = Self;
+ fn mul(self, rhs: Self) -> Self {
+ let mut tmp = self.f as u64 * rhs.f as u64;
+ tmp += 1u64 << 31; // mult_round
+ DiyFp {
+ f: (tmp >> 32) as u32,
+ e: self.e + rhs.e + 32,
+ }
+ }
+}
+
+impl ops::Mul for DiyFp<u64, isize> {
+ type Output = Self;
+ fn mul(self, rhs: Self) -> Self {
+ let m32 = 0xFFFFFFFFu64;
+ let a = self.f >> 32;
+ let b = self.f & m32;
+ let c = rhs.f >> 32;
+ let d = rhs.f & m32;
+ let ac = a * c;
+ let bc = b * c;
+ let ad = a * d;
+ let bd = b * d;
+ let mut tmp = (bd >> 32) + (ad & m32) + (bc & m32);
+ tmp += 1u64 << 31; // mult_round
+ DiyFp {
+ f: ac + (ad >> 32) + (bc >> 32) + (tmp >> 32),
+ e: self.e + rhs.e + 64,
+ }
+ }
+}
+
+#[doc(hidden)]
+#[macro_export]
+macro_rules! diyfp {(
+ floating_type: $fty:ty,
+ significand_type: $sigty:ty,
+ exponent_type: $expty:ty,
+
+ diy_significand_size: $diy_significand_size:expr,
+ significand_size: $significand_size:expr,
+ exponent_bias: $exponent_bias:expr,
+ mask_type: $mask_type:ty,
+ exponent_mask: $exponent_mask:expr,
+ significand_mask: $significand_mask:expr,
+ hidden_bit: $hidden_bit:expr,
+ cached_powers_f: $cached_powers_f:expr,
+ cached_powers_e: $cached_powers_e:expr,
+ min_power: $min_power:expr,
+) => {
+
+type DiyFp = diyfp::DiyFp<$sigty, $expty>;
+
+impl DiyFp {
+ // Preconditions:
+ // `d` must have a positive sign and must not be infinity or NaN.
+ /*
+ explicit DiyFp(double d) {
+ union {
+ double d;
+ uint64_t u64;
+ } u = { d };
+
+ int biased_e = static_cast<int>((u.u64 & kDpExponentMask) >> kDpSignificandSize);
+ uint64_t significand = (u.u64 & kDpSignificandMask);
+ if (biased_e != 0) {
+ f = significand + kDpHiddenBit;
+ e = biased_e - kDpExponentBias;
+ }
+ else {
+ f = significand;
+ e = kDpMinExponent + 1;
+ }
+ }
+ */
+ unsafe fn from(d: $fty) -> Self {
+ let u: $mask_type = mem::transmute(d);
+
+ let biased_e = ((u & $exponent_mask) >> $significand_size) as $expty;
+ let significand = u & $significand_mask;
+ if biased_e != 0 {
+ DiyFp {
+ f: significand + $hidden_bit,
+ e: biased_e - $exponent_bias - $significand_size,
+ }
+ } else {
+ DiyFp {
+ f: significand,
+ e: 1 - $exponent_bias - $significand_size,
+ }
+ }
+ }
+
+ // Normalizes so that the highest bit of the diy significand is 1.
+ /*
+ DiyFp Normalize() const {
+ DiyFp res = *this;
+ while (!(res.f & (static_cast<uint64_t>(1) << 63))) {
+ res.f <<= 1;
+ res.e--;
+ }
+ return res;
+ }
+ */
+ fn normalize(self) -> DiyFp {
+ let mut res = self;
+ while (res.f & (1 << ($diy_significand_size - 1))) == 0 {
+ res.f <<= 1;
+ res.e -= 1;
+ }
+ res
+ }
+
+ // Normalizes so that the highest bit of the diy significand is 1.
+ //
+ // Precondition:
+ // `self.f` must be no more than 2 bits longer than the f64 significand.
+ /*
+ DiyFp NormalizeBoundary() const {
+ DiyFp res = *this;
+ while (!(res.f & (kDpHiddenBit << 1))) {
+ res.f <<= 1;
+ res.e--;
+ }
+ res.f <<= (kDiySignificandSize - kDpSignificandSize - 2);
+ res.e = res.e - (kDiySignificandSize - kDpSignificandSize - 2);
+ return res;
+ }
+ */
+ fn normalize_boundary(self) -> DiyFp {
+ let mut res = self;
+ while (res.f & $hidden_bit << 1) == 0 {
+ res.f <<= 1;
+ res.e -= 1;
+ }
+ res.f <<= $diy_significand_size - $significand_size - 2;
+ res.e -= $diy_significand_size - $significand_size - 2;
+ res
+ }
+
+ // Normalizes `self - e` and `self + e` where `e` is half of the least
+ // significant digit of `self`. The plus is normalized so that the highest
+ // bit of the diy significand is 1. The minus is normalized so that it has
+ // the same exponent as the plus.
+ //
+ // Preconditions:
+ // `self` must have been returned directly from `DiyFp::from_f64`.
+ // `self.f` must not be zero.
+ /*
+ void NormalizedBoundaries(DiyFp* minus, DiyFp* plus) const {
+ DiyFp pl = DiyFp((f << 1) + 1, e - 1).NormalizeBoundary();
+ DiyFp mi = (f == kDpHiddenBit) ? DiyFp((f << 2) - 1, e - 2) : DiyFp((f << 1) - 1, e - 1);
+ mi.f <<= mi.e - pl.e;
+ mi.e = pl.e;
+ *plus = pl;
+ *minus = mi;
+ }
+ */
+ fn normalized_boundaries(self) -> (DiyFp, DiyFp) {
+ let pl = DiyFp::new((self.f << 1) + 1, self.e - 1).normalize_boundary();
+ let mut mi = if self.f == $hidden_bit {
+ DiyFp::new((self.f << 2) - 1, self.e - 2)
+ } else {
+ DiyFp::new((self.f << 1) - 1, self.e - 1)
+ };
+ mi.f <<= mi.e - pl.e;
+ mi.e = pl.e;
+ (mi, pl)
+ }
+}
+
+impl ops::Sub for DiyFp {
+ type Output = Self;
+ fn sub(self, rhs: Self) -> Self {
+ DiyFp {
+ f: self.f - rhs.f,
+ e: self.e,
+ }
+ }
+}
+
+/*
+inline DiyFp GetCachedPower(int e, int* K) {
+ //int k = static_cast<int>(ceil((-61 - e) * 0.30102999566398114)) + 374;
+ double dk = (-61 - e) * 0.30102999566398114 + 347; // dk must be positive, so can do ceiling in positive
+ int k = static_cast<int>(dk);
+ if (dk - k > 0.0)
+ k++;
+
+ unsigned index = static_cast<unsigned>((k >> 3) + 1);
+ *K = -(-348 + static_cast<int>(index << 3)); // decimal exponent no need lookup table
+
+ return GetCachedPowerByIndex(index);
+}
+*/
+#[inline]
+fn get_cached_power(e: $expty) -> (DiyFp, isize) {
+ let dk = (3 - $diy_significand_size - e) as f64 * 0.30102999566398114f64 - ($min_power + 1) as f64;
+ let mut k = dk as isize;
+ if dk - k as f64 > 0.0 {
+ k += 1;
+ }
+
+ let index = ((k >> 3) + 1) as usize;
+ let k = -($min_power + (index << 3) as isize);
+
+ (DiyFp::new($cached_powers_f[index], $cached_powers_e[index] as $expty), k)
+}
+
+}}
diff --git a/third_party/rust/dtoa/src/dtoa.rs b/third_party/rust/dtoa/src/dtoa.rs
new file mode 100644
index 0000000000..8642a38920
--- /dev/null
+++ b/third_party/rust/dtoa/src/dtoa.rs
@@ -0,0 +1,509 @@
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+//
+// ---
+//
+// The C++ implementation preserved here in comments is licensed as follows:
+//
+// Tencent is pleased to support the open source community by making RapidJSON
+// available.
+//
+// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All
+// rights reserved.
+//
+// Licensed under the MIT License (the "License"); you may not use this file
+// except in compliance with the License. You may obtain a copy of the License
+// at
+//
+// http://opensource.org/licenses/MIT
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+// License for the specific language governing permissions and limitations under
+// the License.
+
+#[doc(hidden)]
+#[macro_export]
+macro_rules! dtoa {(
+ floating_type: $fty:ty,
+ significand_type: $sigty:ty,
+ exponent_type: $expty:ty,
+ $($diyfp_param:ident: $diyfp_value:tt,)*
+) => {
+
+diyfp! {
+ floating_type: $fty,
+ significand_type: $sigty,
+ exponent_type: $expty,
+ $($diyfp_param: $diyfp_value,)*
+};
+
+/*
+inline void GrisuRound(char* buffer, int len, uint64_t delta, uint64_t rest, uint64_t ten_kappa, uint64_t wp_w) {
+ while (rest < wp_w && delta - rest >= ten_kappa &&
+ (rest + ten_kappa < wp_w || /// closer
+ wp_w - rest > rest + ten_kappa - wp_w)) {
+ buffer[len - 1]--;
+ rest += ten_kappa;
+ }
+}
+*/
+
+#[inline]
+unsafe fn grisu_round(buffer: *mut u8, len: isize, delta: $sigty, mut rest: $sigty, ten_kappa: $sigty, wp_w: $sigty) {
+ while rest < wp_w && delta - rest >= ten_kappa &&
+ (rest + ten_kappa < wp_w || // closer
+ wp_w - rest > rest + ten_kappa - wp_w) {
+ *buffer.offset(len - 1) -= 1;
+ rest += ten_kappa;
+ }
+}
+
+/*
+inline unsigned CountDecimalDigit32(uint32_t n) {
+ // Simple pure C++ implementation was faster than __builtin_clz version in this situation.
+ if (n < 10) return 1;
+ if (n < 100) return 2;
+ if (n < 1000) return 3;
+ if (n < 10000) return 4;
+ if (n < 100000) return 5;
+ if (n < 1000000) return 6;
+ if (n < 10000000) return 7;
+ if (n < 100000000) return 8;
+ // Will not reach 10 digits in DigitGen()
+ //if (n < 1000000000) return 9;
+ //return 10;
+ return 9;
+}
+*/
+
+#[inline]
+fn count_decimal_digit32(n: u32) -> usize {
+ if n < 10 { 1 }
+ else if n < 100 { 2 }
+ else if n < 1000 { 3 }
+ else if n < 10000 { 4 }
+ else if n < 100000 { 5 }
+ else if n < 1000000 { 6 }
+ else if n < 10000000 { 7 }
+ else if n < 100000000 { 8 }
+ // Will not reach 10 digits in digit_gen()
+ else { 9 }
+}
+
+/*
+inline void DigitGen(const DiyFp& W, const DiyFp& Mp, uint64_t delta, char* buffer, int* len, int* K) {
+ static const uint32_t kPow10[] = { 1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000 };
+ const DiyFp one(uint64_t(1) << -Mp.e, Mp.e);
+ const DiyFp wp_w = Mp - W;
+ uint32_t p1 = static_cast<uint32_t>(Mp.f >> -one.e);
+ uint64_t p2 = Mp.f & (one.f - 1);
+ unsigned kappa = CountDecimalDigit32(p1); // kappa in [0, 9]
+ *len = 0;
+*/
+
+// Returns length and k.
+#[inline]
+unsafe fn digit_gen(w: DiyFp, mp: DiyFp, mut delta: $sigty, buffer: *mut u8, mut k: isize) -> (isize, isize) {
+ static POW10: [$sigty; 10] = [ 1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000 ];
+ let one = DiyFp::new(1 << -mp.e, mp.e);
+ let wp_w = mp - w;
+ let mut p1 = (mp.f >> -one.e) as u32;
+ let mut p2 = mp.f & (one.f - 1);
+ let mut kappa = count_decimal_digit32(p1); // kappa in [0, 9]
+ let mut len = 0;
+
+ /*
+ while (kappa > 0) {
+ uint32_t d = 0;
+ switch (kappa) {
+ case 9: d = p1 / 100000000; p1 %= 100000000; break;
+ case 8: d = p1 / 10000000; p1 %= 10000000; break;
+ case 7: d = p1 / 1000000; p1 %= 1000000; break;
+ case 6: d = p1 / 100000; p1 %= 100000; break;
+ case 5: d = p1 / 10000; p1 %= 10000; break;
+ case 4: d = p1 / 1000; p1 %= 1000; break;
+ case 3: d = p1 / 100; p1 %= 100; break;
+ case 2: d = p1 / 10; p1 %= 10; break;
+ case 1: d = p1; p1 = 0; break;
+ default:;
+ }
+ if (d || *len)
+ buffer[(*len)++] = static_cast<char>('0' + static_cast<char>(d));
+ kappa--;
+ uint64_t tmp = (static_cast<uint64_t>(p1) << -one.e) + p2;
+ if (tmp <= delta) {
+ *K += kappa;
+ GrisuRound(buffer, *len, delta, tmp, static_cast<uint64_t>(kPow10[kappa]) << -one.e, wp_w.f);
+ return;
+ }
+ }
+ */
+ while kappa > 0 {
+ let mut d = 0u32;
+ match kappa {
+ 9 => { d = p1 / 100000000; p1 %= 100000000; }
+ 8 => { d = p1 / 10000000; p1 %= 10000000; }
+ 7 => { d = p1 / 1000000; p1 %= 1000000; }
+ 6 => { d = p1 / 100000; p1 %= 100000; }
+ 5 => { d = p1 / 10000; p1 %= 10000; }
+ 4 => { d = p1 / 1000; p1 %= 1000; }
+ 3 => { d = p1 / 100; p1 %= 100; }
+ 2 => { d = p1 / 10; p1 %= 10; }
+ 1 => { d = p1; p1 = 0; }
+ _ => {}
+ }
+ if d != 0 || len != 0 {
+ *buffer.offset(len) = b'0' + d as u8;
+ len += 1;
+ }
+ kappa -= 1;
+ let tmp = (p1 as $sigty << -one.e) + p2;
+ if tmp <= delta {
+ k += kappa as isize;
+ grisu_round(buffer, len, delta, tmp, POW10[kappa] << -one.e, wp_w.f);
+ return (len, k);
+ }
+ }
+
+ // kappa = 0
+ /*
+ for (;;) {
+ p2 *= 10;
+ delta *= 10;
+ char d = static_cast<char>(p2 >> -one.e);
+ if (d || *len)
+ buffer[(*len)++] = static_cast<char>('0' + d);
+ p2 &= one.f - 1;
+ kappa--;
+ if (p2 < delta) {
+ *K += kappa;
+ int index = -static_cast<int>(kappa);
+ GrisuRound(buffer, *len, delta, p2, one.f, wp_w.f * (index < 9 ? kPow10[-static_cast<int>(kappa)] : 0));
+ return;
+ }
+ }
+ */
+ loop {
+ p2 *= 10;
+ delta *= 10;
+ let d = (p2 >> -one.e) as u8;
+ if d != 0 || len != 0 {
+ *buffer.offset(len) = b'0' + d;
+ len += 1;
+ }
+ p2 &= one.f - 1;
+ kappa = kappa.wrapping_sub(1);
+ if p2 < delta {
+ k += kappa as isize;
+ let index = -(kappa as isize);
+ grisu_round(buffer, len, delta, p2, one.f, wp_w.f * if index < 9 { POW10[-(kappa as isize) as usize] } else { 0 });
+ return (len, k);
+ }
+ }
+}
+
+/*
+inline void Grisu2(double value, char* buffer, int* length, int* K) {
+ const DiyFp v(value);
+ DiyFp w_m, w_p;
+ v.NormalizedBoundaries(&w_m, &w_p);
+
+ const DiyFp c_mk = GetCachedPower(w_p.e, K);
+ const DiyFp W = v.Normalize() * c_mk;
+ DiyFp Wp = w_p * c_mk;
+ DiyFp Wm = w_m * c_mk;
+ Wm.f++;
+ Wp.f--;
+ DigitGen(W, Wp, Wp.f - Wm.f, buffer, length, K);
+}
+*/
+
+// Returns length and k.
+#[inline]
+unsafe fn grisu2(value: $fty, buffer: *mut u8) -> (isize, isize) {
+ let v = DiyFp::from(value);
+ let (w_m, w_p) = v.normalized_boundaries();
+
+ let (c_mk, k) = get_cached_power(w_p.e);
+ let w = v.normalize() * c_mk;
+ let mut wp = w_p * c_mk;
+ let mut wm = w_m * c_mk;
+ wm.f += 1;
+ wp.f -= 1;
+ digit_gen(w, wp, wp.f - wm.f, buffer, k)
+}
+
+/*
+inline char* WriteExponent(int K, char* buffer) {
+ if (K < 0) {
+ *buffer++ = '-';
+ K = -K;
+ }
+
+ if (K >= 100) {
+ *buffer++ = static_cast<char>('0' + static_cast<char>(K / 100));
+ K %= 100;
+ const char* d = GetDigitsLut() + K * 2;
+ *buffer++ = d[0];
+ *buffer++ = d[1];
+ }
+ else if (K >= 10) {
+ const char* d = GetDigitsLut() + K * 2;
+ *buffer++ = d[0];
+ *buffer++ = d[1];
+ }
+ else
+ *buffer++ = static_cast<char>('0' + static_cast<char>(K));
+
+ return buffer;
+}
+*/
+
+#[inline]
+unsafe fn write_exponent(mut k: isize, mut buffer: *mut u8) -> *mut u8 {
+ if k < 0 {
+ *buffer = b'-';
+ buffer = buffer.offset(1);
+ k = -k;
+ }
+
+ if k >= 100 {
+ *buffer = b'0' + (k / 100) as u8;
+ k %= 100;
+ let d = DEC_DIGITS_LUT.get_unchecked(k as usize * 2);
+ ptr::copy_nonoverlapping(d, buffer.offset(1), 2);
+ buffer.offset(3)
+ } else if k >= 10 {
+ let d = DEC_DIGITS_LUT.get_unchecked(k as usize * 2);
+ ptr::copy_nonoverlapping(d, buffer, 2);
+ buffer.offset(2)
+ } else {
+ *buffer = b'0' + k as u8;
+ buffer.offset(1)
+ }
+}
+
+/*
+inline char* Prettify(char* buffer, int length, int k, int maxDecimalPlaces) {
+ const int kk = length + k; // 10^(kk-1) <= v < 10^kk
+*/
+
+#[inline]
+unsafe fn prettify(buffer: *mut u8, length: isize, k: isize) -> *mut u8 {
+ let kk = length + k; // 10^(kk-1) <= v < 10^kk
+
+ /*
+ if (0 <= k && kk <= 21) {
+ // 1234e7 -> 12340000000
+ for (int i = length; i < kk; i++)
+ buffer[i] = '0';
+ buffer[kk] = '.';
+ buffer[kk + 1] = '0';
+ return &buffer[kk + 2];
+ }
+ */
+ if 0 <= k && kk <= 21 {
+ // 1234e7 -> 12340000000
+ for i in length..kk {
+ *buffer.offset(i) = b'0';
+ }
+ *buffer.offset(kk) = b'.';
+ *buffer.offset(kk + 1) = b'0';
+ buffer.offset(kk + 2)
+ }
+
+ /*
+ else if (0 < kk && kk <= 21) {
+ // 1234e-2 -> 12.34
+ std::memmove(&buffer[kk + 1], &buffer[kk], static_cast<size_t>(length - kk));
+ buffer[kk] = '.';
+ if (0 > k + maxDecimalPlaces) {
+ // When maxDecimalPlaces = 2, 1.2345 -> 1.23, 1.102 -> 1.1
+ // Remove extra trailing zeros (at least one) after truncation.
+ for (int i = kk + maxDecimalPlaces; i > kk + 1; i--)
+ if (buffer[i] != '0')
+ return &buffer[i + 1];
+ return &buffer[kk + 2]; // Reserve one zero
+ }
+ else
+ return &buffer[length + 1];
+ }
+ */
+ else if 0 < kk && kk <= 21 {
+ // 1234e-2 -> 12.34
+ ptr::copy(buffer.offset(kk), buffer.offset(kk + 1), (length - kk) as usize);
+ *buffer.offset(kk) = b'.';
+ if 0 > k + MAX_DECIMAL_PLACES {
+ // When MAX_DECIMAL_PLACES = 2, 1.2345 -> 1.23, 1.102 -> 1.1
+ // Remove extra trailing zeros (at least one) after truncation.
+ for i in (kk + 2 .. kk + MAX_DECIMAL_PLACES + 1).rev() {
+ if *buffer.offset(i) != b'0' {
+ return buffer.offset(i + 1);
+ }
+ }
+ buffer.offset(kk + 2) // Reserve one zero
+ } else {
+ buffer.offset(length + 1)
+ }
+ }
+
+ /*
+ else if (-6 < kk && kk <= 0) {
+ // 1234e-6 -> 0.001234
+ const int offset = 2 - kk;
+ std::memmove(&buffer[offset], &buffer[0], static_cast<size_t>(length));
+ buffer[0] = '0';
+ buffer[1] = '.';
+ for (int i = 2; i < offset; i++)
+ buffer[i] = '0';
+ if (length - kk > maxDecimalPlaces) {
+ // When maxDecimalPlaces = 2, 0.123 -> 0.12, 0.102 -> 0.1
+ // Remove extra trailing zeros (at least one) after truncation.
+ for (int i = maxDecimalPlaces + 1; i > 2; i--)
+ if (buffer[i] != '0')
+ return &buffer[i + 1];
+ return &buffer[3]; // Reserve one zero
+ }
+ else
+ return &buffer[length + offset];
+ }
+ */
+ else if -6 < kk && kk <= 0 {
+ // 1234e-6 -> 0.001234
+ let offset = 2 - kk;
+ ptr::copy(buffer, buffer.offset(offset), length as usize);
+ *buffer = b'0';
+ *buffer.offset(1) = b'.';
+ for i in 2..offset {
+ *buffer.offset(i) = b'0';
+ }
+ if length - kk > MAX_DECIMAL_PLACES {
+ // When MAX_DECIMAL_PLACES = 2, 0.123 -> 0.12, 0.102 -> 0.1
+ // Remove extra trailing zeros (at least one) after truncation.
+ for i in (3 .. MAX_DECIMAL_PLACES + 2).rev() {
+ if *buffer.offset(i) != b'0' {
+ return buffer.offset(i + 1);
+ }
+ }
+ buffer.offset(3) // Reserve one zero
+ } else {
+ buffer.offset(length + offset)
+ }
+ }
+
+ /*
+ else if (kk < -maxDecimalPlaces) {
+ // Truncate to zero
+ buffer[0] = '0';
+ buffer[1] = '.';
+ buffer[2] = '0';
+ return &buffer[3];
+ }
+ */
+ else if kk < -MAX_DECIMAL_PLACES {
+ *buffer = b'0';
+ *buffer.offset(1) = b'.';
+ *buffer.offset(2) = b'0';
+ buffer.offset(3)
+ }
+
+ /*
+ else if (length == 1) {
+ // 1e30
+ buffer[1] = 'e';
+ return WriteExponent(kk - 1, &buffer[2]);
+ }
+ */
+ else if length == 1 {
+ // 1e30
+ *buffer.offset(1) = b'e';
+ write_exponent(kk - 1, buffer.offset(2))
+ }
+
+ /*
+ else {
+ // 1234e30 -> 1.234e33
+ std::memmove(&buffer[2], &buffer[1], static_cast<size_t>(length - 1));
+ buffer[1] = '.';
+ buffer[length + 1] = 'e';
+ return WriteExponent(kk - 1, &buffer[0 + length + 2]);
+ }
+ */
+ else {
+ // 1234e30 -> 1.234e33
+ ptr::copy(buffer.offset(1), buffer.offset(2), (length - 1) as usize);
+ *buffer.offset(1) = b'.';
+ *buffer.offset(length + 1) = b'e';
+ write_exponent(kk - 1, buffer.offset(length + 2))
+ }
+}
+
+/*
+inline char* dtoa(double value, char* buffer, int maxDecimalPlaces = 324) {
+ RAPIDJSON_ASSERT(maxDecimalPlaces >= 1);
+ Double d(value);
+ if (d.IsZero()) {
+ if (d.Sign())
+ *buffer++ = '-'; // -0.0, Issue #289
+ buffer[0] = '0';
+ buffer[1] = '.';
+ buffer[2] = '0';
+ return &buffer[3];
+ }
+ else {
+ if (value < 0) {
+ *buffer++ = '-';
+ value = -value;
+ }
+ int length, K;
+ Grisu2(value, buffer, &length, &K);
+ return Prettify(buffer, length, K, maxDecimalPlaces);
+ }
+}
+*/
+
+#[allow(deprecated)]
+#[inline]
+unsafe fn dtoa<W: io::Write>(mut wr: W, mut value: $fty) -> io::Result<usize> {
+ if value == 0.0 {
+ if value.is_sign_negative() {
+ match wr.write_all(b"-0.0") {
+ Ok(()) => Ok(4),
+ Err(e) => Err(e),
+ }
+ } else {
+ match wr.write_all(b"0.0") {
+ Ok(()) => Ok(3),
+ Err(e) => Err(e),
+ }
+ }
+ } else {
+ let negative = value < 0.0;
+ if negative {
+ if let Err(e) = wr.write_all(b"-") {
+ return Err(e);
+ }
+ value = -value;
+ }
+ let mut buffer: [u8; 24] = mem::uninitialized();
+ let buf_ptr = buffer.as_mut_ptr();
+ let (length, k) = grisu2(value, buf_ptr);
+ let end = prettify(buf_ptr, length, k);
+ let len = end as usize - buf_ptr as usize;
+ if let Err(e) = wr.write_all(slice::from_raw_parts(buf_ptr, len)) {
+ return Err(e);
+ }
+ if negative {
+ Ok(len + 1)
+ } else {
+ Ok(len)
+ }
+ }
+}
+
+}}
diff --git a/third_party/rust/dtoa/src/lib.rs b/third_party/rust/dtoa/src/lib.rs
new file mode 100644
index 0000000000..aed62f500b
--- /dev/null
+++ b/third_party/rust/dtoa/src/lib.rs
@@ -0,0 +1,205 @@
+//! [![github]](https://github.com/dtolnay/dtoa)&ensp;[![crates-io]](https://crates.io/crates/dtoa)&ensp;[![docs-rs]](https://docs.rs/dtoa)
+//!
+//! [github]: https://img.shields.io/badge/github-8da0cb?style=for-the-badge&labelColor=555555&logo=github
+//! [crates-io]: https://img.shields.io/badge/crates.io-fc8d62?style=for-the-badge&labelColor=555555&logo=rust
+//! [docs-rs]: https://img.shields.io/badge/docs.rs-66c2a5?style=for-the-badge&labelColor=555555&logoColor=white&logo=data:image/svg+xml;base64,PHN2ZyByb2xlPSJpbWciIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgdmlld0JveD0iMCAwIDUxMiA1MTIiPjxwYXRoIGZpbGw9IiNmNWY1ZjUiIGQ9Ik00ODguNiAyNTAuMkwzOTIgMjE0VjEwNS41YzAtMTUtOS4zLTI4LjQtMjMuNC0zMy43bC0xMDAtMzcuNWMtOC4xLTMuMS0xNy4xLTMuMS0yNS4zIDBsLTEwMCAzNy41Yy0xNC4xIDUuMy0yMy40IDE4LjctMjMuNCAzMy43VjIxNGwtOTYuNiAzNi4yQzkuMyAyNTUuNSAwIDI2OC45IDAgMjgzLjlWMzk0YzAgMTMuNiA3LjcgMjYuMSAxOS45IDMyLjJsMTAwIDUwYzEwLjEgNS4xIDIyLjEgNS4xIDMyLjIgMGwxMDMuOS01MiAxMDMuOSA1MmMxMC4xIDUuMSAyMi4xIDUuMSAzMi4yIDBsMTAwLTUwYzEyLjItNi4xIDE5LjktMTguNiAxOS45LTMyLjJWMjgzLjljMC0xNS05LjMtMjguNC0yMy40LTMzLjd6TTM1OCAyMTQuOGwtODUgMzEuOXYtNjguMmw4NS0zN3Y3My4zek0xNTQgMTA0LjFsMTAyLTM4LjIgMTAyIDM4LjJ2LjZsLTEwMiA0MS40LTEwMi00MS40di0uNnptODQgMjkxLjFsLTg1IDQyLjV2LTc5LjFsODUtMzguOHY3NS40em0wLTExMmwtMTAyIDQxLjQtMTAyLTQxLjR2LS42bDEwMi0zOC4yIDEwMiAzOC4ydi42em0yNDAgMTEybC04NSA0Mi41di03OS4xbDg1LTM4Ljh2NzUuNHptMC0xMTJsLTEwMiA0MS40LTEwMi00MS40di0uNmwxMDItMzguMiAxMDIgMzguMnYuNnoiPjwvcGF0aD48L3N2Zz4K
+//!
+//! <br>
+//!
+//! This crate provides fast functions for printing floating-point primitives to
+//! an [`io::Write`]. The implementation is a straightforward Rust port of [Milo
+//! Yip]'s C++ implementation [dtoa.h]. The original C++ code of each function
+//! is included in comments.
+//!
+//! See also [`itoa`] for printing integer primitives.
+//!
+//! [`io::Write`]: https://doc.rust-lang.org/std/io/trait.Write.html
+//! [Milo Yip]: https://github.com/miloyip
+//! [dtoa.h]: https://github.com/miloyip/rapidjson/blob/master/include/rapidjson/internal/dtoa.h
+//! [`itoa`]: https://github.com/dtolnay/itoa
+//!
+//! <br>
+//!
+//! ## Performance (lower is better)
+//!
+//! ![performance](https://raw.githubusercontent.com/dtolnay/dtoa/master/performance.png)
+//!
+//! <br>
+//!
+//! # Examples
+//!
+//! ```edition2018
+//! use std::io;
+//!
+//! fn main() -> io::Result<()> {
+//! // Write to a vector or other io::Write.
+//! let mut buf = Vec::new();
+//! dtoa::write(&mut buf, 2.71828f64)?;
+//! println!("{:?}", buf);
+//!
+//! // Write to a stack buffer.
+//! let mut bytes = [b'\0'; 20];
+//! let n = dtoa::write(&mut bytes[..], 2.71828f64)?;
+//! println!("{:?}", &bytes[..n]);
+//!
+//! Ok(())
+//! }
+//! ```
+
+#![doc(html_root_url = "https://docs.rs/dtoa/0.4.8")]
+#![cfg_attr(feature = "cargo-clippy", allow(renamed_and_removed_lints))]
+#![cfg_attr(
+ feature = "cargo-clippy",
+ allow(
+ cast_lossless,
+ cast_possible_truncation,
+ if_not_else,
+ missing_errors_doc,
+ range_plus_one,
+ shadow_unrelated,
+ transmute_float_to_int,
+ unreadable_literal,
+ unseparated_literal_suffix
+ )
+)]
+
+#[macro_use] mod diyfp;
+#[macro_use] mod dtoa;
+
+use std::{io, mem, ops, ptr, slice};
+
+/// Write float to an `io::Write`.
+#[inline]
+pub fn write<W: io::Write, V: Floating>(wr: W, value: V) -> io::Result<usize> {
+ value.write(wr)
+}
+
+/// An floating point number that can be formatted by `dtoa::write`.
+pub trait Floating {
+ fn write<W: io::Write>(self, wr: W) -> io::Result<usize>;
+}
+
+impl Floating for f32 {
+ fn write<W: io::Write>(self, wr: W) -> io::Result<usize> {
+ dtoa! {
+ floating_type: f32,
+ significand_type: u32,
+ exponent_type: i32,
+
+ diy_significand_size: 32,
+ significand_size: 23,
+ exponent_bias: 0x7F,
+ mask_type: u32,
+ exponent_mask: 0x7F800000,
+ significand_mask: 0x007FFFFF,
+ hidden_bit: 0x00800000,
+ cached_powers_f: CACHED_POWERS_F_32,
+ cached_powers_e: CACHED_POWERS_E_32,
+ min_power: (-36),
+ };
+ unsafe { dtoa(wr, self) }
+ }
+}
+
+impl Floating for f64 {
+ fn write<W: io::Write>(self, wr: W) -> io::Result<usize> {
+ dtoa! {
+ floating_type: f64,
+ significand_type: u64,
+ exponent_type: isize,
+
+ diy_significand_size: 64,
+ significand_size: 52,
+ exponent_bias: 0x3FF,
+ mask_type: u64,
+ exponent_mask: 0x7FF0000000000000,
+ significand_mask: 0x000FFFFFFFFFFFFF,
+ hidden_bit: 0x0010000000000000,
+ cached_powers_f: CACHED_POWERS_F_64,
+ cached_powers_e: CACHED_POWERS_E_64,
+ min_power: (-348),
+ };
+ unsafe { dtoa(wr, self) }
+ }
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
+const MAX_DECIMAL_PLACES: isize = 324;
+
+static DEC_DIGITS_LUT: [u8; 200] = *b"\
+ 0001020304050607080910111213141516171819\
+ 2021222324252627282930313233343536373839\
+ 4041424344454647484950515253545556575859\
+ 6061626364656667686970717273747576777879\
+ 8081828384858687888990919293949596979899";
+
+// 10^-36, 10^-28, ..., 10^52
+static CACHED_POWERS_F_32: [u32; 12] = [
+ 0xaa242499, 0xfd87b5f3, 0xbce50865, 0x8cbccc09,
+ 0xd1b71759, 0x9c400000, 0xe8d4a510, 0xad78ebc6,
+ 0x813f3979, 0xc097ce7c, 0x8f7e32ce, 0xd5d238a5,
+];
+
+static CACHED_POWERS_E_32: [i16; 12] = [
+ -151, -125, -98, -71, -45, -18, 8, 35, 62, 88, 115, 141,
+];
+
+// 10^-348, 10^-340, ..., 10^340
+static CACHED_POWERS_F_64: [u64; 87] = [
+ 0xfa8fd5a0081c0288, 0xbaaee17fa23ebf76,
+ 0x8b16fb203055ac76, 0xcf42894a5dce35ea,
+ 0x9a6bb0aa55653b2d, 0xe61acf033d1a45df,
+ 0xab70fe17c79ac6ca, 0xff77b1fcbebcdc4f,
+ 0xbe5691ef416bd60c, 0x8dd01fad907ffc3c,
+ 0xd3515c2831559a83, 0x9d71ac8fada6c9b5,
+ 0xea9c227723ee8bcb, 0xaecc49914078536d,
+ 0x823c12795db6ce57, 0xc21094364dfb5637,
+ 0x9096ea6f3848984f, 0xd77485cb25823ac7,
+ 0xa086cfcd97bf97f4, 0xef340a98172aace5,
+ 0xb23867fb2a35b28e, 0x84c8d4dfd2c63f3b,
+ 0xc5dd44271ad3cdba, 0x936b9fcebb25c996,
+ 0xdbac6c247d62a584, 0xa3ab66580d5fdaf6,
+ 0xf3e2f893dec3f126, 0xb5b5ada8aaff80b8,
+ 0x87625f056c7c4a8b, 0xc9bcff6034c13053,
+ 0x964e858c91ba2655, 0xdff9772470297ebd,
+ 0xa6dfbd9fb8e5b88f, 0xf8a95fcf88747d94,
+ 0xb94470938fa89bcf, 0x8a08f0f8bf0f156b,
+ 0xcdb02555653131b6, 0x993fe2c6d07b7fac,
+ 0xe45c10c42a2b3b06, 0xaa242499697392d3,
+ 0xfd87b5f28300ca0e, 0xbce5086492111aeb,
+ 0x8cbccc096f5088cc, 0xd1b71758e219652c,
+ 0x9c40000000000000, 0xe8d4a51000000000,
+ 0xad78ebc5ac620000, 0x813f3978f8940984,
+ 0xc097ce7bc90715b3, 0x8f7e32ce7bea5c70,
+ 0xd5d238a4abe98068, 0x9f4f2726179a2245,
+ 0xed63a231d4c4fb27, 0xb0de65388cc8ada8,
+ 0x83c7088e1aab65db, 0xc45d1df942711d9a,
+ 0x924d692ca61be758, 0xda01ee641a708dea,
+ 0xa26da3999aef774a, 0xf209787bb47d6b85,
+ 0xb454e4a179dd1877, 0x865b86925b9bc5c2,
+ 0xc83553c5c8965d3d, 0x952ab45cfa97a0b3,
+ 0xde469fbd99a05fe3, 0xa59bc234db398c25,
+ 0xf6c69a72a3989f5c, 0xb7dcbf5354e9bece,
+ 0x88fcf317f22241e2, 0xcc20ce9bd35c78a5,
+ 0x98165af37b2153df, 0xe2a0b5dc971f303a,
+ 0xa8d9d1535ce3b396, 0xfb9b7cd9a4a7443c,
+ 0xbb764c4ca7a44410, 0x8bab8eefb6409c1a,
+ 0xd01fef10a657842c, 0x9b10a4e5e9913129,
+ 0xe7109bfba19c0c9d, 0xac2820d9623bf429,
+ 0x80444b5e7aa7cf85, 0xbf21e44003acdd2d,
+ 0x8e679c2f5e44ff8f, 0xd433179d9c8cb841,
+ 0x9e19db92b4e31ba9, 0xeb96bf6ebadf77d9,
+ 0xaf87023b9bf0ee6b,
+];
+static CACHED_POWERS_E_64: [i16; 87] = [
+ -1220, -1193, -1166, -1140, -1113, -1087, -1060, -1034, -1007, -980,
+ -954, -927, -901, -874, -847, -821, -794, -768, -741, -715,
+ -688, -661, -635, -608, -582, -555, -529, -502, -475, -449,
+ -422, -396, -369, -343, -316, -289, -263, -236, -210, -183,
+ -157, -130, -103, -77, -50, -24, 3, 30, 56, 83,
+ 109, 136, 162, 189, 216, 242, 269, 295, 322, 348,
+ 375, 402, 428, 455, 481, 508, 534, 561, 588, 614,
+ 641, 667, 694, 720, 747, 774, 800, 827, 853, 880,
+ 907, 933, 960, 986, 1013, 1039, 1066,
+];
diff --git a/third_party/rust/dtoa/tests/test.rs b/third_party/rust/dtoa/tests/test.rs
new file mode 100644
index 0000000000..4f92d7ee13
--- /dev/null
+++ b/third_party/rust/dtoa/tests/test.rs
@@ -0,0 +1,38 @@
+extern crate dtoa;
+
+use std::str;
+
+#[test]
+fn test_f64() {
+ test_write(1.234e20f64, "123400000000000000000.0");
+ test_write(1.234e21f64, "1.234e21");
+ test_write(2.71828f64, "2.71828");
+ test_write(0.0f64, "0.0");
+ test_write(-0.0f64, "-0.0");
+ test_write(1.1e128f64, "1.1e128");
+ test_write(1.1e-64f64, "1.1e-64");
+ test_write(2.718281828459045f64, "2.718281828459045");
+ test_write(5e-324f64, "5e-324");
+ test_write(::std::f64::MAX, "1.7976931348623157e308");
+}
+
+#[test]
+fn test_f32() {
+ test_write(1.234e20f32, "123400000000000000000.0");
+ test_write(1.234e21f32, "1.234e21");
+ test_write(2.71828f32, "2.71828");
+ test_write(0.0f32, "0.0");
+ test_write(-0.0f32, "-0.0");
+ test_write(1.1e32f32, "1.1e32");
+ test_write(1.1e-32f32, "1.1e-32");
+ test_write(2.7182817f32, "2.7182817");
+ test_write(1e-45f32, "1e-45");
+ test_write(::std::f32::MAX, "3.4028235e38");
+}
+
+fn test_write<F: dtoa::Floating>(value: F, expected: &'static str) {
+ let mut buf = [b'\0'; 30];
+ let len = dtoa::write(&mut buf[..], value).unwrap();
+ let result = str::from_utf8(&buf[..len]).unwrap();
+ assert_eq!(result, expected.to_string());
+}