package org.quicktheories.quicktheories.generators;

import org.quicktheories.quicktheories.core.Source;

final class Doubles {

  private static final long POSITIVE_INFINITY_CORRESPONDING_LONG = 0x7ff0000000000000L;
  private static final long NEGATIVE_INFINITY_CORRESPONDING_LONG = 0xfff0000000000000L;
  private static final long ONE_CORRESPONDING_LONG = 4607182418800017408L;
  private static final long NEGATIVE_ZERO_CORRESPONDING_LONG = Long.MIN_VALUE;

  static Source<Double> fromNegativeInfinityToPositiveInfinity() {
    return Compositions.interleave(fromNegativeInfinityToNegativeZero(),
        fromZeroToPositiveInfinity());
  }

  static Source<Double> fromNegativeDoubleMaxToDoubleMax() {
    return Compositions.interleave(fromNegativeDoubleMaxToNegativeZero(),
        fromZeroToDoubleMax());
  }

  static Source<Double> fromNegativeInfinityToNegativeZero() {
    return range(NEGATIVE_ZERO_CORRESPONDING_LONG,
        NEGATIVE_INFINITY_CORRESPONDING_LONG, NEGATIVE_ZERO_CORRESPONDING_LONG);
  }

  static Source<Double> fromNegativeDoubleMaxToNegativeZero() {
    return range(NEGATIVE_ZERO_CORRESPONDING_LONG,
        NEGATIVE_INFINITY_CORRESPONDING_LONG - 1,
        NEGATIVE_ZERO_CORRESPONDING_LONG);
  }

  static Source<Double> fromZeroToPositiveInfinity() {
    return range(0, POSITIVE_INFINITY_CORRESPONDING_LONG);
  }

  static Source<Double> fromZeroToDoubleMax() {
    return range(0, POSITIVE_INFINITY_CORRESPONDING_LONG - 1);
  }

  static Source<Double> fromZeroToOne() {
    return range(0, ONE_CORRESPONDING_LONG);
  }

  static Source<Double> range(long startInclusive, long endInclusive) {
    return range(startInclusive, endInclusive, 0);
  }

  static Source<Double> range(long startInclusive, long endInclusive,
      long target) {
    return Longs.range(startInclusive, endInclusive)
        .withShrinker(Longs.shrinkTowardsTarget(target))
        .as(i -> Double.longBitsToDouble(i), j -> Double.doubleToLongBits(j));
  }

}

@@ -99,16 +99,53 @@
 ource;%0A%0A
+import java.util.function.Function;%0A%0A
 final cl
@@ -341,80 +341,179 @@
 ;%0A  
-private static final long ONE_CORRESPONDING_LONG = 4607182418800017408L;
+//fraction portion of double, last 52 bits%0A  private static final long FRACTION_BITS = 1L %3C%3C 53;%0A  private static final double DOUBLE_UNIT = 0x1.0p-53; // 1.0 / (1L %3C%3C 53)
 %0A  p
@@ -1659,30 +1659,85 @@
 (0, 
-ONE_CORRESPONDING_LONG
+FRACTION_BITS, 0,%0A        l -%3E l * DOUBLE_UNIT, d -%3E (long) (d / DOUBLE_UNIT)
 );%0A 
@@ -1955,24 +1955,314 @@
 g target) %7B%0A
+    return range(startInclusive, endInclusive, target,%0A        Double::longBitsToDouble, Double::doubleToLongBits);%0A  %7D%0A%0A  static Source%3CDouble%3E range(long startInclusive, long endInclusive,%0A      long target, Function%3CLong, Double%3E conversion,%0A      Function%3CDouble, Long%3E backFunction) %7B%0A
     return L
@@ -2375,72 +2375,32 @@
 .as(
-i -%3E Double.longBitsToDouble(i), j -%3E Double.doubleToLongBits(j)
+conversion, backFunction
 );%0A 

Fix doubles().fromZeroToOne() to generate uniformly distributed values