Browse Source

Implement MappedShuffle for tracking the permutation of an array

pull/4/head
Jack Grigg 8 years ago
parent
commit
0382417fee
No known key found for this signature in database GPG Key ID: 6A6914DAFBEA00DA
  1. 1
      src/Makefile.gtest.include
  2. 34
      src/gtest/test_random.cpp
  3. 24
      src/random.h

1
src/Makefile.gtest.include

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

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

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

Loading…
Cancel
Save