Bug 1716518 - Upgrade rand to v0.7.3 and rand_chacha to v0.2.2. r=emilio

This removes c2-chacha.

Differential Revision: https://phabricator.services.mozilla.com/D117841
This commit is contained in:
Mike Hommey 2021-06-15 22:17:30 +00:00
Родитель 7fda4d5401
Коммит aed4dbceb0
63 изменённых файлов: 1640 добавлений и 2163 удалений

19
Cargo.lock сгенерированный
Просмотреть файл

@ -468,15 +468,6 @@ version = "0.5.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0e4cec68f03f32e44924783795810fa50a7035d8c8ebe78580ad7e6c703fba38"
[[package]]
name = "c2-chacha"
version = "0.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "214238caa1bf3a496ec3392968969cab8549f96ff30652c9e56885329315f6bb"
dependencies = [
"ppv-lite86",
]
[[package]]
name = "cache-padded"
version = "1.1.1"
@ -4035,9 +4026,9 @@ dependencies = [
[[package]]
name = "rand"
version = "0.7.2"
version = "0.7.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3ae1b169243eaf61759b8475a998f0a385e42042370f3a7dbaf35246eacc8412"
checksum = "6a6b1679d49b24bbfe0c803429aa1874472f50d9b363131f0e89fc356b544d03"
dependencies = [
"getrandom",
"libc",
@ -4049,11 +4040,11 @@ dependencies = [
[[package]]
name = "rand_chacha"
version = "0.2.1"
version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "03a2a90da8c7523f554344f921aa97283eadf6ac484a6d2a7d0212fa7f8d6853"
checksum = "f4c8ed856279c9737206bf725bf36935d8666ead7aa69b52be55af369d193402"
dependencies = [
"c2-chacha",
"ppv-lite86",
"rand_core",
]

Просмотреть файл

@ -1 +0,0 @@
{"files":{"Cargo.toml":"ca60f483e157aa3a4da8f2e81328a91085df95aac950af29b98ba00264670118","LICENSE-APACHE":"0218327e7a480793ffdd4eb792379a9709e5c135c7ba267f709d6f6d4d70af0a","LICENSE-MIT":"4cada0bd02ea3692eee6f16400d86c6508bbd3bafb2b65fed0419f36d4f83e8f","README.md":"e884c49fd9cf2d6316cb825e1cfc310ed8d9005ecf702506393f95330102a63b","benches/chacha20.rs":"e499e9d8607ad6ac89663258fb8ce4d37cebb5cd231bc8d9c1112fb7905eccb6","src/guts.rs":"ef6337688f5a3d5cbd848e882b53ef2b96824126783103c77709c5dd2856b660","src/lib.rs":"f963f2932409ff28a21a89d5dc4f44c1a9b320705cc474246a93067abcf4b528","src/rustcrypto_impl.rs":"805692d33643b40430559710184e52ac49c82d41a23e6c112e19251e2ea84656"},"package":"214238caa1bf3a496ec3392968969cab8549f96ff30652c9e56885329315f6bb"}

46
third_party/rust/c2-chacha/Cargo.toml поставляемый
Просмотреть файл

@ -1,46 +0,0 @@
# 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]
edition = "2018"
name = "c2-chacha"
version = "0.2.3"
authors = ["The CryptoCorrosion Contributors"]
description = "The ChaCha family of stream ciphers"
documentation = "https://docs.rs/c2-chacha"
readme = "README.md"
keywords = ["chacha", "chacha20", "xchacha20", "cipher", "crypto"]
categories = ["cryptography", "no-std"]
license = "MIT/Apache-2.0"
repository = "https://github.com/cryptocorrosion/cryptocorrosion"
[dependencies.byteorder]
version = "1.3"
optional = true
[dependencies.ppv-lite86]
version = "0.2.6"
default-features = false
package = "ppv-lite86"
[dependencies.stream-cipher]
version = "0.3"
optional = true
[dev-dependencies.hex-literal]
version = "0.2"
[features]
default = ["std", "simd", "rustcrypto_api"]
rustcrypto_api = ["stream-cipher", "byteorder"]
simd = ["ppv-lite86/simd"]
std = ["ppv-lite86/std"]
[badges.travis-ci]
repository = "cryptocorrosion/cryptocorrosion"

201
third_party/rust/c2-chacha/LICENSE-APACHE поставляемый
Просмотреть файл

@ -1,201 +0,0 @@
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 2019 The CryptoCorrosion Contributors
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.

25
third_party/rust/c2-chacha/LICENSE-MIT поставляемый
Просмотреть файл

@ -1,25 +0,0 @@
Copyright (c) 2019 The CryptoCorrosion Contributors
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.

24
third_party/rust/c2-chacha/README.md поставляемый
Просмотреть файл

@ -1,24 +0,0 @@
# The ChaCha family of stream ciphers
## Features
- pure Rust implementation
- supports the RustCrypto API
- builds on stable Rust
- portable
- fast: within 15% of throughput of a hand-optimized ASM SIMD implementation
(floodberry/chacha-opt) on my machine (a Xeon X5650, using ppv-lite86)
- no-std compatible (std required only for runtime algorithm selection)
## Supported Variants
ChaCha20: used in chacha20-poly1305 in TLS, OpenSSH; arc4random in the BSDs,
Linux /dev/urandom since 4.8.
Ietf: IETF RFC 7539. Longer nonce, short block counter.
XChaCha20: constructed analogously to XSalsa20; a mixing step during
initialization allows using a long nonce and along with a full-sized block
counter.
ChaCha12, ChaCha8: faster; lower security margin of safety.

Просмотреть файл

@ -1,20 +0,0 @@
#![feature(test)]
extern crate c2_chacha;
extern crate stream_cipher;
extern crate test;
use c2_chacha::ChaCha20;
use stream_cipher::{NewStreamCipher, SyncStreamCipher};
use test::Bencher;
#[bench]
pub fn stream_10k(b: &mut Bencher) {
let mut state = ChaCha20::new_var(&[0; 32], &[0; 8]).unwrap();
let mut result = [0; 1024];
b.iter(|| {
for _ in 0..10 {
state.apply_keystream(&mut result)
}
});
b.bytes = 10240;
}

45
third_party/rust/c2-chacha/src/lib.rs поставляемый
Просмотреть файл

@ -1,45 +0,0 @@
// copyright 2019 Kaz Wesley
//! Pure Rust ChaCha with SIMD optimizations.
//!
//! Stream-cipher usage:
//! ```
//! extern crate c2_chacha;
//!
//! use c2_chacha::stream_cipher::{NewStreamCipher, SyncStreamCipher, SyncStreamCipherSeek};
//! use c2_chacha::{ChaCha20, ChaCha12};
//!
//! let key = b"very secret key-the most secret.";
//! let iv = b"my nonce";
//! let plaintext = b"The quick brown fox jumps over the lazy dog.";
//!
//! let mut buffer = plaintext.to_vec();
//! // create cipher instance
//! let mut cipher = ChaCha20::new_var(key, iv).unwrap();
//! // apply keystream (encrypt)
//! cipher.apply_keystream(&mut buffer);
//! // and decrypt it back
//! cipher.seek(0);
//! cipher.apply_keystream(&mut buffer);
//! // stream ciphers can be used with streaming messages
//! let mut cipher = ChaCha12::new_var(key, iv).unwrap();
//! for chunk in buffer.chunks_mut(3) {
//! cipher.apply_keystream(chunk);
//! }
//! ```
#![cfg_attr(not(feature = "std"), no_std)]
#[cfg(test)]
#[macro_use]
extern crate hex_literal;
#[macro_use]
extern crate ppv_lite86;
pub mod guts;
#[cfg(feature = "rustcrypto_api")]
mod rustcrypto_impl;
#[cfg(feature = "rustcrypto_api")]
pub use self::rustcrypto_impl::{stream_cipher, ChaCha12, ChaCha20, ChaCha8, Ietf, XChaCha20};

Просмотреть файл

@ -1,548 +0,0 @@
use byteorder::{ByteOrder, LE};
use core::cmp;
use crate::guts::generic_array::typenum::{Unsigned, U10, U12, U24, U32, U4, U6, U8};
use crate::guts::generic_array::{ArrayLength, GenericArray};
use crate::guts::{ChaCha, Machine, BLOCK, BLOCK64, BUFSZ};
pub use stream_cipher;
use stream_cipher::{LoopError, NewStreamCipher, SyncStreamCipher, SyncStreamCipherSeek};
const BIG_LEN: u64 = 0;
const SMALL_LEN: u64 = 1 << 32;
#[derive(Clone)]
pub struct Buffer {
pub state: ChaCha,
pub out: [u8; BLOCK],
pub have: i8,
pub len: u64,
pub fresh: bool,
}
#[derive(Default)]
pub struct X;
#[derive(Default)]
pub struct O;
#[derive(Clone)]
pub struct ChaChaAny<NonceSize, Rounds, IsX> {
pub state: Buffer,
pub _nonce_size: NonceSize,
pub _rounds: Rounds,
pub _is_x: IsX,
}
impl Buffer {
fn try_apply_keystream<EnableWide: AsBool>(
&mut self,
mut data: &mut [u8],
drounds: u32,
) -> Result<(), ()> {
// Lazy fill: after a seek() we may be partway into a block we don't have yet.
// We can do this before the overflow check because this is not an effect of the current
// operation.
if self.have < 0 {
self.state.refill(drounds, &mut self.out);
self.have += BLOCK as i8;
// checked in seek()
self.len -= 1;
}
let mut have = self.have as usize;
let have_ready = cmp::min(have, data.len());
// Check if the requested position would wrap the block counter. Use self.fresh as an extra
// bit to distinguish the initial state from the valid state with no blocks left.
let datalen = (data.len() - have_ready) as u64;
let blocks_needed = datalen / BLOCK64 + u64::from(datalen % BLOCK64 != 0);
let (l, o) = self.len.overflowing_sub(blocks_needed);
if o && !self.fresh {
return Err(());
}
self.len = l;
self.fresh &= blocks_needed == 0;
// If we have data in the buffer, use that first.
let (d0, d1) = data.split_at_mut(have_ready);
for (data_b, key_b) in d0.iter_mut().zip(&self.out[(BLOCK - have)..]) {
*data_b ^= *key_b;
}
data = d1;
have -= have_ready;
// Process wide chunks.
if EnableWide::BOOL {
let (d0, d1) = data.split_at_mut(data.len() & !(BUFSZ - 1));
for dd in d0.chunks_exact_mut(BUFSZ) {
let mut buf = [0; BUFSZ];
self.state.refill4(drounds, &mut buf);
for (data_b, key_b) in dd.iter_mut().zip(buf.iter()) {
*data_b ^= *key_b;
}
}
data = d1;
}
// Handle the tail a block at a time so we'll have storage for any leftovers.
for dd in data.chunks_mut(BLOCK) {
self.state.refill(drounds, &mut self.out);
for (data_b, key_b) in dd.iter_mut().zip(self.out.iter()) {
*data_b ^= *key_b;
}
have = BLOCK - dd.len();
}
self.have = have as i8;
Ok(())
}
}
dispatch_light128!(m, Mach, {
fn seek64(buf: &mut Buffer, ct: u64) {
let blockct = ct / BLOCK64;
buf.len = BIG_LEN.wrapping_sub(blockct);
buf.fresh = blockct == 0;
buf.have = -((ct % BLOCK64) as i8);
buf.state.seek64(m, blockct);
}
});
dispatch_light128!(m, Mach, {
fn seek32(buf: &mut Buffer, ct: u64) {
let blockct = ct / BLOCK64;
assert!(blockct < SMALL_LEN || (blockct == SMALL_LEN && ct % BLOCK64 == 0));
buf.len = SMALL_LEN - blockct;
buf.have = -((ct % BLOCK64) as i8);
buf.state.seek32(m, blockct as u32);
}
});
#[cfg(test)]
impl<NonceSize, Rounds: Unsigned, IsX> ChaChaAny<NonceSize, Rounds, IsX> {
pub fn try_apply_keystream_narrow(&mut self, data: &mut [u8]) -> Result<(), ()> {
self.state
.try_apply_keystream::<WideDisabled>(data, Rounds::U32)
}
}
impl<NonceSize, Rounds> ChaChaAny<NonceSize, Rounds, O>
where
NonceSize: Unsigned + ArrayLength<u8> + Default,
Rounds: Default,
{
#[inline]
fn new(key: &GenericArray<u8, U32>, nonce: &GenericArray<u8, NonceSize>) -> Self {
let nonce_len = nonce.len();
ChaChaAny {
state: Buffer {
state: init_chacha(key, nonce),
out: [0; BLOCK],
have: 0,
len: if nonce_len == 12 { SMALL_LEN } else { BIG_LEN },
fresh: nonce_len != 12,
},
_nonce_size: Default::default(),
_rounds: Default::default(),
_is_x: Default::default(),
}
}
}
impl<Rounds: Unsigned + Default> ChaChaAny<U24, Rounds, X> {
fn new(key: &GenericArray<u8, U32>, nonce: &GenericArray<u8, U24>) -> Self {
ChaChaAny {
state: Buffer {
state: init_chacha_x(key, nonce, Rounds::U32),
out: [0; BLOCK],
have: 0,
len: BIG_LEN,
fresh: true,
},
_nonce_size: Default::default(),
_rounds: Default::default(),
_is_x: Default::default(),
}
}
}
impl<NonceSize: Unsigned, Rounds, IsX> ChaChaAny<NonceSize, Rounds, IsX> {
#[inline(always)]
fn seek(&mut self, ct: u64) {
if NonceSize::U32 != 12 {
seek64(&mut self.state, ct);
} else {
seek32(&mut self.state, ct);
}
}
}
impl<NonceSize, Rounds: Unsigned, IsX> ChaChaAny<NonceSize, Rounds, IsX> {
#[inline]
fn try_apply_keystream(&mut self, data: &mut [u8]) -> Result<(), ()> {
self.state
.try_apply_keystream::<WideEnabled>(data, Rounds::U32)
}
}
impl<NonceSize, Rounds> NewStreamCipher for ChaChaAny<NonceSize, Rounds, O>
where
NonceSize: Unsigned + ArrayLength<u8> + Default,
Rounds: Default,
{
type KeySize = U32;
type NonceSize = NonceSize;
#[inline]
fn new(
key: &GenericArray<u8, Self::KeySize>,
nonce: &GenericArray<u8, Self::NonceSize>,
) -> Self {
Self::new(key, nonce)
}
}
impl<Rounds: Unsigned + Default> NewStreamCipher for ChaChaAny<U24, Rounds, X> {
type KeySize = U32;
type NonceSize = U24;
#[inline]
fn new(
key: &GenericArray<u8, Self::KeySize>,
nonce: &GenericArray<u8, Self::NonceSize>,
) -> Self {
Self::new(key, nonce)
}
}
impl<NonceSize: Unsigned, Rounds, IsX> SyncStreamCipherSeek for ChaChaAny<NonceSize, Rounds, IsX> {
#[inline]
fn current_pos(&self) -> u64 {
unimplemented!()
}
#[inline(always)]
fn seek(&mut self, ct: u64) {
Self::seek(self, ct)
}
}
impl<NonceSize, Rounds: Unsigned, IsX> SyncStreamCipher for ChaChaAny<NonceSize, Rounds, IsX> {
#[inline]
fn try_apply_keystream(&mut self, data: &mut [u8]) -> Result<(), LoopError> {
Self::try_apply_keystream(self, data).map_err(|_| LoopError)
}
}
trait AsBool {
const BOOL: bool;
}
struct WideEnabled;
impl AsBool for WideEnabled {
const BOOL: bool = true;
}
#[cfg(test)]
struct WideDisabled;
#[cfg(test)]
impl AsBool for WideDisabled {
const BOOL: bool = false;
}
dispatch_light128!(m, Mach, {
fn init_chacha(key: &GenericArray<u8, U32>, nonce: &[u8]) -> ChaCha {
let ctr_nonce = [
0,
if nonce.len() == 12 {
LE::read_u32(&nonce[0..4])
} else {
0
},
LE::read_u32(&nonce[nonce.len() - 8..nonce.len() - 4]),
LE::read_u32(&nonce[nonce.len() - 4..]),
];
let key0: Mach::u32x4 = m.read_le(&key[..16]);
let key1: Mach::u32x4 = m.read_le(&key[16..]);
ChaCha {
b: key0.into(),
c: key1.into(),
d: ctr_nonce.into(),
}
}
});
dispatch_light128!(m, Mach, {
fn init_chacha_x(
key: &GenericArray<u8, U32>,
nonce: &GenericArray<u8, U24>,
rounds: u32,
) -> ChaCha {
let key0: Mach::u32x4 = m.read_le(&key[..16]);
let key1: Mach::u32x4 = m.read_le(&key[16..]);
let nonce0: Mach::u32x4 = m.read_le(&nonce[..16]);
let mut state = ChaCha {
b: key0.into(),
c: key1.into(),
d: nonce0.into(),
};
let x = state.refill_rounds(rounds);
let ctr_nonce1 = [
0,
0,
LE::read_u32(&nonce[16..20]),
LE::read_u32(&nonce[20..24]),
];
state.b = x.a;
state.c = x.d;
state.d = ctr_nonce1.into();
state
}
});
/// IETF RFC 7539 ChaCha. Unsuitable for messages longer than 256 GiB.
pub type Ietf = ChaChaAny<U12, U10, O>;
/// ChaCha20, as used in several standards; from Bernstein's original publication.
pub type ChaCha20 = ChaChaAny<U8, U10, O>;
/// Similar to ChaCha20, but with fewer rounds for higher performance.
pub type ChaCha12 = ChaChaAny<U8, U6, O>;
/// Similar to ChaCha20, but with fewer rounds for higher performance.
pub type ChaCha8 = ChaChaAny<U8, U4, O>;
/// Constructed analogously to XSalsa20; mixes during initialization to support both a long nonce
/// and a full-length (64-bit) block counter.
pub type XChaCha20 = ChaChaAny<U24, U10, X>;
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn chacha20_case_1() {
let key = hex!("fa44478c59ca70538e3549096ce8b523232c50d9e8e8d10c203ef6c8d07098a5");
let nonce = hex!("8d3a0d6d7827c007");
let expected = hex!("
1546a547ff77c5c964e44fd039e913c6395c8f19d43efaa880750f6687b4e6e2d8f42f63546da2d133b5aa2f1ef3f218b6c72943089e4012
210c2cbed0e8e93498a6825fc8ff7a504f26db33b6cbe36299436244c9b2eff88302c55933911b7d5dea75f2b6d4761ba44bb6f814c9879d
2ba2ac8b178fa1104a368694872339738ffb960e33db39efb8eaef885b910eea078e7a1feb3f8185dafd1455b704d76da3a0ce4760741841
217bba1e4ece760eaf68617133431feb806c061173af6b8b2a23be90c5d145cc258e3c119aab2800f0c7bc1959dae75481712cab731b7dfd
783fa3a228f9968aaea68f36a92f43c9b523337a55b97bcaf5f5774447bf41e8");
let mut state = ChaCha20::new(
GenericArray::from_slice(&key),
GenericArray::from_slice(&nonce),
);
let offset = 0x3fffffff70u64;
assert!((offset >> 38) != ((offset + 240) >> 38)); // This will overflow the small word of the counter
state.seek(offset);
let mut result = [0; 256];
state.apply_keystream(&mut result);
assert_eq!(&expected[..], &result[..]);
}
#[test]
fn chacha12_case_1() {
let key = hex!("27fc120b013b829f1faeefd1ab417e8662f43e0d73f98de866e346353180fdb7");
let nonce = hex!("db4b4a41d8df18aa");
let expected = hex!("
5f3c8c190a78ab7fe808cae9cbcb0a9837c893492d963a1c2eda6c1558b02c83fc02a44cbbb7e6204d51d1c2430e9c0b58f2937bf593840c
850bda9051a1f051ddf09d2a03ebf09f01bdba9da0b6da791b2e645641047d11ebf85087d4de5c015fddd044");
let mut state = ChaCha12::new(
GenericArray::from_slice(&key),
GenericArray::from_slice(&nonce),
);
let mut result = [0u8; 100];
state.apply_keystream(&mut result);
assert_eq!(&expected[..], &result[..]);
}
#[test]
fn chacha8_case_1() {
let key = hex!("641aeaeb08036b617a42cf14e8c5d2d115f8d7cb6ea5e28b9bfaf83e038426a7");
let nonce = hex!("a14a1168271d459b");
let mut state = ChaCha8::new(
GenericArray::from_slice(&key),
GenericArray::from_slice(&nonce),
);
let expected = hex!(
"1721c044a8a6453522dddb3143d0be3512633ca3c79bf8ccc3594cb2c2f310f7bd544f55ce0db38123412d6c45207d5cf9af0c6c680cce1f
7e43388d1b0346b7133c59fd6af4a5a568aa334ccdc38af5ace201df84d0a3ca225494ca6209345fcf30132e");
let mut result = [0u8; 100];
state.apply_keystream(&mut result);
assert_eq!(&expected[..], &result[..]);
}
#[test]
fn test_ietf() {
let key = hex!("000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f");
let nonce = hex!("000000090000004a00000000");
let expected = hex!(
"
10f1e7e4d13b5915500fdd1fa32071c4c7d1f4c733c068030422aa9ac3d46c4e
d2826446079faa0914c2d705d98b02a2b5129cd1de164eb9cbd083e8a2503c4e"
);
let mut state = Ietf::new(
GenericArray::from_slice(&key),
GenericArray::from_slice(&nonce),
);
let mut result = [0; 64];
state.seek(64);
state.apply_keystream(&mut result);
assert_eq!(&expected[..], &result[..]);
}
#[test]
fn rfc_7539_case_1() {
let key = hex!("000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f");
let nonce = hex!("000000090000004a00000000");
let mut state = Ietf::new(
GenericArray::from_slice(&key),
GenericArray::from_slice(&nonce),
);
let mut result = [0; 128];
state.apply_keystream(&mut result);
let expected = hex!(
"10f1e7e4d13b5915500fdd1fa32071c4c7d1f4c733c068030422aa9ac3d46c4e
d2826446079faa0914c2d705d98b02a2b5129cd1de164eb9cbd083e8a2503c4e"
);
assert_eq!(&expected[..], &result[64..]);
}
#[test]
fn rfc_7539_case_2() {
let key = hex!("000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f");
let nonce = hex!("000000000000004a00000000");
let mut state = Ietf::new(
GenericArray::from_slice(&key),
GenericArray::from_slice(&nonce),
);
let plaintext = b"Ladies and Gentlemen of the class of '99: If I could offer you only one tip for the future, sunscreen would be it.";
let mut buf = [0u8; 178];
buf[64..].copy_from_slice(plaintext);
state.apply_keystream(&mut buf);
let expected = hex!("
6e2e359a2568f98041ba0728dd0d6981e97e7aec1d4360c20a27afccfd9fae0bf91b65c5524733ab8f593dabcd62b3571639d624e65152ab
8f530c359f0861d807ca0dbf500d6a6156a38e088a22b65e52bc514d16ccf806818ce91ab77937365af90bbf74a35be6b40b8eedf2785e42
874d");
assert_eq!(&expected[..], &buf[64..]);
}
#[test]
fn rfc_7539_case_2_chunked() {
let key = hex!("000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f");
let nonce = hex!("000000000000004a00000000");
let mut state = Ietf::new(
GenericArray::from_slice(&key),
GenericArray::from_slice(&nonce),
);
let plaintext = b"Ladies and Gentlemen of the class of '99: If I could offer you only one tip for the future, sunscreen would be it.";
let mut buf = [0u8; 178];
buf[64..].copy_from_slice(plaintext);
state.apply_keystream(&mut buf[..40]);
state.apply_keystream(&mut buf[40..78]);
state.apply_keystream(&mut buf[78..79]);
state.apply_keystream(&mut buf[79..128]);
state.apply_keystream(&mut buf[128..]);
let expected = hex!("
6e2e359a2568f98041ba0728dd0d6981e97e7aec1d4360c20a27afccfd9fae0bf91b65c5524733ab8f593dabcd62b3571639d624e65152ab
8f530c359f0861d807ca0dbf500d6a6156a38e088a22b65e52bc514d16ccf806818ce91ab77937365af90bbf74a35be6b40b8eedf2785e42
874d");
assert_eq!(&expected[..], &buf[64..]);
}
#[test]
fn xchacha20_case_1() {
let key = hex!("82f411a074f656c66e7dbddb0a2c1b22760b9b2105f4ffdbb1d4b1e824e21def");
let nonce = hex!("3b07ca6e729eb44a510b7a1be51847838a804f8b106b38bd");
let mut state = XChaCha20::new(
GenericArray::from_slice(&key),
GenericArray::from_slice(&nonce),
);
let mut xs = [0u8; 100];
state.apply_keystream(&mut xs);
let expected = hex!("
201863970b8e081f4122addfdf32f6c03e48d9bc4e34a59654f49248b9be59d3eaa106ac3376e7e7d9d1251f2cbf61ef27000f3d19afb76b
9c247151e7bc26467583f520518eccd2055ccd6cc8a195953d82a10c2065916778db35da2be44415d2f5efb0");
assert_eq!(&expected[..], &xs[..]);
}
#[test]
fn seek_off_end() {
let mut st = Ietf::new(
GenericArray::from_slice(&[0xff; 32]),
GenericArray::from_slice(&[0; 12]),
);
st.seek(0x40_0000_0000);
assert!(st.try_apply_keystream(&mut [0u8; 1]).is_err());
}
#[test]
fn read_last_bytes() {
let mut st = Ietf::new(
GenericArray::from_slice(&[0xff; 32]),
GenericArray::from_slice(&[0; 12]),
);
st.seek(0x40_0000_0000 - 10);
st.apply_keystream(&mut [0u8; 10]);
assert!(st.try_apply_keystream(&mut [0u8; 1]).is_err());
st.seek(0x40_0000_0000 - 10);
assert!(st.try_apply_keystream(&mut [0u8; 11]).is_err());
}
#[test]
fn seek_consistency() {
let mut st = Ietf::new(
GenericArray::from_slice(&[50; 32]),
GenericArray::from_slice(&[44; 12]),
);
let mut continuous = [0u8; 1000];
st.apply_keystream(&mut continuous);
let mut chunks = [0u8; 1000];
st.seek(128);
st.apply_keystream(&mut chunks[128..300]);
st.seek(0);
st.apply_keystream(&mut chunks[0..10]);
st.seek(300);
st.apply_keystream(&mut chunks[300..533]);
st.seek(533);
st.apply_keystream(&mut chunks[533..]);
st.seek(10);
st.apply_keystream(&mut chunks[10..128]);
assert_eq!(&continuous[..], &chunks[..]);
}
#[test]
fn wide_matches_narrow() {
let key = hex!("fa44478c59ca70538e3549096ce8b523232c50d9e8e8d10c203ef6c8d07098a5");
let nonce = hex!("8d3a0d6d7827c007");
let mut buf = [0; 2048];
let mut state = ChaCha20::new(
GenericArray::from_slice(&key),
GenericArray::from_slice(&nonce),
);
let lens = [
2048, 2047, 1537, 1536, 1535, 1025, 1024, 1023, 768, 513, 512, 511, 200, 100, 50,
];
for &len in &lens {
let buf = &mut buf[0..len];
// encrypt with hybrid wide/narrow
state.seek(0);
state.apply_keystream(buf);
state.seek(0);
// decrypt with narrow only
state.try_apply_keystream_narrow(buf).unwrap();
for &byte in buf.iter() {
assert_eq!(byte, 0);
}
// encrypt with hybrid wide/narrow
let offset = 0x3fffffff70u64;
state.seek(offset);
state.apply_keystream(buf);
// decrypt with narrow only
state.seek(offset);
state.try_apply_keystream_narrow(buf).unwrap();
for &byte in buf.iter() {
assert_eq!(byte, 0);
}
}
}
}

2
third_party/rust/rand/.cargo-checksum.json поставляемый
Просмотреть файл

@ -1 +1 @@
{"files":{"CHANGELOG.md":"6b229076724946d94360b3f6d06b6b3e36426d8b684a6d3d6b23d0ce3eed5fe5","COPYRIGHT":"90eb64f0279b0d9432accfa6023ff803bc4965212383697eee27a0f426d5f8d5","Cargo.lock":"d50ba66a164f236b6f4efe4ab8f0cf6f31361618a364324104fa1c55483e0f59","Cargo.toml":"0e5d02de8aecef9090f78a7f81921a63c4261140a00e9154f5e6c51d58f3acf5","LICENSE-APACHE":"aaff376532ea30a0cd5330b9502ad4a4c8bf769c539c87ffe78819d188a18ebf","LICENSE-MIT":"209fbbe0ad52d9235e37badf9cadfe4dbdc87203179c0899e738b39ade42177b","README.md":"7739fbd8b2a916d9e18fea431ccf0e55fd128428d4b6c64849dbba60dfda8a01","benches/generators.rs":"f431e5c618b5d7ceedb4720d0b0f0d20b73a4f895129e01bc24a47461b158116","benches/misc.rs":"ef3180a16c469cfcda2cf5146d8ea0e77552316f9e0ad0de4690cf492d725dfe","benches/seq.rs":"dea8cfb68e944acdd488fe464fbb68298f07bb972f55d0a963c775b5b253eb57","benches/weighted.rs":"67a40f456c7b024000c2db24f64af7ae24a147d3c2c55af1349970de3faca3fd","examples/monte-carlo.rs":"5c01a47885a31445e78fab076f8328a7732bca41d84e0d4ba5670b80ca7a883f","examples/monty-hall.rs":"437d5150e8375f64e24d6bac63b5385114196698d5457c8a1b4f50defa427a37","rustfmt.toml":"f0f95df871dbc3b5e6619a6a652746ff50d6185e4d5198fc9b70de703047c660","src/distributions/bernoulli.rs":"b711106b20af024378669991fd228e60ad3e402792fa8541fd7a82e030a42d19","src/distributions/binomial.rs":"0fc44a6ceb3440e706c52d38631f741c00b1b03165cf1f1acd4adfb89a6c998a","src/distributions/cauchy.rs":"c58768bf151786ff08148fe06024f9db05e450a4e24ffb50a94d8399f67b817b","src/distributions/dirichlet.rs":"bc3fa16b5d5c8ae472924f142efe1de06980ba31f73378750958348eba546390","src/distributions/exponential.rs":"02afd305a813bd6dd7d6f9148fd3284bb85e8aa07a9ba2b18e16ad66c2ca0cde","src/distributions/float.rs":"550e5bde1857bdfdb30bf4588384bb208f2092e2e89fc4f6d6cc7cf5dbdd4e1c","src/distributions/gamma.rs":"7853b91e322ad6dda2ecc944e5291e46524c32955d8e93d15eb22e68ecbadf55","src/distributions/integer.rs":"2f03db82cd3e9283c85d39b04e9437d9ba3e7b33a140f48d9b117a60876e4eb0","src/distributions/mod.rs":"a12883606bbb7b0be3c579d5fc25049223d30051a3362fd28072545bc43c0541","src/distributions/normal.rs":"afd5dfafc1ab4c6905ff823e5ece0a808731108c67bd9f7435454e1962018bba","src/distributions/other.rs":"8d198bc0c36775dea3bed1150746e868683b8504de763b678b49adf34bd68fdb","src/distributions/pareto.rs":"3d8f9467daa0c6a831da90e14cf2600352da32a37c5483858ae718f4c888c936","src/distributions/poisson.rs":"b6d848616f07cc6387a69fe1e8fcb7718fc25e7c7c5db27fb7356e29446346f1","src/distributions/triangular.rs":"0b1584f874eeef21b55189c072e3ba6003014a9507f461a0ae0a3e9a95a6a536","src/distributions/uniform.rs":"87024d6b3fd6c5630015bc0dac72e663503170c5ed8adc1e02533ad250771e34","src/distributions/unit_circle.rs":"34f58c46f57c7995cd6b8fe32906cd529bfe7bc8e53963177b7a478745af0bc1","src/distributions/unit_sphere.rs":"4db4f3af623cf4e40e00bf00b4c3f549a5ff8bf0c31468a4c77838f9dee5587a","src/distributions/utils.rs":"1c91cac422c52050091ee73873e79fbcaa7a4d6c99cf7f198b8e7f9c1936c05a","src/distributions/weibull.rs":"403a5c9e5b82ac252e27fd5d295769c557bb41d817cc98a3cbd6910d6221d2de","src/distributions/weighted/alias_method.rs":"2040efd98389f3073dba9dcc9b3f5055814fb9cbdc61794ae8d396512d8b5647","src/distributions/weighted/mod.rs":"f66d0101d02df411430fef07e04ca55f450ff1dd2873eb7073b30a6733f66c78","src/distributions/ziggurat_tables.rs":"6368acec20801c703ae76dd1e08983793732c5ac221c491f85d719ef75448b6d","src/lib.rs":"c5fb3ed272ed93bd8d799c50e46f872158d1a05ded1c89406d51052cd9dca37c","src/prelude.rs":"331b6249754e89cf0c493e443b41455ffce4146c24de2bffdd596f355d86e5f8","src/rngs/adapter/mod.rs":"a625303a793b3f7ee2e25d210204493d1774e0cee8b39dc2cab0035e80c0ce24","src/rngs/adapter/read.rs":"35a1f2bbd29485d4130b1e4b75f9fe0e9a0ef7e779e4c77b0dbfd23900bfdb42","src/rngs/adapter/reseeding.rs":"c62b32e7d925cdfb5972672a493d6edd8f304403fb6f6d5c0fb063d77467917b","src/rngs/entropy.rs":"3bf02b8b1d1531608e8483c8723a96fd30204f84318880851d2c431eabc72439","src/rngs/mock.rs":"18fad8c5c0c4625b2941919b5be89ef77f2a7841261005320b8689c9b1e5a8e3","src/rngs/mod.rs":"0678444670a1d88fbee6b7fcc17f4a84a584998b3e6367c86379d212180b2383","src/rngs/small.rs":"7435781d3229d1e17dfc4e2db991067395250dca7e6af724db09f93c6f96e277","src/rngs/std.rs":"2765d7a1cf85556af12cf46e24986711ba52592d4b8b139f7164368f4886a53b","src/rngs/thread.rs":"fe575428f4a1c9eeddefacf305b85ce645fa0b5d8caa4d1e41f9bbb63cc3ac0c","src/seq/index.rs":"a13461729540080c19da0f8a4b36d844f4519524858adb05adfffe386d330064","src/seq/mod.rs":"caa14c4ca934ffbf3bdc1bc0862f96852a5af39ebd0bc1784aa52981d44e5404"},"package":"3ae1b169243eaf61759b8475a998f0a385e42042370f3a7dbaf35246eacc8412"}
{"files":{"CHANGELOG.md":"28794454ddd6739a1c0cfc6df90a25af3a6a62827d7f7aaea3ee39440b9ab87b","COPYRIGHT":"90eb64f0279b0d9432accfa6023ff803bc4965212383697eee27a0f426d5f8d5","Cargo.lock":"ee32a72318ee8c6986509e36ae276406b622897cb82324c3f0e39551f0edc2cb","Cargo.toml":"4bc436e4b01131f4809c2d3dbdd3ede6987135d3fb53f718cd4a85cafa240224","LICENSE-APACHE":"aaff376532ea30a0cd5330b9502ad4a4c8bf769c539c87ffe78819d188a18ebf","LICENSE-MIT":"209fbbe0ad52d9235e37badf9cadfe4dbdc87203179c0899e738b39ade42177b","README.md":"cc7af91db7807de40503b3033ea596aeb78a89c0997894ffd0e56c2fb06eab36","SECURITY.md":"b1c8e24e88bd81bb65bad212b1176d18a73f5191ae650a75784954a74acc31d4","benches/generators.rs":"361886b55d31449e7a649518e5a751eff4494cad8f3e247aee741dddd82d99a4","benches/misc.rs":"6fa587fb3bab8502b7dd88805a4255c5fc6b42b8b3f5d8eb727af1b80b0ebe29","benches/seq.rs":"bdc6c92a8cedb5ff41ac028618053eaf5bf4c7be8b16c83c79e9467039381302","benches/weighted.rs":"3649964f75cd6cb4e50134fbb14e09fb995ca6667cb34f99d0bd27a9429de3ea","examples/monte-carlo.rs":"e55087f1e1f48d723ffc49fb107f5846c163a5e0c97206cd43a261cbdf6bb1b4","examples/monty-hall.rs":"c079293ec0633717b4d903c63f9db166c2a0fe6c8ba9a98f084fb4975fccbc07","rustfmt.toml":"a582a93dc6492d36daae52df7800e369887ba0984d68d98f70b99ca870fed268","src/distributions/bernoulli.rs":"fa81935ea2091d43d373bb7f2f579522a5beae33c9aa9598fe8490298753eba7","src/distributions/binomial.rs":"667f4f2cddb7994aa68926dbdda4482c24ce28f9d392d2a439a9eb675bfe04be","src/distributions/cauchy.rs":"bf55d4535960136351938a92254d4429689c20ebba051808c171f818adbb1191","src/distributions/dirichlet.rs":"ef28a435d9fa6b2f8d953613135cf1be7905f3909edd86b65be4e77685dd9c47","src/distributions/exponential.rs":"0419f25e369b66226ecaaf500395bf3b0decc5f90aedba1151553085774129bf","src/distributions/float.rs":"8dc11e2e4ae743e19e7799da02862480f4499789d8c58c47fbeca5f7930d7cb9","src/distributions/gamma.rs":"bfa848d6165e653d6e461e5b92f49bb119c6f9e259ffe7d7b8fbb34234d611d1","src/distributions/integer.rs":"3eb86fe2a1aca9125463cc581245b498d8c23c0f80422e5496582d2763e605fc","src/distributions/mod.rs":"d2a2b3e36f2f8bdeb93ffc1f3032175b6a062f485e6bf78502401aa854c4fb24","src/distributions/normal.rs":"2ef7e174877f7ccb7c4ff5cbce5dc24eaad0cc700fad33a6d3c20b52ed8f4bcb","src/distributions/other.rs":"e0a6f5e2d6699e460267f463c95797781daf347bff9192b7af7630a18885290c","src/distributions/pareto.rs":"2c1fee43a4b408e9da32abec384542a243b96c5303371a63d0fc2f1baaa02c64","src/distributions/poisson.rs":"ec123c26b0029cb96325e2551e6c82c9b7f7a41c933cc3f40f6f6f6ac7990cef","src/distributions/triangular.rs":"4be8ba5eccdda8ab90319325381ff6952caf59261b59a7a6f79f8867ac426249","src/distributions/uniform.rs":"5a1af322eb2b6cca701bd0a14247b4387e78686318fd01f3213d0f3252cbea18","src/distributions/unit_circle.rs":"36d8640cb8b26fcdb1b7d4d6c0b349316117f9300f480304c8a15d9d148f5937","src/distributions/unit_sphere.rs":"4ecc4260d4e4cc3ebea679a29d2ec343a54d56016c37b2632d78e888a92cb584","src/distributions/utils.rs":"6478e01b2bd0de99e917373f3c86db1142ea10c67488691cbc10af29891ac6dc","src/distributions/weibull.rs":"9b5acc5981a44309820d3a1fd3fff17984590aeebb41a1cdf5098890ad1dec04","src/distributions/weighted/alias_method.rs":"6172aad0d461f6816a944dec00aac09e943fd13123ec518184995658538de7ed","src/distributions/weighted/mod.rs":"54386cf92d39c69b38208bc9b0e2f74949512784a43684d63523bee03c1cc8bc","src/distributions/ziggurat_tables.rs":"2994bb821a60681e0d7a2bb45fcdcbea1040aa775c9aab2c80a7161d753d1ad0","src/lib.rs":"588e35ffc5c859b588d99de6d331251939440383b09da92b1017ddced19a3f41","src/prelude.rs":"cb49fcfc4f0d3b6eaa43c00a667dd3456e6a321e98eee17320ec4a703d6faf4b","src/rngs/adapter/mod.rs":"851918de58eda79c0cb3f2c0756fb756a7769f35115a77a5ae2025e05b4c1d93","src/rngs/adapter/read.rs":"c162cd131c9ed4868415360f627aba17046d4acdae6b7cdc9c75a41e60757caa","src/rngs/adapter/reseeding.rs":"93d2fbf62d1a5765437c4360b94a2df69921fb9cd5b704c4c2023f53eb15ee03","src/rngs/entropy.rs":"a7a07e1f23c45332994eb0b76d250f68a2394048ab6fe3c6691fef719e30fb42","src/rngs/mock.rs":"d1ac752afa589bc3925067f98fe6c13223bda6c3e22b85abe22e4cd60e22bf90","src/rngs/mod.rs":"9ae5e9aa965d3393ef90983ab85834599432c9fc2c1d40de1b9237ab3fc91eb1","src/rngs/small.rs":"8cc5d1ae357554181b4c5fa978e95b667147c251f8431881da66b97ff584224c","src/rngs/std.rs":"82117975ada00199c8ca3677fc4e00bb8b574c50cd321e04b37d0c7542fa0b30","src/rngs/thread.rs":"ccb98ead28d49f6e35d6e50150cbd89579409fcfd792565aceb03e716447de9b","src/seq/index.rs":"4f2566bd9c189fc68a68fc1ad913c6efe3d3ea0699b1b1e110df9d51725c5b3d","src/seq/mod.rs":"26707ad8595093746852799c1d2eee159b69044abfedfcbfe26263a25f8035fa"},"package":"6a6b1679d49b24bbfe0c803429aa1874472f50d9b363131f0e89fc356b544d03"}

18
third_party/rust/rand/CHANGELOG.md поставляемый
Просмотреть файл

@ -8,6 +8,19 @@ A [separate changelog is kept for rand_core](rand_core/CHANGELOG.md).
You may also find the [Upgrade Guide](https://rust-random.github.io/book/update.html) useful.
## [0.7.3] - 2020-01-10
### Fixes
- The `Bernoulli` distribution constructors now reports an error on NaN and on
`denominator == 0`. (#925)
- Use `std::sync::Once` to register fork handler, avoiding possible atomicity violation (#928)
- Fix documentation on the precision of generated floating-point values
### Changes
- Unix: make libc dependency optional; only use fork protection with std feature (#928)
### Additions
- Implement `std::error::Error` for `BernoulliError` (#919)
## [0.7.2] - 2019-09-16
### Fixes
- Fix dependency on `rand_core` 0.5.1 (#890)
@ -16,6 +29,11 @@ You may also find the [Upgrade Guide](https://rust-random.github.io/book/update.
- Unit tests for value stability of distributions added (#888)
## [0.7.1] - 2019-09-13
### Yanked
This release was yanked since it depends on `rand_core::OsRng` added in 0.5.1
but specifies a dependency on version 0.5.0 (#890), causing a broken builds
when updating from `rand 0.7.0` without also updating `rand_core`.
### Fixes
- Fix `no_std` behaviour, appropriately enable c2-chacha's `std` feature (#844)
- `alloc` feature in `no_std` is available since Rust 1.36 (#856)

45
third_party/rust/rand/Cargo.lock сгенерированный поставляемый
Просмотреть файл

@ -1,10 +1,5 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
[[package]]
name = "autocfg"
version = "0.1.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "base-x"
version = "0.2.5"
@ -116,7 +111,7 @@ dependencies = [
[[package]]
name = "rand"
version = "0.7.2"
version = "0.7.3"
dependencies = [
"getrandom 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)",
@ -125,10 +120,7 @@ dependencies = [
"rand_chacha 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
"rand_core 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
"rand_hc 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
"rand_isaac 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
"rand_pcg 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
"rand_xorshift 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
"rand_xoshiro 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
"rand_pcg 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
@ -156,34 +148,9 @@ dependencies = [
"rand_core 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "rand_isaac"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"rand_core 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "rand_pcg"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"autocfg 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
"rand_core 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "rand_xorshift"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"rand_core 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "rand_xoshiro"
version = "0.4.0"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"rand_core 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
@ -377,7 +344,6 @@ version = "0.2.50"
source = "registry+https://github.com/rust-lang/crates.io-index"
[metadata]
"checksum autocfg 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "b671c8fb71b457dd4ae18c4ba1e59aa81793daacc361d82fcd410cef0d491875"
"checksum base-x 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "76f4eae81729e69bb1819a26c6caac956cc429238388091f98cb6cd858f16443"
"checksum bumpalo 2.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ad807f2fc2bf185eeb98ff3a901bd46dc5ad58163d0fa4577ba0d25674d71708"
"checksum c2-chacha 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7d64d04786e0f528460fc884753cf8dddcc466be308f6026f8e355c41a0e4101"
@ -397,10 +363,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
"checksum rand_chacha 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "03a2a90da8c7523f554344f921aa97283eadf6ac484a6d2a7d0212fa7f8d6853"
"checksum rand_core 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19"
"checksum rand_hc 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ca3129af7b92a17112d59ad498c6f81eaf463253766b90396d39ea7a39d6613c"
"checksum rand_isaac 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8df6b0b3dc9991a10b2d91a86d1129314502169a1bf6afa67328945e02498b76"
"checksum rand_pcg 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3e196346cbbc5c70c77e7b4926147ee8e383a38ee4d15d58a08098b169e492b6"
"checksum rand_xorshift 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "77d416b86801d23dde1aa643023b775c3a462efc0ed96443add11546cdf1dca8"
"checksum rand_xoshiro 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a9fcdd2e881d02f1d9390ae47ad8e5696a9e4be7b547a1da2afbc61973217004"
"checksum rand_pcg 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "16abd0c1b639e9eb4d7c50c0b8100b0d0f849be2349829c740fe8e6eb4816429"
"checksum rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a"
"checksum ryu 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c92464b447c0ee8c4fb3824ecc8383b81717b9f1e74ba2e72540aef7b9f82997"
"checksum semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403"

14
third_party/rust/rand/Cargo.toml поставляемый
Просмотреть файл

@ -13,7 +13,7 @@
[package]
edition = "2018"
name = "rand"
version = "0.7.2"
version = "0.7.3"
authors = ["The Rand Project Developers", "The Rust Project Developers"]
exclude = ["/utils/*", "/.travis.yml", "/appveyor.yml", ".gitignore"]
autobenches = true
@ -50,18 +50,9 @@ optional = true
[dev-dependencies.rand_hc]
version = "0.2"
[dev-dependencies.rand_isaac]
version = "0.2"
[dev-dependencies.rand_pcg]
version = "0.2"
[dev-dependencies.rand_xorshift]
version = "0.2"
[dev-dependencies.rand_xoshiro]
version = "0.4"
[features]
alloc = ["rand_core/alloc"]
default = ["std"]
@ -70,7 +61,7 @@ nightly = ["simd_support"]
serde1 = []
simd_support = ["packed_simd"]
small_rng = ["rand_pcg"]
std = ["rand_core/std", "rand_chacha/std", "alloc", "getrandom"]
std = ["rand_core/std", "rand_chacha/std", "alloc", "getrandom", "libc"]
stdweb = ["getrandom_package/stdweb"]
wasm-bindgen = ["getrandom_package/wasm-bindgen"]
[target."cfg(not(target_os = \"emscripten\"))".dependencies.rand_chacha]
@ -80,6 +71,7 @@ default-features = false
version = "0.2"
[target."cfg(unix)".dependencies.libc]
version = "0.2.22"
optional = true
default-features = false
[badges.appveyor]
repository = "rust-random/rand"

6
third_party/rust/rand/README.md поставляемый
Просмотреть файл

@ -67,6 +67,12 @@ A detailed [changelog](CHANGELOG.md) is available.
When upgrading to the next minor series (especially 0.4 → 0.5), we recommend
reading the [Upgrade Guide](https://rust-random.github.io/book/update.html).
### Yanked versions
Some versions of Rand crates have been yanked ("unreleased"). Where this occurs,
the crate's CHANGELOG *should* be updated with a rationale, and a search on the
issue tracker with the keyword `yank` *should* uncover the motivation.
### Rust version requirements
Since version 0.7, Rand requires **Rustc version 1.32 or greater**.

69
third_party/rust/rand/SECURITY.md поставляемый Normal file
Просмотреть файл

@ -0,0 +1,69 @@
# Security Policy
## No guarantees
Support is provided on a best-effort bases only.
No binding guarantees can be provided.
## Security premises
Rand provides the trait `rand_core::CryptoRng` aka `rand::CryptoRng` as a marker
trait. Generators implementating `RngCore` *and* `CryptoRng`, and given the
additional constraints that:
- Instances of seedable RNGs (those implementing `SeedableRng`) are
constructed with cryptographically secure seed values
- The state (memory) of the RNG and its seed value are not be exposed
are expected to provide the following:
- An attacker can gain no advantage over chance (50% for each bit) in
predicting the RNG output, even with full knowledge of all prior outputs.
For some RNGs, notably `OsRng`, `ThreadRng` and those wrapped by `ReseedingRng`,
we provide limited mitigations against side-channel attacks:
- After a process fork on Unix, there is an upper-bound on the number of bits
output by the RNG before the processes diverge, after which outputs from
each process's RNG are uncorrelated
- After the state (memory) of an RNG is leaked, there is an upper-bound on the
number of bits of output by the RNG before prediction of output by an
observer again becomes computationally-infeasible
Additionally, derivations from such an RNG (including the `Rng` trait,
implementations of the `Distribution` trait, and `seq` algorithms) should not
introduce signficant bias other than that expected from the operation in
question (e.g. bias from a weighted distribution).
## Supported Versions
We will attempt to uphold these premises in the following crate versions,
provided that only the latest patch version is used, and with potential
exceptions for theoretical issues without a known exploit:
| Crate | Versions | Exceptions |
| ----- | -------- | ---------- |
| `rand` | 0.7 | |
| `rand` | 0.5, 0.6 | Jitter |
| `rand` | 0.4 | Jitter, ISAAC |
| `rand_core` | 0.2 - 0.5 | |
| `rand_chacha` | 0.1 - 0.2 | |
| `rand_hc` | 0.1 - 0.2 | |
Explanation of exceptions:
- Jitter: `JitterRng` is used as an entropy source when the primary source
fails; this source may not be secure against side-channel attacks, see #699.
- ISAAC: the [ISAAC](https://burtleburtle.net/bob/rand/isaacafa.html) RNG used
to implement `thread_rng` is difficult to analyse and thus cannot provide
strong assertions of security.
## Known issues
In `rand` version 0.3 (0.3.18 and later), if `OsRng` fails, `thread_rng` is
seeded from the system time in an insecure manner.
## Reporting a Vulnerability
To report a vulnerability, [open a new issue](https://github.com/rust-random/rand/issues/new).
Once the issue is resolved, the vulnerability should be [reported to RustSec](https://github.com/RustSec/advisory-db/blob/master/CONTRIBUTING.md).

81
third_party/rust/rand/benches/generators.rs поставляемый
Просмотреть файл

@ -19,15 +19,10 @@ use test::{black_box, Bencher};
use rand::prelude::*;
use rand::rngs::adapter::ReseedingRng;
use rand::rngs::{OsRng, mock::StepRng};
use rand_isaac::{IsaacRng, Isaac64Rng};
use rand_chacha::{ChaCha20Core, ChaCha8Rng, ChaCha12Rng, ChaCha20Rng};
use rand_hc::{Hc128Rng};
use rand::rngs::{mock::StepRng, OsRng};
use rand_chacha::{ChaCha12Rng, ChaCha20Core, ChaCha20Rng, ChaCha8Rng};
use rand_hc::Hc128Rng;
use rand_pcg::{Pcg32, Pcg64, Pcg64Mcg};
use rand_xorshift::XorShiftRng;
use rand_xoshiro::{Xoshiro256StarStar, Xoshiro256Plus, Xoshiro128StarStar,
Xoshiro128Plus, Xoroshiro128StarStar, Xoroshiro128Plus, SplitMix64,
Xoroshiro64StarStar, Xoroshiro64Star};
macro_rules! gen_bytes {
($fnn:ident, $gen:expr) => {
@ -43,20 +38,10 @@ macro_rules! gen_bytes {
});
b.bytes = BYTES_LEN as u64 * RAND_BENCH_N;
}
}
};
}
gen_bytes!(gen_bytes_step, StepRng::new(0, 1));
gen_bytes!(gen_bytes_xorshift, XorShiftRng::from_entropy());
gen_bytes!(gen_bytes_xoshiro256starstar, Xoshiro256StarStar::from_entropy());
gen_bytes!(gen_bytes_xoshiro256plus, Xoshiro256Plus::from_entropy());
gen_bytes!(gen_bytes_xoshiro128starstar, Xoshiro128StarStar::from_entropy());
gen_bytes!(gen_bytes_xoshiro128plus, Xoshiro128Plus::from_entropy());
gen_bytes!(gen_bytes_xoroshiro128starstar, Xoroshiro128StarStar::from_entropy());
gen_bytes!(gen_bytes_xoroshiro128plus, Xoroshiro128Plus::from_entropy());
gen_bytes!(gen_bytes_xoroshiro64starstar, Xoroshiro64StarStar::from_entropy());
gen_bytes!(gen_bytes_xoroshiro64star, Xoroshiro64Star::from_entropy());
gen_bytes!(gen_bytes_splitmix64, SplitMix64::from_entropy());
gen_bytes!(gen_bytes_pcg32, Pcg32::from_entropy());
gen_bytes!(gen_bytes_pcg64, Pcg64::from_entropy());
gen_bytes!(gen_bytes_pcg64mcg, Pcg64Mcg::from_entropy());
@ -64,10 +49,8 @@ gen_bytes!(gen_bytes_chacha8, ChaCha8Rng::from_entropy());
gen_bytes!(gen_bytes_chacha12, ChaCha12Rng::from_entropy());
gen_bytes!(gen_bytes_chacha20, ChaCha20Rng::from_entropy());
gen_bytes!(gen_bytes_hc128, Hc128Rng::from_entropy());
gen_bytes!(gen_bytes_isaac, IsaacRng::from_entropy());
gen_bytes!(gen_bytes_isaac64, Isaac64Rng::from_entropy());
gen_bytes!(gen_bytes_std, StdRng::from_entropy());
#[cfg(feature="small_rng")]
#[cfg(feature = "small_rng")]
gen_bytes!(gen_bytes_small, SmallRng::from_entropy());
gen_bytes!(gen_bytes_os, OsRng);
@ -85,20 +68,10 @@ macro_rules! gen_uint {
});
b.bytes = size_of::<$ty>() as u64 * RAND_BENCH_N;
}
}
};
}
gen_uint!(gen_u32_step, u32, StepRng::new(0, 1));
gen_uint!(gen_u32_xorshift, u32, XorShiftRng::from_entropy());
gen_uint!(gen_u32_xoshiro256starstar, u32, Xoshiro256StarStar::from_entropy());
gen_uint!(gen_u32_xoshiro256plus, u32, Xoshiro256Plus::from_entropy());
gen_uint!(gen_u32_xoshiro128starstar, u32, Xoshiro128StarStar::from_entropy());
gen_uint!(gen_u32_xoshiro128plus, u32, Xoshiro128Plus::from_entropy());
gen_uint!(gen_u32_xoroshiro128starstar, u32, Xoroshiro128StarStar::from_entropy());
gen_uint!(gen_u32_xoroshiro128plus, u32, Xoroshiro128Plus::from_entropy());
gen_uint!(gen_u32_xoroshiro64starstar, u32, Xoroshiro64StarStar::from_entropy());
gen_uint!(gen_u32_xoroshiro64star, u32, Xoroshiro64Star::from_entropy());
gen_uint!(gen_u32_splitmix64, u32, SplitMix64::from_entropy());
gen_uint!(gen_u32_pcg32, u32, Pcg32::from_entropy());
gen_uint!(gen_u32_pcg64, u32, Pcg64::from_entropy());
gen_uint!(gen_u32_pcg64mcg, u32, Pcg64Mcg::from_entropy());
@ -106,24 +79,12 @@ gen_uint!(gen_u32_chacha8, u32, ChaCha8Rng::from_entropy());
gen_uint!(gen_u32_chacha12, u32, ChaCha12Rng::from_entropy());
gen_uint!(gen_u32_chacha20, u32, ChaCha20Rng::from_entropy());
gen_uint!(gen_u32_hc128, u32, Hc128Rng::from_entropy());
gen_uint!(gen_u32_isaac, u32, IsaacRng::from_entropy());
gen_uint!(gen_u32_isaac64, u32, Isaac64Rng::from_entropy());
gen_uint!(gen_u32_std, u32, StdRng::from_entropy());
#[cfg(feature="small_rng")]
#[cfg(feature = "small_rng")]
gen_uint!(gen_u32_small, u32, SmallRng::from_entropy());
gen_uint!(gen_u32_os, u32, OsRng);
gen_uint!(gen_u64_step, u64, StepRng::new(0, 1));
gen_uint!(gen_u64_xorshift, u64, XorShiftRng::from_entropy());
gen_uint!(gen_u64_xoshiro256starstar, u64, Xoshiro256StarStar::from_entropy());
gen_uint!(gen_u64_xoshiro256plus, u64, Xoshiro256Plus::from_entropy());
gen_uint!(gen_u64_xoshiro128starstar, u64, Xoshiro128StarStar::from_entropy());
gen_uint!(gen_u64_xoshiro128plus, u64, Xoshiro128Plus::from_entropy());
gen_uint!(gen_u64_xoroshiro128starstar, u64, Xoroshiro128StarStar::from_entropy());
gen_uint!(gen_u64_xoroshiro128plus, u64, Xoroshiro128Plus::from_entropy());
gen_uint!(gen_u64_xoroshiro64starstar, u64, Xoroshiro64StarStar::from_entropy());
gen_uint!(gen_u64_xoroshiro64star, u64, Xoroshiro64Star::from_entropy());
gen_uint!(gen_u64_splitmix64, u64, SplitMix64::from_entropy());
gen_uint!(gen_u64_pcg32, u64, Pcg32::from_entropy());
gen_uint!(gen_u64_pcg64, u64, Pcg64::from_entropy());
gen_uint!(gen_u64_pcg64mcg, u64, Pcg64Mcg::from_entropy());
@ -131,10 +92,8 @@ gen_uint!(gen_u64_chacha8, u64, ChaCha8Rng::from_entropy());
gen_uint!(gen_u64_chacha12, u64, ChaCha12Rng::from_entropy());
gen_uint!(gen_u64_chacha20, u64, ChaCha20Rng::from_entropy());
gen_uint!(gen_u64_hc128, u64, Hc128Rng::from_entropy());
gen_uint!(gen_u64_isaac, u64, IsaacRng::from_entropy());
gen_uint!(gen_u64_isaac64, u64, Isaac64Rng::from_entropy());
gen_uint!(gen_u64_std, u64, StdRng::from_entropy());
#[cfg(feature="small_rng")]
#[cfg(feature = "small_rng")]
gen_uint!(gen_u64_small, u64, SmallRng::from_entropy());
gen_uint!(gen_u64_os, u64, OsRng);
@ -142,31 +101,19 @@ macro_rules! init_gen {
($fnn:ident, $gen:ident) => {
#[bench]
fn $fnn(b: &mut Bencher) {
let mut rng = XorShiftRng::from_entropy();
let mut rng = Pcg32::from_entropy();
b.iter(|| {
let r2 = $gen::from_rng(&mut rng).unwrap();
r2
});
}
}
};
}
init_gen!(init_xorshift, XorShiftRng);
init_gen!(init_xoshiro256starstar, Xoshiro256StarStar);
init_gen!(init_xoshiro256plus, Xoshiro256Plus);
init_gen!(init_xoshiro128starstar, Xoshiro128StarStar);
init_gen!(init_xoshiro128plus, Xoshiro128Plus);
init_gen!(init_xoroshiro128starstar, Xoroshiro128StarStar);
init_gen!(init_xoroshiro128plus, Xoroshiro128Plus);
init_gen!(init_xoroshiro64starstar, Xoroshiro64StarStar);
init_gen!(init_xoroshiro64star, Xoroshiro64Star);
init_gen!(init_splitmix64, SplitMix64);
init_gen!(init_pcg32, Pcg32);
init_gen!(init_pcg64, Pcg64);
init_gen!(init_pcg64mcg, Pcg64Mcg);
init_gen!(init_hc128, Hc128Rng);
init_gen!(init_isaac, IsaacRng);
init_gen!(init_isaac64, Isaac64Rng);
init_gen!(init_chacha, ChaCha20Rng);
const RESEEDING_BYTES_LEN: usize = 1024 * 1024;
@ -176,9 +123,7 @@ macro_rules! reseeding_bytes {
($fnn:ident, $thresh:expr) => {
#[bench]
fn $fnn(b: &mut Bencher) {
let mut rng = ReseedingRng::new(ChaCha20Core::from_entropy(),
$thresh * 1024,
OsRng);
let mut rng = ReseedingRng::new(ChaCha20Core::from_entropy(), $thresh * 1024, OsRng);
let mut buf = [0u8; RESEEDING_BYTES_LEN];
b.iter(|| {
for _ in 0..RESEEDING_BENCH_N {
@ -188,7 +133,7 @@ macro_rules! reseeding_bytes {
});
b.bytes = RESEEDING_BYTES_LEN as u64 * RESEEDING_BENCH_N;
}
}
};
}
reseeding_bytes!(reseeding_chacha20_4k, 4);
@ -213,7 +158,7 @@ macro_rules! threadrng_uint {
});
b.bytes = size_of::<$ty>() as u64 * RAND_BENCH_N;
}
}
};
}
threadrng_uint!(thread_rng_u32, u32);

2
third_party/rust/rand/benches/misc.rs поставляемый
Просмотреть файл

@ -14,8 +14,8 @@ const RAND_BENCH_N: u64 = 1000;
use test::Bencher;
use rand::distributions::{Bernoulli, Distribution, Standard};
use rand::prelude::*;
use rand::distributions::{Distribution, Standard, Bernoulli};
use rand_pcg::{Pcg32, Pcg64Mcg};
#[bench]

50
third_party/rust/rand/benches/seq.rs поставляемый
Просмотреть файл

@ -26,7 +26,7 @@ const RAND_BENCH_N: u64 = 1000;
#[bench]
fn seq_shuffle_100(b: &mut Bencher) {
let mut rng = SmallRng::from_rng(thread_rng()).unwrap();
let x : &mut [usize] = &mut [1; 100];
let x: &mut [usize] = &mut [1; 100];
b.iter(|| {
x.shuffle(&mut rng);
x[0]
@ -36,7 +36,7 @@ fn seq_shuffle_100(b: &mut Bencher) {
#[bench]
fn seq_slice_choose_1_of_1000(b: &mut Bencher) {
let mut rng = SmallRng::from_rng(thread_rng()).unwrap();
let x : &mut [usize] = &mut [1; 1000];
let x: &mut [usize] = &mut [1; 1000];
for i in 0..1000 {
x[i] = i;
}
@ -55,19 +55,18 @@ macro_rules! seq_slice_choose_multiple {
#[bench]
fn $name(b: &mut Bencher) {
let mut rng = SmallRng::from_rng(thread_rng()).unwrap();
let x : &[i32] = &[$amount; $length];
let x: &[i32] = &[$amount; $length];
let mut result = [0i32; $amount];
b.iter(|| {
// Collect full result to prevent unwanted shortcuts getting
// first element (in case sample_indices returns an iterator).
for (slot, sample) in result.iter_mut().zip(
x.choose_multiple(&mut rng, $amount)) {
for (slot, sample) in result.iter_mut().zip(x.choose_multiple(&mut rng, $amount)) {
*slot = *sample;
}
result[$amount-1]
result[$amount - 1]
})
}
}
};
}
seq_slice_choose_multiple!(seq_slice_choose_multiple_1_of_1000, 1, 1000);
@ -78,7 +77,7 @@ seq_slice_choose_multiple!(seq_slice_choose_multiple_90_of_100, 90, 100);
#[bench]
fn seq_iter_choose_from_1000(b: &mut Bencher) {
let mut rng = SmallRng::from_rng(thread_rng()).unwrap();
let x : &mut [usize] = &mut [1; 1000];
let x: &mut [usize] = &mut [1; 1000];
for i in 0..1000 {
x[i] = i;
}
@ -98,6 +97,7 @@ struct UnhintedIterator<I: Iterator + Clone> {
}
impl<I: Iterator + Clone> Iterator for UnhintedIterator<I> {
type Item = I::Item;
fn next(&mut self) -> Option<Self::Item> {
self.iter.next()
}
@ -110,9 +110,11 @@ struct WindowHintedIterator<I: ExactSizeIterator + Iterator + Clone> {
}
impl<I: ExactSizeIterator + Iterator + Clone> Iterator for WindowHintedIterator<I> {
type Item = I::Item;
fn next(&mut self) -> Option<Self::Item> {
self.iter.next()
}
fn size_hint(&self) -> (usize, Option<usize>) {
(std::cmp::min(self.iter.len(), self.window_size), None)
}
@ -121,38 +123,40 @@ impl<I: ExactSizeIterator + Iterator + Clone> Iterator for WindowHintedIterator<
#[bench]
fn seq_iter_unhinted_choose_from_1000(b: &mut Bencher) {
let mut rng = SmallRng::from_rng(thread_rng()).unwrap();
let x : &[usize] = &[1; 1000];
let x: &[usize] = &[1; 1000];
b.iter(|| {
UnhintedIterator { iter: x.iter() }.choose(&mut rng).unwrap()
UnhintedIterator { iter: x.iter() }
.choose(&mut rng)
.unwrap()
})
}
#[bench]
fn seq_iter_window_hinted_choose_from_1000(b: &mut Bencher) {
let mut rng = SmallRng::from_rng(thread_rng()).unwrap();
let x : &[usize] = &[1; 1000];
let x: &[usize] = &[1; 1000];
b.iter(|| {
WindowHintedIterator { iter: x.iter(), window_size: 7 }.choose(&mut rng)
WindowHintedIterator {
iter: x.iter(),
window_size: 7,
}
.choose(&mut rng)
})
}
#[bench]
fn seq_iter_choose_multiple_10_of_100(b: &mut Bencher) {
let mut rng = SmallRng::from_rng(thread_rng()).unwrap();
let x : &[usize] = &[1; 100];
b.iter(|| {
x.iter().cloned().choose_multiple(&mut rng, 10)
})
let x: &[usize] = &[1; 100];
b.iter(|| x.iter().cloned().choose_multiple(&mut rng, 10))
}
#[bench]
fn seq_iter_choose_multiple_fill_10_of_100(b: &mut Bencher) {
let mut rng = SmallRng::from_rng(thread_rng()).unwrap();
let x : &[usize] = &[1; 100];
let x: &[usize] = &[1; 100];
let mut buf = [0; 10];
b.iter(|| {
x.iter().cloned().choose_multiple_fill(&mut rng, &mut buf)
})
b.iter(|| x.iter().cloned().choose_multiple_fill(&mut rng, &mut buf))
}
macro_rules! sample_indices {
@ -160,11 +164,9 @@ macro_rules! sample_indices {
#[bench]
fn $name(b: &mut Bencher) {
let mut rng = SmallRng::from_rng(thread_rng()).unwrap();
b.iter(|| {
index::$fn(&mut rng, $length, $amount)
})
b.iter(|| index::$fn(&mut rng, $length, $amount))
}
}
};
}
sample_indices!(misc_sample_indices_1_of_1k, sample, 1, 1000);

4
third_party/rust/rand/benches/weighted.rs поставляемый
Просмотреть файл

@ -10,9 +10,9 @@
extern crate test;
use test::Bencher;
use rand::Rng;
use rand::distributions::WeightedIndex;
use rand::Rng;
use test::Bencher;
#[bench]
fn weighted_index_creation(b: &mut Bencher) {

Просмотреть файл

@ -38,11 +38,14 @@ fn main() {
for _ in 0..total {
let a = range.sample(&mut rng);
let b = range.sample(&mut rng);
if a*a + b*b <= 1.0 {
if a * a + b * b <= 1.0 {
in_circle += 1;
}
}
// prints something close to 3.14159...
println!("π is approximately {}", 4. * (in_circle as f64) / (total as f64));
println!(
"π is approximately {}",
4. * (in_circle as f64) / (total as f64)
);
}

29
third_party/rust/rand/examples/monty-hall.rs поставляемый
Просмотреть файл

@ -52,7 +52,10 @@ fn simulate<R: Rng>(random_door: &Uniform<u32>, rng: &mut R) -> SimulationResult
choice = switch_door(choice, open);
}
SimulationResult { win: choice == car, switch }
SimulationResult {
win: choice == car,
switch,
}
}
// Returns the door the game host opens given our choice and knowledge of
@ -97,16 +100,24 @@ fn main() {
let total_switches = switch_wins + switch_losses;
let total_keeps = keep_wins + keep_losses;
println!("Switched door {} times with {} wins and {} losses",
total_switches, switch_wins, switch_losses);
println!(
"Switched door {} times with {} wins and {} losses",
total_switches, switch_wins, switch_losses
);
println!("Kept our choice {} times with {} wins and {} losses",
total_keeps, keep_wins, keep_losses);
println!(
"Kept our choice {} times with {} wins and {} losses",
total_keeps, keep_wins, keep_losses
);
// With a large number of simulations, the values should converge to
// 0.667 and 0.333 respectively.
println!("Estimated chance to win if we switch: {}",
switch_wins as f32 / total_switches as f32);
println!("Estimated chance to win if we don't: {}",
keep_wins as f32 / total_keeps as f32);
println!(
"Estimated chance to win if we switch: {}",
switch_wins as f32 / total_switches as f32
);
println!(
"Estimated chance to win if we don't: {}",
keep_wins as f32 / total_keeps as f32
);
}

8
third_party/rust/rand/rustfmt.toml поставляемый
Просмотреть файл

@ -4,13 +4,14 @@
# Comments:
normalize_comments = true
wrap_comments = false
format_doc_comments = true
comment_width = 90 # small excess is okay but prefer 80
# Arguments:
use_small_heuristics = "max"
fn_args_density = "compressed"
use_small_heuristics = "Default"
# TODO: single line functions only where short, please?
# https://github.com/rust-lang/rustfmt/issues/3358
fn_single_line = false
fn_args_layout = "Compressed"
overflow_delimited_expr = true
where_single_line = true
@ -21,6 +22,7 @@ where_single_line = true
edition = "2018" # we require compatibility back to 1.32.0
# Misc:
inline_attribute_width = 80
blank_lines_upper_bound = 2
reorder_impl_items = true
# report_todo = "Unnumbered"

Просмотреть файл

@ -8,8 +8,9 @@
//! The Bernoulli distribution.
use crate::Rng;
use crate::distributions::Distribution;
use crate::Rng;
use core::{fmt, u64};
/// The Bernoulli distribution.
///
@ -55,7 +56,7 @@ pub struct Bernoulli {
// the RNG, and pay the performance price for all uses that *are* reasonable.
// Luckily, if `new()` and `sample` are close, the compiler can optimize out the
// extra check.
const ALWAYS_TRUE: u64 = ::core::u64::MAX;
const ALWAYS_TRUE: u64 = u64::MAX;
// This is just `2.0.powi(64)`, but written this way because it is not available
// in `no_std` mode.
@ -68,6 +69,17 @@ pub enum BernoulliError {
InvalidProbability,
}
impl fmt::Display for BernoulliError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_str(match self {
BernoulliError::InvalidProbability => "p is outside [0, 1] in Bernoulli distribution",
})
}
}
#[cfg(feature = "std")]
impl ::std::error::Error for BernoulliError {}
impl Bernoulli {
/// Construct a new `Bernoulli` with the given probability of success `p`.
///
@ -81,26 +93,32 @@ impl Bernoulli {
/// 2<sup>-64</sup> in `[0, 1]` can be represented as a `f64`.)
#[inline]
pub fn new(p: f64) -> Result<Bernoulli, BernoulliError> {
if p < 0.0 || p >= 1.0 {
if p == 1.0 { return Ok(Bernoulli { p_int: ALWAYS_TRUE }) }
if !(p >= 0.0 && p < 1.0) {
if p == 1.0 {
return Ok(Bernoulli { p_int: ALWAYS_TRUE });
}
return Err(BernoulliError::InvalidProbability);
}
Ok(Bernoulli { p_int: (p * SCALE) as u64 })
Ok(Bernoulli {
p_int: (p * SCALE) as u64,
})
}
/// Construct a new `Bernoulli` with the probability of success of
/// `numerator`-in-`denominator`. I.e. `new_ratio(2, 3)` will return
/// a `Bernoulli` with a 2-in-3 chance, or about 67%, of returning `true`.
///
/// If `numerator == denominator` then the returned `Bernoulli` will always
/// return `true`. If `numerator == 0` it will always return `false`.
/// For `numerator > denominator` and `denominator == 0`, this returns an
/// error. Otherwise, for `numerator == denominator`, samples are always
/// true; for `numerator == 0` samples are always false.
#[inline]
pub fn from_ratio(numerator: u32, denominator: u32) -> Result<Bernoulli, BernoulliError> {
if numerator > denominator {
if numerator > denominator || denominator == 0 {
return Err(BernoulliError::InvalidProbability);
}
if numerator == denominator {
return Ok(Bernoulli { p_int: ALWAYS_TRUE })
return Ok(Bernoulli { p_int: ALWAYS_TRUE });
}
let p_int = ((f64::from(numerator) / f64::from(denominator)) * SCALE) as u64;
Ok(Bernoulli { p_int })
@ -111,7 +129,9 @@ impl Distribution<bool> for Bernoulli {
#[inline]
fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> bool {
// Make sure to always return true for p = 1.0.
if self.p_int == ALWAYS_TRUE { return true; }
if self.p_int == ALWAYS_TRUE {
return true;
}
let v: u64 = rng.gen();
v < self.p_int
}
@ -119,9 +139,9 @@ impl Distribution<bool> for Bernoulli {
#[cfg(test)]
mod test {
use crate::Rng;
use crate::distributions::Distribution;
use super::Bernoulli;
use crate::distributions::Distribution;
use crate::Rng;
#[test]
fn test_trivial() {
@ -137,7 +157,7 @@ mod test {
}
#[test]
#[cfg(not(miri))] // Miri is too slow
#[cfg_attr(miri, ignore)] // Miri is too slow
fn test_average() {
const P: f64 = 0.3;
const NUM: u32 = 3;
@ -161,9 +181,9 @@ mod test {
assert!((avg1 - P).abs() < 5e-3);
let avg2 = (sum2 as f64) / (N as f64);
assert!((avg2 - (NUM as f64)/(DENOM as f64)).abs() < 5e-3);
assert!((avg2 - (NUM as f64) / (DENOM as f64)).abs() < 5e-3);
}
#[test]
fn value_stability() {
let mut rng = crate::test::rng(3);
@ -172,6 +192,8 @@ mod test {
for x in &mut buf {
*x = rng.sample(&distr);
}
assert_eq!(buf, [true, false, false, true, false, false, true, true, true, true]);
assert_eq!(buf, [
true, false, false, true, false, false, true, true, true, true
]);
}
}

Просмотреть файл

@ -11,14 +11,14 @@
#![allow(deprecated)]
#![allow(clippy::all)]
use crate::Rng;
use crate::distributions::{Distribution, Uniform};
use crate::Rng;
/// The binomial distribution `Binomial(n, p)`.
///
/// This distribution has density function:
/// `f(k) = n!/(k! (n-k)!) p^k (1-p)^(n-k)` for `k >= 0`.
#[deprecated(since="0.7.0", note="moved to rand_distr crate")]
#[deprecated(since = "0.7.0", note = "moved to rand_distr crate")]
#[derive(Clone, Copy, Debug)]
pub struct Binomial {
/// Number of trials.
@ -58,11 +58,7 @@ impl Distribution<u64> for Binomial {
// The binomial distribution is symmetrical with respect to p -> 1-p,
// k -> n-k switch p so that it is less than 0.5 - this allows for lower
// expected values we will just invert the result at the end
let p = if self.p <= 0.5 {
self.p
} else {
1.0 - self.p
};
let p = if self.p <= 0.5 { self.p } else { 1.0 - self.p };
let result;
let q = 1. - p;
@ -79,8 +75,7 @@ impl Distribution<u64> for Binomial {
// Ranlib uses 30, and GSL uses 14.
const BINV_THRESHOLD: f64 = 10.;
if (self.n as f64) * p < BINV_THRESHOLD &&
self.n <= (::std::i32::MAX as u64) {
if (self.n as f64) * p < BINV_THRESHOLD && self.n <= (::std::i32::MAX as u64) {
// Use the BINV algorithm.
let s = p / q;
let a = ((self.n + 1) as f64) * s;
@ -212,8 +207,8 @@ impl Distribution<u64> for Binomial {
// Step 5.2: Squeezing. Check the value of ln(v) againts upper and
// lower bound of ln(f(y)).
let k = k as f64;
let rho = (k / npq) * ((k * (k / 3. + 0.625) + 1./6.) / npq + 0.5);
let t = -0.5 * k*k / npq;
let rho = (k / npq) * ((k * (k / 3. + 0.625) + 1. / 6.) / npq + 0.5);
let t = -0.5 * k * k / npq;
let alpha = v.ln();
if alpha < t - rho {
break;
@ -233,15 +228,19 @@ impl Distribution<u64> for Binomial {
(13860. - (462. - (132. - (99. - 140. / a2) / a2) / a2) / a2) / a / 166320.
}
if alpha > x_m * (f1 / x1).ln()
+ (n - (m as f64) + 0.5) * (z / w).ln()
+ ((y - m) as f64) * (w * p / (x1 * q)).ln()
// We use the signs from the GSL implementation, which are
// different than the ones in the reference. According to
// the GSL authors, the new signs were verified to be
// correct by one of the original designers of the
// algorithm.
+ stirling(f1) + stirling(z) - stirling(x1) - stirling(w)
if alpha
> x_m * (f1 / x1).ln()
+ (n - (m as f64) + 0.5) * (z / w).ln()
+ ((y - m) as f64) * (w * p / (x1 * q)).ln()
// We use the signs from the GSL implementation, which are
// different than the ones in the reference. According to
// the GSL authors, the new signs were verified to be
// correct by one of the original designers of the
// algorithm.
+ stirling(f1)
+ stirling(z)
- stirling(x1)
- stirling(w)
{
continue;
}
@ -263,9 +262,9 @@ impl Distribution<u64> for Binomial {
#[cfg(test)]
mod test {
use crate::Rng;
use crate::distributions::Distribution;
use super::Binomial;
use crate::distributions::Distribution;
use crate::Rng;
fn test_binomial_mean_and_variance<R: Rng>(n: u64, p: f64, rng: &mut R) {
let binomial = Binomial::new(n, p);
@ -274,21 +273,30 @@ mod test {
let expected_variance = n as f64 * p * (1.0 - p);
let mut results = [0.0; 1000];
for i in results.iter_mut() { *i = binomial.sample(rng) as f64; }
for i in results.iter_mut() {
*i = binomial.sample(rng) as f64;
}
let mean = results.iter().sum::<f64>() / results.len() as f64;
assert!((mean as f64 - expected_mean).abs() < expected_mean / 50.0,
"mean: {}, expected_mean: {}", mean, expected_mean);
assert!(
(mean as f64 - expected_mean).abs() < expected_mean / 50.0,
"mean: {}, expected_mean: {}",
mean,
expected_mean
);
let variance =
results.iter().map(|x| (x - mean) * (x - mean)).sum::<f64>()
/ results.len() as f64;
assert!((variance - expected_variance).abs() < expected_variance / 10.0,
"variance: {}, expected_variance: {}", variance, expected_variance);
results.iter().map(|x| (x - mean) * (x - mean)).sum::<f64>() / results.len() as f64;
assert!(
(variance - expected_variance).abs() < expected_variance / 10.0,
"variance: {}, expected_variance: {}",
variance,
expected_variance
);
}
#[test]
#[cfg(not(miri))] // Miri is too slow
#[cfg_attr(miri, ignore)] // Miri is too slow
fn test_binomial() {
let mut rng = crate::test::rng(351);
test_binomial_mean_and_variance(150, 0.1, &mut rng);

Просмотреть файл

@ -11,19 +11,19 @@
#![allow(deprecated)]
#![allow(clippy::all)]
use crate::Rng;
use crate::distributions::Distribution;
use crate::Rng;
use std::f64::consts::PI;
/// The Cauchy distribution `Cauchy(median, scale)`.
///
/// This distribution has a density function:
/// `f(x) = 1 / (pi * scale * (1 + ((x - median) / scale)^2))`
#[deprecated(since="0.7.0", note="moved to rand_distr crate")]
#[deprecated(since = "0.7.0", note = "moved to rand_distr crate")]
#[derive(Clone, Copy, Debug)]
pub struct Cauchy {
median: f64,
scale: f64
scale: f64,
}
impl Cauchy {
@ -32,10 +32,7 @@ impl Cauchy {
/// Panics if `scale <= 0`.
pub fn new(median: f64, scale: f64) -> Cauchy {
assert!(scale > 0.0, "Cauchy::new called with scale factor <= 0");
Cauchy {
median,
scale
}
Cauchy { median, scale }
}
}
@ -54,8 +51,8 @@ impl Distribution<f64> for Cauchy {
#[cfg(test)]
mod test {
use crate::distributions::Distribution;
use super::Cauchy;
use crate::distributions::Distribution;
fn median(mut numbers: &mut [f64]) -> f64 {
sort(&mut numbers);
@ -68,7 +65,6 @@ mod test {
}
#[test]
#[cfg(not(miri))] // Miri doesn't support transcendental functions
fn test_cauchy_averages() {
// NOTE: given that the variance and mean are undefined,
// this test does not have any rigorous statistical meaning.

Просмотреть файл

@ -11,16 +11,16 @@
#![allow(deprecated)]
#![allow(clippy::all)]
use crate::Rng;
use crate::distributions::Distribution;
use crate::distributions::gamma::Gamma;
use crate::distributions::Distribution;
use crate::Rng;
/// The dirichelet distribution `Dirichlet(alpha)`.
///
/// The Dirichlet distribution is a family of continuous multivariate
/// probability distributions parameterized by a vector alpha of positive reals.
/// It is a multivariate generalization of the beta distribution.
#[deprecated(since="0.7.0", note="moved to rand_distr crate")]
#[deprecated(since = "0.7.0", note = "moved to rand_distr crate")]
#[derive(Clone, Debug)]
pub struct Dirichlet {
/// Concentration parameters (alpha)
@ -32,7 +32,6 @@ impl Dirichlet {
///
/// # Panics
/// - if `alpha.len() < 2`
///
#[inline]
pub fn new<V: Into<Vec<f64>>>(alpha: V) -> Dirichlet {
let a = alpha.into();
@ -49,7 +48,6 @@ impl Dirichlet {
/// # Panics
/// - if `alpha <= 0.0`
/// - if `size < 2`
///
#[inline]
pub fn new_with_param(alpha: f64, size: usize) -> Dirichlet {
assert!(alpha > 0.0);

Просмотреть файл

@ -10,9 +10,9 @@
//! The exponential distribution.
#![allow(deprecated)]
use crate::{Rng};
use crate::distributions::{ziggurat_tables, Distribution};
use crate::distributions::utils::ziggurat;
use crate::distributions::{ziggurat_tables, Distribution};
use crate::Rng;
/// Samples floating-point numbers according to the exponential distribution,
/// with rate parameter `λ = 1`. This is equivalent to `Exp::new(1.0)` or
@ -28,7 +28,7 @@ use crate::distributions::utils::ziggurat;
/// Generate Normal Random Samples*](
/// https://www.doornik.com/research/ziggurat.pdf).
/// Nuffield College, Oxford
#[deprecated(since="0.7.0", note="moved to rand_distr crate")]
#[deprecated(since = "0.7.0", note = "moved to rand_distr crate")]
#[derive(Clone, Copy, Debug)]
pub struct Exp1;
@ -45,10 +45,14 @@ impl Distribution<f64> for Exp1 {
ziggurat_tables::ZIG_EXP_R - rng.gen::<f64>().ln()
}
ziggurat(rng, false,
&ziggurat_tables::ZIG_EXP_X,
&ziggurat_tables::ZIG_EXP_F,
pdf, zero_case)
ziggurat(
rng,
false,
&ziggurat_tables::ZIG_EXP_X,
&ziggurat_tables::ZIG_EXP_F,
pdf,
zero_case,
)
}
}
@ -56,13 +60,13 @@ impl Distribution<f64> for Exp1 {
///
/// This distribution has density function: `f(x) = lambda * exp(-lambda * x)`
/// for `x > 0`.
///
///
/// Note that [`Exp1`](crate::distributions::Exp1) is an optimised implementation for `lambda = 1`.
#[deprecated(since="0.7.0", note="moved to rand_distr crate")]
#[deprecated(since = "0.7.0", note = "moved to rand_distr crate")]
#[derive(Clone, Copy, Debug)]
pub struct Exp {
/// `lambda` stored as `1/lambda`, since this is what we scale by.
lambda_inverse: f64
lambda_inverse: f64,
}
impl Exp {
@ -71,7 +75,9 @@ impl Exp {
#[inline]
pub fn new(lambda: f64) -> Exp {
assert!(lambda > 0.0, "Exp::new called with `lambda` <= 0");
Exp { lambda_inverse: 1.0 / lambda }
Exp {
lambda_inverse: 1.0 / lambda,
}
}
}
@ -84,8 +90,8 @@ impl Distribution<f64> for Exp {
#[cfg(test)]
mod test {
use crate::distributions::Distribution;
use super::Exp;
use crate::distributions::Distribution;
#[test]
fn test_exp() {

Просмотреть файл

@ -8,18 +8,17 @@
//! Basic floating-point number distributions
use core::mem;
use crate::Rng;
use crate::distributions::{Distribution, Standard};
use crate::distributions::utils::FloatSIMDUtils;
#[cfg(feature="simd_support")]
use packed_simd::*;
use crate::distributions::{Distribution, Standard};
use crate::Rng;
use core::mem;
#[cfg(feature = "simd_support")] use packed_simd::*;
/// A distribution to sample floating point numbers uniformly in the half-open
/// interval `(0, 1]`, i.e. including 1 but not 0.
///
/// All values that can be generated are of the form `n * ε/2`. For `f32`
/// the 23 most significant random bits of a `u32` are used and for `f64` the
/// the 24 most significant random bits of a `u32` are used and for `f64` the
/// 53 most significant bits of a `u64` are used. The conversion uses the
/// multiplicative method.
///
@ -46,7 +45,7 @@ pub struct OpenClosed01;
/// interval `(0, 1)`, i.e. not including either endpoint.
///
/// All values that can be generated are of the form `n * ε + ε/2`. For `f32`
/// the 22 most significant random bits of an `u32` are used, for `f64` 52 from
/// the 23 most significant random bits of an `u32` are used, for `f64` 52 from
/// an `u64`. The conversion uses a transmute-based method.
///
/// See also: [`Standard`] which samples from `[0, 1)`, [`OpenClosed01`]
@ -149,20 +148,20 @@ macro_rules! float_impls {
float_impls! { f32, u32, f32, u32, 23, 127 }
float_impls! { f64, u64, f64, u64, 52, 1023 }
#[cfg(feature="simd_support")]
#[cfg(feature = "simd_support")]
float_impls! { f32x2, u32x2, f32, u32, 23, 127 }
#[cfg(feature="simd_support")]
#[cfg(feature = "simd_support")]
float_impls! { f32x4, u32x4, f32, u32, 23, 127 }
#[cfg(feature="simd_support")]
#[cfg(feature = "simd_support")]
float_impls! { f32x8, u32x8, f32, u32, 23, 127 }
#[cfg(feature="simd_support")]
#[cfg(feature = "simd_support")]
float_impls! { f32x16, u32x16, f32, u32, 23, 127 }
#[cfg(feature="simd_support")]
#[cfg(feature = "simd_support")]
float_impls! { f64x2, u64x2, f64, u64, 52, 1023 }
#[cfg(feature="simd_support")]
#[cfg(feature = "simd_support")]
float_impls! { f64x4, u64x4, f64, u64, 52, 1023 }
#[cfg(feature="simd_support")]
#[cfg(feature = "simd_support")]
float_impls! { f64x8, u64x8, f64, u64, 52, 1023 }
@ -188,8 +187,7 @@ mod tests {
// OpenClosed01
let mut zeros = StepRng::new(0, 0);
assert_eq!(zeros.sample::<$ty, _>(OpenClosed01),
0.0 + $EPSILON / 2.0);
assert_eq!(zeros.sample::<$ty, _>(OpenClosed01), 0.0 + $EPSILON / 2.0);
let mut one = StepRng::new(1 << 8 | 1 << (8 + 32), 0);
assert_eq!(one.sample::<$ty, _>(OpenClosed01), $EPSILON);
let mut max = StepRng::new(!0, 0);
@ -203,16 +201,16 @@ mod tests {
let mut max = StepRng::new(!0, 0);
assert_eq!(max.sample::<$ty, _>(Open01), 1.0 - $EPSILON / 2.0);
}
}
};
}
test_f32! { f32_edge_cases, f32, 0.0, EPSILON32 }
#[cfg(feature="simd_support")]
#[cfg(feature = "simd_support")]
test_f32! { f32x2_edge_cases, f32x2, f32x2::splat(0.0), f32x2::splat(EPSILON32) }
#[cfg(feature="simd_support")]
#[cfg(feature = "simd_support")]
test_f32! { f32x4_edge_cases, f32x4, f32x4::splat(0.0), f32x4::splat(EPSILON32) }
#[cfg(feature="simd_support")]
#[cfg(feature = "simd_support")]
test_f32! { f32x8_edge_cases, f32x8, f32x8::splat(0.0), f32x8::splat(EPSILON32) }
#[cfg(feature="simd_support")]
#[cfg(feature = "simd_support")]
test_f32! { f32x16_edge_cases, f32x16, f32x16::splat(0.0), f32x16::splat(EPSILON32) }
macro_rules! test_f64 {
@ -229,8 +227,7 @@ mod tests {
// OpenClosed01
let mut zeros = StepRng::new(0, 0);
assert_eq!(zeros.sample::<$ty, _>(OpenClosed01),
0.0 + $EPSILON / 2.0);
assert_eq!(zeros.sample::<$ty, _>(OpenClosed01), 0.0 + $EPSILON / 2.0);
let mut one = StepRng::new(1 << 11, 0);
assert_eq!(one.sample::<$ty, _>(OpenClosed01), $EPSILON);
let mut max = StepRng::new(!0, 0);
@ -244,20 +241,20 @@ mod tests {
let mut max = StepRng::new(!0, 0);
assert_eq!(max.sample::<$ty, _>(Open01), 1.0 - $EPSILON / 2.0);
}
}
};
}
test_f64! { f64_edge_cases, f64, 0.0, EPSILON64 }
#[cfg(feature="simd_support")]
#[cfg(feature = "simd_support")]
test_f64! { f64x2_edge_cases, f64x2, f64x2::splat(0.0), f64x2::splat(EPSILON64) }
#[cfg(feature="simd_support")]
#[cfg(feature = "simd_support")]
test_f64! { f64x4_edge_cases, f64x4, f64x4::splat(0.0), f64x4::splat(EPSILON64) }
#[cfg(feature="simd_support")]
#[cfg(feature = "simd_support")]
test_f64! { f64x8_edge_cases, f64x8, f64x8::splat(0.0), f64x8::splat(EPSILON64) }
#[test]
fn value_stability() {
fn test_samples<T: Copy + core::fmt::Debug + PartialEq, D: Distribution<T>>(
distr: &D, zero: T, expected: &[T]
distr: &D, zero: T, expected: &[T],
) {
let mut rng = crate::test::rng(0x6f44f5646c2a7334);
let mut buf = [zero; 3];
@ -266,33 +263,45 @@ mod tests {
}
assert_eq!(&buf, expected);
}
test_samples(&Standard, 0f32, &[0.0035963655, 0.7346052, 0.09778172]);
test_samples(&Standard, 0f64, &[0.7346051961657583,
0.20298547462974248, 0.8166436635290655]);
test_samples(&Standard, 0f64, &[
0.7346051961657583,
0.20298547462974248,
0.8166436635290655,
]);
test_samples(&OpenClosed01, 0f32, &[0.003596425, 0.73460525, 0.09778178]);
test_samples(&OpenClosed01, 0f64, &[0.7346051961657584,
0.2029854746297426, 0.8166436635290656]);
test_samples(&OpenClosed01, 0f64, &[
0.7346051961657584,
0.2029854746297426,
0.8166436635290656,
]);
test_samples(&Open01, 0f32, &[0.0035963655, 0.73460525, 0.09778172]);
test_samples(&Open01, 0f64, &[0.7346051961657584,
0.20298547462974248, 0.8166436635290656]);
#[cfg(feature="simd_support")] {
test_samples(&Open01, 0f64, &[
0.7346051961657584,
0.20298547462974248,
0.8166436635290656,
]);
#[cfg(feature = "simd_support")]
{
// We only test a sub-set of types here. Values are identical to
// non-SIMD types; we assume this pattern continues across all
// SIMD types.
test_samples(&Standard, f32x2::new(0.0, 0.0), &[
f32x2::new(0.0035963655, 0.7346052),
f32x2::new(0.09778172, 0.20298547),
f32x2::new(0.34296435, 0.81664366)]);
f32x2::new(0.0035963655, 0.7346052),
f32x2::new(0.09778172, 0.20298547),
f32x2::new(0.34296435, 0.81664366),
]);
test_samples(&Standard, f64x2::new(0.0, 0.0), &[
f64x2::new(0.7346051961657583, 0.20298547462974248),
f64x2::new(0.8166436635290655, 0.7423708925400552),
f64x2::new(0.16387782224016323, 0.9087068770169618)]);
f64x2::new(0.7346051961657583, 0.20298547462974248),
f64x2::new(0.8166436635290655, 0.7423708925400552),
f64x2::new(0.16387782224016323, 0.9087068770169618),
]);
}
}
}

Просмотреть файл

@ -10,12 +10,12 @@
//! The Gamma and derived distributions.
#![allow(deprecated)]
use self::GammaRepr::*;
use self::ChiSquaredRepr::*;
use self::GammaRepr::*;
use crate::Rng;
use crate::distributions::normal::StandardNormal;
use crate::distributions::{Distribution, Exp, Open01};
use crate::Rng;
/// The Gamma distribution `Gamma(shape, scale)` distribution.
///
@ -37,7 +37,7 @@ use crate::distributions::{Distribution, Exp, Open01};
/// Generating Gamma Variables" *ACM Trans. Math. Softw.* 26, 3
/// (September 2000), 363-372.
/// DOI:[10.1145/358407.358414](https://doi.acm.org/10.1145/358407.358414)
#[deprecated(since="0.7.0", note="moved to rand_distr crate")]
#[deprecated(since = "0.7.0", note = "moved to rand_distr crate")]
#[derive(Clone, Copy, Debug)]
pub struct Gamma {
repr: GammaRepr,
@ -47,7 +47,7 @@ pub struct Gamma {
enum GammaRepr {
Large(GammaLargeShape),
One(Exp),
Small(GammaSmallShape)
Small(GammaSmallShape),
}
// These two helpers could be made public, but saving the
@ -67,7 +67,7 @@ enum GammaRepr {
#[derive(Clone, Copy, Debug)]
struct GammaSmallShape {
inv_shape: f64,
large_shape: GammaLargeShape
large_shape: GammaLargeShape,
}
/// Gamma distribution where the shape parameter is larger than 1.
@ -78,7 +78,7 @@ struct GammaSmallShape {
struct GammaLargeShape {
scale: f64,
c: f64,
d: f64
d: f64,
}
impl Gamma {
@ -106,7 +106,7 @@ impl GammaSmallShape {
fn new_raw(shape: f64, scale: f64) -> GammaSmallShape {
GammaSmallShape {
inv_shape: 1. / shape,
large_shape: GammaLargeShape::new_raw(shape + 1.0, scale)
large_shape: GammaLargeShape::new_raw(shape + 1.0, scale),
}
}
}
@ -117,7 +117,7 @@ impl GammaLargeShape {
GammaLargeShape {
scale,
c: 1. / (9. * d).sqrt(),
d
d,
}
}
}
@ -143,17 +143,19 @@ impl Distribution<f64> for GammaLargeShape {
loop {
let x = rng.sample(StandardNormal);
let v_cbrt = 1.0 + self.c * x;
if v_cbrt <= 0.0 { // a^3 <= 0 iff a <= 0
continue
if v_cbrt <= 0.0 {
// a^3 <= 0 iff a <= 0
continue;
}
let v = v_cbrt * v_cbrt * v_cbrt;
let u: f64 = rng.sample(Open01);
let x_sqr = x * x;
if u < 1.0 - 0.0331 * x_sqr * x_sqr ||
u.ln() < 0.5 * x_sqr + self.d * (1.0 - v + v.ln()) {
return self.d * v * self.scale
if u < 1.0 - 0.0331 * x_sqr * x_sqr
|| u.ln() < 0.5 * x_sqr + self.d * (1.0 - v + v.ln())
{
return self.d * v * self.scale;
}
}
}
@ -166,7 +168,7 @@ impl Distribution<f64> for GammaLargeShape {
/// of `k` independent standard normal random variables. For other
/// `k`, this uses the equivalent characterisation
/// `χ²(k) = Gamma(k/2, 2)`.
#[deprecated(since="0.7.0", note="moved to rand_distr crate")]
#[deprecated(since = "0.7.0", note = "moved to rand_distr crate")]
#[derive(Clone, Copy, Debug)]
pub struct ChiSquared {
repr: ChiSquaredRepr,
@ -202,7 +204,7 @@ impl Distribution<f64> for ChiSquared {
let norm = rng.sample(StandardNormal);
norm * norm
}
DoFAnythingElse(ref g) => g.sample(rng)
DoFAnythingElse(ref g) => g.sample(rng),
}
}
}
@ -212,7 +214,7 @@ impl Distribution<f64> for ChiSquared {
/// This distribution is equivalent to the ratio of two normalised
/// chi-squared distributions, that is, `F(m,n) = (χ²(m)/m) /
/// (χ²(n)/n)`.
#[deprecated(since="0.7.0", note="moved to rand_distr crate")]
#[deprecated(since = "0.7.0", note = "moved to rand_distr crate")]
#[derive(Clone, Copy, Debug)]
pub struct FisherF {
numer: ChiSquared,
@ -232,7 +234,7 @@ impl FisherF {
FisherF {
numer: ChiSquared::new(m),
denom: ChiSquared::new(n),
dof_ratio: n / m
dof_ratio: n / m,
}
}
}
@ -244,11 +246,11 @@ impl Distribution<f64> for FisherF {
/// The Student t distribution, `t(nu)`, where `nu` is the degrees of
/// freedom.
#[deprecated(since="0.7.0", note="moved to rand_distr crate")]
#[deprecated(since = "0.7.0", note = "moved to rand_distr crate")]
#[derive(Clone, Copy, Debug)]
pub struct StudentT {
chi: ChiSquared,
dof: f64
dof: f64,
}
impl StudentT {
@ -258,7 +260,7 @@ impl StudentT {
assert!(n > 0.0, "StudentT::new called with `n <= 0`");
StudentT {
chi: ChiSquared::new(n),
dof: n
dof: n,
}
}
}
@ -270,7 +272,7 @@ impl Distribution<f64> for StudentT {
}
/// The Beta distribution with shape parameters `alpha` and `beta`.
#[deprecated(since="0.7.0", note="moved to rand_distr crate")]
#[deprecated(since = "0.7.0", note = "moved to rand_distr crate")]
#[derive(Clone, Copy, Debug)]
pub struct Beta {
gamma_a: Gamma,
@ -301,8 +303,8 @@ impl Distribution<f64> for Beta {
#[cfg(test)]
mod test {
use super::{Beta, ChiSquared, FisherF, StudentT};
use crate::distributions::Distribution;
use super::{Beta, ChiSquared, StudentT, FisherF};
const N: u32 = 100;

Просмотреть файл

@ -8,16 +8,14 @@
//! The implementations of the `Standard` distribution for integer types.
use crate::{Rng};
use crate::distributions::{Distribution, Standard};
use core::num::{NonZeroU8, NonZeroU16, NonZeroU32, NonZeroU64, NonZeroUsize};
#[cfg(not(target_os = "emscripten"))] use core::num::NonZeroU128;
#[cfg(feature="simd_support")]
use packed_simd::*;
#[cfg(all(target_arch = "x86", feature="nightly"))]
use core::arch::x86::*;
#[cfg(all(target_arch = "x86_64", feature="nightly"))]
use crate::Rng;
#[cfg(all(target_arch = "x86", feature = "nightly"))] use core::arch::x86::*;
#[cfg(all(target_arch = "x86_64", feature = "nightly"))]
use core::arch::x86_64::*;
#[cfg(not(target_os = "emscripten"))] use core::num::NonZeroU128;
use core::num::{NonZeroU16, NonZeroU32, NonZeroU64, NonZeroU8, NonZeroUsize};
#[cfg(feature = "simd_support")] use packed_simd::*;
impl Distribution<u8> for Standard {
#[inline]
@ -80,14 +78,15 @@ macro_rules! impl_int_from_uint {
rng.gen::<$uty>() as $ty
}
}
}
};
}
impl_int_from_uint! { i8, u8 }
impl_int_from_uint! { i16, u16 }
impl_int_from_uint! { i32, u32 }
impl_int_from_uint! { i64, u64 }
#[cfg(not(target_os = "emscripten"))] impl_int_from_uint! { i128, u128 }
#[cfg(not(target_os = "emscripten"))]
impl_int_from_uint! { i128, u128 }
impl_int_from_uint! { isize, usize }
macro_rules! impl_nzint {
@ -101,17 +100,18 @@ macro_rules! impl_nzint {
}
}
}
}
};
}
impl_nzint!(NonZeroU8, NonZeroU8::new);
impl_nzint!(NonZeroU16, NonZeroU16::new);
impl_nzint!(NonZeroU32, NonZeroU32::new);
impl_nzint!(NonZeroU64, NonZeroU64::new);
#[cfg(not(target_os = "emscripten"))] impl_nzint!(NonZeroU128, NonZeroU128::new);
#[cfg(not(target_os = "emscripten"))]
impl_nzint!(NonZeroU128, NonZeroU128::new);
impl_nzint!(NonZeroUsize, NonZeroUsize::new);
#[cfg(feature="simd_support")]
#[cfg(feature = "simd_support")]
macro_rules! simd_impl {
($(($intrinsic:ident, $vec:ty),)+) => {$(
impl Distribution<$intrinsic> for Standard {
@ -141,29 +141,33 @@ macro_rules! simd_impl {
};
}
#[cfg(feature="simd_support")]
#[cfg(feature = "simd_support")]
simd_impl!(16, u8x2, i8x2,);
#[cfg(feature="simd_support")]
#[cfg(feature = "simd_support")]
simd_impl!(32, u8x4, i8x4, u16x2, i16x2,);
#[cfg(feature="simd_support")]
#[cfg(feature = "simd_support")]
simd_impl!(64, u8x8, i8x8, u16x4, i16x4, u32x2, i32x2,);
#[cfg(feature="simd_support")]
#[cfg(feature = "simd_support")]
simd_impl!(128, u8x16, i8x16, u16x8, i16x8, u32x4, i32x4, u64x2, i64x2,);
#[cfg(feature="simd_support")]
#[cfg(feature = "simd_support")]
simd_impl!(256, u8x32, i8x32, u16x16, i16x16, u32x8, i32x8, u64x4, i64x4,);
#[cfg(feature="simd_support")]
#[cfg(feature = "simd_support")]
simd_impl!(512, u8x64, i8x64, u16x32, i16x32, u32x16, i32x16, u64x8, i64x8,);
#[cfg(all(feature="simd_support", feature="nightly", any(target_arch="x86", target_arch="x86_64")))]
#[cfg(all(
feature = "simd_support",
feature = "nightly",
any(target_arch = "x86", target_arch = "x86_64")
))]
simd_impl!((__m64, u8x8), (__m128i, u8x16), (__m256i, u8x32),);
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_integers() {
let mut rng = crate::test::rng(806);
rng.sample::<isize, _>(Standard);
rng.sample::<i8, _>(Standard);
rng.sample::<i16, _>(Standard);
@ -171,7 +175,7 @@ mod tests {
rng.sample::<i64, _>(Standard);
#[cfg(not(target_os = "emscripten"))]
rng.sample::<i128, _>(Standard);
rng.sample::<usize, _>(Standard);
rng.sample::<u8, _>(Standard);
rng.sample::<u16, _>(Standard);
@ -180,14 +184,11 @@ mod tests {
#[cfg(not(target_os = "emscripten"))]
rng.sample::<u128, _>(Standard);
}
#[test]
fn value_stability() {
fn test_samples<T: Copy + core::fmt::Debug + PartialEq>(
zero: T, expected: &[T]
)
where Standard: Distribution<T>
{
fn test_samples<T: Copy + core::fmt::Debug + PartialEq>(zero: T, expected: &[T])
where Standard: Distribution<T> {
let mut rng = crate::test::rng(807);
let mut buf = [zero; 3];
for x in &mut buf {
@ -195,49 +196,84 @@ mod tests {
}
assert_eq!(&buf, expected);
}
test_samples(0u8, &[9, 247, 111]);
test_samples(0u16, &[32265, 42999, 38255]);
test_samples(0u32, &[2220326409, 2575017975, 2018088303]);
test_samples(0u64, &[11059617991457472009,
16096616328739788143, 1487364411147516184]);
test_samples(0u128, &[296930161868957086625409848350820761097,
145644820879247630242265036535529306392,
111087889832015897993126088499035356354]);
test_samples(0u64, &[
11059617991457472009,
16096616328739788143,
1487364411147516184,
]);
test_samples(0u128, &[
296930161868957086625409848350820761097,
145644820879247630242265036535529306392,
111087889832015897993126088499035356354,
]);
#[cfg(any(target_pointer_width = "32", target_pointer_width = "16"))]
test_samples(0usize, &[2220326409, 2575017975, 2018088303]);
#[cfg(target_pointer_width = "64")]
test_samples(0usize, &[11059617991457472009,
16096616328739788143, 1487364411147516184]);
test_samples(0usize, &[
11059617991457472009,
16096616328739788143,
1487364411147516184,
]);
test_samples(0i8, &[9, -9, 111]);
// Skip further i* types: they are simple reinterpretation of u* samples
#[cfg(feature="simd_support")] {
#[cfg(feature = "simd_support")]
{
// We only test a sub-set of types here and make assumptions about the rest.
test_samples(u8x2::default(), &[u8x2::new(9, 126),
u8x2::new(247, 167), u8x2::new(111, 149)]);
test_samples(u8x4::default(), &[u8x4::new(9, 126, 87, 132),
u8x4::new(247, 167, 123, 153), u8x4::new(111, 149, 73, 120)]);
test_samples(u8x2::default(), &[
u8x2::new(9, 126),
u8x2::new(247, 167),
u8x2::new(111, 149),
]);
test_samples(u8x4::default(), &[
u8x4::new(9, 126, 87, 132),
u8x4::new(247, 167, 123, 153),
u8x4::new(111, 149, 73, 120),
]);
test_samples(u8x8::default(), &[
u8x8::new(9, 126, 87, 132, 247, 167, 123, 153),
u8x8::new(111, 149, 73, 120, 68, 171, 98, 223),
u8x8::new(24, 121, 1, 50, 13, 46, 164, 20)]);
u8x8::new(9, 126, 87, 132, 247, 167, 123, 153),
u8x8::new(111, 149, 73, 120, 68, 171, 98, 223),
u8x8::new(24, 121, 1, 50, 13, 46, 164, 20),
]);
test_samples(i64x8::default(), &[
i64x8::new(-7387126082252079607, -2350127744969763473,
1487364411147516184, 7895421560427121838,
602190064936008898, 6022086574635100741,
-5080089175222015595, -4066367846667249123),
i64x8::new(9180885022207963908, 3095981199532211089,
6586075293021332726, 419343203796414657,
3186951873057035255, 5287129228749947252,
444726432079249540, -1587028029513790706),
i64x8::new(6075236523189346388, 1351763722368165432,
-6192309979959753740, -7697775502176768592,
-4482022114172078123, 7522501477800909500,
-1837258847956201231, -586926753024886735)]);
i64x8::new(
-7387126082252079607,
-2350127744969763473,
1487364411147516184,
7895421560427121838,
602190064936008898,
6022086574635100741,
-5080089175222015595,
-4066367846667249123,
),
i64x8::new(
9180885022207963908,
3095981199532211089,
6586075293021332726,
419343203796414657,
3186951873057035255,
5287129228749947252,
444726432079249540,
-1587028029513790706,
),
i64x8::new(
6075236523189346388,
1351763722368165432,
-6192309979959753740,
-7697775502176768592,
-4482022114172078123,
7522501477800909500,
-1837258847956201231,
-586926753024886735,
),
]);
}
}
}

131
third_party/rust/rand/src/distributions/mod.rs поставляемый
Просмотреть файл

@ -31,17 +31,17 @@
//! # The `Standard` distribution
//!
//! The [`Standard`] distribution is important to mention. This is the
//! distribution used by [`Rng::gen()`] and represents the "default" way to
//! distribution used by [`Rng::gen`] and represents the "default" way to
//! produce a random value for many different types, including most primitive
//! types, tuples, arrays, and a few derived types. See the documentation of
//! [`Standard`] for more details.
//!
//! Implementing `Distribution<T>` for [`Standard`] for user types `T` makes it
//! possible to generate type `T` with [`Rng::gen()`], and by extension also
//! with the [`random()`] function.
//! possible to generate type `T` with [`Rng::gen`], and by extension also
//! with the [`random`] function.
//!
//! ## Random characters
//!
//!
//! [`Alphanumeric`] is a simple distribution to sample random letters and
//! numbers of the `char` type; in contrast [`Standard`] may sample any valid
//! `char`.
@ -89,78 +89,83 @@
//! [`rand_distr`]: https://crates.io/crates/rand_distr
//! [`statrs`]: https://crates.io/crates/statrs
//! [`Alphanumeric`]: distributions::Alphanumeric
//! [`Bernoulli`]: distributions::Bernoulli
//! [`Open01`]: distributions::Open01
//! [`OpenClosed01`]: distributions::OpenClosed01
//! [`Standard`]: distributions::Standard
//! [`Uniform`]: distributions::Uniform
//! [`Uniform::new`]: distributions::Uniform::new
//! [`Uniform::new_inclusive`]: distributions::Uniform::new_inclusive
//! [`weighted`]: distributions::weighted
//! [`random`]: crate::random
//! [`rand_distr`]: https://crates.io/crates/rand_distr
//! [`statrs`]: https://crates.io/crates/statrs
use core::iter;
use crate::Rng;
use core::iter;
pub use self::bernoulli::{Bernoulli, BernoulliError};
pub use self::float::{Open01, OpenClosed01};
pub use self::other::Alphanumeric;
#[doc(inline)] pub use self::uniform::Uniform;
pub use self::float::{OpenClosed01, Open01};
pub use self::bernoulli::{Bernoulli, BernoulliError};
#[cfg(feature="alloc")] pub use self::weighted::{WeightedIndex, WeightedError};
#[cfg(feature = "alloc")]
pub use self::weighted::{WeightedError, WeightedIndex};
// The following are all deprecated after being moved to rand_distr
#[allow(deprecated)]
#[cfg(feature="std")] pub use self::unit_sphere::UnitSphereSurface;
#[cfg(feature = "std")]
pub use self::binomial::Binomial;
#[allow(deprecated)]
#[cfg(feature="std")] pub use self::unit_circle::UnitCircle;
#[cfg(feature = "std")]
pub use self::cauchy::Cauchy;
#[allow(deprecated)]
#[cfg(feature="std")] pub use self::gamma::{Gamma, ChiSquared, FisherF,
StudentT, Beta};
#[cfg(feature = "std")]
pub use self::dirichlet::Dirichlet;
#[allow(deprecated)]
#[cfg(feature="std")] pub use self::normal::{Normal, LogNormal, StandardNormal};
#[cfg(feature = "std")]
pub use self::exponential::{Exp, Exp1};
#[allow(deprecated)]
#[cfg(feature="std")] pub use self::exponential::{Exp, Exp1};
#[cfg(feature = "std")]
pub use self::gamma::{Beta, ChiSquared, FisherF, Gamma, StudentT};
#[allow(deprecated)]
#[cfg(feature="std")] pub use self::pareto::Pareto;
#[cfg(feature = "std")]
pub use self::normal::{LogNormal, Normal, StandardNormal};
#[allow(deprecated)]
#[cfg(feature="std")] pub use self::poisson::Poisson;
#[cfg(feature = "std")]
pub use self::pareto::Pareto;
#[allow(deprecated)]
#[cfg(feature="std")] pub use self::binomial::Binomial;
#[cfg(feature = "std")]
pub use self::poisson::Poisson;
#[allow(deprecated)]
#[cfg(feature="std")] pub use self::cauchy::Cauchy;
#[cfg(feature = "std")]
pub use self::triangular::Triangular;
#[allow(deprecated)]
#[cfg(feature="std")] pub use self::dirichlet::Dirichlet;
#[cfg(feature = "std")]
pub use self::unit_circle::UnitCircle;
#[allow(deprecated)]
#[cfg(feature="std")] pub use self::triangular::Triangular;
#[cfg(feature = "std")]
pub use self::unit_sphere::UnitSphereSurface;
#[allow(deprecated)]
#[cfg(feature="std")] pub use self::weibull::Weibull;
#[cfg(feature = "std")]
pub use self::weibull::Weibull;
pub mod uniform;
mod bernoulli;
#[cfg(feature="alloc")] pub mod weighted;
#[cfg(feature="std")] mod unit_sphere;
#[cfg(feature="std")] mod unit_circle;
#[cfg(feature="std")] mod gamma;
#[cfg(feature="std")] mod normal;
#[cfg(feature="std")] mod exponential;
#[cfg(feature="std")] mod pareto;
#[cfg(feature="std")] mod poisson;
#[cfg(feature="std")] mod binomial;
#[cfg(feature="std")] mod cauchy;
#[cfg(feature="std")] mod dirichlet;
#[cfg(feature="std")] mod triangular;
#[cfg(feature="std")] mod weibull;
#[cfg(feature = "std")] mod binomial;
#[cfg(feature = "std")] mod cauchy;
#[cfg(feature = "std")] mod dirichlet;
#[cfg(feature = "std")] mod exponential;
#[cfg(feature = "std")] mod gamma;
#[cfg(feature = "std")] mod normal;
#[cfg(feature = "std")] mod pareto;
#[cfg(feature = "std")] mod poisson;
#[cfg(feature = "std")] mod triangular;
pub mod uniform;
#[cfg(feature = "std")] mod unit_circle;
#[cfg(feature = "std")] mod unit_sphere;
#[cfg(feature = "std")] mod weibull;
#[cfg(feature = "alloc")] pub mod weighted;
mod float;
#[doc(hidden)] pub mod hidden_export {
pub use super::float::IntoFloat; // used by rand_distr
#[doc(hidden)]
pub mod hidden_export {
pub use super::float::IntoFloat; // used by rand_distr
}
mod integer;
mod other;
mod utils;
#[cfg(feature="std")] mod ziggurat_tables;
#[cfg(feature = "std")] mod ziggurat_tables;
/// Types (distributions) that can be used to create a random instance of `T`.
///
@ -215,7 +220,9 @@ pub trait Distribution<T> {
/// }
/// ```
fn sample_iter<R>(self, rng: R) -> DistIter<Self, R, T>
where R: Rng, Self: Sized
where
R: Rng,
Self: Sized,
{
DistIter {
distr: self,
@ -247,7 +254,9 @@ pub struct DistIter<D, R, T> {
}
impl<D, R, T> Iterator for DistIter<D, R, T>
where D: Distribution<T>, R: Rng
where
D: Distribution<T>,
R: Rng,
{
type Item = T;
@ -265,11 +274,19 @@ impl<D, R, T> Iterator for DistIter<D, R, T>
}
impl<D, R, T> iter::FusedIterator for DistIter<D, R, T>
where D: Distribution<T>, R: Rng {}
where
D: Distribution<T>,
R: Rng,
{
}
#[cfg(features = "nightly")]
impl<D, R, T> iter::TrustedLen for DistIter<D, R, T>
where D: Distribution<T>, R: Rng {}
where
D: Distribution<T>,
R: Rng,
{
}
/// A generic random value distribution, implemented for many primitive types.
@ -337,7 +354,7 @@ impl<D, R, T> iter::TrustedLen for DistIter<D, R, T>
/// the half-open interval `[0, 1)`, i.e. including 0 but not 1.
///
/// All values that can be generated are of the form `n * ε/2`. For `f32`
/// the 23 most significant random bits of a `u32` are used and for `f64` the
/// the 24 most significant random bits of a `u32` are used and for `f64` the
/// 53 most significant bits of a `u64` are used. The conversion uses the
/// multiplicative method: `(rng.gen::<$uty>() >> N) as $ty * (ε/2)`.
///
@ -355,8 +372,8 @@ pub struct Standard;
#[cfg(all(test, feature = "std"))]
mod tests {
use crate::Rng;
use super::{Distribution, Uniform};
use crate::Rng;
#[test]
fn test_distributions_iter() {
@ -366,16 +383,18 @@ mod tests {
let results: Vec<f32> = distr.sample_iter(&mut rng).take(100).collect();
println!("{:?}", results);
}
#[test]
fn test_make_an_iter() {
fn ten_dice_rolls_other_than_five<'a, R: Rng>(rng: &'a mut R) -> impl Iterator<Item = i32> + 'a {
fn ten_dice_rolls_other_than_five<'a, R: Rng>(
rng: &'a mut R,
) -> impl Iterator<Item = i32> + 'a {
Uniform::new_inclusive(1, 6)
.sample_iter(rng)
.filter(|x| *x != 5)
.take(10)
}
let mut rng = crate::test::rng(211);
let mut count = 0;
for val in ten_dice_rolls_other_than_five(&mut rng) {

Просмотреть файл

@ -10,9 +10,9 @@
//! The normal and derived distributions.
#![allow(deprecated)]
use crate::Rng;
use crate::distributions::{ziggurat_tables, Distribution, Open01};
use crate::distributions::utils::ziggurat;
use crate::distributions::{ziggurat_tables, Distribution, Open01};
use crate::Rng;
/// Samples floating-point numbers according to the normal distribution
/// `N(0, 1)` (a.k.a. a standard normal, or Gaussian). This is equivalent to
@ -26,7 +26,7 @@ use crate::distributions::utils::ziggurat;
/// Generate Normal Random Samples*](
/// https://www.doornik.com/research/ziggurat.pdf).
/// Nuffield College, Oxford
#[deprecated(since="0.7.0", note="moved to rand_distr crate")]
#[deprecated(since = "0.7.0", note = "moved to rand_distr crate")]
#[derive(Clone, Copy, Debug)]
pub struct StandardNormal;
@ -34,7 +34,7 @@ impl Distribution<f64> for StandardNormal {
fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> f64 {
#[inline]
fn pdf(x: f64) -> f64 {
(-x*x/2.0).exp()
(-x * x / 2.0).exp()
}
#[inline]
fn zero_case<R: Rng + ?Sized>(rng: &mut R, u: f64) -> f64 {
@ -55,13 +55,21 @@ impl Distribution<f64> for StandardNormal {
y = y_.ln();
}
if u < 0.0 { x - ziggurat_tables::ZIG_NORM_R } else { ziggurat_tables::ZIG_NORM_R - x }
if u < 0.0 {
x - ziggurat_tables::ZIG_NORM_R
} else {
ziggurat_tables::ZIG_NORM_R - x
}
}
ziggurat(rng, true, // this is symmetric
&ziggurat_tables::ZIG_NORM_X,
&ziggurat_tables::ZIG_NORM_F,
pdf, zero_case)
ziggurat(
rng,
true, // this is symmetric
&ziggurat_tables::ZIG_NORM_X,
&ziggurat_tables::ZIG_NORM_F,
pdf,
zero_case,
)
}
}
@ -69,12 +77,12 @@ impl Distribution<f64> for StandardNormal {
///
/// This uses the ZIGNOR variant of the Ziggurat method, see [`StandardNormal`]
/// for more details.
///
///
/// Note that [`StandardNormal`] is an optimised implementation for mean 0, and
/// standard deviation 1.
///
/// [`StandardNormal`]: crate::distributions::StandardNormal
#[deprecated(since="0.7.0", note="moved to rand_distr crate")]
#[deprecated(since = "0.7.0", note = "moved to rand_distr crate")]
#[derive(Clone, Copy, Debug)]
pub struct Normal {
mean: f64,
@ -91,10 +99,7 @@ impl Normal {
#[inline]
pub fn new(mean: f64, std_dev: f64) -> Normal {
assert!(std_dev >= 0.0, "Normal::new called with `std_dev` < 0");
Normal {
mean,
std_dev
}
Normal { mean, std_dev }
}
}
impl Distribution<f64> for Normal {
@ -109,10 +114,10 @@ impl Distribution<f64> for Normal {
///
/// If `X` is log-normal distributed, then `ln(X)` is `N(mean, std_dev**2)`
/// distributed.
#[deprecated(since="0.7.0", note="moved to rand_distr crate")]
#[deprecated(since = "0.7.0", note = "moved to rand_distr crate")]
#[derive(Clone, Copy, Debug)]
pub struct LogNormal {
norm: Normal
norm: Normal,
}
impl LogNormal {
@ -125,7 +130,9 @@ impl LogNormal {
#[inline]
pub fn new(mean: f64, std_dev: f64) -> LogNormal {
assert!(std_dev >= 0.0, "LogNormal::new called with `std_dev` < 0");
LogNormal { norm: Normal::new(mean, std_dev) }
LogNormal {
norm: Normal::new(mean, std_dev),
}
}
}
impl Distribution<f64> for LogNormal {
@ -136,8 +143,8 @@ impl Distribution<f64> for LogNormal {
#[cfg(test)]
mod tests {
use super::{LogNormal, Normal};
use crate::distributions::Distribution;
use super::{Normal, LogNormal};
#[test]
fn test_normal() {

Просмотреть файл

@ -11,21 +11,21 @@
use core::char;
use core::num::Wrapping;
use crate::Rng;
use crate::distributions::{Distribution, Standard, Uniform};
use crate::Rng;
// ----- Sampling distributions -----
/// Sample a `char`, uniformly distributed over ASCII letters and numbers:
/// a-z, A-Z and 0-9.
///
///
/// # Example
///
/// ```
/// use std::iter;
/// use rand::{Rng, thread_rng};
/// use rand::distributions::Alphanumeric;
///
///
/// let mut rng = thread_rng();
/// let chars: String = iter::repeat(())
/// .map(|()| rng.sample(Alphanumeric))
@ -63,8 +63,7 @@ impl Distribution<char> for Standard {
impl Distribution<char> for Alphanumeric {
fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> char {
const RANGE: u32 = 26 + 26 + 10;
const GEN_ASCII_STR_CHARSET: &[u8] =
b"ABCDEFGHIJKLMNOPQRSTUVWXYZ\
const GEN_ASCII_STR_CHARSET: &[u8] = b"ABCDEFGHIJKLMNOPQRSTUVWXYZ\
abcdefghijklmnopqrstuvwxyz\
0123456789";
// We can pick from 62 characters. This is so close to a power of 2, 64,
@ -74,7 +73,7 @@ impl Distribution<char> for Alphanumeric {
loop {
let var = rng.next_u32() >> (32 - 6);
if var < RANGE {
return GEN_ASCII_STR_CHARSET[var as usize] as char
return GEN_ASCII_STR_CHARSET[var as usize] as char;
}
}
}
@ -118,20 +117,22 @@ macro_rules! tuple_impl {
impl Distribution<()> for Standard {
#[allow(clippy::unused_unit)]
#[inline]
fn sample<R: Rng + ?Sized>(&self, _: &mut R) -> () { () }
fn sample<R: Rng + ?Sized>(&self, _: &mut R) -> () {
()
}
}
tuple_impl!{A}
tuple_impl!{A, B}
tuple_impl!{A, B, C}
tuple_impl!{A, B, C, D}
tuple_impl!{A, B, C, D, E}
tuple_impl!{A, B, C, D, E, F}
tuple_impl!{A, B, C, D, E, F, G}
tuple_impl!{A, B, C, D, E, F, G, H}
tuple_impl!{A, B, C, D, E, F, G, H, I}
tuple_impl!{A, B, C, D, E, F, G, H, I, J}
tuple_impl!{A, B, C, D, E, F, G, H, I, J, K}
tuple_impl!{A, B, C, D, E, F, G, H, I, J, K, L}
tuple_impl! {A}
tuple_impl! {A, B}
tuple_impl! {A, B, C}
tuple_impl! {A, B, C, D}
tuple_impl! {A, B, C, D, E}
tuple_impl! {A, B, C, D, E, F}
tuple_impl! {A, B, C, D, E, F, G}
tuple_impl! {A, B, C, D, E, F, G, H}
tuple_impl! {A, B, C, D, E, F, G, H, I}
tuple_impl! {A, B, C, D, E, F, G, H, I, J}
tuple_impl! {A, B, C, D, E, F, G, H, I, J, K}
tuple_impl! {A, B, C, D, E, F, G, H, I, J, K, L}
macro_rules! array_impl {
// recursive, given at least one type parameter:
@ -153,9 +154,11 @@ macro_rules! array_impl {
};
}
array_impl!{32, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T,}
array_impl! {32, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T,}
impl<T> Distribution<Option<T>> for Standard where Standard: Distribution<T> {
impl<T> Distribution<Option<T>> for Standard
where Standard: Distribution<T>
{
#[inline]
fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> Option<T> {
// UFCS is needed here: https://github.com/rust-lang/rust/issues/24066
@ -167,7 +170,9 @@ impl<T> Distribution<Option<T>> for Standard where Standard: Distribution<T> {
}
}
impl<T> Distribution<Wrapping<T>> for Standard where Standard: Distribution<T> {
impl<T> Distribution<Wrapping<T>> for Standard
where Standard: Distribution<T>
{
#[inline]
fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> Wrapping<T> {
Wrapping(rng.gen())
@ -179,17 +184,17 @@ impl<T> Distribution<Wrapping<T>> for Standard where Standard: Distribution<T> {
mod tests {
use super::*;
use crate::RngCore;
#[cfg(all(not(feature="std"), feature="alloc"))] use alloc::string::String;
#[cfg(all(not(feature = "std"), feature = "alloc"))] use alloc::string::String;
#[test]
fn test_misc() {
let rng: &mut dyn RngCore = &mut crate::test::rng(820);
rng.sample::<char, _>(Standard);
rng.sample::<bool, _>(Standard);
}
#[cfg(feature="alloc")]
#[cfg(feature = "alloc")]
#[test]
fn test_chars() {
use core::iter;
@ -198,7 +203,9 @@ mod tests {
// Test by generating a relatively large number of chars, so we also
// take the rejection sampling path.
let word: String = iter::repeat(())
.map(|()| rng.gen::<char>()).take(1000).collect();
.map(|()| rng.gen::<char>())
.take(1000)
.collect();
assert!(word.len() != 0);
}
@ -217,11 +224,12 @@ mod tests {
}
assert!(incorrect == false);
}
#[test]
fn value_stability() {
fn test_samples<T: Copy + core::fmt::Debug + PartialEq, D: Distribution<T>>(
distr: &D, zero: T, expected: &[T]) {
distr: &D, zero: T, expected: &[T],
) {
let mut rng = crate::test::rng(807);
let mut buf = [zero; 5];
for x in &mut buf {
@ -229,25 +237,55 @@ mod tests {
}
assert_eq!(&buf, expected);
}
test_samples(&Standard, 'a', &['\u{8cdac}', '\u{a346a}', '\u{80120}', '\u{ed692}', '\u{35888}']);
test_samples(&Standard, 'a', &[
'\u{8cdac}',
'\u{a346a}',
'\u{80120}',
'\u{ed692}',
'\u{35888}',
]);
test_samples(&Alphanumeric, 'a', &['h', 'm', 'e', '3', 'M']);
test_samples(&Standard, false, &[true, true, false, true, false]);
test_samples(&Standard, None as Option<bool>,
&[Some(true), None, Some(false), None, Some(false)]);
test_samples(&Standard, Wrapping(0i32), &[Wrapping(-2074640887),
Wrapping(-1719949321), Wrapping(2018088303),
Wrapping(-547181756), Wrapping(838957336)]);
test_samples(&Standard, None as Option<bool>, &[
Some(true),
None,
Some(false),
None,
Some(false),
]);
test_samples(&Standard, Wrapping(0i32), &[
Wrapping(-2074640887),
Wrapping(-1719949321),
Wrapping(2018088303),
Wrapping(-547181756),
Wrapping(838957336),
]);
// We test only sub-sets of tuple and array impls
test_samples(&Standard, (), &[(), (), (), (), ()]);
test_samples(&Standard, (false,), &[(true,), (true,), (false,), (true,), (false,)]);
test_samples(&Standard, (false,false), &[(true,true), (false,true),
(false,false), (true,false), (false,false)]);
test_samples(&Standard, (false,), &[
(true,),
(true,),
(false,),
(true,),
(false,),
]);
test_samples(&Standard, (false, false), &[
(true, true),
(false, true),
(false, false),
(true, false),
(false, false),
]);
test_samples(&Standard, [0u8; 0], &[[], [], [], [], []]);
test_samples(&Standard, [0u8; 3], &[[9, 247, 111],
[68, 24, 13], [174, 19, 194],
[172, 69, 213], [149, 207, 29]]);
test_samples(&Standard, [0u8; 3], &[
[9, 247, 111],
[68, 24, 13],
[174, 19, 194],
[172, 69, 213],
[149, 207, 29],
]);
}
}

Просмотреть файл

@ -9,11 +9,11 @@
//! The Pareto distribution.
#![allow(deprecated)]
use crate::Rng;
use crate::distributions::{Distribution, OpenClosed01};
use crate::Rng;
/// Samples floating-point numbers according to the Pareto distribution
#[deprecated(since="0.7.0", note="moved to rand_distr crate")]
#[deprecated(since = "0.7.0", note = "moved to rand_distr crate")]
#[derive(Clone, Copy, Debug)]
pub struct Pareto {
scale: f64,
@ -31,7 +31,10 @@ impl Pareto {
/// `scale` and `shape` have to be non-zero and positive.
pub fn new(scale: f64, shape: f64) -> Pareto {
assert!((scale > 0.) & (shape > 0.));
Pareto { scale, inv_neg_shape: -1.0 / shape }
Pareto {
scale,
inv_neg_shape: -1.0 / shape,
}
}
}
@ -44,8 +47,8 @@ impl Distribution<f64> for Pareto {
#[cfg(test)]
mod tests {
use crate::distributions::Distribution;
use super::Pareto;
use crate::distributions::Distribution;
#[test]
#[should_panic]

Просмотреть файл

@ -10,15 +10,15 @@
//! The Poisson distribution.
#![allow(deprecated)]
use crate::Rng;
use crate::distributions::{Distribution, Cauchy};
use crate::distributions::utils::log_gamma;
use crate::distributions::{Cauchy, Distribution};
use crate::Rng;
/// The Poisson distribution `Poisson(lambda)`.
///
/// This distribution has a density function:
/// `f(k) = lambda^k * exp(-lambda) / k!` for `k >= 0`.
#[deprecated(since="0.7.0", note="moved to rand_distr crate")]
#[deprecated(since = "0.7.0", note = "moved to rand_distr crate")]
#[derive(Clone, Copy, Debug)]
pub struct Poisson {
lambda: f64,
@ -90,7 +90,8 @@ impl Distribution<u64> for Poisson {
// the magic value scales the distribution function to a range of approximately 0-1
// since it is not exact, we multiply the ratio by 0.9 to avoid ratios greater than 1
// this doesn't change the resulting distribution, only increases the rate of failed drawings
let check = 0.9 * (1.0 + comp_dev * comp_dev)
let check = 0.9
* (1.0 + comp_dev * comp_dev)
* (result * self.log_lambda - log_gamma(1.0 + result) - self.magic_val).exp();
// check with uniform random value - if below the threshold, we are within the target distribution
@ -105,11 +106,11 @@ impl Distribution<u64> for Poisson {
#[cfg(test)]
mod test {
use crate::distributions::Distribution;
use super::Poisson;
use crate::distributions::Distribution;
#[test]
#[cfg(not(miri))] // Miri is too slow
#[cfg_attr(miri, ignore)] // Miri is too slow
fn test_poisson_10() {
let poisson = Poisson::new(10.0);
let mut rng = crate::test::rng(123);
@ -123,7 +124,6 @@ mod test {
}
#[test]
#[cfg(not(miri))] // Miri doesn't support transcendental functions
fn test_poisson_15() {
// Take the 'high expected values' path
let poisson = Poisson::new(15.0);

Просмотреть файл

@ -9,11 +9,11 @@
//! The triangular distribution.
#![allow(deprecated)]
use crate::Rng;
use crate::distributions::{Distribution, Standard};
use crate::Rng;
/// The triangular distribution.
#[deprecated(since="0.7.0", note="moved to rand_distr crate")]
#[deprecated(since = "0.7.0", note = "moved to rand_distr crate")]
#[derive(Clone, Copy, Debug)]
pub struct Triangular {
min: f64,
@ -28,7 +28,6 @@ impl Triangular {
/// # Panics
///
/// If `max < mode`, `mode < max` or `max == min`.
///
#[inline]
pub fn new(min: f64, max: f64, mode: f64) -> Triangular {
assert!(max >= mode);
@ -54,14 +53,19 @@ impl Distribution<f64> for Triangular {
#[cfg(test)]
mod test {
use crate::distributions::Distribution;
use super::Triangular;
use crate::distributions::Distribution;
#[test]
fn test_new() {
for &(min, max, mode) in &[
(-1., 1., 0.), (1., 2., 1.), (5., 25., 25.), (1e-5, 1e5, 1e-3),
(0., 1., 0.9), (-4., -0.5, -2.), (-13.039, 8.41, 1.17),
(-1., 1., 0.),
(1., 2., 1.),
(5., 25., 25.),
(1e-5, 1e5, 1e-3),
(0., 1., 0.9),
(-4., -0.5, -2.),
(-13.039, 8.41, 1.17),
] {
println!("{} {} {}", min, max, mode);
let _ = Triangular::new(min, max, mode);

Просмотреть файл

@ -103,23 +103,20 @@
//! [`UniformDuration`]: crate::distributions::uniform::UniformDuration
//! [`SampleBorrow::borrow`]: crate::distributions::uniform::SampleBorrow::borrow
#[cfg(feature = "std")]
use std::time::Duration;
#[cfg(not(feature = "std"))]
use core::time::Duration;
#[cfg(not(feature = "std"))] use core::time::Duration;
#[cfg(feature = "std")] use std::time::Duration;
use crate::Rng;
use crate::distributions::Distribution;
use crate::distributions::float::IntoFloat;
use crate::distributions::utils::{WideningMultiply, FloatSIMDUtils, FloatAsSIMD, BoolAsSIMD};
use crate::distributions::utils::{BoolAsSIMD, FloatAsSIMD, FloatSIMDUtils, WideningMultiply};
use crate::distributions::Distribution;
use crate::Rng;
#[cfg(not(feature = "std"))]
#[allow(unused_imports)] // rustc doesn't detect that this is actually used
use crate::distributions::utils::Float;
#[cfg(feature="simd_support")]
use packed_simd::*;
#[cfg(feature = "simd_support")] use packed_simd::*;
/// Sample values uniformly between two bounds.
///
@ -168,8 +165,9 @@ impl<X: SampleUniform> Uniform<X> {
/// Create a new `Uniform` instance which samples uniformly from the half
/// open range `[low, high)` (excluding `high`). Panics if `low >= high`.
pub fn new<B1, B2>(low: B1, high: B2) -> Uniform<X>
where B1: SampleBorrow<X> + Sized,
B2: SampleBorrow<X> + Sized
where
B1: SampleBorrow<X> + Sized,
B2: SampleBorrow<X> + Sized,
{
Uniform(X::Sampler::new(low, high))
}
@ -177,8 +175,9 @@ impl<X: SampleUniform> Uniform<X> {
/// Create a new `Uniform` instance which samples uniformly from the closed
/// range `[low, high]` (inclusive). Panics if `low > high`.
pub fn new_inclusive<B1, B2>(low: B1, high: B2) -> Uniform<X>
where B1: SampleBorrow<X> + Sized,
B2: SampleBorrow<X> + Sized
where
B1: SampleBorrow<X> + Sized,
B2: SampleBorrow<X> + Sized,
{
Uniform(X::Sampler::new_inclusive(low, high))
}
@ -222,8 +221,9 @@ pub trait UniformSampler: Sized {
/// Usually users should not call this directly but instead use
/// `Uniform::new`, which asserts that `low < high` before calling this.
fn new<B1, B2>(low: B1, high: B2) -> Self
where B1: SampleBorrow<Self::X> + Sized,
B2: SampleBorrow<Self::X> + Sized;
where
B1: SampleBorrow<Self::X> + Sized,
B2: SampleBorrow<Self::X> + Sized;
/// Construct self, with inclusive bounds `[low, high]`.
///
@ -231,8 +231,9 @@ pub trait UniformSampler: Sized {
/// `Uniform::new_inclusive`, which asserts that `low <= high` before
/// calling this.
fn new_inclusive<B1, B2>(low: B1, high: B2) -> Self
where B1: SampleBorrow<Self::X> + Sized,
B2: SampleBorrow<Self::X> + Sized;
where
B1: SampleBorrow<Self::X> + Sized,
B2: SampleBorrow<Self::X> + Sized;
/// Sample a value.
fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> Self::X;
@ -256,10 +257,10 @@ pub trait UniformSampler: Sized {
/// <T as SampleUniform>::Sampler::sample_single(lb, ub, &mut rng)
/// }
/// ```
fn sample_single<R: Rng + ?Sized, B1, B2>(low: B1, high: B2, rng: &mut R)
-> Self::X
where B1: SampleBorrow<Self::X> + Sized,
B2: SampleBorrow<Self::X> + Sized
fn sample_single<R: Rng + ?Sized, B1, B2>(low: B1, high: B2, rng: &mut R) -> Self::X
where
B1: SampleBorrow<Self::X> + Sized,
B2: SampleBorrow<Self::X> + Sized,
{
let uniform: Self = UniformSampler::new(low, high);
uniform.sample(rng)
@ -289,13 +290,21 @@ pub trait SampleBorrow<Borrowed> {
/// [`Borrow::borrow`]: std::borrow::Borrow::borrow
fn borrow(&self) -> &Borrowed;
}
impl<Borrowed> SampleBorrow<Borrowed> for Borrowed where Borrowed: SampleUniform {
impl<Borrowed> SampleBorrow<Borrowed> for Borrowed
where Borrowed: SampleUniform
{
#[inline(always)]
fn borrow(&self) -> &Borrowed { self }
fn borrow(&self) -> &Borrowed {
self
}
}
impl<'a, Borrowed> SampleBorrow<Borrowed> for &'a Borrowed where Borrowed: SampleUniform {
impl<'a, Borrowed> SampleBorrow<Borrowed> for &'a Borrowed
where Borrowed: SampleUniform
{
#[inline(always)]
fn borrow(&self) -> &Borrowed { *self }
fn borrow(&self) -> &Borrowed {
*self
}
}
////////////////////////////////////////////////////////////////////////////////
@ -341,7 +350,7 @@ impl<'a, Borrowed> SampleBorrow<Borrowed> for &'a Borrowed where Borrowed: Sampl
pub struct UniformInt<X> {
low: X,
range: X,
z: X, // either ints_to_reject or zone depending on implementation
z: X, // either ints_to_reject or zone depending on implementation
}
macro_rules! uniform_int_impl {
@ -361,8 +370,9 @@ macro_rules! uniform_int_impl {
#[inline] // if the range is constant, this helps LLVM to do the
// calculations at compile-time.
fn new<B1, B2>(low_b: B1, high_b: B2) -> Self
where B1: SampleBorrow<Self::X> + Sized,
B2: SampleBorrow<Self::X> + Sized
where
B1: SampleBorrow<Self::X> + Sized,
B2: SampleBorrow<Self::X> + Sized,
{
let low = *low_b.borrow();
let high = *high_b.borrow();
@ -373,29 +383,31 @@ macro_rules! uniform_int_impl {
#[inline] // if the range is constant, this helps LLVM to do the
// calculations at compile-time.
fn new_inclusive<B1, B2>(low_b: B1, high_b: B2) -> Self
where B1: SampleBorrow<Self::X> + Sized,
B2: SampleBorrow<Self::X> + Sized
where
B1: SampleBorrow<Self::X> + Sized,
B2: SampleBorrow<Self::X> + Sized,
{
let low = *low_b.borrow();
let high = *high_b.borrow();
assert!(low <= high,
"Uniform::new_inclusive called with `low > high`");
assert!(
low <= high,
"Uniform::new_inclusive called with `low > high`"
);
let unsigned_max = ::core::$u_large::MAX;
let range = high.wrapping_sub(low).wrapping_add(1) as $unsigned;
let ints_to_reject =
if range > 0 {
let range = $u_large::from(range);
(unsigned_max - range + 1) % range
} else {
0
};
let ints_to_reject = if range > 0 {
let range = $u_large::from(range);
(unsigned_max - range + 1) % range
} else {
0
};
UniformInt {
low: low,
// These are really $unsigned values, but store as $ty:
range: range as $ty,
z: ints_to_reject as $unsigned as $ty
z: ints_to_reject as $unsigned as $ty,
}
}
@ -417,29 +429,27 @@ macro_rules! uniform_int_impl {
}
}
fn sample_single<R: Rng + ?Sized, B1, B2>(low_b: B1, high_b: B2, rng: &mut R)
-> Self::X
where B1: SampleBorrow<Self::X> + Sized,
B2: SampleBorrow<Self::X> + Sized
fn sample_single<R: Rng + ?Sized, B1, B2>(low_b: B1, high_b: B2, rng: &mut R) -> Self::X
where
B1: SampleBorrow<Self::X> + Sized,
B2: SampleBorrow<Self::X> + Sized,
{
let low = *low_b.borrow();
let high = *high_b.borrow();
assert!(low < high,
"UniformSampler::sample_single: low >= high");
assert!(low < high, "UniformSampler::sample_single: low >= high");
let range = high.wrapping_sub(low) as $unsigned as $u_large;
let zone =
if ::core::$unsigned::MAX <= ::core::u16::MAX as $unsigned {
// Using a modulus is faster than the approximation for
// i8 and i16. I suppose we trade the cost of one
// modulus for near-perfect branch prediction.
let unsigned_max: $u_large = ::core::$u_large::MAX;
let ints_to_reject = (unsigned_max - range + 1) % range;
unsigned_max - ints_to_reject
} else {
// conservative but fast approximation. `- 1` is necessary to allow the
// same comparison without bias.
(range << range.leading_zeros()).wrapping_sub(1)
};
let zone = if ::core::$unsigned::MAX <= ::core::u16::MAX as $unsigned {
// Using a modulus is faster than the approximation for
// i8 and i16. I suppose we trade the cost of one
// modulus for near-perfect branch prediction.
let unsigned_max: $u_large = ::core::$u_large::MAX;
let ints_to_reject = (unsigned_max - range + 1) % range;
unsigned_max - ints_to_reject
} else {
// conservative but fast approximation. `- 1` is necessary to allow the
// same comparison without bias.
(range << range.leading_zeros()).wrapping_sub(1)
};
loop {
let v: $u_large = rng.gen();
@ -450,7 +460,7 @@ macro_rules! uniform_int_impl {
}
}
}
}
};
}
uniform_int_impl! { i8, u8, u32 }
@ -627,7 +637,7 @@ uniform_simd_int_impl! {
///
/// The floats are first converted to a value in the `[1, 2)` interval using a
/// transmute-based method, and then mapped to the expected range with a
/// multiply and addition. Values produced this way have what equals 22 bits of
/// multiply and addition. Values produced this way have what equals 23 bits of
/// random digits for an `f32`, and 52 for an `f64`.
///
/// [`new`]: UniformSampler::new
@ -649,17 +659,20 @@ macro_rules! uniform_float_impl {
type X = $ty;
fn new<B1, B2>(low_b: B1, high_b: B2) -> Self
where B1: SampleBorrow<Self::X> + Sized,
B2: SampleBorrow<Self::X> + Sized
where
B1: SampleBorrow<Self::X> + Sized,
B2: SampleBorrow<Self::X> + Sized,
{
let low = *low_b.borrow();
let high = *high_b.borrow();
assert!(low.all_lt(high),
"Uniform::new called with `low >= high`");
assert!(low.all_finite() && high.all_finite(),
"Uniform::new called with non-finite boundaries");
let max_rand = <$ty>::splat((::core::$u_scalar::MAX >> $bits_to_discard)
.into_float_with_exponent(0) - 1.0);
assert!(low.all_lt(high), "Uniform::new called with `low >= high`");
assert!(
low.all_finite() && high.all_finite(),
"Uniform::new called with non-finite boundaries"
);
let max_rand = <$ty>::splat(
(::core::$u_scalar::MAX >> $bits_to_discard).into_float_with_exponent(0) - 1.0,
);
let mut scale = high - low;
@ -677,17 +690,23 @@ macro_rules! uniform_float_impl {
}
fn new_inclusive<B1, B2>(low_b: B1, high_b: B2) -> Self
where B1: SampleBorrow<Self::X> + Sized,
B2: SampleBorrow<Self::X> + Sized
where
B1: SampleBorrow<Self::X> + Sized,
B2: SampleBorrow<Self::X> + Sized,
{
let low = *low_b.borrow();
let high = *high_b.borrow();
assert!(low.all_le(high),
"Uniform::new_inclusive called with `low > high`");
assert!(low.all_finite() && high.all_finite(),
"Uniform::new_inclusive called with non-finite boundaries");
let max_rand = <$ty>::splat((::core::$u_scalar::MAX >> $bits_to_discard)
.into_float_with_exponent(0) - 1.0);
assert!(
low.all_le(high),
"Uniform::new_inclusive called with `low > high`"
);
assert!(
low.all_finite() && high.all_finite(),
"Uniform::new_inclusive called with non-finite boundaries"
);
let max_rand = <$ty>::splat(
(::core::$u_scalar::MAX >> $bits_to_discard).into_float_with_exponent(0) - 1.0,
);
let mut scale = (high - low) / max_rand;
@ -706,8 +725,7 @@ macro_rules! uniform_float_impl {
fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> Self::X {
// Generate a value in the range [1, 2)
let value1_2 = (rng.gen::<$uty>() >> $bits_to_discard)
.into_float_with_exponent(0);
let value1_2 = (rng.gen::<$uty>() >> $bits_to_discard).into_float_with_exponent(0);
// Get a value in the range [0, 1) in order to avoid
// overflowing into infinity when multiplying with scale
@ -722,21 +740,23 @@ macro_rules! uniform_float_impl {
}
#[inline]
fn sample_single<R: Rng + ?Sized, B1, B2>(low_b: B1, high_b: B2, rng: &mut R)
-> Self::X
where B1: SampleBorrow<Self::X> + Sized,
B2: SampleBorrow<Self::X> + Sized
fn sample_single<R: Rng + ?Sized, B1, B2>(low_b: B1, high_b: B2, rng: &mut R) -> Self::X
where
B1: SampleBorrow<Self::X> + Sized,
B2: SampleBorrow<Self::X> + Sized,
{
let low = *low_b.borrow();
let high = *high_b.borrow();
assert!(low.all_lt(high),
"UniformSampler::sample_single: low >= high");
assert!(
low.all_lt(high),
"UniformSampler::sample_single: low >= high"
);
let mut scale = high - low;
loop {
// Generate a value in the range [1, 2)
let value1_2 = (rng.gen::<$uty>() >> $bits_to_discard)
.into_float_with_exponent(0);
let value1_2 =
(rng.gen::<$uty>() >> $bits_to_discard).into_float_with_exponent(0);
// Get a value in the range [0, 1) in order to avoid
// overflowing into infinity when multiplying with scale
@ -780,37 +800,38 @@ macro_rules! uniform_float_impl {
// rare, so handle it here after the common case.
let mask = !scale.finite_mask();
if mask.any() {
assert!(low.all_finite() && high.all_finite(),
"Uniform::sample_single: low and high must be finite");
assert!(
low.all_finite() && high.all_finite(),
"Uniform::sample_single: low and high must be finite"
);
scale = scale.decrease_masked(mask);
}
}
}
}
}
};
}
uniform_float_impl! { f32, u32, f32, u32, 32 - 23 }
uniform_float_impl! { f64, u64, f64, u64, 64 - 52 }
#[cfg(feature="simd_support")]
#[cfg(feature = "simd_support")]
uniform_float_impl! { f32x2, u32x2, f32, u32, 32 - 23 }
#[cfg(feature="simd_support")]
#[cfg(feature = "simd_support")]
uniform_float_impl! { f32x4, u32x4, f32, u32, 32 - 23 }
#[cfg(feature="simd_support")]
#[cfg(feature = "simd_support")]
uniform_float_impl! { f32x8, u32x8, f32, u32, 32 - 23 }
#[cfg(feature="simd_support")]
#[cfg(feature = "simd_support")]
uniform_float_impl! { f32x16, u32x16, f32, u32, 32 - 23 }
#[cfg(feature="simd_support")]
#[cfg(feature = "simd_support")]
uniform_float_impl! { f64x2, u64x2, f64, u64, 64 - 52 }
#[cfg(feature="simd_support")]
#[cfg(feature = "simd_support")]
uniform_float_impl! { f64x4, u64x4, f64, u64, 64 - 52 }
#[cfg(feature="simd_support")]
#[cfg(feature = "simd_support")]
uniform_float_impl! { f64x8, u64x8, f64, u64, 64 - 52 }
/// The back-end implementing [`UniformSampler`] for `Duration`.
///
/// Unless you are implementing [`UniformSampler`] for your own types, this type
@ -834,7 +855,7 @@ enum UniformDurationMode {
max_secs: u64,
max_nanos: u32,
secs: Uniform<u64>,
}
},
}
impl SampleUniform for Duration {
@ -846,8 +867,9 @@ impl UniformSampler for UniformDuration {
#[inline]
fn new<B1, B2>(low_b: B1, high_b: B2) -> Self
where B1: SampleBorrow<Self::X> + Sized,
B2: SampleBorrow<Self::X> + Sized
where
B1: SampleBorrow<Self::X> + Sized,
B2: SampleBorrow<Self::X> + Sized,
{
let low = *low_b.borrow();
let high = *high_b.borrow();
@ -857,12 +879,16 @@ impl UniformSampler for UniformDuration {
#[inline]
fn new_inclusive<B1, B2>(low_b: B1, high_b: B2) -> Self
where B1: SampleBorrow<Self::X> + Sized,
B2: SampleBorrow<Self::X> + Sized
where
B1: SampleBorrow<Self::X> + Sized,
B2: SampleBorrow<Self::X> + Sized,
{
let low = *low_b.borrow();
let high = *high_b.borrow();
assert!(low <= high, "Uniform::new_inclusive called with `low > high`");
assert!(
low <= high,
"Uniform::new_inclusive called with `low > high`"
);
let low_s = low.as_secs();
let low_n = low.subsec_nanos();
@ -916,7 +942,11 @@ impl UniformSampler for UniformDuration {
let nanos = nanos.sample(rng);
Duration::new(nanos / 1_000_000_000, (nanos % 1_000_000_000) as u32)
}
UniformDurationMode::Large { max_secs, max_nanos, secs } => {
UniformDurationMode::Large {
max_secs,
max_nanos,
secs,
} => {
// constant folding means this is at least as fast as `gen_range`
let nano_range = Uniform::new(0, 1_000_000_000);
loop {
@ -959,12 +989,11 @@ mod tests {
}
#[test]
#[cfg(not(miri))] // Miri is too slow
#[cfg_attr(miri, ignore)] // Miri is too slow
fn test_integers() {
use core::{i8, i16, i32, i64, isize};
use core::{u8, u16, u32, u64, usize};
#[cfg(not(target_os = "emscripten"))]
use core::{i128, u128};
#[cfg(not(target_os = "emscripten"))] use core::{i128, u128};
use core::{i16, i32, i64, i8, isize};
use core::{u16, u32, u64, u8, usize};
let mut rng = crate::test::rng(251);
macro_rules! t {
@ -1025,8 +1054,7 @@ mod tests {
);)*
}};
}
t!(i8, i16, i32, i64, isize,
u8, u16, u32, u64, usize);
t!(i8, i16, i32, i64, isize, u8, u16, u32, u64, usize);
#[cfg(not(target_os = "emscripten"))]
t!(i128, u128);
@ -1044,29 +1072,29 @@ mod tests {
}
#[test]
#[cfg(not(miri))] // Miri is too slow
#[cfg_attr(miri, ignore)] // Miri is too slow
fn test_floats() {
let mut rng = crate::test::rng(252);
let mut zero_rng = StepRng::new(0, 0);
let mut max_rng = StepRng::new(0xffff_ffff_ffff_ffff, 0);
macro_rules! t {
($ty:ty, $f_scalar:ident, $bits_shifted:expr) => {{
let v: &[($f_scalar, $f_scalar)]=
&[(0.0, 100.0),
(-1e35, -1e25),
(1e-35, 1e-25),
(-1e35, 1e35),
(<$f_scalar>::from_bits(0), <$f_scalar>::from_bits(3)),
(-<$f_scalar>::from_bits(10), -<$f_scalar>::from_bits(1)),
(-<$f_scalar>::from_bits(5), 0.0),
(-<$f_scalar>::from_bits(7), -0.0),
(10.0, ::core::$f_scalar::MAX),
(-100.0, ::core::$f_scalar::MAX),
(-::core::$f_scalar::MAX / 5.0, ::core::$f_scalar::MAX),
(-::core::$f_scalar::MAX, ::core::$f_scalar::MAX / 5.0),
(-::core::$f_scalar::MAX * 0.8, ::core::$f_scalar::MAX * 0.7),
(-::core::$f_scalar::MAX, ::core::$f_scalar::MAX),
];
let v: &[($f_scalar, $f_scalar)] = &[
(0.0, 100.0),
(-1e35, -1e25),
(1e-35, 1e-25),
(-1e35, 1e35),
(<$f_scalar>::from_bits(0), <$f_scalar>::from_bits(3)),
(-<$f_scalar>::from_bits(10), -<$f_scalar>::from_bits(1)),
(-<$f_scalar>::from_bits(5), 0.0),
(-<$f_scalar>::from_bits(7), -0.0),
(10.0, ::core::$f_scalar::MAX),
(-100.0, ::core::$f_scalar::MAX),
(-::core::$f_scalar::MAX / 5.0, ::core::$f_scalar::MAX),
(-::core::$f_scalar::MAX, ::core::$f_scalar::MAX / 5.0),
(-::core::$f_scalar::MAX * 0.8, ::core::$f_scalar::MAX * 0.7),
(-::core::$f_scalar::MAX, ::core::$f_scalar::MAX),
];
for &(low_scalar, high_scalar) in v.iter() {
for lane in 0..<$ty>::lanes() {
let low = <$ty>::splat(0.0 as $f_scalar).replace(lane, low_scalar);
@ -1082,7 +1110,10 @@ mod tests {
assert!(low_scalar <= v && v < high_scalar);
}
assert_eq!(rng.sample(Uniform::new_inclusive(low, low)).extract(lane), low_scalar);
assert_eq!(
rng.sample(Uniform::new_inclusive(low, low)).extract(lane),
low_scalar
);
assert_eq!(zero_rng.sample(my_uniform).extract(lane), low_scalar);
assert_eq!(zero_rng.sample(my_incl_uniform).extract(lane), low_scalar);
@ -1094,26 +1125,37 @@ mod tests {
// since for those rounding might result in selecting high for a very
// long time.
if (high_scalar - low_scalar) > 0.0001 {
let mut lowering_max_rng =
StepRng::new(0xffff_ffff_ffff_ffff,
(-1i64 << $bits_shifted) as u64);
assert!(lowering_max_rng.gen_range(low, high).extract(lane) < high_scalar);
let mut lowering_max_rng = StepRng::new(
0xffff_ffff_ffff_ffff,
(-1i64 << $bits_shifted) as u64,
);
assert!(
lowering_max_rng.gen_range(low, high).extract(lane) < high_scalar
);
}
}
}
assert_eq!(rng.sample(Uniform::new_inclusive(::core::$f_scalar::MAX,
::core::$f_scalar::MAX)),
::core::$f_scalar::MAX);
assert_eq!(rng.sample(Uniform::new_inclusive(-::core::$f_scalar::MAX,
-::core::$f_scalar::MAX)),
-::core::$f_scalar::MAX);
}}
assert_eq!(
rng.sample(Uniform::new_inclusive(
::core::$f_scalar::MAX,
::core::$f_scalar::MAX
)),
::core::$f_scalar::MAX
);
assert_eq!(
rng.sample(Uniform::new_inclusive(
-::core::$f_scalar::MAX,
-::core::$f_scalar::MAX
)),
-::core::$f_scalar::MAX
);
}};
}
t!(f32, f32, 32 - 23);
t!(f64, f64, 64 - 52);
#[cfg(feature="simd_support")]
#[cfg(feature = "simd_support")]
{
t!(f32x2, f32, 32 - 23);
t!(f32x4, f32, 32 - 23);
@ -1126,13 +1168,14 @@ mod tests {
}
#[test]
#[cfg(all(feature="std",
not(target_arch = "wasm32"),
not(target_arch = "asmjs")))]
#[cfg(not(miri))] // Miri does not support catching panics
#[cfg(all(
feature = "std",
not(target_arch = "wasm32"),
not(target_arch = "asmjs")
))]
fn test_float_assertions() {
use std::panic::catch_unwind;
use super::SampleUniform;
use std::panic::catch_unwind;
fn range<T: SampleUniform>(low: T, high: T) {
let mut rng = crate::test::rng(253);
rng.gen_range(low, high);
@ -1140,20 +1183,23 @@ mod tests {
macro_rules! t {
($ty:ident, $f_scalar:ident) => {{
let v: &[($f_scalar, $f_scalar)] =
&[(::std::$f_scalar::NAN, 0.0),
(1.0, ::std::$f_scalar::NAN),
(::std::$f_scalar::NAN, ::std::$f_scalar::NAN),
(1.0, 0.5),
(::std::$f_scalar::MAX, -::std::$f_scalar::MAX),
(::std::$f_scalar::INFINITY, ::std::$f_scalar::INFINITY),
(::std::$f_scalar::NEG_INFINITY, ::std::$f_scalar::NEG_INFINITY),
(::std::$f_scalar::NEG_INFINITY, 5.0),
(5.0, ::std::$f_scalar::INFINITY),
(::std::$f_scalar::NAN, ::std::$f_scalar::INFINITY),
(::std::$f_scalar::NEG_INFINITY, ::std::$f_scalar::NAN),
(::std::$f_scalar::NEG_INFINITY, ::std::$f_scalar::INFINITY),
];
let v: &[($f_scalar, $f_scalar)] = &[
(::std::$f_scalar::NAN, 0.0),
(1.0, ::std::$f_scalar::NAN),
(::std::$f_scalar::NAN, ::std::$f_scalar::NAN),
(1.0, 0.5),
(::std::$f_scalar::MAX, -::std::$f_scalar::MAX),
(::std::$f_scalar::INFINITY, ::std::$f_scalar::INFINITY),
(
::std::$f_scalar::NEG_INFINITY,
::std::$f_scalar::NEG_INFINITY,
),
(::std::$f_scalar::NEG_INFINITY, 5.0),
(5.0, ::std::$f_scalar::INFINITY),
(::std::$f_scalar::NAN, ::std::$f_scalar::INFINITY),
(::std::$f_scalar::NEG_INFINITY, ::std::$f_scalar::NAN),
(::std::$f_scalar::NEG_INFINITY, ::std::$f_scalar::INFINITY),
];
for &(low_scalar, high_scalar) in v.iter() {
for lane in 0..<$ty>::lanes() {
let low = <$ty>::splat(0.0 as $f_scalar).replace(lane, low_scalar);
@ -1165,12 +1211,12 @@ mod tests {
assert!(catch_unwind(|| Uniform::new(low, low)).is_err());
}
}
}}
}};
}
t!(f32, f32);
t!(f64, f64);
#[cfg(feature="simd_support")]
#[cfg(feature = "simd_support")]
{
t!(f32x2, f32);
t!(f32x4, f32);
@ -1184,18 +1230,21 @@ mod tests {
#[test]
#[cfg(not(miri))] // Miri is too slow
#[cfg_attr(miri, ignore)] // Miri is too slow
fn test_durations() {
#[cfg(feature = "std")]
use std::time::Duration;
#[cfg(not(feature = "std"))]
use core::time::Duration;
#[cfg(not(feature = "std"))] use core::time::Duration;
#[cfg(feature = "std")] use std::time::Duration;
let mut rng = crate::test::rng(253);
let v = &[(Duration::new(10, 50000), Duration::new(100, 1234)),
(Duration::new(0, 100), Duration::new(1, 50)),
(Duration::new(0, 0), Duration::new(u64::max_value(), 999_999_999))];
let v = &[
(Duration::new(10, 50000), Duration::new(100, 1234)),
(Duration::new(0, 100), Duration::new(1, 50)),
(
Duration::new(0, 0),
Duration::new(u64::max_value(), 999_999_999),
),
];
for &(low, high) in v.iter() {
let my_uniform = Uniform::new(low, high);
for _ in 0..1000 {
@ -1207,7 +1256,9 @@ mod tests {
#[test]
fn test_custom_uniform() {
use crate::distributions::uniform::{UniformSampler, UniformFloat, SampleUniform, SampleBorrow};
use crate::distributions::uniform::{
SampleBorrow, SampleUniform, UniformFloat, UniformSampler,
};
#[derive(Clone, Copy, PartialEq, PartialOrd)]
struct MyF32 {
x: f32,
@ -1216,27 +1267,34 @@ mod tests {
struct UniformMyF32(UniformFloat<f32>);
impl UniformSampler for UniformMyF32 {
type X = MyF32;
fn new<B1, B2>(low: B1, high: B2) -> Self
where B1: SampleBorrow<Self::X> + Sized,
B2: SampleBorrow<Self::X> + Sized
where
B1: SampleBorrow<Self::X> + Sized,
B2: SampleBorrow<Self::X> + Sized,
{
UniformMyF32(UniformFloat::<f32>::new(low.borrow().x, high.borrow().x))
}
fn new_inclusive<B1, B2>(low: B1, high: B2) -> Self
where B1: SampleBorrow<Self::X> + Sized,
B2: SampleBorrow<Self::X> + Sized
where
B1: SampleBorrow<Self::X> + Sized,
B2: SampleBorrow<Self::X> + Sized,
{
UniformSampler::new(low, high)
}
fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> Self::X {
MyF32 { x: self.0.sample(rng) }
MyF32 {
x: self.0.sample(rng),
}
}
}
impl SampleUniform for MyF32 {
type Sampler = UniformMyF32;
}
let (low, high) = (MyF32{ x: 17.0f32 }, MyF32{ x: 22.0f32 });
let (low, high) = (MyF32 { x: 17.0f32 }, MyF32 { x: 22.0f32 });
let uniform = Uniform::new(low, high);
let mut rng = crate::test::rng(804);
for _ in 0..100 {
@ -1265,42 +1323,58 @@ mod tests {
assert!(r.0.scale > 5.0);
assert!(r.0.scale < 5.0 + 1e-14);
}
#[test]
fn value_stability() {
fn test_samples<T: SampleUniform + Copy + core::fmt::Debug + PartialEq>(
lb: T, ub: T, expected_single: &[T], expected_multiple: &[T]
)
where Uniform<T>: Distribution<T>
{
lb: T, ub: T, expected_single: &[T], expected_multiple: &[T],
) where Uniform<T>: Distribution<T> {
let mut rng = crate::test::rng(897);
let mut buf = [lb; 3];
for x in &mut buf {
*x = T::Sampler::sample_single(lb, ub, &mut rng);
}
assert_eq!(&buf, expected_single);
let distr = Uniform::new(lb, ub);
for x in &mut buf {
*x = rng.sample(&distr);
}
assert_eq!(&buf, expected_multiple);
}
// We test on a sub-set of types; possibly we should do more.
// TODO: SIMD types
test_samples(11u8, 219, &[17, 66, 214], &[181, 93, 165]);
test_samples(11u32, 219, &[17, 66, 214], &[181, 93, 165]);
test_samples(0f32, 1e-2f32, &[0.0003070104, 0.0026630748, 0.00979833],
&[0.008194133, 0.00398172, 0.007428536]);
test_samples(-1e10f64, 1e10f64,
&[-4673848682.871551, 6388267422.932352, 4857075081.198343],
&[1173375212.1808167, 1917642852.109581, 2365076174.3153973]);
test_samples(Duration::new(2, 0), Duration::new(4, 0),
&[Duration::new(2,532615131), Duration::new(3,638826742), Duration::new(3,485707508)], &[Duration::new(3,117337521), Duration::new(3,191764285), Duration::new(3,236507617)]);
test_samples(0f32, 1e-2f32, &[0.0003070104, 0.0026630748, 0.00979833], &[
0.008194133,
0.00398172,
0.007428536,
]);
test_samples(
-1e10f64,
1e10f64,
&[-4673848682.871551, 6388267422.932352, 4857075081.198343],
&[1173375212.1808167, 1917642852.109581, 2365076174.3153973],
);
test_samples(
Duration::new(2, 0),
Duration::new(4, 0),
&[
Duration::new(2, 532615131),
Duration::new(3, 638826742),
Duration::new(3, 485707508),
],
&[
Duration::new(3, 117337521),
Duration::new(3, 191764285),
Duration::new(3, 236507617),
],
);
}
}

Просмотреть файл

@ -9,8 +9,8 @@
#![allow(deprecated)]
#![allow(clippy::all)]
use crate::Rng;
use crate::distributions::{Distribution, Uniform};
use crate::Rng;
/// Samples uniformly from the edge of the unit circle in two dimensions.
///
@ -20,7 +20,7 @@ use crate::distributions::{Distribution, Uniform};
/// Random Digits.*](https://mcnp.lanl.gov/pdf_files/nbs_vonneumann.pdf)
/// NBS Appl. Math. Ser., No. 12. Washington, DC: U.S. Government Printing
/// Office, pp. 36-38.
#[deprecated(since="0.7.0", note="moved to rand_distr crate")]
#[deprecated(since = "0.7.0", note = "moved to rand_distr crate")]
#[derive(Clone, Copy, Debug)]
pub struct UnitCircle;
@ -42,35 +42,36 @@ impl Distribution<[f64; 2]> for UnitCircle {
loop {
x1 = uniform.sample(rng);
x2 = uniform.sample(rng);
sum = x1*x1 + x2*x2;
sum = x1 * x1 + x2 * x2;
if sum < 1. {
break;
}
}
let diff = x1*x1 - x2*x2;
[diff / sum, 2.*x1*x2 / sum]
let diff = x1 * x1 - x2 * x2;
[diff / sum, 2. * x1 * x2 / sum]
}
}
#[cfg(test)]
mod tests {
use crate::distributions::Distribution;
use super::UnitCircle;
use crate::distributions::Distribution;
/// Assert that two numbers are almost equal to each other.
///
/// On panic, this macro will print the values of the expressions with their
/// debug representations.
macro_rules! assert_almost_eq {
($a:expr, $b:expr, $prec:expr) => (
($a:expr, $b:expr, $prec:expr) => {
let diff = ($a - $b).abs();
if diff > $prec {
panic!(format!(
"assertion failed: `abs(left - right) = {:.1e} < {:e}`, \
(left: `{}`, right: `{}`)",
diff, $prec, $a, $b));
diff, $prec, $a, $b
));
}
);
};
}
#[test]
@ -79,7 +80,7 @@ mod tests {
let dist = UnitCircle::new();
for _ in 0..1000 {
let x = dist.sample(&mut rng);
assert_almost_eq!(x[0]*x[0] + x[1]*x[1], 1., 1e-15);
assert_almost_eq!(x[0] * x[0] + x[1] * x[1], 1., 1e-15);
}
}
@ -87,15 +88,15 @@ mod tests {
fn value_stability() {
let mut rng = crate::test::rng(2);
let expected = [
[-0.9965658683520504, -0.08280380447614634],
[-0.9790853270389644, -0.20345004884984505],
[-0.8449189758898707, 0.5348943112253227],
];
[-0.9965658683520504, -0.08280380447614634],
[-0.9790853270389644, -0.20345004884984505],
[-0.8449189758898707, 0.5348943112253227],
];
let samples = [
UnitCircle.sample(&mut rng),
UnitCircle.sample(&mut rng),
UnitCircle.sample(&mut rng),
];
UnitCircle.sample(&mut rng),
UnitCircle.sample(&mut rng),
UnitCircle.sample(&mut rng),
];
assert_eq!(samples, expected);
}
}

Просмотреть файл

@ -9,8 +9,8 @@
#![allow(deprecated)]
#![allow(clippy::all)]
use crate::Rng;
use crate::distributions::{Distribution, Uniform};
use crate::Rng;
/// Samples uniformly from the surface of the unit sphere in three dimensions.
///
@ -19,7 +19,7 @@ use crate::distributions::{Distribution, Uniform};
/// [^1]: Marsaglia, George (1972). [*Choosing a Point from the Surface of a
/// Sphere.*](https://doi.org/10.1214/aoms/1177692644)
/// Ann. Math. Statist. 43, no. 2, 645--646.
#[deprecated(since="0.7.0", note="moved to rand_distr crate")]
#[deprecated(since = "0.7.0", note = "moved to rand_distr crate")]
#[derive(Clone, Copy, Debug)]
pub struct UnitSphereSurface;
@ -37,35 +37,36 @@ impl Distribution<[f64; 3]> for UnitSphereSurface {
let uniform = Uniform::new(-1., 1.);
loop {
let (x1, x2) = (uniform.sample(rng), uniform.sample(rng));
let sum = x1*x1 + x2*x2;
let sum = x1 * x1 + x2 * x2;
if sum >= 1. {
continue;
}
let factor = 2. * (1.0_f64 - sum).sqrt();
return [x1 * factor, x2 * factor, 1. - 2.*sum];
return [x1 * factor, x2 * factor, 1. - 2. * sum];
}
}
}
#[cfg(test)]
mod tests {
use crate::distributions::Distribution;
use super::UnitSphereSurface;
use crate::distributions::Distribution;
/// Assert that two numbers are almost equal to each other.
///
/// On panic, this macro will print the values of the expressions with their
/// debug representations.
macro_rules! assert_almost_eq {
($a:expr, $b:expr, $prec:expr) => (
($a:expr, $b:expr, $prec:expr) => {
let diff = ($a - $b).abs();
if diff > $prec {
panic!(format!(
"assertion failed: `abs(left - right) = {:.1e} < {:e}`, \
(left: `{}`, right: `{}`)",
diff, $prec, $a, $b));
diff, $prec, $a, $b
));
}
);
};
}
#[test]
@ -74,7 +75,7 @@ mod tests {
let dist = UnitSphereSurface::new();
for _ in 0..1000 {
let x = dist.sample(&mut rng);
assert_almost_eq!(x[0]*x[0] + x[1]*x[1] + x[2]*x[2], 1., 1e-15);
assert_almost_eq!(x[0] * x[0] + x[1] * x[1] + x[2] * x[2], 1., 1e-15);
}
}
@ -82,15 +83,15 @@ mod tests {
fn value_stability() {
let mut rng = crate::test::rng(2);
let expected = [
[0.03247542860231647, -0.7830477442152738, 0.6211131755296027],
[-0.09978440840914075, 0.9706650829833128, -0.21875184231323952],
[0.2735582468624679, 0.9435374242279655, -0.1868234852870203],
];
[0.03247542860231647, -0.7830477442152738, 0.6211131755296027],
[-0.09978440840914075, 0.9706650829833128, -0.21875184231323952],
[0.2735582468624679, 0.9435374242279655, -0.1868234852870203],
];
let samples = [
UnitSphereSurface.sample(&mut rng),
UnitSphereSurface.sample(&mut rng),
UnitSphereSurface.sample(&mut rng),
];
UnitSphereSurface.sample(&mut rng),
UnitSphereSurface.sample(&mut rng),
UnitSphereSurface.sample(&mut rng),
];
assert_eq!(samples, expected);
}
}

Просмотреть файл

@ -8,12 +8,9 @@
//! Math helper functions
#[cfg(feature="simd_support")]
use packed_simd::*;
#[cfg(feature="std")]
use crate::distributions::ziggurat_tables;
#[cfg(feature="std")]
use crate::Rng;
#[cfg(feature = "std")] use crate::distributions::ziggurat_tables;
#[cfg(feature = "std")] use crate::Rng;
#[cfg(feature = "simd_support")] use packed_simd::*;
pub trait WideningMultiply<RHS = Self> {
@ -141,7 +138,7 @@ macro_rules! wmul_impl_usize {
(high as usize, low as usize)
}
}
}
};
}
#[cfg(target_pointer_width = "32")]
wmul_impl_usize! { u32 }
@ -150,11 +147,9 @@ wmul_impl_usize! { u64 }
#[cfg(all(feature = "simd_support", feature = "nightly"))]
mod simd_wmul {
#[cfg(target_arch = "x86")]
use core::arch::x86::*;
#[cfg(target_arch = "x86_64")]
use core::arch::x86_64::*;
use super::*;
#[cfg(target_arch = "x86")] use core::arch::x86::*;
#[cfg(target_arch = "x86_64")] use core::arch::x86_64::*;
wmul_impl! {
(u8x2, u16x2),
@ -248,25 +243,35 @@ pub(crate) trait FloatSIMDUtils {
/// Implement functions available in std builds but missing from core primitives
#[cfg(not(std))]
pub(crate) trait Float : Sized {
pub(crate) trait Float: Sized {
fn is_nan(self) -> bool;
fn is_infinite(self) -> bool;
fn is_finite(self) -> bool;
}
/// Implement functions on f32/f64 to give them APIs similar to SIMD types
pub(crate) trait FloatAsSIMD : Sized {
pub(crate) trait FloatAsSIMD: Sized {
#[inline(always)]
fn lanes() -> usize { 1 }
fn lanes() -> usize {
1
}
#[inline(always)]
fn splat(scalar: Self) -> Self { scalar }
fn splat(scalar: Self) -> Self {
scalar
}
#[inline(always)]
fn extract(self, index: usize) -> Self { debug_assert_eq!(index, 0); self }
fn extract(self, index: usize) -> Self {
debug_assert_eq!(index, 0);
self
}
#[inline(always)]
fn replace(self, index: usize, new_value: Self) -> Self { debug_assert_eq!(index, 0); new_value }
fn replace(self, index: usize, new_value: Self) -> Self {
debug_assert_eq!(index, 0);
new_value
}
}
pub(crate) trait BoolAsSIMD : Sized {
pub(crate) trait BoolAsSIMD: Sized {
fn any(self) -> bool;
fn all(self) -> bool;
fn none(self) -> bool;
@ -274,11 +279,19 @@ pub(crate) trait BoolAsSIMD : Sized {
impl BoolAsSIMD for bool {
#[inline(always)]
fn any(self) -> bool { self }
fn any(self) -> bool {
self
}
#[inline(always)]
fn all(self) -> bool { self }
fn all(self) -> bool {
self
}
#[inline(always)]
fn none(self) -> bool { !self }
fn none(self) -> bool {
!self
}
}
macro_rules! scalar_float_impl {
@ -303,46 +316,80 @@ macro_rules! scalar_float_impl {
impl FloatSIMDUtils for $ty {
type Mask = bool;
type UInt = $uty;
#[inline(always)]
fn all_lt(self, other: Self) -> bool { self < other }
fn all_lt(self, other: Self) -> bool {
self < other
}
#[inline(always)]
fn all_le(self, other: Self) -> bool { self <= other }
fn all_le(self, other: Self) -> bool {
self <= other
}
#[inline(always)]
fn all_finite(self) -> bool { self.is_finite() }
fn all_finite(self) -> bool {
self.is_finite()
}
#[inline(always)]
fn finite_mask(self) -> Self::Mask { self.is_finite() }
fn finite_mask(self) -> Self::Mask {
self.is_finite()
}
#[inline(always)]
fn gt_mask(self, other: Self) -> Self::Mask { self > other }
fn gt_mask(self, other: Self) -> Self::Mask {
self > other
}
#[inline(always)]
fn ge_mask(self, other: Self) -> Self::Mask { self >= other }
fn ge_mask(self, other: Self) -> Self::Mask {
self >= other
}
#[inline(always)]
fn decrease_masked(self, mask: Self::Mask) -> Self {
debug_assert!(mask, "At least one lane must be set");
<$ty>::from_bits(self.to_bits() - 1)
}
type UInt = $uty;
fn cast_from_int(i: Self::UInt) -> Self { i as $ty }
#[inline]
fn cast_from_int(i: Self::UInt) -> Self {
i as $ty
}
}
impl FloatAsSIMD for $ty {}
}
};
}
scalar_float_impl!(f32, u32);
scalar_float_impl!(f64, u64);
#[cfg(feature="simd_support")]
#[cfg(feature = "simd_support")]
macro_rules! simd_impl {
($ty:ident, $f_scalar:ident, $mty:ident, $uty:ident) => {
impl FloatSIMDUtils for $ty {
type Mask = $mty;
type UInt = $uty;
#[inline(always)]
fn all_lt(self, other: Self) -> bool { self.lt(other).all() }
fn all_lt(self, other: Self) -> bool {
self.lt(other).all()
}
#[inline(always)]
fn all_le(self, other: Self) -> bool { self.le(other).all() }
fn all_le(self, other: Self) -> bool {
self.le(other).all()
}
#[inline(always)]
fn all_finite(self) -> bool { self.finite_mask().all() }
fn all_finite(self) -> bool {
self.finite_mask().all()
}
#[inline(always)]
fn finite_mask(self) -> Self::Mask {
// This can possibly be done faster by checking bit patterns
@ -350,10 +397,17 @@ macro_rules! simd_impl {
let pos_inf = $ty::splat(::core::$f_scalar::INFINITY);
self.gt(neg_inf) & self.lt(pos_inf)
}
#[inline(always)]
fn gt_mask(self, other: Self) -> Self::Mask { self.gt(other) }
fn gt_mask(self, other: Self) -> Self::Mask {
self.gt(other)
}
#[inline(always)]
fn ge_mask(self, other: Self) -> Self::Mask { self.ge(other) }
fn ge_mask(self, other: Self) -> Self::Mask {
self.ge(other)
}
#[inline(always)]
fn decrease_masked(self, mask: Self::Mask) -> Self {
// Casting a mask into ints will produce all bits set for
@ -365,11 +419,13 @@ macro_rules! simd_impl {
debug_assert!(mask.any(), "At least one lane must be set");
<$ty>::from_bits(<$uty>::from_bits(self) + <$uty>::from_bits(mask))
}
type UInt = $uty;
#[inline]
fn cast_from_int(i: Self::UInt) -> Self { i.cast() }
fn cast_from_int(i: Self::UInt) -> Self {
i.cast()
}
}
}
};
}
#[cfg(feature="simd_support")] simd_impl! { f32x2, f32, m32x2, u32x2 }
@ -393,7 +449,7 @@ macro_rules! simd_impl {
/// `Ag(z)` is an infinite series with coefficients that can be calculated
/// ahead of time - we use just the first 6 terms, which is good enough
/// for most purposes.
#[cfg(feature="std")]
#[cfg(feature = "std")]
pub fn log_gamma(x: f64) -> f64 {
// precalculated 6 coefficients for the first 6 terms of the series
let coefficients: [f64; 6] = [
@ -438,16 +494,20 @@ pub fn log_gamma(x: f64) -> f64 {
// the perf improvement (25-50%) is definitely worth the extra code
// size from force-inlining.
#[cfg(feature="std")]
#[cfg(feature = "std")]
#[inline(always)]
pub fn ziggurat<R: Rng + ?Sized, P, Z>(
rng: &mut R,
symmetric: bool,
x_tab: ziggurat_tables::ZigTable,
f_tab: ziggurat_tables::ZigTable,
mut pdf: P,
mut zero_case: Z)
-> f64 where P: FnMut(f64) -> f64, Z: FnMut(&mut R, f64) -> f64 {
rng: &mut R,
symmetric: bool,
x_tab: ziggurat_tables::ZigTable,
f_tab: ziggurat_tables::ZigTable,
mut pdf: P,
mut zero_case: Z
) -> f64
where
P: FnMut(f64) -> f64,
Z: FnMut(&mut R, f64) -> f64,
{
use crate::distributions::float::IntoFloat;
loop {
// As an optimisation we re-implement the conversion to a f64.
@ -466,12 +526,11 @@ pub fn ziggurat<R: Rng + ?Sized, P, Z>(
(bits >> 12).into_float_with_exponent(1) - 3.0
} else {
// Convert to a value in the range [1,2) and substract to get (0,1)
(bits >> 12).into_float_with_exponent(0)
- (1.0 - ::core::f64::EPSILON / 2.0)
(bits >> 12).into_float_with_exponent(0) - (1.0 - ::core::f64::EPSILON / 2.0)
};
let x = u * x_tab[i];
let test_x = if symmetric { x.abs() } else {x};
let test_x = if symmetric { x.abs() } else { x };
// algebraically equivalent to |u| < x_tab[i+1]/x_tab[i] (or u < x_tab[i+1]/x_tab[i])
if test_x < x_tab[i + 1] {

Просмотреть файл

@ -9,11 +9,11 @@
//! The Weibull distribution.
#![allow(deprecated)]
use crate::Rng;
use crate::distributions::{Distribution, OpenClosed01};
use crate::Rng;
/// Samples floating-point numbers according to the Weibull distribution
#[deprecated(since="0.7.0", note="moved to rand_distr crate")]
#[deprecated(since = "0.7.0", note = "moved to rand_distr crate")]
#[derive(Clone, Copy, Debug)]
pub struct Weibull {
inv_shape: f64,
@ -28,7 +28,10 @@ impl Weibull {
/// `scale` and `shape` have to be non-zero and positive.
pub fn new(scale: f64, shape: f64) -> Weibull {
assert!((scale > 0.) & (shape > 0.));
Weibull { inv_shape: 1./shape, scale }
Weibull {
inv_shape: 1. / shape,
scale,
}
}
}
@ -41,8 +44,8 @@ impl Distribution<f64> for Weibull {
#[cfg(test)]
mod tests {
use crate::distributions::Distribution;
use super::Weibull;
use crate::distributions::Distribution;
#[test]
#[should_panic]

Просмотреть файл

@ -2,17 +2,15 @@
//! indices with probabilities proportional to a collection of weights.
use super::WeightedError;
#[cfg(not(feature = "std"))]
use crate::alloc::vec::Vec;
#[cfg(not(feature = "std"))]
use crate::alloc::vec;
use core::fmt;
use core::iter::Sum;
use core::ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Sub, SubAssign};
#[cfg(not(feature = "std"))] use crate::alloc::vec;
#[cfg(not(feature = "std"))] use crate::alloc::vec::Vec;
use crate::distributions::uniform::SampleUniform;
use crate::distributions::Distribution;
use crate::distributions::Uniform;
use crate::Rng;
use core::fmt;
use core::iter::Sum;
use core::ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Sub, SubAssign};
/// A distribution using weighted sampling to pick a discretely selected item.
///
@ -192,9 +190,8 @@ impl<W: Weight> WeightedIndex<W> {
let b = aliases.pop_big();
aliases.set_alias(s, b);
no_alias_odds[b as usize] = no_alias_odds[b as usize]
- weight_sum
+ no_alias_odds[s as usize];
no_alias_odds[b as usize] =
no_alias_odds[b as usize] - weight_sum + no_alias_odds[s as usize];
if no_alias_odds[b as usize] < weight_sum {
aliases.push_small(b);
@ -253,8 +250,7 @@ where
}
impl<W: Weight> Clone for WeightedIndex<W>
where
Uniform<W>: Clone,
where Uniform<W>: Clone
{
fn clone(&self) -> Self {
Self {
@ -370,7 +366,7 @@ mod test {
use super::*;
#[test]
#[cfg(not(miri))] // Miri is too slow
#[cfg_attr(miri, ignore)] // Miri is too slow
fn test_weighted_index_f32() {
test_weighted_index(f32::into);
@ -399,14 +395,14 @@ mod test {
#[cfg(not(target_os = "emscripten"))]
#[test]
#[cfg(not(miri))] // Miri is too slow
#[cfg_attr(miri, ignore)] // Miri is too slow
fn test_weighted_index_u128() {
test_weighted_index(|x: u128| x as f64);
}
#[cfg(all(rustc_1_26, not(target_os = "emscripten")))]
#[test]
#[cfg(not(miri))] // Miri is too slow
#[cfg_attr(miri, ignore)] // Miri is too slow
fn test_weighted_index_i128() {
test_weighted_index(|x: i128| x as f64);
@ -422,13 +418,13 @@ mod test {
}
#[test]
#[cfg(not(miri))] // Miri is too slow
#[cfg_attr(miri, ignore)] // Miri is too slow
fn test_weighted_index_u8() {
test_weighted_index(u8::into);
}
#[test]
#[cfg(not(miri))] // Miri is too slow
#[cfg_attr(miri, ignore)] // Miri is too slow
fn test_weighted_index_i8() {
test_weighted_index(i8::into);
@ -444,9 +440,7 @@ mod test {
}
fn test_weighted_index<W: Weight, F: Fn(W) -> f64>(w_to_f64: F)
where
WeightedIndex<W>: fmt::Debug,
{
where WeightedIndex<W>: fmt::Debug {
const NUM_WEIGHTS: u32 = 10;
const ZERO_WEIGHT_INDEX: u32 = 3;
const NUM_SAMPLES: u32 = 15000;
@ -496,7 +490,7 @@ mod test {
WeightedError::InvalidWeight
);
}
#[test]
fn value_stability() {
fn test_samples<W: Weight>(weights: Vec<W>, buf: &mut [usize], expected: &[usize]) {
@ -508,10 +502,16 @@ mod test {
}
assert_eq!(buf, expected);
}
let mut buf = [0; 10];
test_samples(vec![1i32,1,1,1,1,1,1,1,1], &mut buf, &[6, 5, 7, 5, 8, 7, 6, 2, 3, 7]);
test_samples(vec![0.7f32, 0.1, 0.1, 0.1], &mut buf, &[2, 0, 0, 0, 0, 0, 0, 0, 1, 3]);
test_samples(vec![1.0f64, 0.999, 0.998, 0.997], &mut buf, &[2, 1, 2, 3, 2, 1, 3, 2, 1, 1]);
test_samples(vec![1i32, 1, 1, 1, 1, 1, 1, 1, 1], &mut buf, &[
6, 5, 7, 5, 8, 7, 6, 2, 3, 7,
]);
test_samples(vec![0.7f32, 0.1, 0.1, 0.1], &mut buf, &[
2, 0, 0, 0, 0, 0, 0, 0, 1, 3,
]);
test_samples(vec![1.0f64, 0.999, 0.998, 0.997], &mut buf, &[
2, 1, 2, 3, 2, 1, 3, 2, 1, 1,
]);
}
}

Просмотреть файл

@ -7,9 +7,9 @@
// except according to those terms.
//! Weighted index sampling
//!
//!
//! This module provides two implementations for sampling indices:
//!
//!
//! * [`WeightedIndex`] allows `O(log N)` sampling
//! * [`alias_method::WeightedIndex`] allows `O(1)` sampling, but with
//! much greater set-up cost
@ -18,14 +18,14 @@
pub mod alias_method;
use crate::Rng;
use crate::distributions::uniform::{SampleBorrow, SampleUniform, UniformSampler};
use crate::distributions::Distribution;
use crate::distributions::uniform::{UniformSampler, SampleUniform, SampleBorrow};
use crate::Rng;
use core::cmp::PartialOrd;
use core::fmt;
// Note that this whole module is only imported if feature="alloc" is enabled.
#[cfg(not(feature="std"))] use crate::alloc::vec::Vec;
#[cfg(not(feature = "std"))] use crate::alloc::vec::Vec;
/// A distribution using weighted sampling to pick a discretely selected
/// item.
@ -98,16 +98,13 @@ impl<X: SampleUniform + PartialOrd> WeightedIndex<X> {
///
/// [`Uniform<X>`]: crate::distributions::uniform::Uniform
pub fn new<I>(weights: I) -> Result<WeightedIndex<X>, WeightedError>
where I: IntoIterator,
I::Item: SampleBorrow<X>,
X: for<'a> ::core::ops::AddAssign<&'a X> +
Clone +
Default {
where
I: IntoIterator,
I::Item: SampleBorrow<X>,
X: for<'a> ::core::ops::AddAssign<&'a X> + Clone + Default,
{
let mut iter = weights.into_iter();
let mut total_weight: X = iter.next()
.ok_or(WeightedError::NoItem)?
.borrow()
.clone();
let mut total_weight: X = iter.next().ok_or(WeightedError::NoItem)?.borrow().clone();
let zero = <X as Default>::default();
if total_weight < zero {
@ -128,7 +125,11 @@ impl<X: SampleUniform + PartialOrd> WeightedIndex<X> {
}
let distr = X::Sampler::new(zero, total_weight.clone());
Ok(WeightedIndex { cumulative_weights: weights, total_weight, weight_distribution: distr })
Ok(WeightedIndex {
cumulative_weights: weights,
total_weight,
weight_distribution: distr,
})
}
/// Update a subset of weights, without changing the number of weights.
@ -141,10 +142,10 @@ impl<X: SampleUniform + PartialOrd> WeightedIndex<X> {
///
/// In case of error, `self` is not modified.
pub fn update_weights(&mut self, new_weights: &[(usize, &X)]) -> Result<(), WeightedError>
where X: for<'a> ::core::ops::AddAssign<&'a X> +
for<'a> ::core::ops::SubAssign<&'a X> +
Clone +
Default {
where X: for<'a> ::core::ops::AddAssign<&'a X>
+ for<'a> ::core::ops::SubAssign<&'a X>
+ Clone
+ Default {
if new_weights.is_empty() {
return Ok(());
}
@ -196,17 +197,17 @@ impl<X: SampleUniform + PartialOrd> WeightedIndex<X> {
let mut cumulative_weight = if first_new_index > 0 {
self.cumulative_weights[first_new_index - 1].clone()
} else {
zero.clone()
zero.clone()
};
for i in first_new_index..self.cumulative_weights.len() {
match next_new_weight {
Some(&(j, w)) if i == j => {
cumulative_weight += w;
next_new_weight = iter.next();
},
}
_ => {
let mut tmp = self.cumulative_weights[i].clone();
tmp -= &prev_weight; // We know this is positive.
tmp -= &prev_weight; // We know this is positive.
cumulative_weight += &tmp;
}
}
@ -221,14 +222,22 @@ impl<X: SampleUniform + PartialOrd> WeightedIndex<X> {
}
}
impl<X> Distribution<usize> for WeightedIndex<X> where
X: SampleUniform + PartialOrd {
impl<X> Distribution<usize> for WeightedIndex<X>
where X: SampleUniform + PartialOrd
{
fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> usize {
use ::core::cmp::Ordering;
let chosen_weight = self.weight_distribution.sample(rng);
// Find the first item which has a weight *higher* than the chosen weight.
self.cumulative_weights.binary_search_by(
|w| if *w <= chosen_weight { Ordering::Less } else { Ordering::Greater }).unwrap_err()
self.cumulative_weights
.binary_search_by(|w| {
if *w <= chosen_weight {
Ordering::Less
} else {
Ordering::Greater
}
})
.unwrap_err()
}
}
@ -237,7 +246,7 @@ mod test {
use super::*;
#[test]
#[cfg(not(miri))] // Miri is too slow
#[cfg_attr(miri, ignore)] // Miri is too slow
fn test_weightedindex() {
let mut r = crate::test::rng(700);
const N_REPS: u32 = 5000;
@ -282,28 +291,52 @@ mod test {
for _ in 0..5 {
assert_eq!(WeightedIndex::new(&[0, 1]).unwrap().sample(&mut r), 1);
assert_eq!(WeightedIndex::new(&[1, 0]).unwrap().sample(&mut r), 0);
assert_eq!(WeightedIndex::new(&[0, 0, 0, 0, 10, 0]).unwrap().sample(&mut r), 4);
assert_eq!(
WeightedIndex::new(&[0, 0, 0, 0, 10, 0])
.unwrap()
.sample(&mut r),
4
);
}
assert_eq!(WeightedIndex::new(&[10][0..0]).unwrap_err(), WeightedError::NoItem);
assert_eq!(WeightedIndex::new(&[0]).unwrap_err(), WeightedError::AllWeightsZero);
assert_eq!(WeightedIndex::new(&[10, 20, -1, 30]).unwrap_err(), WeightedError::InvalidWeight);
assert_eq!(WeightedIndex::new(&[-10, 20, 1, 30]).unwrap_err(), WeightedError::InvalidWeight);
assert_eq!(WeightedIndex::new(&[-10]).unwrap_err(), WeightedError::InvalidWeight);
assert_eq!(
WeightedIndex::new(&[10][0..0]).unwrap_err(),
WeightedError::NoItem
);
assert_eq!(
WeightedIndex::new(&[0]).unwrap_err(),
WeightedError::AllWeightsZero
);
assert_eq!(
WeightedIndex::new(&[10, 20, -1, 30]).unwrap_err(),
WeightedError::InvalidWeight
);
assert_eq!(
WeightedIndex::new(&[-10, 20, 1, 30]).unwrap_err(),
WeightedError::InvalidWeight
);
assert_eq!(
WeightedIndex::new(&[-10]).unwrap_err(),
WeightedError::InvalidWeight
);
}
#[test]
fn test_update_weights() {
let data = [
(&[10u32, 2, 3, 4][..],
&[(1, &100), (2, &4)][..], // positive change
&[10, 100, 4, 4][..]),
(&[1u32, 2, 3, 0, 5, 6, 7, 1, 2, 3, 4, 5, 6, 7][..],
&[(2, &1), (5, &1), (13, &100)][..], // negative change and last element
&[1u32, 2, 1, 0, 5, 1, 7, 1, 2, 3, 4, 5, 6, 100][..]),
(
&[10u32, 2, 3, 4][..],
&[(1, &100), (2, &4)][..], // positive change
&[10, 100, 4, 4][..],
),
(
&[1u32, 2, 3, 0, 5, 6, 7, 1, 2, 3, 4, 5, 6, 7][..],
&[(2, &1), (5, &1), (13, &100)][..], // negative change and last element
&[1u32, 2, 1, 0, 5, 1, 7, 1, 2, 3, 4, 5, 6, 100][..],
),
];
for (weights, update, expected_weights) in data.into_iter() {
for (weights, update, expected_weights) in data.iter() {
let total_weight = weights.iter().sum::<u32>();
let mut distr = WeightedIndex::new(weights.to_vec()).unwrap();
assert_eq!(distr.total_weight, total_weight);
@ -316,20 +349,15 @@ mod test {
assert_eq!(distr.cumulative_weights, expected_distr.cumulative_weights);
}
}
#[test]
fn value_stability() {
fn test_samples<X: SampleUniform + PartialOrd, I>
(
weights: I,
buf: &mut [usize],
expected: &[usize]
)
where I: IntoIterator,
I::Item: SampleBorrow<X>,
X: for<'a> ::core::ops::AddAssign<&'a X> +
Clone +
Default
fn test_samples<X: SampleUniform + PartialOrd, I>(
weights: I, buf: &mut [usize], expected: &[usize],
) where
I: IntoIterator,
I::Item: SampleBorrow<X>,
X: for<'a> ::core::ops::AddAssign<&'a X> + Clone + Default,
{
assert_eq!(buf.len(), expected.len());
let distr = WeightedIndex::new(weights).unwrap();
@ -339,11 +367,17 @@ mod test {
}
assert_eq!(buf, expected);
}
let mut buf = [0; 10];
test_samples(&[1i32,1,1,1,1,1,1,1,1], &mut buf, &[0, 6, 2, 6, 3, 4, 7, 8, 2, 5]);
test_samples(&[0.7f32, 0.1, 0.1, 0.1], &mut buf, &[0, 0, 0, 1, 0, 0, 2, 3, 0, 0]);
test_samples(&[1.0f64, 0.999, 0.998, 0.997], &mut buf, &[2, 2, 1, 3, 2, 1, 3, 3, 2, 1]);
test_samples(&[1i32, 1, 1, 1, 1, 1, 1, 1, 1], &mut buf, &[
0, 6, 2, 6, 3, 4, 7, 8, 2, 5,
]);
test_samples(&[0.7f32, 0.1, 0.1, 0.1], &mut buf, &[
0, 0, 0, 1, 0, 0, 2, 3, 0, 0,
]);
test_samples(&[1.0f64, 0.999, 0.998, 0.997], &mut buf, &[
2, 2, 1, 3, 2, 1, 3, 3, 2, 1,
]);
}
}
@ -359,34 +393,21 @@ pub enum WeightedError {
/// All items in the provided weight collection are zero.
AllWeightsZero,
/// Too many weights are provided (length greater than `u32::MAX`)
TooMany,
}
impl WeightedError {
fn msg(&self) -> &str {
match *self {
WeightedError::NoItem => "No weights provided.",
WeightedError::InvalidWeight => "A weight is invalid.",
WeightedError::AllWeightsZero => "All weights are zero.",
WeightedError::TooMany => "Too many weights (hit u32::MAX)",
}
}
}
#[cfg(feature="std")]
impl ::std::error::Error for WeightedError {
fn description(&self) -> &str {
self.msg()
}
fn cause(&self) -> Option<&dyn (::std::error::Error)> {
None
}
}
#[cfg(feature = "std")]
impl ::std::error::Error for WeightedError {}
impl fmt::Display for WeightedError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{}", self.msg())
match *self {
WeightedError::NoItem => write!(f, "No weights provided."),
WeightedError::InvalidWeight => write!(f, "A weight is invalid."),
WeightedError::AllWeightsZero => write!(f, "All weights are zero."),
WeightedError::TooMany => write!(f, "Too many weights (hit u32::MAX)"),
}
}
}

Просмотреть файл

@ -12,6 +12,7 @@
pub type ZigTable = &'static [f64; 257];
pub const ZIG_NORM_R: f64 = 3.654152885361008796;
#[rustfmt::skip]
pub static ZIG_NORM_X: [f64; 257] =
[3.910757959537090045, 3.654152885361008796, 3.449278298560964462, 3.320244733839166074,
3.224575052047029100, 3.147889289517149969, 3.083526132001233044, 3.027837791768635434,
@ -78,6 +79,7 @@ pub static ZIG_NORM_X: [f64; 257] =
0.487443966121754335, 0.463634336771763245, 0.437518402186662658, 0.408389134588000746,
0.375121332850465727, 0.335737519180459465, 0.286174591747260509, 0.215241895913273806,
0.000000000000000000];
#[rustfmt::skip]
pub static ZIG_NORM_F: [f64; 257] =
[0.000477467764586655, 0.001260285930498598, 0.002609072746106363, 0.004037972593371872,
0.005522403299264754, 0.007050875471392110, 0.008616582769422917, 0.010214971439731100,
@ -145,6 +147,7 @@ pub static ZIG_NORM_F: [f64; 257] =
0.932060075968990209, 0.945198953453078028, 0.959879091812415930, 0.977101701282731328,
1.000000000000000000];
pub const ZIG_EXP_R: f64 = 7.697117470131050077;
#[rustfmt::skip]
pub static ZIG_EXP_X: [f64; 257] =
[8.697117470131052741, 7.697117470131050077, 6.941033629377212577, 6.478378493832569696,
6.144164665772472667, 5.882144315795399869, 5.666410167454033697, 5.482890627526062488,
@ -211,6 +214,7 @@ pub static ZIG_EXP_X: [f64; 257] =
0.253658363385912022, 0.233790483059674731, 0.212671510630966620, 0.189958689622431842,
0.165127622564187282, 0.137304980940012589, 0.104838507565818778, 0.063852163815001570,
0.000000000000000000];
#[rustfmt::skip]
pub static ZIG_EXP_F: [f64; 257] =
[0.000167066692307963, 0.000454134353841497, 0.000967269282327174, 0.001536299780301573,
0.002145967743718907, 0.002788798793574076, 0.003460264777836904, 0.004157295120833797,

84
third_party/rust/rand/src/lib.rs поставляемый
Просмотреть файл

@ -40,22 +40,23 @@
//! For the user guide and futher documentation, please read
//! [The Rust Rand Book](https://rust-random.github.io/book).
#![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk.png",
html_favicon_url = "https://www.rust-lang.org/favicon.ico",
html_root_url = "https://rust-random.github.io/rand/")]
#![doc(
html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk.png",
html_favicon_url = "https://www.rust-lang.org/favicon.ico",
html_root_url = "https://rust-random.github.io/rand/"
)]
#![deny(missing_docs)]
#![deny(missing_debug_implementations)]
#![doc(test(attr(allow(unused_variables), deny(warnings))))]
#![cfg_attr(not(feature = "std"), no_std)]
#![cfg_attr(all(feature = "simd_support", feature = "nightly"), feature(stdsimd))]
#![allow(
clippy::excessive_precision,
clippy::unreadable_literal,
clippy::float_cmp
)]
#![cfg_attr(not(feature="std"), no_std)]
#![cfg_attr(all(feature="simd_support", feature="nightly"), feature(stdsimd))]
#![allow(clippy::excessive_precision, clippy::unreadable_literal, clippy::float_cmp)]
#[cfg(all(feature="alloc", not(feature="std")))]
extern crate alloc;
#[cfg(all(feature = "alloc", not(feature = "std")))] extern crate alloc;
#[allow(unused)]
macro_rules! trace { ($($x:tt)*) => (
@ -89,10 +90,10 @@ macro_rules! error { ($($x:tt)*) => (
) }
// Re-exports from rand_core
pub use rand_core::{RngCore, CryptoRng, SeedableRng, Error};
pub use rand_core::{CryptoRng, Error, RngCore, SeedableRng};
// Public exports
#[cfg(feature="std")] pub use crate::rngs::thread::thread_rng;
#[cfg(feature = "std")] pub use crate::rngs::thread::thread_rng;
// Public modules
pub mod distributions;
@ -101,10 +102,10 @@ pub mod rngs;
pub mod seq;
use core::{mem, slice};
use core::num::Wrapping;
use crate::distributions::uniform::{SampleBorrow, SampleUniform, UniformSampler};
use crate::distributions::{Distribution, Standard};
use crate::distributions::uniform::{SampleUniform, UniformSampler, SampleBorrow};
use core::num::Wrapping;
use core::{mem, slice};
/// An automatically-implemented extension trait on [`RngCore`] providing high-level
/// generic methods for sampling values and other convenience methods.
@ -268,7 +269,10 @@ pub trait Rng: RngCore {
/// }
/// ```
fn sample_iter<T, D>(self, distr: D) -> distributions::DistIter<D, Self, T>
where D: Distribution<T>, Self: Sized {
where
D: Distribution<T>,
Self: Sized,
{
distr.sample_iter(self)
}
@ -468,9 +472,11 @@ macro_rules! impl_as_byte_slice {
}
impl_as_byte_slice!(u16, u32, u64, usize,);
#[cfg(not(target_os = "emscripten"))] impl_as_byte_slice!(u128);
#[cfg(not(target_os = "emscripten"))]
impl_as_byte_slice!(u128);
impl_as_byte_slice!(i8, i16, i32, i64, isize,);
#[cfg(not(target_os = "emscripten"))] impl_as_byte_slice!(i128);
#[cfg(not(target_os = "emscripten"))]
impl_as_byte_slice!(i128);
macro_rules! impl_as_byte_slice_arrays {
($n:expr,) => {};
@ -495,6 +501,7 @@ macro_rules! impl_as_byte_slice_arrays {
impl_as_byte_slice_arrays!(!div $n / 2, $($NN,)*);
};
}
#[rustfmt::skip]
impl_as_byte_slice_arrays!(32, N,N,N,N,N,N,N,N,N,N,N,N,N,N,N,N,N,N,N,N,N,N,N,N,N,N,N,N,N,N,N,N,N,);
impl_as_byte_slice_arrays!(!div 4096, N,N,N,N,N,N,N,);
@ -540,7 +547,7 @@ impl_as_byte_slice_arrays!(!div 4096, N,N,N,N,N,N,N,);
/// ```
///
/// [`Standard`]: distributions::Standard
#[cfg(feature="std")]
#[cfg(feature = "std")]
#[inline]
pub fn random<T>() -> T
where Standard: Distribution<T> {
@ -549,9 +556,9 @@ where Standard: Distribution<T> {
#[cfg(test)]
mod test {
use crate::rngs::mock::StepRng;
use super::*;
#[cfg(all(not(feature="std"), feature="alloc"))] use alloc::boxed::Box;
use crate::rngs::mock::StepRng;
#[cfg(all(not(feature = "std"), feature = "alloc"))] use alloc::boxed::Box;
/// Construct a deterministic RNG with the given seed
pub fn rng(seed: u64) -> impl RngCore {
@ -566,8 +573,7 @@ mod test {
let mut r = StepRng::new(0x11_22_33_44_55_66_77_88, 0);
// check every remainder mod 8, both in small and big vectors.
let lengths = [0, 1, 2, 3, 4, 5, 6, 7,
80, 81, 82, 83, 84, 85, 86, 87];
let lengths = [0, 1, 2, 3, 4, 5, 6, 7, 80, 81, 82, 83, 84, 85, 86, 87];
for &n in lengths.iter() {
let mut buffer = [0u8; 87];
let v = &mut buffer[0..n];
@ -584,7 +590,7 @@ mod test {
#[test]
fn test_fill() {
let x = 9041086907909331047; // a random u64
let x = 9041086907909331047; // a random u64
let mut rng = StepRng::new(x, 0);
// Convert to byte sequence and back to u64; byte-swap twice if BE.
@ -670,7 +676,7 @@ mod test {
}
#[test]
#[cfg(feature="alloc")]
#[cfg(feature = "alloc")]
fn test_rng_boxed_trait() {
use crate::distributions::{Distribution, Standard};
let rng = rng(110);
@ -682,22 +688,22 @@ mod test {
}
#[test]
#[cfg(feature="std")]
#[cfg(feature = "std")]
fn test_random() {
// not sure how to test this aside from just getting some values
let _n : usize = random();
let _f : f32 = random();
let _o : Option<Option<i8>> = random();
let _many : ((),
(usize,
isize,
Option<(u32, (bool,))>),
(u8, i8, u16, i16, u32, i32, u64, i64),
(f32, (f64, (f64,)))) = random();
let _n: usize = random();
let _f: f32 = random();
let _o: Option<Option<i8>> = random();
let _many: (
(),
(usize, isize, Option<(u32, (bool,))>),
(u8, i8, u16, i16, u32, i32, u64, i64),
(f32, (f64, (f64,))),
) = random();
}
#[test]
#[cfg(not(miri))] // Miri is too slow
#[cfg_attr(miri, ignore)] // Miri is too slow
fn test_gen_ratio_average() {
const NUM: u32 = 3;
const DENOM: u32 = 10;
@ -711,7 +717,7 @@ mod test {
}
}
// Have Binomial(N, NUM/DENOM) distribution
let expected = (NUM * N) / DENOM; // exact integer
let expected = (NUM * N) / DENOM; // exact integer
assert!(((sum - expected) as i32).abs() < 500);
}
}

17
third_party/rust/rand/src/prelude.rs поставляемый
Просмотреть файл

@ -19,10 +19,15 @@
//! ```
#[doc(no_inline)] pub use crate::distributions::Distribution;
#[cfg(feature = "small_rng")]
#[doc(no_inline)]
pub use crate::rngs::SmallRng;
#[doc(no_inline)] pub use crate::rngs::StdRng;
#[cfg(feature="small_rng")]
#[doc(no_inline)] pub use crate::rngs::SmallRng;
#[doc(no_inline)] #[cfg(feature="std")] pub use crate::rngs::ThreadRng;
#[doc(no_inline)] pub use crate::{Rng, RngCore, CryptoRng, SeedableRng};
#[doc(no_inline)] #[cfg(feature="std")] pub use crate::{random, thread_rng};
#[doc(no_inline)] pub use crate::seq::{SliceRandom, IteratorRandom};
#[doc(no_inline)]
#[cfg(feature = "std")]
pub use crate::rngs::ThreadRng;
#[doc(no_inline)] pub use crate::seq::{IteratorRandom, SliceRandom};
#[doc(no_inline)]
#[cfg(feature = "std")]
pub use crate::{random, thread_rng};
#[doc(no_inline)] pub use crate::{CryptoRng, Rng, RngCore, SeedableRng};

Просмотреть файл

@ -8,8 +8,8 @@
//! Wrappers / adapters forming RNGs
#[cfg(feature="std")] mod read;
#[cfg(feature = "std")] mod read;
mod reseeding;
#[cfg(feature="std")] pub use self::read::{ReadRng, ReadError};
#[cfg(feature = "std")] pub use self::read::{ReadError, ReadRng};
pub use self::reseeding::ReseedingRng;

Просмотреть файл

@ -9,10 +9,10 @@
//! A wrapper around any Read to treat it as an RNG.
use std::io::Read;
use std::fmt;
use std::io::Read;
use rand_core::{RngCore, Error, impls};
use rand_core::{impls, Error, RngCore};
/// An RNG that reads random bytes straight from any type supporting
@ -45,15 +45,13 @@ use rand_core::{RngCore, Error, impls};
/// [`try_fill_bytes`]: RngCore::try_fill_bytes
#[derive(Debug)]
pub struct ReadRng<R> {
reader: R
reader: R,
}
impl<R: Read> ReadRng<R> {
/// Create a new `ReadRng` from a `Read`.
pub fn new(r: R) -> ReadRng<R> {
ReadRng {
reader: r
}
ReadRng { reader: r }
}
}
@ -67,14 +65,22 @@ impl<R: Read> RngCore for ReadRng<R> {
}
fn fill_bytes(&mut self, dest: &mut [u8]) {
self.try_fill_bytes(dest).unwrap_or_else(|err|
panic!("reading random bytes from Read implementation failed; error: {}", err));
self.try_fill_bytes(dest).unwrap_or_else(|err| {
panic!(
"reading random bytes from Read implementation failed; error: {}",
err
)
});
}
fn try_fill_bytes(&mut self, dest: &mut [u8]) -> Result<(), Error> {
if dest.is_empty() { return Ok(()); }
if dest.is_empty() {
return Ok(());
}
// Use `std::io::read_exact`, which retries on `ErrorKind::Interrupted`.
self.reader.read_exact(dest).map_err(|e| Error::new(ReadError(e)))
self.reader
.read_exact(dest)
.map_err(|e| Error::new(ReadError(e)))
}
}
@ -103,6 +109,7 @@ mod test {
#[test]
fn test_reader_rng_u64() {
// transmute from the target to avoid endianness concerns.
#[rustfmt::skip]
let v = vec![0u8, 0, 0, 0, 0, 0, 0, 1,
0 , 0, 0, 0, 0, 0, 0, 2,
0, 0, 0, 0, 0, 0, 0, 3];

Просмотреть файл

@ -12,8 +12,8 @@
use core::mem::size_of;
use rand_core::{RngCore, CryptoRng, SeedableRng, Error};
use rand_core::block::{BlockRngCore, BlockRng};
use rand_core::block::{BlockRng, BlockRngCore};
use rand_core::{CryptoRng, Error, RngCore, SeedableRng};
/// A wrapper around any PRNG that implements [`BlockRngCore`], that adds the
/// ability to reseed it.
@ -77,12 +77,14 @@ use rand_core::block::{BlockRngCore, BlockRng};
/// [`reseed()`]: ReseedingRng::reseed
#[derive(Debug)]
pub struct ReseedingRng<R, Rsdr>(BlockRng<ReseedingCore<R, Rsdr>>)
where R: BlockRngCore + SeedableRng,
Rsdr: RngCore;
where
R: BlockRngCore + SeedableRng,
Rsdr: RngCore;
impl<R, Rsdr> ReseedingRng<R, Rsdr>
where R: BlockRngCore + SeedableRng,
Rsdr: RngCore
where
R: BlockRngCore + SeedableRng,
Rsdr: RngCore,
{
/// Create a new `ReseedingRng` from an existing PRNG, combined with a RNG
/// to use as reseeder.
@ -103,8 +105,9 @@ where R: BlockRngCore + SeedableRng,
// TODO: this should be implemented for any type where the inner type
// implements RngCore, but we can't specify that because ReseedingCore is private
impl<R, Rsdr: RngCore> RngCore for ReseedingRng<R, Rsdr>
where R: BlockRngCore<Item = u32> + SeedableRng,
<R as BlockRngCore>::Results: AsRef<[u32]> + AsMut<[u32]>
where
R: BlockRngCore<Item = u32> + SeedableRng,
<R as BlockRngCore>::Results: AsRef<[u32]> + AsMut<[u32]>,
{
#[inline(always)]
fn next_u32(&mut self) -> u32 {
@ -126,8 +129,9 @@ where R: BlockRngCore<Item = u32> + SeedableRng,
}
impl<R, Rsdr> Clone for ReseedingRng<R, Rsdr>
where R: BlockRngCore + SeedableRng + Clone,
Rsdr: RngCore + Clone
where
R: BlockRngCore + SeedableRng + Clone,
Rsdr: RngCore + Clone,
{
fn clone(&self) -> ReseedingRng<R, Rsdr> {
// Recreating `BlockRng` seems easier than cloning it and resetting
@ -137,8 +141,11 @@ where R: BlockRngCore + SeedableRng + Clone,
}
impl<R, Rsdr> CryptoRng for ReseedingRng<R, Rsdr>
where R: BlockRngCore + SeedableRng + CryptoRng,
Rsdr: RngCore + CryptoRng {}
where
R: BlockRngCore + SeedableRng + CryptoRng,
Rsdr: RngCore + CryptoRng,
{
}
#[derive(Debug)]
struct ReseedingCore<R, Rsdr> {
@ -150,16 +157,16 @@ struct ReseedingCore<R, Rsdr> {
}
impl<R, Rsdr> BlockRngCore for ReseedingCore<R, Rsdr>
where R: BlockRngCore + SeedableRng,
Rsdr: RngCore
where
R: BlockRngCore + SeedableRng,
Rsdr: RngCore,
{
type Item = <R as BlockRngCore>::Item;
type Results = <R as BlockRngCore>::Results;
fn generate(&mut self, results: &mut Self::Results) {
let global_fork_counter = fork::get_fork_counter();
if self.bytes_until_reseed <= 0 ||
self.is_forked(global_fork_counter) {
if self.bytes_until_reseed <= 0 || self.is_forked(global_fork_counter) {
// We get better performance by not calling only `reseed` here
// and continuing with the rest of the function, but by directly
// returning from a non-inlined function.
@ -172,8 +179,9 @@ where R: BlockRngCore + SeedableRng,
}
impl<R, Rsdr> ReseedingCore<R, Rsdr>
where R: BlockRngCore + SeedableRng,
Rsdr: RngCore
where
R: BlockRngCore + SeedableRng,
Rsdr: RngCore,
{
/// Create a new `ReseedingCore`.
fn new(rng: R, threshold: u64, reseeder: Rsdr) -> Self {
@ -184,10 +192,13 @@ where R: BlockRngCore + SeedableRng,
// current hardware, we just clamp to that value.
// Also we set a threshold of 0, which indicates no limit, to that
// value.
let threshold =
if threshold == 0 { MAX }
else if threshold <= MAX as u64 { threshold as i64 }
else { MAX };
let threshold = if threshold == 0 {
MAX
} else if threshold <= MAX as u64 {
threshold as i64
} else {
MAX
};
ReseedingCore {
inner: rng,
@ -221,19 +232,17 @@ where R: BlockRngCore + SeedableRng,
}
#[inline(never)]
fn reseed_and_generate(&mut self,
results: &mut <Self as BlockRngCore>::Results,
global_fork_counter: usize)
{
#![allow(clippy::if_same_then_else)] // false positive
fn reseed_and_generate(
&mut self, results: &mut <Self as BlockRngCore>::Results, global_fork_counter: usize,
) {
#![allow(clippy::if_same_then_else)] // false positive
if self.is_forked(global_fork_counter) {
info!("Fork detected, reseeding RNG");
} else {
trace!("Reseeding RNG (periodic reseed)");
}
let num_bytes =
results.as_ref().len() * size_of::<<R as BlockRngCore>::Item>();
let num_bytes = results.as_ref().len() * size_of::<<R as BlockRngCore>::Item>();
if let Err(e) = self.reseed() {
warn!("Reseeding RNG failed: {}", e);
@ -247,8 +256,9 @@ where R: BlockRngCore + SeedableRng,
}
impl<R, Rsdr> Clone for ReseedingCore<R, Rsdr>
where R: BlockRngCore + SeedableRng + Clone,
Rsdr: RngCore + Clone
where
R: BlockRngCore + SeedableRng + Clone,
Rsdr: RngCore + Clone,
{
fn clone(&self) -> ReseedingCore<R, Rsdr> {
ReseedingCore {
@ -262,15 +272,17 @@ where R: BlockRngCore + SeedableRng + Clone,
}
impl<R, Rsdr> CryptoRng for ReseedingCore<R, Rsdr>
where R: BlockRngCore + SeedableRng + CryptoRng,
Rsdr: RngCore + CryptoRng {}
where
R: BlockRngCore + SeedableRng + CryptoRng,
Rsdr: RngCore + CryptoRng,
{
}
#[cfg(all(unix, not(target_os="emscripten")))]
#[cfg(all(unix, feature = "std", not(target_os = "emscripten")))]
mod fork {
use core::sync::atomic::{AtomicUsize, AtomicBool, Ordering};
#[allow(deprecated)] // Required for compatibility with Rust < 1.24.
use core::sync::atomic::{ATOMIC_USIZE_INIT, ATOMIC_BOOL_INIT};
use core::sync::atomic::{AtomicUsize, Ordering};
use std::sync::Once;
// Fork protection
//
@ -284,43 +296,41 @@ mod fork {
// don't update `fork_counter`, so a reseed is attempted as soon as
// possible.
#[allow(deprecated)]
static RESEEDING_RNG_FORK_COUNTER: AtomicUsize = ATOMIC_USIZE_INIT;
static RESEEDING_RNG_FORK_COUNTER: AtomicUsize = AtomicUsize::new(0);
pub fn get_fork_counter() -> usize {
RESEEDING_RNG_FORK_COUNTER.load(Ordering::Relaxed)
}
#[allow(deprecated)]
static FORK_HANDLER_REGISTERED: AtomicBool = ATOMIC_BOOL_INIT;
extern fn fork_handler() {
extern "C" fn fork_handler() {
// Note: fetch_add is defined to wrap on overflow
// (which is what we want).
RESEEDING_RNG_FORK_COUNTER.fetch_add(1, Ordering::Relaxed);
}
pub fn register_fork_handler() {
if !FORK_HANDLER_REGISTERED.load(Ordering::Relaxed) {
unsafe { libc::pthread_atfork(None, None, Some(fork_handler)) };
FORK_HANDLER_REGISTERED.store(true, Ordering::Relaxed);
}
static REGISTER: Once = Once::new();
REGISTER.call_once(|| unsafe {
libc::pthread_atfork(None, None, Some(fork_handler));
});
}
}
#[cfg(not(all(unix, not(target_os="emscripten"))))]
#[cfg(not(all(unix, feature = "std", not(target_os = "emscripten"))))]
mod fork {
pub fn get_fork_counter() -> usize { 0 }
pub fn get_fork_counter() -> usize {
0
}
pub fn register_fork_handler() {}
}
#[cfg(test)]
mod test {
use crate::{Rng, SeedableRng};
use crate::rngs::std::Core;
use crate::rngs::mock::StepRng;
use super::ReseedingRng;
use crate::rngs::mock::StepRng;
use crate::rngs::std::Core;
use crate::{Rng, SeedableRng};
#[test]
fn test_reseeding() {
@ -346,10 +356,12 @@ mod test {
fn test_clone_reseeding() {
let mut zero = StepRng::new(0, 0);
let rng = Core::from_rng(&mut zero).unwrap();
let mut rng1 = ReseedingRng::new(rng, 32*4, zero);
let mut rng1 = ReseedingRng::new(rng, 32 * 4, zero);
let first: u32 = rng1.gen();
for _ in 0..10 { let _ = rng1.gen::<u32>(); }
for _ in 0..10 {
let _ = rng1.gen::<u32>();
}
let mut rng2 = rng1.clone();
assert_eq!(first, rng2.gen::<u32>());

10
third_party/rust/rand/src/rngs/entropy.rs поставляемый
Просмотреть файл

@ -8,19 +8,19 @@
//! Entropy generator, or wrapper around external generators
#![allow(deprecated)] // whole module is deprecated
#![allow(deprecated)] // whole module is deprecated
use rand_core::{RngCore, CryptoRng, Error};
use crate::rngs::OsRng;
use rand_core::{CryptoRng, Error, RngCore};
/// An interface returning random data from external source(s), provided
/// specifically for securely seeding algorithmic generators (PRNGs).
///
/// This is deprecated. It is suggested you use [`rngs::OsRng`] instead.
///
///
/// [`rngs::OsRng`]: crate::rngs::OsRng
#[derive(Debug)]
#[deprecated(since="0.7.0", note="use rngs::OsRng instead")]
#[deprecated(since = "0.7.0", note = "use rngs::OsRng instead")]
pub struct EntropyRng {
source: OsRng,
}
@ -71,6 +71,6 @@ mod test {
fn test_entropy() {
let mut rng = EntropyRng::new();
let n = (rng.next_u32() ^ rng.next_u32()).count_ones();
assert!(n >= 2); // p(failure) approx 1e-7
assert!(n >= 2); // p(failure) approx 1e-7
}
}

13
third_party/rust/rand/src/rngs/mock.rs поставляемый
Просмотреть файл

@ -8,18 +8,18 @@
//! Mock random number generator
use rand_core::{RngCore, Error, impls};
use rand_core::{impls, Error, RngCore};
/// A simple implementation of `RngCore` for testing purposes.
///
///
/// This generates an arithmetic sequence (i.e. adds a constant each step)
/// over a `u64` number, using wrapping arithmetic. If the increment is 0
/// the generator yields a constant.
///
///
/// ```
/// use rand::Rng;
/// use rand::rngs::mock::StepRng;
///
///
/// let mut my_rng = StepRng::new(2, 1);
/// let sample: [u64; 3] = my_rng.gen();
/// assert_eq!(sample, [2, 3, 4]);
@ -34,7 +34,10 @@ impl StepRng {
/// Create a `StepRng`, yielding an arithmetic sequence starting with
/// `initial` and incremented by `increment` each time.
pub fn new(initial: u64, increment: u64) -> Self {
StepRng { v: initial, a: increment }
StepRng {
v: initial,
a: increment,
}
}
}

33
third_party/rust/rand/src/rngs/mod.rs поставляемый
Просмотреть файл

@ -84,13 +84,11 @@
//! Some suggestions are: [`rand_chacha`], [`rand_pcg`], [`rand_xoshiro`].
//! A full list can be found by searching for crates with the [`rng` tag].
//!
//! [`SmallRng`]: rngs::SmallRng
//! [`StdRng`]: rngs::StdRng
//! [`OsRng`]: rngs::OsRng
//! [`ThreadRng`]: rngs::ThreadRng
//! [`mock::StepRng`]: rngs::mock::StepRng
//! [`adapter::ReadRng`]: rngs::adapter::ReadRng
//! [`adapter::ReseedingRng`]: rngs::adapter::ReseedingRng
//! [`Rng`]: crate::Rng
//! [`RngCore`]: crate::RngCore
//! [`CryptoRng`]: crate::CryptoRng
//! [`SeedableRng`]: crate::SeedableRng
//! [`thread_rng`]: crate::thread_rng
//! [`rdrand`]: https://crates.io/crates/rdrand
//! [`rand_jitter`]: https://crates.io/crates/rand_jitter
//! [`rand_chacha`]: https://crates.io/crates/rand_chacha
@ -100,20 +98,19 @@
pub mod adapter;
#[cfg(feature="std")] mod entropy;
pub mod mock; // Public so we don't export `StepRng` directly, making it a bit
// more clear it is intended for testing.
#[cfg(feature="small_rng")]
mod small;
#[cfg(feature = "std")] mod entropy;
pub mod mock; // Public so we don't export `StepRng` directly, making it a bit
// more clear it is intended for testing.
#[cfg(feature = "small_rng")] mod small;
mod std;
#[cfg(feature="std")] pub(crate) mod thread;
#[cfg(feature = "std")] pub(crate) mod thread;
#[allow(deprecated)]
#[cfg(feature="std")] pub use self::entropy::EntropyRng;
#[cfg(feature = "std")]
pub use self::entropy::EntropyRng;
#[cfg(feature="small_rng")]
pub use self::small::SmallRng;
#[cfg(feature = "small_rng")] pub use self::small::SmallRng;
pub use self::std::StdRng;
#[cfg(feature="std")] pub use self::thread::ThreadRng;
#[cfg(feature = "std")] pub use self::thread::ThreadRng;
#[cfg(feature="getrandom")] pub use rand_core::OsRng;
#[cfg(feature = "getrandom")] pub use rand_core::OsRng;

8
third_party/rust/rand/src/rngs/small.rs поставляемый
Просмотреть файл

@ -8,7 +8,7 @@
//! A small fast RNG
use rand_core::{RngCore, SeedableRng, Error};
use rand_core::{Error, RngCore, SeedableRng};
#[cfg(all(not(target_os = "emscripten"), target_pointer_width = "64"))]
type Rng = rand_pcg::Pcg64Mcg;
@ -56,7 +56,6 @@ type Rng = rand_pcg::Pcg32;
/// efficient:
///
/// ```
/// use std::iter;
/// use rand::{SeedableRng, thread_rng};
/// use rand::rngs::SmallRng;
///
@ -65,9 +64,8 @@ type Rng = rand_pcg::Pcg32;
/// let mut thread_rng = thread_rng();
/// // Create small, cheap to initialize and fast RNGs with random seeds.
/// // One can generally assume this won't fail.
/// let rngs: Vec<SmallRng> = iter::repeat(())
/// .map(|()| SmallRng::from_rng(&mut thread_rng).unwrap())
/// .take(10)
/// let rngs: Vec<SmallRng> = (0..10)
/// .map(|_| SmallRng::from_rng(&mut thread_rng).unwrap())
/// .collect();
/// ```
///

20
third_party/rust/rand/src/rngs/std.rs поставляемый
Просмотреть файл

@ -8,22 +8,21 @@
//! The standard RNG
use crate::{RngCore, CryptoRng, Error, SeedableRng};
use crate::{CryptoRng, Error, RngCore, SeedableRng};
#[cfg(all(any(test, feature = "std"), target_os = "emscripten"))]
pub(crate) use rand_hc::Hc128Core as Core;
#[cfg(all(any(test, feature = "std"), not(target_os = "emscripten")))]
pub(crate) use rand_chacha::ChaCha20Core as Core;
#[cfg(all(any(test, feature = "std"), target_os = "emscripten"))]
pub(crate) use rand_hc::Hc128Core as Core;
#[cfg(target_os = "emscripten")] use rand_hc::Hc128Rng as Rng;
#[cfg(not(target_os = "emscripten"))] use rand_chacha::ChaCha20Rng as Rng;
#[cfg(target_os = "emscripten")] use rand_hc::Hc128Rng as Rng;
/// The standard RNG. The PRNG algorithm in `StdRng` is chosen to be efficient
/// on the current platform, to be statistically strong and unpredictable
/// (meaning a cryptographically secure PRNG).
///
/// The current algorithm used is the ChaCha block cipher with either 20 or 12
/// rounds (see the `stdrng_*` feature flags, documented in the README).
/// The current algorithm used is the ChaCha block cipher with 20 rounds.
/// This may change as new evidence of cipher security and performance
/// becomes available.
///
@ -77,21 +76,22 @@ impl CryptoRng for StdRng {}
#[cfg(test)]
mod test {
use crate::{RngCore, SeedableRng};
use crate::rngs::StdRng;
use crate::{RngCore, SeedableRng};
#[test]
fn test_stdrng_construction() {
// Test value-stability of StdRng. This is expected to break any time
// the algorithm is changed.
#[rustfmt::skip]
let seed = [1,0,0,0, 23,0,0,0, 200,1,0,0, 210,30,0,0,
0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0];
#[cfg(any(feature="stdrng_strong", not(feature="stdrng_fast")))]
#[cfg(any(feature = "stdrng_strong", not(feature = "stdrng_fast")))]
let target = [3950704604716924505, 5573172343717151650];
#[cfg(all(not(feature="stdrng_strong"), feature="stdrng_fast"))]
#[cfg(all(not(feature = "stdrng_strong"), feature = "stdrng_fast"))]
let target = [10719222850664546238, 14064965282130556830];
let mut rng0 = StdRng::from_seed(seed);
let x0 = rng0.next_u64();

4
third_party/rust/rand/src/rngs/thread.rs поставляемый
Просмотреть файл

@ -11,10 +11,10 @@
use std::cell::UnsafeCell;
use std::ptr::NonNull;
use crate::{RngCore, CryptoRng, SeedableRng, Error};
use super::std::Core;
use crate::rngs::adapter::ReseedingRng;
use crate::rngs::OsRng;
use super::std::Core;
use crate::{CryptoRng, Error, RngCore, SeedableRng};
// Rationale for using `UnsafeCell` in `ThreadRng`:
//

101
third_party/rust/rand/src/seq/index.rs поставляемый
Просмотреть файл

@ -8,15 +8,18 @@
//! Low-level API for sampling indices
#[cfg(feature="alloc")] use core::slice;
#[cfg(feature = "alloc")] use core::slice;
#[cfg(feature="std")] use std::vec;
#[cfg(all(feature="alloc", not(feature="std")))] use crate::alloc::vec::{self, Vec};
#[cfg(all(feature = "alloc", not(feature = "std")))]
use crate::alloc::vec::{self, Vec};
#[cfg(feature = "std")] use std::vec;
// BTreeMap is not as fast in tests, but better than nothing.
#[cfg(feature="std")] use std::collections::{HashSet};
#[cfg(all(feature="alloc", not(feature="std")))] use crate::alloc::collections::BTreeSet;
#[cfg(all(feature = "alloc", not(feature = "std")))]
use crate::alloc::collections::BTreeSet;
#[cfg(feature = "std")] use std::collections::HashSet;
#[cfg(feature="alloc")] use crate::distributions::{Distribution, Uniform, uniform::SampleUniform};
#[cfg(feature = "alloc")]
use crate::distributions::{uniform::SampleUniform, Distribution, Uniform};
use crate::Rng;
/// A vector of indices.
@ -24,8 +27,10 @@ use crate::Rng;
/// Multiple internal representations are possible.
#[derive(Clone, Debug)]
pub enum IndexVec {
#[doc(hidden)] U32(Vec<u32>),
#[doc(hidden)] USize(Vec<usize>),
#[doc(hidden)]
U32(Vec<u32>),
#[doc(hidden)]
USize(Vec<usize>),
}
impl IndexVec {
@ -93,10 +98,12 @@ impl PartialEq for IndexVec {
match (self, other) {
(&U32(ref v1), &U32(ref v2)) => v1 == v2,
(&USize(ref v1), &USize(ref v2)) => v1 == v2,
(&U32(ref v1), &USize(ref v2)) => (v1.len() == v2.len())
&& (v1.iter().zip(v2.iter()).all(|(x, y)| *x as usize == *y)),
(&USize(ref v1), &U32(ref v2)) => (v1.len() == v2.len())
&& (v1.iter().zip(v2.iter()).all(|(x, y)| *x == *y as usize)),
(&U32(ref v1), &USize(ref v2)) => {
(v1.len() == v2.len()) && (v1.iter().zip(v2.iter()).all(|(x, y)| *x as usize == *y))
}
(&USize(ref v1), &U32(ref v2)) => {
(v1.len() == v2.len()) && (v1.iter().zip(v2.iter()).all(|(x, y)| *x == *y as usize))
}
}
}
}
@ -118,12 +125,15 @@ impl From<Vec<usize>> for IndexVec {
/// Return type of `IndexVec::iter`.
#[derive(Debug)]
pub enum IndexVecIter<'a> {
#[doc(hidden)] U32(slice::Iter<'a, u32>),
#[doc(hidden)] USize(slice::Iter<'a, usize>),
#[doc(hidden)]
U32(slice::Iter<'a, u32>),
#[doc(hidden)]
USize(slice::Iter<'a, usize>),
}
impl<'a> Iterator for IndexVecIter<'a> {
type Item = usize;
#[inline]
fn next(&mut self) -> Option<usize> {
use self::IndexVecIter::*;
@ -147,8 +157,10 @@ impl<'a> ExactSizeIterator for IndexVecIter<'a> {}
/// Return type of `IndexVec::into_iter`.
#[derive(Clone, Debug)]
pub enum IndexVecIntoIter {
#[doc(hidden)] U32(vec::IntoIter<u32>),
#[doc(hidden)] USize(vec::IntoIter<usize>),
#[doc(hidden)]
U32(vec::IntoIter<u32>),
#[doc(hidden)]
USize(vec::IntoIter<usize>),
}
impl Iterator for IndexVecIntoIter {
@ -216,7 +228,7 @@ where R: Rng + ?Sized {
// We do some calculations with f32. Accuracy is not very important.
if amount < 163 {
const C: [[f32; 2]; 2] = [[1.6, 8.0/45.0], [10.0, 70.0/9.0]];
const C: [[f32; 2]; 2] = [[1.6, 8.0 / 45.0], [10.0, 70.0 / 9.0]];
let j = if length < 500_000 { 0 } else { 1 };
let amount_fp = amount as f32;
let m4 = C[0][j] * amount_fp;
@ -227,7 +239,7 @@ where R: Rng + ?Sized {
sample_floyd(rng, length, amount)
}
} else {
const C: [f32; 2] = [270.0, 330.0/9.0];
const C: [f32; 2] = [270.0, 330.0 / 9.0];
let j = if length < 500_000 { 0 } else { 1 };
if (length as f32) < C[j] * (amount as f32) {
sample_inplace(rng, length, amount)
@ -252,7 +264,7 @@ where R: Rng + ?Sized {
debug_assert!(amount <= length);
let mut indices = Vec::with_capacity(amount as usize);
for j in length - amount .. length {
for j in length - amount..length {
let t = rng.gen_range(0, j + 1);
if floyd_shuffle {
if let Some(pos) = indices.iter().position(|&x| x == t) {
@ -306,12 +318,26 @@ trait UInt: Copy + PartialOrd + Ord + PartialEq + Eq + SampleUniform + core::has
fn as_usize(self) -> usize;
}
impl UInt for u32 {
#[inline] fn zero() -> Self { 0 }
#[inline] fn as_usize(self) -> usize { self as usize }
#[inline]
fn zero() -> Self {
0
}
#[inline]
fn as_usize(self) -> usize {
self as usize
}
}
impl UInt for usize {
#[inline] fn zero() -> Self { 0 }
#[inline] fn as_usize(self) -> usize { self }
#[inline]
fn zero() -> Self {
0
}
#[inline]
fn as_usize(self) -> usize {
self
}
}
/// Randomly sample exactly `amount` indices from `0..length`, using rejection
@ -320,14 +346,19 @@ impl UInt for usize {
/// Since `amount <<< length` there is a low chance of a random sample in
/// `0..length` being a duplicate. We test for duplicates and resample where
/// necessary. The algorithm is `O(amount)` time and memory.
///
///
/// This function is generic over X primarily so that results are value-stable
/// over 32-bit and 64-bit platforms.
fn sample_rejection<X: UInt, R>(rng: &mut R, length: X, amount: X) -> IndexVec
where R: Rng + ?Sized, IndexVec: From<Vec<X>> {
where
R: Rng + ?Sized,
IndexVec: From<Vec<X>>,
{
debug_assert!(amount < length);
#[cfg(feature="std")] let mut cache = HashSet::with_capacity(amount.as_usize());
#[cfg(not(feature="std"))] let mut cache = BTreeSet::new();
#[cfg(feature = "std")]
let mut cache = HashSet::with_capacity(amount.as_usize());
#[cfg(not(feature = "std"))]
let mut cache = BTreeSet::new();
let distr = Uniform::new(X::zero(), length);
let mut indices = Vec::with_capacity(amount.as_usize());
for _ in 0..amount.as_usize() {
@ -344,9 +375,9 @@ where R: Rng + ?Sized, IndexVec: From<Vec<X>> {
#[cfg(test)]
mod test {
#[cfg(feature="std")] use std::vec;
#[cfg(all(feature="alloc", not(feature="std")))] use crate::alloc::vec;
use super::*;
#[cfg(all(feature = "alloc", not(feature = "std")))] use crate::alloc::vec;
#[cfg(feature = "std")] use std::vec;
#[test]
fn test_sample_boundaries() {
@ -363,17 +394,15 @@ mod test {
assert_eq!(sample_floyd(&mut r, 1, 1).into_vec(), vec![0]);
// These algorithms should be fast with big numbers. Test average.
let sum: usize = sample_rejection(&mut r, 1 << 25, 10u32)
.into_iter().sum();
let sum: usize = sample_rejection(&mut r, 1 << 25, 10u32).into_iter().sum();
assert!(1 << 25 < sum && sum < (1 << 25) * 25);
let sum: usize = sample_floyd(&mut r, 1 << 25, 10)
.into_iter().sum();
let sum: usize = sample_floyd(&mut r, 1 << 25, 10).into_iter().sum();
assert!(1 << 25 < sum && sum < (1 << 25) * 25);
}
#[test]
#[cfg(not(miri))] // Miri is too slow
#[cfg_attr(miri, ignore)] // Miri is too slow
fn test_sample_alg() {
let seed_rng = crate::test::rng;
@ -393,14 +422,14 @@ mod test {
assert!(v1 != v3);
// A large length and small amount should use Floyd
let (length, amount): (usize, usize) = (1<<20, 50);
let (length, amount): (usize, usize) = (1 << 20, 50);
let v1 = sample(&mut seed_rng(421), length, amount);
let v2 = sample_floyd(&mut seed_rng(421), length as u32, amount as u32);
assert!(v1.iter().all(|e| e < length));
assert_eq!(v1, v2);
// A large length and larger amount should use cache
let (length, amount): (usize, usize) = (1<<20, 600);
let (length, amount): (usize, usize) = (1 << 20, 600);
let v1 = sample(&mut seed_rng(422), length, amount);
let v2 = sample_rejection(&mut seed_rng(422), length as u32, amount as u32);
assert!(v1.iter().all(|e| e < length));

177
third_party/rust/rand/src/seq/mod.rs поставляемый
Просмотреть файл

@ -7,42 +7,43 @@
// except according to those terms.
//! Sequence-related functionality
//!
//!
//! This module provides:
//!
//! * [`seq::SliceRandom`] slice sampling and mutation
//! * [`seq::IteratorRandom`] iterator sampling
//! * [`seq::index::sample`] low-level API to choose multiple indices from
//!
//! * [`SliceRandom`] slice sampling and mutation
//! * [`IteratorRandom`] iterator sampling
//! * [`index::sample`] low-level API to choose multiple indices from
//! `0..length`
//!
//!
//! Also see:
//!
//! * [`distributions::weighted`] module which provides implementations of
//! weighted index sampling.
//!
//!
//! * [`crate::distributions::weighted`] module which provides
//! implementations of weighted index sampling.
//!
//! In order to make results reproducible across 32-64 bit architectures, all
//! `usize` indices are sampled as a `u32` where possible (also providing a
//! small performance boost in some cases).
#[cfg(feature="alloc")] pub mod index;
#[cfg(feature = "alloc")] pub mod index;
#[cfg(feature="alloc")] use core::ops::Index;
#[cfg(feature = "alloc")] use core::ops::Index;
#[cfg(all(feature="alloc", not(feature="std")))] use crate::alloc::vec::Vec;
#[cfg(all(feature = "alloc", not(feature = "std")))] use crate::alloc::vec::Vec;
#[cfg(feature = "alloc")]
use crate::distributions::uniform::{SampleBorrow, SampleUniform};
#[cfg(feature = "alloc")] use crate::distributions::WeightedError;
use crate::Rng;
#[cfg(feature="alloc")] use crate::distributions::WeightedError;
#[cfg(feature="alloc")] use crate::distributions::uniform::{SampleUniform, SampleBorrow};
/// Extension trait on slices, providing random mutation and sampling methods.
///
///
/// This trait is implemented on all `[T]` slice types, providing several
/// methods for choosing and shuffling elements. You must `use` this trait:
///
///
/// ```
/// use rand::seq::SliceRandom;
///
///
/// fn main() {
/// let mut rng = rand::thread_rng();
/// let mut bytes = "Hello, random!".to_string().into_bytes();
@ -61,7 +62,7 @@ pub trait SliceRandom {
/// Returns a reference to one random element of the slice, or `None` if the
/// slice is empty.
///
///
/// For slices, complexity is `O(1)`.
///
/// # Example
@ -115,7 +116,7 @@ pub trait SliceRandom {
/// Similar to [`choose`], but where the likelihood of each outcome may be
/// specified.
///
///
/// The specified function `weight` maps each item `x` to a relative
/// likelihood `weight(x)`. The probability of each item being selected is
/// therefore `weight(x) / s`, where `s` is the sum of all `weight(x)`.
@ -152,7 +153,7 @@ pub trait SliceRandom {
/// Similar to [`choose_mut`], but where the likelihood of each outcome may
/// be specified.
///
///
/// The specified function `weight` maps each item `x` to a relative
/// likelihood `weight(x)`. The probability of each item being selected is
/// therefore `weight(x) / s`, where `s` is the sum of all `weight(x)`.
@ -220,13 +221,13 @@ pub trait SliceRandom {
}
/// Extension trait on iterators, providing random sampling methods.
///
///
/// This trait is implemented on all sized iterators, providing methods for
/// choosing one or more elements. You must `use` this trait:
///
///
/// ```
/// use rand::seq::IteratorRandom;
///
///
/// fn main() {
/// let mut rng = rand::thread_rng();
///
@ -240,7 +241,7 @@ pub trait SliceRandom {
/// ```
pub trait IteratorRandom: Iterator + Sized {
/// Choose one element at random from the iterator.
///
///
/// Returns `None` if and only if the iterator is empty.
///
/// This method uses [`Iterator::size_hint`] for optimisation. With an
@ -248,7 +249,7 @@ pub trait IteratorRandom: Iterator + Sized {
/// this method can offer `O(1)` performance. Where no size hint is
/// available, complexity is `O(n)` where `n` is the iterator length.
/// Partial hints (where `lower > 0`) also improve performance.
///
///
/// For slices, prefer [`SliceRandom::choose`] which guarantees `O(1)`
/// performance.
fn choose<R>(mut self, rng: &mut R) -> Option<Self::Item>
@ -258,7 +259,11 @@ pub trait IteratorRandom: Iterator + Sized {
let mut result = None;
if upper == Some(lower) {
return if lower == 0 { None } else { self.nth(gen_index(rng, lower)) };
return if lower == 0 {
None
} else {
self.nth(gen_index(rng, lower))
};
}
// Continue until the iterator is exhausted
@ -478,7 +483,7 @@ impl<I> IteratorRandom for I where I: Iterator + Sized {}
/// An iterator over multiple slice elements.
///
///
/// This struct is created by
/// [`SliceRandom::choose_multiple`](trait.SliceRandom.html#tymethod.choose_multiple).
#[cfg(feature = "alloc")]
@ -530,13 +535,14 @@ fn gen_index<R: Rng + ?Sized>(rng: &mut R, ubound: usize) -> usize {
mod test {
use super::*;
#[cfg(feature = "alloc")] use crate::Rng;
#[cfg(all(feature="alloc", not(feature="std")))]
use alloc::vec::Vec;
#[cfg(all(feature = "alloc", not(feature = "std")))] use alloc::vec::Vec;
#[test]
fn test_slice_choose() {
let mut r = crate::test::rng(107);
let chars = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n'];
let chars = [
'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n',
];
let mut chosen = [0i32; 14];
// The below all use a binomial distribution with n=1000, p=1/14.
// binocdf(40, 1000, 1/14) ~= 2e-5; 1-binocdf(106, ..) ~= 2e-5
@ -567,6 +573,7 @@ mod test {
}
impl<I: Iterator + Clone> Iterator for UnhintedIterator<I> {
type Item = I::Item;
fn next(&mut self) -> Option<Self::Item> {
self.iter.next()
}
@ -581,18 +588,25 @@ mod test {
}
impl<I: ExactSizeIterator + Iterator + Clone> Iterator for ChunkHintedIterator<I> {
type Item = I::Item;
fn next(&mut self) -> Option<Self::Item> {
if self.chunk_remaining == 0 {
self.chunk_remaining = ::core::cmp::min(self.chunk_size,
self.iter.len());
self.chunk_remaining = ::core::cmp::min(self.chunk_size, self.iter.len());
}
self.chunk_remaining = self.chunk_remaining.saturating_sub(1);
self.iter.next()
}
fn size_hint(&self) -> (usize, Option<usize>) {
(self.chunk_remaining,
if self.hint_total_size { Some(self.iter.len()) } else { None })
(
self.chunk_remaining,
if self.hint_total_size {
Some(self.iter.len())
} else {
None
},
)
}
}
@ -604,20 +618,28 @@ mod test {
}
impl<I: ExactSizeIterator + Iterator + Clone> Iterator for WindowHintedIterator<I> {
type Item = I::Item;
fn next(&mut self) -> Option<Self::Item> {
self.iter.next()
}
fn size_hint(&self) -> (usize, Option<usize>) {
(::core::cmp::min(self.iter.len(), self.window_size),
if self.hint_total_size { Some(self.iter.len()) } else { None })
(
::core::cmp::min(self.iter.len(), self.window_size),
if self.hint_total_size {
Some(self.iter.len())
} else {
None
},
)
}
}
#[test]
#[cfg(not(miri))] // Miri is too slow
#[cfg_attr(miri, ignore)] // Miri is too slow
fn test_iterator_choose() {
let r = &mut crate::test::rng(109);
fn test_iter<R: Rng + ?Sized, Iter: Iterator<Item=usize> + Clone>(r: &mut R, iter: Iter) {
fn test_iter<R: Rng + ?Sized, Iter: Iterator<Item = usize> + Clone>(r: &mut R, iter: Iter) {
let mut chosen = [0i32; 9];
for _ in 0..1000 {
let picked = iter.clone().choose(r).unwrap();
@ -627,7 +649,11 @@ mod test {
// Samples should follow Binomial(1000, 1/9)
// Octave: binopdf(x, 1000, 1/9) gives the prob of *count == x
// Note: have seen 153, which is unlikely but not impossible.
assert!(72 < *count && *count < 154, "count not close to 1000/9: {}", count);
assert!(
72 < *count && *count < 154,
"count not close to 1000/9: {}",
count
);
}
}
@ -636,17 +662,35 @@ mod test {
#[cfg(feature = "alloc")]
test_iter(r, (0..9).collect::<Vec<_>>().into_iter());
test_iter(r, UnhintedIterator { iter: 0..9 });
test_iter(r, ChunkHintedIterator { iter: 0..9, chunk_size: 4, chunk_remaining: 4, hint_total_size: false });
test_iter(r, ChunkHintedIterator { iter: 0..9, chunk_size: 4, chunk_remaining: 4, hint_total_size: true });
test_iter(r, WindowHintedIterator { iter: 0..9, window_size: 2, hint_total_size: false });
test_iter(r, WindowHintedIterator { iter: 0..9, window_size: 2, hint_total_size: true });
test_iter(r, ChunkHintedIterator {
iter: 0..9,
chunk_size: 4,
chunk_remaining: 4,
hint_total_size: false,
});
test_iter(r, ChunkHintedIterator {
iter: 0..9,
chunk_size: 4,
chunk_remaining: 4,
hint_total_size: true,
});
test_iter(r, WindowHintedIterator {
iter: 0..9,
window_size: 2,
hint_total_size: false,
});
test_iter(r, WindowHintedIterator {
iter: 0..9,
window_size: 2,
hint_total_size: true,
});
assert_eq!((0..0).choose(r), None);
assert_eq!(UnhintedIterator{ iter: 0..0 }.choose(r), None);
assert_eq!(UnhintedIterator { iter: 0..0 }.choose(r), None);
}
#[test]
#[cfg(not(miri))] // Miri is too slow
#[cfg_attr(miri, ignore)] // Miri is too slow
fn test_shuffle() {
let mut r = crate::test::rng(108);
let empty: &mut [isize] = &mut [];
@ -694,15 +738,15 @@ mod test {
assert!(352 <= *count && *count <= 483, "count: {}", count);
}
}
#[test]
fn test_partial_shuffle() {
let mut r = crate::test::rng(118);
let mut empty: [u32; 0] = [];
let res = empty.partial_shuffle(&mut r, 10);
assert_eq!((res.0.len(), res.1.len()), (0, 0));
let mut v = [1, 2, 3, 4, 5];
let res = v.partial_shuffle(&mut r, 2);
assert_eq!((res.0.len(), res.1.len()), (2, 3));
@ -727,14 +771,14 @@ mod test {
// no randomization happens when amount >= len
assert_eq!(large_sample, vals.iter().collect::<Vec<_>>());
assert!(small_sample.iter().all(|e| {
**e >= min_val && **e <= max_val
}));
assert!(small_sample
.iter()
.all(|e| { **e >= min_val && **e <= max_val }));
}
#[test]
#[cfg(feature = "alloc")]
#[cfg(not(miri))] // Miri is too slow
#[cfg_attr(miri, ignore)] // Miri is too slow
fn test_weighted() {
let mut r = crate::test::rng(406);
const N_REPS: u32 = 3000;
@ -782,10 +826,25 @@ mod test {
// Check error cases
let empty_slice = &mut [10][0..0];
assert_eq!(empty_slice.choose_weighted(&mut r, |_| 1), Err(WeightedError::NoItem));
assert_eq!(empty_slice.choose_weighted_mut(&mut r, |_| 1), Err(WeightedError::NoItem));
assert_eq!(['x'].choose_weighted_mut(&mut r, |_| 0), Err(WeightedError::AllWeightsZero));
assert_eq!([0, -1].choose_weighted_mut(&mut r, |x| *x), Err(WeightedError::InvalidWeight));
assert_eq!([-1, 0].choose_weighted_mut(&mut r, |x| *x), Err(WeightedError::InvalidWeight));
assert_eq!(
empty_slice.choose_weighted(&mut r, |_| 1),
Err(WeightedError::NoItem)
);
assert_eq!(
empty_slice.choose_weighted_mut(&mut r, |_| 1),
Err(WeightedError::NoItem)
);
assert_eq!(
['x'].choose_weighted_mut(&mut r, |_| 0),
Err(WeightedError::AllWeightsZero)
);
assert_eq!(
[0, -1].choose_weighted_mut(&mut r, |x| *x),
Err(WeightedError::InvalidWeight)
);
assert_eq!(
[-1, 0].choose_weighted_mut(&mut r, |x| *x),
Err(WeightedError::InvalidWeight)
);
}
}

Просмотреть файл

@ -1 +1 @@
{"files":{"CHANGELOG.md":"f4db0c6a73be9b43000a8cbd77b357db26b6021d24b8820170510ca533e4788d","COPYRIGHT":"90eb64f0279b0d9432accfa6023ff803bc4965212383697eee27a0f426d5f8d5","Cargo.toml":"16dfc2309bba54b46dde69b242dc2af8096104076f34748b808259dbf181d2cd","LICENSE-APACHE":"aaff376532ea30a0cd5330b9502ad4a4c8bf769c539c87ffe78819d188a18ebf","LICENSE-MIT":"209fbbe0ad52d9235e37badf9cadfe4dbdc87203179c0899e738b39ade42177b","README.md":"5b6d753b28e14cc08a25aaa56c941f038c0e3d8e340129492c3e2824401bdd66","src/chacha.rs":"b16ca319071ac4e83474e6a6c749d0ab7ef1df47a3bdba72bb8b566d9d4f598d","src/lib.rs":"01a10cc42b0a0d61308f0e5706c8a02f345271b744fc5f238e36b4a61127ad6e"},"package":"03a2a90da8c7523f554344f921aa97283eadf6ac484a6d2a7d0212fa7f8d6853"}
{"files":{"CHANGELOG.md":"cfa5a57b442ab6da8e03c4b5f82e63a74c97a999edfbf7841646d4612f399206","COPYRIGHT":"90eb64f0279b0d9432accfa6023ff803bc4965212383697eee27a0f426d5f8d5","Cargo.toml":"254d87eb2174bd4375fba1b2818d7295d558721582af12f600241da250250310","LICENSE-APACHE":"aaff376532ea30a0cd5330b9502ad4a4c8bf769c539c87ffe78819d188a18ebf","LICENSE-MIT":"209fbbe0ad52d9235e37badf9cadfe4dbdc87203179c0899e738b39ade42177b","README.md":"5b6d753b28e14cc08a25aaa56c941f038c0e3d8e340129492c3e2824401bdd66","src/chacha.rs":"1ce534f0a3c6d3cd86aa077a56feb72969cbe4d37237ef6c698623a768a48f7f","src/guts.rs":"e8ff037f9461cdbdd8338927acfdef1497b11fa695fdd4247ec7f081bb5f459f","src/lib.rs":"a27fe2bff676a764d43d604a20cf30a41dc1c5ef4053eb41129d2479f5ae83fe"},"package":"f4c8ed856279c9737206bf725bf36935d8666ead7aa69b52be55af369d193402"}

4
third_party/rust/rand_chacha/CHANGELOG.md поставляемый
Просмотреть файл

@ -4,6 +4,10 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/)
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## [0.2.2] - 2020-03-09
- Integrate `c2-chacha`, reducing dependency count (#931)
- Add CryptoRng to ChaChaXCore (#944)
## [0.2.1] - 2019-07-22
- Force enable the `simd` feature of `c2-chacha` (#845)

10
third_party/rust/rand_chacha/Cargo.toml поставляемый
Просмотреть файл

@ -13,7 +13,7 @@
[package]
edition = "2018"
name = "rand_chacha"
version = "0.2.1"
version = "0.2.2"
authors = ["The Rand Project Developers", "The Rust Project Developers", "The CryptoCorrosion Contributors"]
description = "ChaCha random number generator\n"
homepage = "https://crates.io/crates/rand_chacha"
@ -21,10 +21,10 @@ documentation = "https://rust-random.github.io/rand/rand_chacha/"
readme = "README.md"
keywords = ["random", "rng", "chacha"]
categories = ["algorithms", "no-std"]
license = "MIT/Apache-2.0"
license = "MIT OR Apache-2.0"
repository = "https://github.com/rust-random/rand"
[dependencies.c2-chacha]
version = "0.2.2"
[dependencies.ppv-lite86]
version = "0.2.6"
features = ["simd"]
default-features = false
@ -34,7 +34,7 @@ version = "0.5"
[features]
default = ["std", "simd"]
simd = []
std = ["c2-chacha/std"]
std = ["ppv-lite86/std"]
[badges.appveyor]
repository = "rust-random/rand"

39
third_party/rust/rand_chacha/src/chacha.rs поставляемый
Просмотреть файл

@ -8,13 +8,11 @@
//! The ChaCha random number generator.
#[cfg(feature = "std")]
use std as core;
#[cfg(not(feature = "std"))]
use core;
#[cfg(not(feature = "std"))] use core;
#[cfg(feature = "std")] use std as core;
use c2_chacha::guts::ChaCha;
use self::core::fmt;
use crate::guts::ChaCha;
use rand_core::block::{BlockRng, BlockRngCore};
use rand_core::{CryptoRng, Error, RngCore, SeedableRng};
@ -22,16 +20,21 @@ const STREAM_PARAM_NONCE: u32 = 1;
const STREAM_PARAM_BLOCK: u32 = 0;
pub struct Array64<T>([T; 64]);
impl<T> Default for Array64<T> where T: Default {
impl<T> Default for Array64<T>
where T: Default
{
#[rustfmt::skip]
fn default() -> Self {
Self([T::default(), T::default(), T::default(), T::default(), T::default(), T::default(), T::default(), T::default(),
T::default(), T::default(), T::default(), T::default(), T::default(), T::default(), T::default(), T::default(),
T::default(), T::default(), T::default(), T::default(), T::default(), T::default(), T::default(), T::default(),
T::default(), T::default(), T::default(), T::default(), T::default(), T::default(), T::default(), T::default(),
T::default(), T::default(), T::default(), T::default(), T::default(), T::default(), T::default(), T::default(),
T::default(), T::default(), T::default(), T::default(), T::default(), T::default(), T::default(), T::default(),
T::default(), T::default(), T::default(), T::default(), T::default(), T::default(), T::default(), T::default(),
T::default(), T::default(), T::default(), T::default(), T::default(), T::default(), T::default(), T::default()])
Self([
T::default(), T::default(), T::default(), T::default(), T::default(), T::default(), T::default(), T::default(),
T::default(), T::default(), T::default(), T::default(), T::default(), T::default(), T::default(), T::default(),
T::default(), T::default(), T::default(), T::default(), T::default(), T::default(), T::default(), T::default(),
T::default(), T::default(), T::default(), T::default(), T::default(), T::default(), T::default(), T::default(),
T::default(), T::default(), T::default(), T::default(), T::default(), T::default(), T::default(), T::default(),
T::default(), T::default(), T::default(), T::default(), T::default(), T::default(), T::default(), T::default(),
T::default(), T::default(), T::default(), T::default(), T::default(), T::default(), T::default(), T::default(),
T::default(), T::default(), T::default(), T::default(), T::default(), T::default(), T::default(), T::default(),
])
}
}
impl<T> AsRef<[T]> for Array64<T> {
@ -44,7 +47,9 @@ impl<T> AsMut<[T]> for Array64<T> {
&mut self.0
}
}
impl<T> Clone for Array64<T> where T: Copy + Default {
impl<T> Clone for Array64<T>
where T: Copy + Default
{
fn clone(&self) -> Self {
let mut new = Self::default();
new.0.copy_from_slice(&self.0);
@ -79,7 +84,7 @@ macro_rules! chacha_impl {
fn generate(&mut self, r: &mut Self::Results) {
// Fill slice of words by writing to equivalent slice of bytes, then fixing endianness.
self.state.refill4($rounds, unsafe {
core::mem::transmute::<&mut Array64<u32>, &mut [u8; 256]>(&mut *r)
&mut *(&mut *r as *mut Array64<u32> as *mut [u8; 256])
});
for x in r.as_mut() {
*x = x.to_le();
@ -95,6 +100,8 @@ macro_rules! chacha_impl {
}
}
impl CryptoRng for $ChaChaXCore {}
/// A cryptographically secure random number generator that uses the ChaCha algorithm.
///
/// ChaCha is a stream cipher designed by Daniel J. Bernstein[^1], that we use as an RNG. It is

Просмотреть файл

@ -1,5 +1,15 @@
#[cfg(feature = "rustcrypto_api")]
pub use stream_cipher::generic_array;
// Copyright 2019 The CryptoCorrosion Contributors
// Copyright 2020 Developers of the Rand project.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
//! The ChaCha random number generator.
use ppv_lite86::{dispatch, dispatch_light128};
pub use ppv_lite86::Machine;
use ppv_lite86::{vec128_storage, ArithOps, BitOps32, LaneWords4, MultiLane, StoreBytes, Vec4};
@ -66,60 +76,12 @@ impl ChaCha {
((d.extract(1) as u64) << 32) | d.extract(0) as u64
}
/// Set 64-bit block count, affecting next refill.
#[inline(always)]
pub(crate) fn seek64<M: Machine>(&mut self, m: M, blockct: u64) {
let d: M::u32x4 = m.unpack(self.d);
self.d = d
.insert((blockct >> 32) as u32, 1)
.insert(blockct as u32, 0)
.into();
}
/// Set 32-bit block count, affecting next refill.
#[inline(always)]
pub(crate) fn seek32<M: Machine>(&mut self, m: M, blockct: u32) {
let d: M::u32x4 = m.unpack(self.d);
self.d = d.insert(blockct, 0).into();
}
/// Produce output from the current state.
#[inline(always)]
fn output_narrow<M: Machine>(&mut self, m: M, x: State<M::u32x4>, out: &mut [u8; BLOCK]) {
let k = m.vec([0x6170_7865, 0x3320_646e, 0x7962_2d32, 0x6b20_6574]);
(x.a + k).write_le(&mut out[0..16]);
(x.b + m.unpack(self.b)).write_le(&mut out[16..32]);
(x.c + m.unpack(self.c)).write_le(&mut out[32..48]);
(x.d + m.unpack(self.d)).write_le(&mut out[48..64]);
}
/// Add one to the block counter (no overflow check).
#[inline(always)]
fn inc_block_ct<M: Machine>(&mut self, m: M) {
let mut pos = self.pos64(m);
let d0: M::u32x4 = m.unpack(self.d);
pos += 1;
let d1 = d0.insert((pos >> 32) as u32, 1).insert(pos as u32, 0);
self.d = d1.into();
}
/// Produce 4 blocks of output, advancing the state
#[inline(always)]
pub fn refill4(&mut self, drounds: u32, out: &mut [u8; BUFSZ]) {
refill_wide(self, drounds, out)
}
/// Produce a block of output, advancing the state
#[inline(always)]
pub fn refill(&mut self, drounds: u32, out: &mut [u8; BLOCK]) {
refill_narrow(self, drounds, out)
}
#[inline(always)]
pub(crate) fn refill_rounds(&mut self, drounds: u32) -> State<vec128_storage> {
refill_narrow_rounds(self, drounds)
}
#[inline(always)]
pub fn set_stream_param(&mut self, param: u32, value: u64) {
set_stream_param(self, param, value)
@ -133,10 +95,7 @@ impl ChaCha {
#[inline(always)]
fn refill_wide_impl<Mach: Machine>(
m: Mach,
state: &mut ChaCha,
drounds: u32,
out: &mut [u8; BUFSZ],
m: Mach, state: &mut ChaCha, drounds: u32, out: &mut [u8; BUFSZ],
) {
let k = m.vec([0x6170_7865, 0x3320_646e, 0x7962_2d32, 0x6b20_6574]);
let mut pos = state.pos64(m);
@ -196,23 +155,8 @@ dispatch!(m, Mach, {
}
});
/// Refill the buffer from a single-block round, updating the block count.
dispatch_light128!(m, Mach, {
fn refill_narrow(state: &mut ChaCha, drounds: u32, out: &mut [u8; BLOCK]) {
let x = refill_narrow_rounds(state, drounds);
let x = State {
a: m.unpack(x.a),
b: m.unpack(x.b),
c: m.unpack(x.c),
d: m.unpack(x.d),
};
state.output_narrow(m, x, out);
state.inc_block_ct(m);
}
});
/// Single-block, rounds-only; shared by try_apply_keystream for tails shorter than BUFSZ
/// and XChaCha's setup step.
// Single-block, rounds-only; shared by try_apply_keystream for tails shorter than BUFSZ
// and XChaCha's setup step.
dispatch!(m, Mach, {
fn refill_narrow_rounds(state: &mut ChaCha, drounds: u32) -> State<vec128_storage> {
let k: Mach::u32x4 = m.vec([0x6170_7865, 0x3320_646e, 0x7962_2d32, 0x6b20_6574]);

15
third_party/rust/rand_chacha/src/lib.rs поставляемый
Просмотреть файл

@ -8,21 +8,24 @@
//! The ChaCha random number generator.
#![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk.png",
html_favicon_url = "https://www.rust-lang.org/favicon.ico",
html_root_url = "https://rust-random.github.io/rand/")]
#![doc(
html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk.png",
html_favicon_url = "https://www.rust-lang.org/favicon.ico",
html_root_url = "https://rust-random.github.io/rand/"
)]
#![deny(missing_docs)]
#![deny(missing_debug_implementations)]
#![doc(test(attr(allow(unused_variables), deny(warnings))))]
#![cfg_attr(not(feature = "std"), no_std)]
pub use rand_core;
mod chacha;
mod guts;
pub use crate::chacha::{ChaCha12Core, ChaCha12Rng, ChaCha20Core, ChaCha20Rng, ChaCha8Core, ChaCha8Rng};
pub use crate::chacha::{
ChaCha12Core, ChaCha12Rng, ChaCha20Core, ChaCha20Rng, ChaCha8Core, ChaCha8Rng,
};
/// ChaCha with 20 rounds
pub type ChaChaRng = ChaCha20Rng;