Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse code

Implemented new flag storage on IChemObject implementations. Flags ar…

…e now stored on a single numeric value (currently a short) and flags are accessed/mutated via bit shifting of this value. This implementation provides space saving over using a boolean array however getFlags() and setFlags() now have a overhead due to conversion from the array to the numeric value. Usage however indicates the singular setFlag/getFlag is used >1000 times where as the setFlags/getFlags is used ~50.

Also removing debug statement from AbstractChemObjectTest

Signed-off-by: Egon Willighagen <egonw@users.sourceforge.net>
  • Loading branch information...
commit 1a1b03d39e13402a222b5d1521a749fae2d98bae 1 parent 0352d30
John May authored September 17, 2012 egonw committed September 18, 2012
2  src/main/org/openscience/cdk/CDKConstants.java
@@ -172,7 +172,7 @@
172 172
     /**
173 173
      * Maximum flags array index. Please update this if the value exceeds 16 -
174 174
      * the flags are currently stored as a single short value (16-bit) in the
175  
-     * ChemObject implementations.
  175
+     * ChemObject implementations (default, silent and query).
176 176
      */
177 177
     public final static int MAX_FLAG_INDEX = 12;
178 178
 
63  src/main/org/openscience/cdk/ChemObject.java
@@ -77,7 +77,7 @@
77 77
 	 *  flag array with self-defined constants (flags[VISITED] = true). 100 flags
78 78
 	 *  per object should be more than enough.
79 79
 	 */
80  
-	private boolean[] flags;
  80
+	private short flags; // flags are currently stored as a single short value MAX_FLAG_INDEX < 16
81 81
 
82 82
 	/**
83 83
 	 *  The ID is null by default.
@@ -90,7 +90,6 @@
90 90
 	 */
91 91
 	public ChemObject()
