Not logged in.  Login/Logout/Register | List snippets | | Create snippet | Upload image | Upload data

335
LINES

< > BotCompany Repo | #1033825 // CompactLongSet [OK]

JavaX fragment (include) [tags: use-pretranspiled]

Libraryless. Click here for Pure Java version (5423L/31K).

1  
/*
2  
 * #!
3  
 * Ontopia Engine
4  
 * #-
5  
 * Copyright (C) 2001 - 2013 The Ontopia Project
6  
 * #-
7  
 * Licensed under the Apache License, Version 2.0 (the "License");
8  
 * you may not use this file except in compliance with the License.
9  
 * You may obtain a copy of the License at
10  
 * 
11  
 *      http://www.apache.org/licenses/LICENSE-2.0
12  
 * 
13  
 * Unless required by applicable law or agreed to in writing, software
14  
 * distributed under the License is distributed on an "AS IS" BASIS,
15  
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  
 * See the License for the specific language governing permissions and
17  
 * limitations under the License.
18  
 * !#
19  
 */
20  
21  
// modified by Stefan Reich
22  
23  
// a compact unordered set of longs. unsynchronized
24  
25  
sclass CompactLongSet extends java.util.AbstractSet<Long> {
26  
  protected final static int INITIAL_SIZE = 3;
27  
  public final static double LOAD_FACTOR = 0.75;
28  
29  
  protected final static long deletedObject = Long.MIN_VALUE;
30  
  
31  
  bool containsZero, containsDeletedObject; // special handling for sentinels
32  
  protected int elements;
33  
  protected int freecells;
34  
  protected long[] objects;
35  
  
36  
  ifndef NoModCount
37  
  protected int modCount;
38  
  endifndef
39  
  
40  
  *() { this(0); }
41  
42  
  // This applies the load factor so the set should be able to hold
43  
  // expectedElements without growing (haven't tested if this works exactly).
44  
  *(int expectedElements) {
45  
    int size = max(INITIAL_SIZE, iceil(expectedElements/LOAD_FACTOR));
46  
    // NOTE: If array size is 0, we get a
47  
    // "java.lang.ArithmeticException: / by zero" in add(Object).
48  
    objects = new long[size];
49  
    freecells = objects.length;
50  
  }
51  
52  
  *(Collection<long> c) {
53  
    this(c.size());
54  
    addAll(c);
55  
  }
56  
57  
  @Override
58  
  public RenamedLongIterator iterator() {
59  
    return new CompactHashIterator;
60  
  }
61  
62  
  @Override
63  
  public int size() {
64  
    return elements;
65  
  }
66  
67  
  @Override
68  
  public boolean isEmpty() {
69  
    return elements == 0;
70  
  }
71  
72  
  @Override
73  
  public bool contains(O o) {
74  
    ret contains((long) o);
75  
  }
76  
  
77  
  public bool contains(long o) {
78  
    if (o == 0) ret containsZero;
79  
    if (o == deletedObject) ret containsDeletedObject;
80  
81  
    int hash = hash(o);
82  
    int index = (hash & 0x7FFFFFFF) % objects.length;
83  
    int offset = 1;
84  
85  
    // search for the object (continue while !null and !this object)
86  
    while (objects[index] != 0) {
87  
      if (objects[index] == o) true;
88  
      index = ((index + offset) & 0x7FFFFFFF) % objects.length;
89  
      offset = offset*2 + 1;
90  
91  
      if (offset == -1)
92  
        offset = 2;
93  
    }
94  
95  
    false;
96  
  }
97  
  
98  
  @Override
99  
  public boolean add(Long o) {
100  
    ret add((long) o);
101  
  }
102  
  
103  
  public boolean add(long o) {
104  
    if (o == 0) {
105  
      if (containsZero) false;
106  
      set containsZero; elements++; true;
107  
    }
108  
    if (o == deletedObject)  {
109  
      if (containsDeletedObject) false;
110  
      set containsDeletedObject; elements++; true;
111  
    }
112  
    int hash = hash(o);
113  
    int index = (hash & 0x7FFFFFFF) % objects.length;
114  
    int offset = 1;
115  
    int deletedix = -1;
116  
    
117  
    // search for the object (continue while !null and !this object)
118  
    while (objects[index] != 0 && objects[index] != o) {
119  
120  
      // if there's a deleted object here we can put this object here,
121  
      // provided it's not in here somewhere else already
122  
      if (objects[index] == deletedObject)
123  
        deletedix = index;
124  
      
125  
      index = ((index + offset) & 0x7FFFFFFF) % objects.length;
126  
      offset = offset*2 + 1;
127  
128  
      if (offset == -1)
129  
        offset = 2;
130  
    }
131  
    
132  
    if (objects[index] == 0) { // wasn't present already
133  
      if (deletedix != -1) // reusing a deleted cell
134  
        index = deletedix;
135  
      else
136  
        freecells--;
137  
138  
      ifndef NoModCount
139  
        modCount++;
140  
      endifndef
141  
      elements++;
142  
143  
      objects[index] = o;
144  
      
145  
      // do we need to rehash?
146  
      if (1 - (freecells / (double) objects.length) > LOAD_FACTOR)
147  
        rehash();
148  
      return true;
149  
    } else // was there already 
150  
      return false;
151  
  }
152  
  
153  
  @Override
154  
  public boolean remove(Object o) {
155  
    ret remove((long) o);
156  
  }
157  
  
158  
  public boolean remove(long o) {
159  
    if (o == 0) {
160  
      if (!containsZero) false;
161  
      containsZero = false; --elements;
162  
      true;
163  
    }
164  
    
165  
    if (o == deletedObject) {
166  
      if (!containsDeletedObject) false;
167  
      containsDeletedObject = false; --elements;
168  
      true;
169  
    }
170  
    
171  
    int hash = hash(o);
172  
    int index = (hash & 0x7FFFFFFF) % objects.length;
173  
    int offset = 1;
174  
    
175  
    // search for the object (continue while !null and !this object)
176  
    while (objects[index] != 0 && objects[index] != o) {
177  
      index = ((index + offset) & 0x7FFFFFFF) % objects.length;
178  
      offset = offset*2 + 1;
179  
180  
      if (offset == -1)
181  
        offset = 2;
182  
    }
183  
184  
    // we found the right position, now do the removal
185  
    if (objects[index] != 0) {
186  
      // we found the object
187  
188  
      // same problem here as with add
189  
      objects[index] = deletedObject;
190  
      ifndef NoModCount
191  
        modCount++;
192  
      endifndef
193  
      elements--;
194  
      return true;
195  
    } else
196  
      // we did not find the object
197  
      return false;
198  
  }
199  
  
200  
  @Override
201  
  public void clear() {
202  
    elements = 0;
203  
    for (int ix = 0; ix < objects.length; ix++)
204  
      objects[ix] = 0;
205  
    containsZero = containsDeletedObject = false;
206  
    freecells = objects.length;
207  
    ifndef NoModCount
208  
      modCount++;
209  
    endifndef
210  
  }
211  
212  
  protected void rehash() {
213  
    int garbagecells = objects.length - (elements + freecells);
214  
    if (garbagecells / (double) objects.length > 0.05)
215  
      // rehash with same size
216  
      rehash(objects.length);
217  
    else
218  
      // rehash with increased capacity
219  
      rehash(objects.length*2 + 1);
220  
  }
221  
  
222  
  protected void rehash(int newCapacity) {
223  
    int oldCapacity = objects.length;
224  
    @SuppressWarnings("unchecked")
225  
    long[] newObjects = new[newCapacity];
226  
227  
    for ix to oldCapacity: {
228  
      long o = objects[ix];
229  
      if (o == 0 || o == deletedObject)
230  
        continue;
231  
      
232  
      int hash = hash(o);
233  
      int index = (hash & 0x7FFFFFFF) % newCapacity;
234  
      int offset = 1;
235  
236  
      // search for the object
237  
      while(newObjects[index] != 0) { // no need to test for duplicates
238  
        index = ((index + offset) & 0x7FFFFFFF) % newCapacity;
239  
        offset = offset*2 + 1;
240  
241  
        if (offset == -1)
242  
          offset = 2;
243  
      }
244  
245  
      newObjects[index] = o;
246  
    }
247  
248  
    objects = newObjects;
249  
    freecells = objects.length - elements;
250  
  }
251  
  
252  
  private class CompactHashIterator extends RenamedLongIterator {
253  
    private int index;
254  
    private int lastReturned = -1;
255  
    bool sendZero, sendDeletedObject;
256  
257  
    ifndef NoModCount
258  
      private int expectedModCount;
259  
    endifndef
260  
261  
    @SuppressWarnings("empty-statement")
262  
    public CompactHashIterator() {
263  
      // find first non-empty slot
264  
      for (index = 0; index < objects.length &&
265  
                      (objects[index] == 0 ||
266  
                      objects[index] == deletedObject); index++)
267  
        ;
268  
      ifndef NoModCount
269  
        expectedModCount = modCount;
270  
      endifndef
271  
      
272  
      sendZero = containsZero;
273  
      sendDeletedObject = containsDeletedObject;
274  
    }
275  
276  
    @Override
277  
    public bool hasNext() {
278  
      ret index < objects.length || sendZero || sendDeletedObject;
279  
    }
280  
281  
    @Override
282  
    public long nextLong() {
283  
      /*if (modCount != expectedModCount)
284  
        throw new ConcurrentModificationException();*/
285  
      int length = objects.length;
286  
      
287  
      if (index >= length) {
288  
        if (sendZero) { sendZero = false; ret 0L; }
289  
        if (sendDeletedObject) { sendDeletedObject = false; ret deletedObject; }
290  
        throw new NoSuchElementException;
291  
      }
292  
293  
      lastReturned = index;
294  
      for (index += 1; index < length &&
295  
                       (objects[index] == 0 ||
296  
                        objects[index] == deletedObject); index++)
297  
        ;
298  
299  
      ret objects[lastReturned];
300  
    }
301  
302  
    @Override
303  
    public void remove() {
304  
        ifndef NoModCount
305  
          if (modCount != expectedModCount)
306  
            throw new ConcurrentModificationException();
307  
        endifndef
308  
        if (lastReturned == -1 || lastReturned == -2)
309  
          throw new IllegalStateException();
310  
        // delete object
311  
        if (objects[lastReturned] != 0 && objects[lastReturned] != deletedObject) {
312  
          objects[lastReturned] = deletedObject;
313  
          elements--;
314  
          ifndef NoModCount
315  
            modCount++;
316  
            expectedModCount = modCount; // this is expected; we made the change
317  
          endifndef
318  
        }
319  
    }
320  
  }
321  
  
322  
  int capacity() { ret objects.length; }
323  
  
324  
  // returns true if there was a shrink
325  
  bool shrinkToFactor(double factor) {
326  
    if (factor > LOAD_FACTOR)
327  
      fail("Shrink factor must be equal to or smaller than load factor: " + factor + " / " + LOAD_FACTOR);
328  
    int newCapacity = max(INITIAL_SIZE, iround(size()/factor);
329  
    if (newCapacity >= capacity()) false;
330  
    rehash(newCapacity);
331  
    true;
332  
  }
333  
  
334  
  int hash(long l) { ret main hashCode(l); }
335  
}

Author comment

Began life as a copy of #1028522

download  show line numbers  debug dex  old transpilations   

Travelled to 4 computer(s): bhatertpkbcr, ekrmjmnbrukm, mowyntqkapby, mqqgnosmbjvj

No comments. add comment

Snippet ID: #1033825
Snippet name: CompactLongSet [OK]
Eternal ID of this version: #1033825/25
Text MD5: b8a1c9cefa4102d0177fabcd515a21eb
Transpilation MD5: bb77863d25cccc540f738b3b81c7b914
Author: stefan
Category: javax / collections
Type: JavaX fragment (include)
Public (visible to everyone): Yes
Archived (hidden from active list): No
Created/modified: 2022-03-22 21:31:38
Source code size: 9219 bytes / 335 lines
Pitched / IR pitched: No / No
Views / Downloads: 185 / 429
Version history: 24 change(s)
Referenced in: [show references]