View Javadoc
1   /*
2    * (c) Copyright 2006-2020 by rapiddweller GmbH & Volker Bergmann. All rights reserved.
3    *
4    * Redistribution and use in source and binary forms, with or without
5    * modification, is permitted under the terms of the
6    * GNU General Public License.
7    *
8    * For redistributing this software or a derivative work under a license other
9    * than the GPL-compatible Free Software License as defined by the Free
10   * Software Foundation or approved by OSI, you must first obtain a commercial
11   * license to this software product from rapiddweller GmbH & Volker Bergmann.
12   *
13   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
14   * WITHOUT A WARRANTY OF ANY KIND. ALL EXPRESS OR IMPLIED CONDITIONS,
15   * REPRESENTATIONS AND WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF
16   * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE
17   * HEREBY EXCLUDED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
18   * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
19   * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
20   * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
21   * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
22   * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
23   * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
24   * POSSIBILITY OF SUCH DAMAGE.
25   */
26  
27  package com.rapiddweller.benerator.primitive;
28  
29  import com.rapiddweller.benerator.GeneratorContext;
30  import com.rapiddweller.benerator.NonNullGenerator;
31  import com.rapiddweller.benerator.distribution.sequence.BitReverseNaturalNumberGenerator;
32  import com.rapiddweller.benerator.wrapper.NonNullGeneratorProxy;
33  
34  /**
35   * Creates unique pseudo-random int arrays.<br/><br/>
36   * Created: 01.08.2011 17:00:57
37   *
38   * @author Volker Bergmann
39   * @since 0.7.0
40   */
41  public class UniqueIntsGenerator extends NonNullGeneratorProxy<int[]> {
42  
43    private int[] digits;
44    private final int[] displayColumn;
45    private final int[] digitOffsets;
46    private int cycleCounter;
47  
48    /**
49     * Instantiates a new Unique ints generator.
50     *
51     * @param radix  the radix
52     * @param length the length
53     */
54    public UniqueIntsGenerator(int radix, int length) {
55      super(new IncrementalIntsGenerator(radix, length));
56      this.displayColumn = new int[length];
57      this.digitOffsets = new int[length];
58    }
59  
60    @Override
61    public IncrementalIntsGenerator getSource() {
62      return (IncrementalIntsGenerator) super.getSource();
63    }
64  
65    /**
66     * Gets radix.
67     *
68     * @return the radix
69     */
70    public int getRadix() {
71      return getSource().getRadix();
72    }
73  
74    /**
75     * Gets length.
76     *
77     * @return the length
78     */
79    public int getLength() {
80      return getSource().getLength();
81    }
82  
83    @Override
84    public synchronized void init(GeneratorContext context) {
85      assertNotInitialized();
86      int length = getLength();
87      int radix = getRadix();
88      NonNullGenerator<Long> colGen = new BitReverseNaturalNumberGenerator(length - 1);
89      colGen.init(context);
90      for (int i = 0; i < length; i++) {
91        this.displayColumn[i] = colGen.generate().intValue();
92        this.digitOffsets[i] = (length - 1 - this.displayColumn[i]) % radix;
93      }
94      resetMembers();
95      super.init(context);
96    }
97  
98    @Override
99    public int[] generate() {
100     if (digits == null) {
101       return null;
102     }
103     int length = getLength();
104     int radix = getRadix();
105     int[] buffer = new int[length];
106     for (int i = 0; i < digits.length; i++) {
107       buffer[displayColumn[i]] = (digits[i] + digitOffsets[i] + cycleCounter) % radix;
108     }
109     if (cycleCounter < radix - 1 && length > 0) {
110       cycleCounter++;
111     } else {
112       digits = super.generate();
113       if (radix == 1 || (digits != null && digits[0] > 0)) {
114         // counter + cycle have run through all combinations
115         digits = null;
116       }
117       cycleCounter = 0;
118     }
119     return buffer;
120   }
121 
122   @Override
123   public void reset() {
124     super.reset();
125     resetMembers();
126   }
127 
128   private void resetMembers() {
129     this.digits = super.generate().clone();
130     this.cycleCounter = 0;
131   }
132 
133 }