With ScalaCheck...
Generating a number from 0..Long.MaxValue is easy.
Generating an unsigned long from 0..Long.MaxValue..2^64-1 is not so easy.
Tried:
❌ Gen.chooseNum(BigInt(0),BigInt(2).pow(64)-1)
Does not work: At this time there is not an implicit defined for BigInt.
❌ Arbitrary.arbBigInt.arbitrary
Does not work: It's type BigInt but still limited to the range of signed Long.
✔ Generate a Long as BigInt and shift left arbitrarily to make an UINT64
Works: Taking Rickard Nilsson's, ScalaCheck code as a guide this passed the test.
This is what I came up with:
// Generate a long and map to type BigInt
def genBigInt : Gen[BigInt] = Gen.chooseNum(0,Long.MaxValue) map (x => BigInt(x))
// Take genBigInt and shift-left a chooseNum(0,64) of positions
def genUInt64 : Gen[BigInt] = for { bi <- genBigInt; n <- Gen.chooseNum(0,64); x = (bi << n) if x >= 0 && x < BigInt(2).pow(64) } yield x
...
// Use the generator, genUInt64()
As noted, Scalacheck number generator between 0 <= x < 2^64, the distribution of the BigInts generated is not even. The preferred generator is @stholzm solution:
def genUInt64b : Gen[BigInt] =
Gen.chooseNum(Long.MinValue,Long.MaxValue) map (x =>
BigInt(x) + BigInt(2).pow(63))
it is simpler, the numbers fed to ScalaCheck will be more evenly distributed, it is faster, and it passes the tests.