1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27 package com.rapiddweller.benerator.distribution;
28
29 import com.rapiddweller.benerator.Generator;
30 import com.rapiddweller.benerator.NonNullGenerator;
31 import com.rapiddweller.benerator.primitive.number.AbstractNonNullNumberGenerator;
32 import com.rapiddweller.benerator.sample.ConstantGenerator;
33 import com.rapiddweller.benerator.sample.SampleGenerator;
34 import com.rapiddweller.benerator.util.GeneratorUtil;
35 import com.rapiddweller.common.Converter;
36 import com.rapiddweller.common.converter.ConverterManager;
37
38 import java.util.List;
39 import java.util.Random;
40
41
42
43
44
45
46
47
48
49
50
51 public abstract class CumulativeDistributionFunction implements Distribution {
52
53
54
55
56
57
58
59 public abstract double cumulativeProbability(double value);
60
61
62
63
64
65
66
67 public abstract double inverse(double probability);
68
69 @Override
70 public <T> Generator<T> applyTo(Generator<T> source, boolean unique) {
71 if (unique) {
72 throw new IllegalArgumentException(this + " cannot generate unique values");
73 }
74 List<T> allProducts = GeneratorUtil.allProducts(source);
75 if (allProducts.size() == 1) {
76 return new ConstantGenerator<>(allProducts.get(0));
77 }
78 return new SampleGenerator<>(source.getGeneratedType(), this, unique, allProducts);
79 }
80
81 @Override
82 public <T extends Number> NonNullGenerator<T> createNumberGenerator(
83 Class<T> numberType, T min, T max, T granularity, boolean unique) {
84 if (unique) {
85 throw new IllegalArgumentException(this + " cannot generate unique values");
86 }
87 return new IPINumberGenerator<>(this, numberType, min, max, granularity);
88 }
89
90 @Override
91 public String toString() {
92 return getClass().getSimpleName();
93 }
94
95
96
97
98
99
100
101
102
103 public static class IPINumberGenerator<E extends Number> extends AbstractNonNullNumberGenerator<E> {
104
105 private final CumulativeDistributionFunction fcn;
106 private final Random random = new Random();
107 private final Converter<Double, E> converter;
108 private final double minProb;
109 private final double probScale;
110 private final double minD;
111 private double maxD;
112 private final double granularityD;
113
114
115
116
117
118
119
120
121
122
123 public IPINumberGenerator(CumulativeDistributionFunction fcn, Class<E> targetType, E min, E max, E granularity) {
124 super(targetType, min, max, granularity);
125 this.fcn = fcn;
126 this.minD = (min != null ? min.doubleValue() : (max != null ? maxD - 9 : 0));
127 this.maxD = (max != null ? max.doubleValue() : (min != null ? minD + 9 : 0));
128 this.granularityD = granularity.doubleValue();
129 this.minProb = fcn.cumulativeProbability(minD);
130 this.probScale = fcn.cumulativeProbability(maxD + granularityD) - this.minProb;
131 this.converter = ConverterManager.getInstance().createConverter(Double.class, targetType);
132 }
133
134 @Override
135 public E generate() {
136 double tmp;
137 double prob = minProb + random.nextDouble() * probScale;
138 tmp = fcn.inverse(prob);
139 tmp = Math.floor((tmp - minD) / granularityD) * granularityD + minD;
140 return converter.convert(tmp);
141 }
142
143 }
144
145 }