92 92
 	{
93  
-		flags = new boolean[CDKConstants.MAX_FLAG_INDEX + 1];
94 93
 		chemObjectListeners = null;
95 94
 		properties = null;
96 95
 		identifier = null;
@@ -105,8 +104,7 @@ public ChemObject()
105 104
 	public ChemObject(IChemObject chemObject) {
106 105
 		// copy the flags
107 106
 		boolean[] oldflags = chemObject.getFlags();
108  
-		flags = new boolean[oldflags.length];
109  
-		System.arraycopy(oldflags, 0, flags, 0, flags.length);
  107
+		flags = chemObject.getFlagValue().shortValue();
110 108
 		// copy the identifier
111 109
 		identifier = chemObject.getID();
112 110
 	}	
@@ -301,8 +299,7 @@ public Object clone() throws CloneNotSupportedException
301 299
 	{
302 300
 		ChemObject clone = (ChemObject)super.clone();
303 301
 		// clone the flags
304  
-		clone.flags = new boolean[CDKConstants.MAX_FLAG_INDEX + 1];
305  
-        System.arraycopy(flags, 0, clone.flags, 0, flags.length);
  302
+		clone.flags = getFlagValue().shortValue();
306 303
         // clone the properties
307 304
 		if (properties != null) {
308 305
 			Map<Object, Object> clonedHashtable = new HashMap<Object, Object>();
@@ -363,33 +360,40 @@ public void setID(String identifier)
363 360
 
364 361
 
365 362
 	/**
366  
-	 *  Sets the value of some flag.
367  
-	 *
368  
-	 *@param  flag_type   Flag to set
369  
-	 *@param  flag_value  Value to assign to flag
370  
-	 *@see                #getFlag
  363
+	 * @inheritDoc
371 364
 	 */
372  
-	public void setFlag(int flag_type, boolean flag_value)
  365
+    @Override
  366
+	public void setFlag(int mask, boolean value)
373 367
 	{
374  
-		flags[flag_type] = flag_value;
375  
-		notifyChanged();
  368
+        // set/unset a bit in the flags value
  369
+        if (value)
  370
+            flags |= mask;
  371
+        else
  372
+            flags &= ~(mask);
  373
+        notifyChanged();
376 374
 	}
377 375
 
378 376
 
379  
-	/**
380  
-	 *  Returns the value of some flag.
381  
-	 *
382  
-	 *@param  flag_type  Flag to retrieve the value of
383  
-	 *@return            true if the flag <code>flag_type</code> is set
384  
-	 *@see               #setFlag
385  
-	 */
386  
-	public boolean getFlag(int flag_type)
  377
+    /**
  378
+     * @inheritDoc
  379
+     */
  380
+    @Override
  381
+    public boolean getFlag(int mask)
387 382
 	{
388  
-		return flags[flag_type];
  383
+        return (flags & mask) != 0;
389 384
 	}
390 385
 
391 386
 
392  
-	/**
  387
+    /**
  388
+     * @inheritDoc
  389
+     */
  390
+    @Override
  391
+    public Short getFlagValue() {
  392
+        return flags;
  393
+    }
  394
+
  395
+
  396
+    /**
393 397
 	 *  Sets the properties of this object.
394 398
 	 *
395 399
 	 *@param  properties  a Hashtable specifying the property values
@@ -414,7 +418,8 @@ public void setProperties(Map<Object,Object> properties)
414 418
 	 * @see                #getFlags
415 419
 	 */
416 420
     public void setFlags(boolean[] flagsNew){
417  
-        flags=flagsNew;
  421
+        for(int i = 0; i < flagsNew.length ; i++)
  422
+            setFlag(CDKConstants.FLAG_MASKS[i], flagsNew[i]);
418 423
         notifyChanged();
419 424
     }
420 425
 
@@ -425,7 +430,13 @@ public void setFlags(boolean[] flagsNew){
425 430
 	 *@see       #setFlags
426 431
 	 */
427 432
     public boolean[] getFlags(){
428  
-        return(flags);
  433
+        // could use a list a invoke .toArray() on the return
  434
+        boolean[] flagArray = new boolean[CDKConstants.MAX_FLAG_INDEX + 1];
  435
+        for(int i = 0 ; i < CDKConstants.FLAG_MASKS.length; i++){
  436
+            int mask = CDKConstants.FLAG_MASKS[i];
  437
+            flagArray[i] = getFlag(mask);
  438
+        }
  439
+        return flagArray;
429 440
     }
430 441
 
431 442
 	/**
1  src/main/org/openscience/cdk/config/NaturalElement.java
@@ -60,6 +60,7 @@ protected NaturalElement(String element, Integer atomicNumber) {
60 60
 
61 61
 	// unsupported methods
62 62
 
  63
+    @Override public Number getFlagValue() { return null; }
63 64
 	@Override public void setProperty(Object description, Object property) {}
64 65
 	@Override public void removeProperty(Object description) {}
65 66
 	@Override public Object getProperty(Object description) { return null; }
11  src/main/org/openscience/cdk/geometry/cip/ImmutableHydrogen.java
@@ -437,6 +437,17 @@ public boolean getFlag(int flagType) {
437 437
         return null;
438 438
     }
439 439
 
  440
+
  441
+    /**
  442
+     * This field is not used by this immutable hydrogen.
  443
+     *
  444
+     * @return null.
  445
+     */
  446
+    @Override
  447
+    public Number getFlagValue() {
  448
+        return null;
  449
+    }
  450
+
440 451
     /** {@inheritDoc}} */
441 452
     /**
442 453
      * This field is not used by this immutable hydrogen.
66  src/main/org/openscience/cdk/interfaces/IChemObject.java
@@ -153,23 +153,42 @@
153 153
 	public void setID(String identifier);
154 154
 
155 155
 	/**
156  
-	 * Sets the value of some flag.
157  
-	 *
158  
-	 * @param  flag_type   Flag to set
159  
-	 * @param  flag_value  Value to assign to flag
160  
-	 * @see                #getFlag
  156
+	 * Sets the value of some flag. The flag is a mask from a given
  157
+     * CDKConstant (e.g. {@link org.openscience.cdk.CDKConstants#ISAROMATIC}
  158
+     * or {@link org.openscience.cdk.CDKConstants#VISITED}).
  159
+     *
  160
+     * <pre>{@code
  161
+     * // set this chem object to be aromatic
  162
+     * chemObject.setFlag(CDKConstants.ISAROMATIC, Boolean.TRUE);
  163
+     * // ...
  164
+     * // indicate we have visited this chem object
  165
+     * chemObject.setFlag(CDKConstants.VISITED, Boolean.TRUE);
  166
+     * }</pre>
  167
+     *
  168
+     * @param  mask   flag to set the value for
  169
+	 * @param  value  value to assign to flag
  170
+	 * @see           #getFlag
  171
+     * @see           org.openscience.cdk.CDKConstants
161 172
 	 */
162  
-	public void setFlag(int flag_type, boolean flag_value);
  173
+	public void setFlag(int mask, boolean value);
163 174
 
164 175
 
165 176
 	/**
166  
-	 * Returns the value of some flag.
  177
+	 * Returns the value of a given flag. The flag is a mask from a given
  178
+     * CDKConstant (e.g. {@link org.openscience.cdk.CDKConstants#ISAROMATIC}).
  179
+     *
  180
+     * <pre>{@code
  181
+     * if(chemObject.getFlag(CDKConstants.ISAROMATIC)){
  182
+     *     // handle aromatic flag on this chem object
  183
+     * }
  184
+     * }</pre>
167 185
 	 *
168  
-	 * @param  flag_type  Flag to retrieve the value of
169  
-	 * @return            true if the flag <code>flag_type</code> is set
170  
-	 * @see               #setFlag
  186
+	 * @param  mask  flag to retrieve the value of
  187
+	 * @return       true if the flag <code>flag_type</code> is set
  188
+	 * @see          #setFlag
  189
+     * @see          org.openscience.cdk.CDKConstants
171 190
 	 */
172  
-	public boolean getFlag(int flag_type);
  191
+	public boolean getFlag(int mask);
173 192
 
174 193
 	/**
175 194
 	 * Sets the properties of this object.
@@ -180,22 +199,39 @@
180 199
 	public void setProperties(Map<Object,Object> properties);
181 200
     
182 201
 	/**
183  
-	 * Sets the whole set of flags.
  202
+	 * Sets the whole set of flags. This set will iteratively invoke
  203
+     * {@link #setFlag(int, boolean)} for each value in the array and
  204
+     * use {@link org.openscience.cdk.CDKConstants#FLAG_MASKS} to look
  205
+     * up the correct mask. If only a single flag is being set it is a lot
  206
+     * faster to use {@link #setFlag(int, boolean)}.
184 207
 	 *
185  
-	 * @param  flagsNew    the new flags.
  208
+	 * @param  newFlags    the new flags to set.
  209
+     * @see                #setFlag(int, boolean)
186 210
 	 * @see                #getFlags
187 211
 	 */
188  
-    public void setFlags(boolean[] flagsNew);
  212
+    public void setFlags(boolean[] newFlags);
189 213
 
190 214
 	/**
191  
-	 * Returns the whole set of flags.
  215
+	 * Returns the whole set of flags. This method will create a new array on
  216
+     * each invocation and it is recommend you use {@link #getFlagValue()}
  217
+     * if you need all the flags. For individual flags please use {@link #getFlag(int)}
192 218
 	 *
193 219
 	 * @return    the flags.
194 220
 	 * @see       #setFlags
  221
+     * @see       #getFlag(int)
  222
+     * @see       #getFlagValue()
195 223
 	 */
196 224
     public boolean[] getFlags();
197 225
 
198 226
     /**
  227
+     * Access the internal value used to store the flags. The flags are stored
  228
+     * on a single numeric value and are set/cleared.
  229
+     *
  230
+     * @return numeric representation of the flags
  231
+     */
  232
+    public Number getFlagValue();
  233
+
  234
+    /**
199 235
      * Returns a one line description of this IChemObject.
200 236
      *
201 237
      * @return a String representation of this object
64  src/main/org/openscience/cdk/isomorphism/matchers/QueryChemObject.java
@@ -28,6 +28,7 @@
28 28
 
29 29
 import org.openscience.cdk.CDKConstants;
30 30
 import org.openscience.cdk.interfaces.IAtom;
  31
+import org.openscience.cdk.interfaces.IChemObject;
31 32
 import org.openscience.cdk.interfaces.IChemObjectBuilder;
32 33
 import org.openscience.cdk.interfaces.IChemObjectChangeEvent;
33 34
 import org.openscience.cdk.interfaces.IChemObjectListener;
@@ -36,7 +37,7 @@
36 37
  * @cdk.module  isomorphism
37 38
  * @cdk.githash
38 39
  */
39  
-public class QueryChemObject {
  40
+public class QueryChemObject implements IChemObject {
40 41
 
41 42
     /**
42 43
      * List for listener administration.
@@ -61,10 +62,9 @@
61 62
      *  flag array with self-defined constants (flags[VISITED] = true). 100 flags
62 63
      *  per object should be more than enough.
63 64
      */
64  
-    private boolean[] flags;
  65
+    private short flags; // flags are currently stored as a single short value MAX_FLAG_INDEX < 16
65 66
 
66 67
     public QueryChemObject() {
67  
-        flags = new boolean[CDKConstants.MAX_FLAG_INDEX + 1];
68 68
         chemObjectListeners = null;
69 69
         properties = null;
70 70
         identifier = null;
@@ -272,28 +272,26 @@ public void setID(String identifier)
272 272
     }
273 273
 
274 274
     /**
275  
-     *  Sets the value of some flag.
276  
-     *
277  
-     *@param  flag_type   Flag to set
278  
-     *@param  flag_value  Value to assign to flag
279  
-     *@see                #getFlag
  275
+     * @inheritDoc
280 276
      */
281  
-    public void setFlag(int flag_type, boolean flag_value)
  277
+    @Override
  278
+    public void setFlag(int mask, boolean value)
282 279
     {
283  
-        flags[flag_type] = flag_value;
  280
+        // set/unset a bit in the flags value
  281
+        if (value)
  282
+            flags |= mask;
  283
+        else
  284
+            flags &= ~(mask);
284 285
         notifyChanged();
285 286
     }
286 287
 
287 288
     /**
288  
-     *  Returns the value of some flag.
289  
-     *
290  
-     *@param  flag_type  Flag to retrieve the value of
291  
-     *@return            true if the flag <code>flag_type</code> is set
292  
-     *@see               #setFlag
  289
+     * @inheritDoc
293 290
      */
294  
-    public boolean getFlag(int flag_type)
  291
+    @Override
  292
+    public boolean getFlag(int mask)
295 293
     {
296  
-        return flags[flag_type];
  294
+        return (flags & mask) != 0;
297 295
     }
298 296
 
299 297
     /**
@@ -316,23 +314,35 @@ public void setProperties(Map<Object,Object> properties)
316 314
     private boolean doNotification = true;
317 315
 
318 316
     /**
319  
-     * Sets the whole set of flags.
320  
-     *
321  
-     * @param  flagsNew    the new flags.
322  
-     * @see                #getFlags
  317
+     * @inheritDoc
323 318
      */
  319
+    @Override
324 320
     public void setFlags(boolean[] flagsNew){
325  
-        flags=flagsNew;
  321
+        for(int i = 0; i < flagsNew.length ; i++)
  322
+            setFlag(CDKConstants.FLAG_MASKS[i], flagsNew[i]);
326 323
     }
327 324
 
328 325
     /**
329  
-     * Returns the whole set of flags.
330  
-     *
331  
-     *@return    the flags.
332  
-     *@see       #setFlags
  326
+     * @inheritDoc
333 327
      */
  328
+    @Override
334 329
     public boolean[] getFlags(){
335  
-        return(flags);
  330
+        // could use a list a invoke .toArray() on the return
  331
+        boolean[] flagArray = new boolean[CDKConstants.MAX_FLAG_INDEX + 1];
  332
+        for(int i = 0 ; i < CDKConstants.FLAG_MASKS.length; i++){
  333
+            int mask = CDKConstants.FLAG_MASKS[i];
  334
+            flagArray[i] = getFlag(mask);
  335
+        }
  336
+        return flagArray;
  337
+    }
  338
+
  339
+
  340
+    /**
  341
+     * @inheritDoc
  342
+     */
  343
+    @Override
  344
+    public Short getFlagValue(){
  345
+        return flags;
336 346
     }
337 347
 
338 348
     public void setNotification(boolean bool) {
97  src/main/org/openscience/cdk/silent/ChemObject.java
@@ -24,9 +24,12 @@
24 24
 package org.openscience.cdk.silent;
25 25
 
26 26
 import java.io.Serializable;
  27
+import java.util.ArrayList;
  28
+import java.util.Arrays;
27 29
 import java.util.HashMap;
28 30
 import java.util.Iterator;
29 31
 import java.util.LinkedHashMap;
  32
+import java.util.List;
30 33
 import java.util.Map;
31 34
 
32 35
 import org.openscience.cdk.CDKConstants;
@@ -69,7 +72,7 @@
69 72
 	 *  flag array with self-defined constants (flags[VISITED] = true). 100 flags
70 73
 	 *  per object should be more than enough.
71 74
 	 */
72  
-	private boolean[] flags;
  75
+	private short flags; // flags are currently stored as a single short value MAX_FLAG_INDEX < 16
73 76
 
74 77
 	/**
75 78
 	 *  The ID is null by default.
@@ -82,7 +85,6 @@
82 85
 	 */
83 86
 	public ChemObject()
84 87
 	{
85  
-		flags = new boolean[CDKConstants.MAX_FLAG_INDEX + 1];
86 88
 		properties = null;
87 89
 		identifier = null;
88 90
 	}
@@ -90,17 +92,15 @@ public ChemObject()
90 92
 	/**
91 93
 	 * Constructs a new IChemObject by copying the flags, and the
92 94
 	 * identifier. It does not copy the listeners and properties.
93  
-	 * 
  95
+	 *
94 96
 	 * @param chemObject the object to copy
95 97
 	 */
96 98
 	public ChemObject(IChemObject chemObject) {
97 99
 		// copy the flags
98  
-		boolean[] oldflags = chemObject.getFlags();
99  
-		flags = new boolean[oldflags.length];
100  
-		System.arraycopy(oldflags, 0, flags, 0, flags.length);
  100
+		flags = chemObject.getFlagValue().shortValue();
101 101
 		// copy the identifier
102 102
 		identifier = chemObject.getID();
103  
-	}	
  103
+	}
104 104
 
105 105
 	/**
106 106
 	 *  Use this to add yourself to this IChemObject as a listener. In order to do
@@ -235,8 +235,8 @@ public Object clone() throws CloneNotSupportedException
235 235
 	{
236 236
 		ChemObject clone = (ChemObject)super.clone();
237 237
 		// clone the flags
238  
-		clone.flags = new boolean[CDKConstants.MAX_FLAG_INDEX + 1];
239  
-        System.arraycopy(flags, 0, clone.flags, 0, flags.length);
  238
+		clone.flags = this.getFlagValue();
  239
+
240 240
         // clone the properties
241 241
 		if (properties != null) {
242 242
 			Map<Object, Object> clonedHashtable = new HashMap<Object, Object>();
@@ -265,7 +265,7 @@ public boolean compare(Object object)
265 265
 			return false;
266 266
 		}
267 267
 		ChemObject chemObj = (ChemObject) object;
268  
-        return identifier == chemObj.identifier;        
  268
+        return identifier == chemObj.identifier;
269 269
     }
270 270
 
271 271
 
@@ -294,30 +294,36 @@ public void setID(String identifier)
294 294
 
295 295
 
296 296
 	/**
297  
-	 *  Sets the value of some flag.
298  
-	 *
299  
-	 *@param  flag_type   Flag to set
300  
-	 *@param  flag_value  Value to assign to flag
301  
-	 *@see                #getFlag
  297
+	 * @inheritDoc
302 298
 	 */
303  
-	public void setFlag(int flag_type, boolean flag_value)
  299
+    @Override
  300
+	public void setFlag(int mask, boolean value)
304 301
 	{
305  
-		flags[flag_type] = flag_value;
  302
+        // set/unset a bit in the flags value
  303
+        if (value)
  304
+            flags |= mask;
  305
+        else
  306
+            flags &= ~(mask);
  307
+
306 308
 	}
307 309
 
308 310
 
309  
-	/**
310  
-	 *  Returns the value of some flag.
311  
-	 *
312  
-	 *@param  flag_type  Flag to retrieve the value of
313  
-	 *@return            true if the flag <code>flag_type</code> is set
314  
-	 *@see               #setFlag
315  
-	 */
316  
-	public boolean getFlag(int flag_type)
  311
+    /**
  312
+     * @inheritDoc
  313
+     */
  314
+    @Override
  315
+    public boolean getFlag(int mask)
317 316
 	{
318  
-		return flags[flag_type];
  317
+		return (flags & mask) != 0;
319 318
 	}
320 319
 
  320
+    /**
  321
+     * @inheritDoc
  322
+     */
  323
+    public Short getFlagValue(){
  324
+        return flags; // auto-boxing
  325
+    }
  326
+
321 327
 
322 328
 	/**
323 329
 	 *  Sets the properties of this object.
@@ -334,26 +340,29 @@ public void setProperties(Map<Object,Object> properties)
334 340
 			lazyProperties().put(key, properties.get(key));
335 341
 		}
336 342
 	}
337  
-  
338  
-  
339  
-	/**
340  
-	 * Sets the whole set of flags.
341  
-	 *
342  
-	 * @param  flagsNew    the new flags.
343  
-	 * @see                #getFlags
344  
-	 */
  343
+
  344
+
  345
+    /**
  346
+     * @inheritDoc
  347
+     */
  348
+    @Override
345 349
     public void setFlags(boolean[] flagsNew){
346  
-        flags=flagsNew;
  350
+        for(int i = 0; i < flagsNew.length ; i++)
  351
+            setFlag(CDKConstants.FLAG_MASKS[i], flagsNew[i]);
347 352
     }
348 353
 
349  
-	/**
350  
-	 * Returns the whole set of flags.
351  
-	 *
352  
-	 *@return    the flags.
353  
-	 *@see       #setFlags
354  
-	 */
  354
+    /**
  355
+     * @inheritDoc
  356
+     */
  357
+    @Override
355 358
     public boolean[] getFlags(){
356  
-        return(flags);
  359
+        // could use a list a invoke .toArray() on the return
  360
+        boolean[] flagArray = new boolean[CDKConstants.MAX_FLAG_INDEX + 1];
  361
+        for(int i = 0 ; i < CDKConstants.FLAG_MASKS.length; i++){
  362
+            int mask = CDKConstants.FLAG_MASKS[i];
  363
+            flagArray[i] = getFlag(mask);
  364
+        }
  365
+        return flagArray;
357 366
     }
358 367
 
359 368
 	/**
@@ -372,13 +381,13 @@ public Object shallowCopy()
372 381
 		}
373 382
 		return copy;
374 383
 	}
375  
-	
  384
+
376 385
     public IChemObjectBuilder getBuilder() {
377 386
         return SilentChemObjectBuilder.getInstance();
378 387
     }
379 388
 
380 389
 	private boolean doNotification = true;
381  
-	
  390
+
382 391
 	public void setNotification(boolean bool) {
383 392
 		this.doNotification = bool;
384 393
 	}
1  src/test/org/openscience/cdk/interfaces/AbstractChemObjectTest.java
@@ -104,7 +104,6 @@
104 104
     }
105 105
     
106 106
     @Test public void testGetFlags(){
107  
-      System.out.println("Test flags:");
108 107
       IChemObject chemObject=newChemObject();
109 108
       chemObject.setFlag(CDKConstants.ISINRING,true);
110 109
       IChemObject chemObject2=newChemObject();

0 notes on commit 1a1b03d

Please sign in to comment.
Something went wrong with that request. Please try again.