Implement MappedShuffle for tracking the permutation of an array

This commit is contained in:
Jack Grigg
2016-10-18 00:20:47 -05:00
parent 1218603f73
commit 0382417fee
3 changed files with 59 additions and 0 deletions

View File

@@ -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
View 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);
}

View File

@@ -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