File: IntList3.java

package info (click to toggle)
bbmap 39.20%2Bdfsg-3
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 26,024 kB
  • sloc: java: 312,743; sh: 18,099; python: 5,247; ansic: 2,074; perl: 96; makefile: 39; xml: 38
file content (260 lines) | stat: -rwxr-xr-x 8,571 bytes parent folder | download | duplicates (4)
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
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
package structures;

import java.util.Arrays;

import shared.KillSwitch;


/** 
 * Like IntList2 but has a size for each array independent of its length.
 * This is similar to a list of IntList but more efficient.
 * Designed for use with HashArrayHybridFast.
 * Assumes each entry is a set with all adds either ascending (Seal)
 * or unique (Sketch).
 * 
 * IntList3 does not extend IntList2 because virtual functions might be slower,
 * but it would make the code more concise.
 * 
 * @author Brian Bushnell
 * @date Dec 10, 2018
 *
 */
public final class IntList3{
	
	/*--------------------------------------------------------------*/
	/*----------------        Initialization        ----------------*/
	/*--------------------------------------------------------------*/
	
	/** Re-call with default initial size and mode. */
	public IntList3(){this(defaultInitialSize, defaultMode);}
	
	/** Construct an IntList3 with this initial size.
	 * Setting the proper mode is the caller's responsibility. */
	public IntList3(int initialSize, int mode_){
		assert(initialSize>0);
		entries=new int[initialSize][];
		sizes=new int[initialSize];
		
		mode=mode_;
		assert(mode==ASCENDING || mode==UNIQUE) : "Unsupported mode: "+mode;
	}
	
	/*--------------------------------------------------------------*/
	/*----------------           Mutation           ----------------*/
	/*--------------------------------------------------------------*/
	
	/** Add this entry to the end of the list */
	public final void add(int[] entry, int len){
		set(size, entry, len);
	}
	
	/** Set this location to specified entry */
	public final void set(int loc, int[] entry, int len){
		assert((entry==null && len==0) || (entry.length>0 && len<=entry.length)) : len+", "+(entry==null ? entry : ""+entry.length);
		
		if(loc>=entries.length){//Resize by doubling if necessary
			resize(max(size*2, loc+1));
		}
		entries[loc]=entry;
		sizes[loc]=len;
		size=max(size, loc+1);
	}
	
	/** 
	 * Add this value to the specified location. 
	 * If an entry exists, insert the value, enlarging if necessary.
	 * Otherwise, create a new entry. */
	public final int insertIntoList(final int v, final int loc){
		
		//If the location is empty
		if(loc>=size || entries[loc]==null){
			//Add a new entry and return
			set(loc, new int[] {v, INVALID}, 1);
			return 1;
		}
			
		int[] entry=get(loc);
		final int oldSize=sizes[loc];
		
		//Scan the latest entries to see if v is already present.
		for(int i=oldSize-1, lim=max(0, oldSize-slowAddLimit); i>=lim; i--){
			if(entry[i]==v){return 0;}
			assert(entry[i]<v || entry[i]!=v); //Ascending, the assumption for Seal; unique, the assumption for Sketch
			assert(entry[i]!=INVALID);
		}
		//At this point the element was not found because it was not present or the size is too big
		
		//If the entry is full, resize it
		if(oldSize>=entry.length){
			assert(oldSize==entry.length);
			entry=KillSwitch.copyAndFill(entry, oldSize*2L, INVALID);
			set(loc, entry, sizes[loc]);
		}
		
		//Quick add
		assert(entry[oldSize]==INVALID);
		entry[oldSize]=v;
		sizes[loc]++;
		return 1;
	}
	
	/*--------------------------------------------------------------*/
	/*----------------           Resizing           ----------------*/
	/*--------------------------------------------------------------*/
	
	/** Resize the array of entries */
	public final void resize(int size2){
		assert(size2>size);
		entries=KillSwitch.copyOf(entries, size2);//TODO: Safe copy to prevent memory exception
		sizes=KillSwitch.copyOf(sizes, size2);
	}
	
	/** Compress the list by eliminating the unused trailing space */
	public final void shrink(){
		if(size==entries.length){return;}
		entries=KillSwitch.copyOf(entries, size);
		sizes=KillSwitch.copyOf(sizes, size);
	}
	
