Implement MappedShuffle for tracking the permutation of an array
This commit is contained in:
@@ -17,6 +17,7 @@ zcash_gtest_SOURCES = \
|
||||
gtest/test_noteencryption.cpp \
|
||||
gtest/test_merkletree.cpp \
|
||||
gtest/test_pow.cpp \
|
||||
gtest/test_random.cpp \
|
||||
gtest/test_rpc.cpp \
|
||||
gtest/test_circuit.cpp \
|
||||
gtest/test_txid.cpp \
|
||||
|
||||
34
src/gtest/test_random.cpp
Normal file
34
src/gtest/test_random.cpp
Normal file
@@ -0,0 +1,34 @@
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include "random.h"
|
||||
|
||||
int GenZero(int n)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int GenMax(int n)
|
||||
{
|
||||
return n-1;
|
||||
}
|
||||
|
||||
TEST(Random, MappedShuffle) {
|
||||
std::vector<int> a {8, 4, 6, 3, 5};
|
||||
std::vector<int> m {0, 1, 2, 3, 4};
|
||||
|
||||
auto a1 = a;
|
||||
auto m1 = m;
|
||||
MappedShuffle(a1.begin(), m1.begin(), a1.size(), GenZero);
|
||||
std::vector<int> ea1 {4, 6, 3, 5, 8};
|
||||
std::vector<int> em1 {1, 2, 3, 4, 0};
|
||||
EXPECT_EQ(ea1, a1);
|
||||
EXPECT_EQ(em1, m1);
|
||||
|
||||
auto a2 = a;
|
||||
auto m2 = m;
|
||||
MappedShuffle(a2.begin(), m2.begin(), a2.size(), GenMax);
|
||||
std::vector<int> ea2 {8, 4, 6, 3, 5};
|
||||
std::vector<int> em2 {0, 1, 2, 3, 4};
|
||||
EXPECT_EQ(ea2, a2);
|
||||
EXPECT_EQ(em2, m2);
|
||||
}
|
||||
24
src/random.h
24
src/random.h
@@ -8,6 +8,7 @@
|
||||
|
||||
#include "uint256.h"
|
||||
|
||||
#include <functional>
|
||||
#include <stdint.h>
|
||||
|
||||
/**
|
||||
@@ -24,6 +25,29 @@ uint64_t GetRand(uint64_t nMax);
|
||||
int GetRandInt(int nMax);
|
||||
uint256 GetRandHash();
|
||||
|
||||
/**
|
||||
* Rearranges the elements in the range [first,first+len) randomly, assuming
|
||||
* that gen is a uniform random number generator. Follows the same algorithm as
|
||||
* std::shuffle in C++11 (a Durstenfeld shuffle).
|
||||
*
|
||||
* The elements in the range [mapFirst,mapFirst+len) are rearranged according to
|
||||
* the same permutation, enabling the permutation to be tracked by the caller.
|
||||
*
|
||||
* gen takes an integer n and produces a uniform random output in [0,n).
|
||||
*/
|
||||
template <typename RandomAccessIterator, typename MapRandomAccessIterator>
|
||||
void MappedShuffle(RandomAccessIterator first,
|
||||
MapRandomAccessIterator mapFirst,
|
||||
size_t len,
|
||||
std::function<int(int)> gen)
|
||||
{
|
||||
for (size_t i = len-1; i > 0; --i) {
|
||||
auto r = gen(i+1);
|
||||
std::swap(first[i], first[r]);
|
||||
std::swap(mapFirst[i], mapFirst[r]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Seed insecure_rand using the random pool.
|
||||
* @param Deterministic Use a deterministic seed
|
||||
|
||||
Reference in New Issue
Block a user