	/**
	 * Provided for supporting disordered additions; not currently used.  
	 * Make each entry unique and minimal-length. 
	 * */
	public final void shrinkToUnique(){
		assert(false) : "TODO: This function has not been tested and is not expected to be used.";
		assert(!shrunk);
		assert(mode==DISORDERED);//Not really necessary
		for(int i=0; i<size; i++){
			if(sizes[i]>slowAddLimit){//Under this limit everything is already unique 
				shrinkToUnique(i);
			}
		}
		shrunk=true;
		assert(readyToUse());
	}
	
	/**
	 * Provided for supporting disordered additions; not currently used. 
	 * I could redo this so that the sets become packed and the size changes without creating a new array. 
	 * */
	private void shrinkToUnique(int loc){
		final int[] entry=entries[loc];
		final int oldSize=sizes[loc];
		assert(oldSize>1);
		Arrays.sort(entry, 0, oldSize);
		int unique=0;
		int prev=INVALID;
		for(int i=0; i<oldSize; i++){
			assert(entry[i]>=0);
			int current=entry[i];
			if(current!=prev){
				unique++;
			}
			prev=current;
		}
		if(unique==oldSize){return;} //No need to condense aside from saving a little RAM
		
		int[] set2=new int[unique];
		unique=0;
		prev=INVALID;
		for(int i=0; i<oldSize; i++){
			int current=entry[i];
			if(current!=prev){
				set2[unique]=current;
				unique++;
			}
			prev=current;
		}
		set(loc, set2, unique);
	}
	
	private boolean readyToUse(){
		return shrunk || mode==ASCENDING || mode==UNIQUE;
	}
	
	/*--------------------------------------------------------------*/
	/*----------------           Reading            ----------------*/
	/*--------------------------------------------------------------*/
	
	/** Get the entry at the location */
	public final int[] get(int loc){
		return(loc>=size ? null : entries[loc]);
	}
	
	/** Added for better IntList2 compatibility */
	public int getLen(int i) {
		return i>=size ? 0 : sizes[i];
	}
	
	/*--------------------------------------------------------------*/
	/*----------------           ToString           ----------------*/
	/*--------------------------------------------------------------*/
	
	@Override
	public String toString(){
		StringBuilder sb=new StringBuilder();
		sb.append('[');
		String comma="";
		for(int i=0; i<size; i++){
			if(entries[i]!=null){//Could be improved to use sizes
				sb.append(comma+"("+i+", "+Arrays.toString(entries[i])+")");
				comma=", ";
			}
		}
		sb.append(']');
		return sb.toString();
	}
	
	/*--------------------------------------------------------------*/
	/*----------------        Static Methods        ----------------*/
	/*--------------------------------------------------------------*/
	
	private static final int min(int x, int y){return x<y ? x : y;}
	private static final int max(int x, int y){return x>y ? x : y;}
	
	/*--------------------------------------------------------------*/
	/*----------------           Fields             ----------------*/
	/*--------------------------------------------------------------*/
	
	/** Holds entries.  Each entry is a sets of numbers in an int[]. 
	 * Leftmost values are valid, rightmost values are invalid. */
	private int[][] entries;
	/** Number of values in each entry. */
	private int[] sizes;
	/** Number of entries in the primary array. */
	public int size=0;
	
	/** True after shrinkToUnique has been called.
	 * Currently unused. */
	private boolean shrunk=false;
	
	/** Preconditions for adding values */
	private final int mode;
	
	/*--------------------------------------------------------------*/
	/*----------------        Static Fields         ----------------*/
	/*--------------------------------------------------------------*/
	
	/** This could be made mutable per instance, but it would be a lot of work. */
	public static final int INVALID=-1;
	
	/** Only scan back this far for duplicates when adding values */
	public static final int slowAddLimit=4;
	
	/*--------------------------------------------------------------*/
	/*----------------            Modes             ----------------*/
	/*--------------------------------------------------------------*/
	
	/** All adds to an entry must be nondescending */
	public static final int ASCENDING=1;
	/** All adds to an entry must be unique */
	public static final int UNIQUE=2;
	/** No requirements for adds.
	 * To ensure set functionality, shrinkToUnique should be called before use. */
	public static final int DISORDERED=3;
	
	/** Should be set prior to creation, e.g. by Seal or Sketch */
	public static int defaultMode=ASCENDING;
	public static int defaultInitialSize=256;
	
}