Permalink
Browse files

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...
1 parent 0352d30 commit 1a1b03d39e13402a222b5d1521a749fae2d98bae @johnmay johnmay committed with egonw Sep 17, 2012
@@ -172,7 +172,7 @@
/**
* Maximum flags array index. Please update this if the value exceeds 16 -
* the flags are currently stored as a single short value (16-bit) in the
- * ChemObject implementations.
+ * ChemObject implementations (default, silent and query).
*/
public final static int MAX_FLAG_INDEX = 12;
@@ -77,7 +77,7 @@
* flag array with self-defined constants (flags[VISITED] = true). 100 flags
* per object should be more than enough.
*/
- private boolean[] flags;
+ private short flags; // flags are currently stored as a single short value MAX_FLAG_INDEX < 16
/**
* The ID is null by default.
@@ -90,7 +90,6 @@
*/
public ChemObject()
{
- flags = new boolean[CDKConstants.MAX_FLAG_INDEX + 1];
chemObjectListeners = null;
properties = null;
identifier = null;
@@ -105,8 +104,7 @@ public ChemObject()
public ChemObject(IChemObject chemObject) {
// copy the flags
boolean[] oldflags = chemObject.getFlags();
- flags = new boolean[oldflags.length];
- System.arraycopy(oldflags, 0, flags, 0, flags.length);
+ flags = chemObject.getFlagValue().shortValue();
// copy the identifier
identifier = chemObject.getID();
}
@@ -301,8 +299,7 @@ public Object clone() throws CloneNotSupportedException
{
ChemObject clone = (ChemObject)super.clone();
// clone the flags
- clone.flags = new boolean[CDKConstants.MAX_FLAG_INDEX + 1];
- System.arraycopy(flags, 0, clone.flags, 0, flags.length);
+ clone.flags = getFlagValue().shortValue();
// clone the properties
if (properties != null) {
Map<Object, Object> clonedHashtable = new HashMap<Object, Object>();
@@ -363,33 +360,40 @@ public void setID(String identifier)
/**
- * Sets the value of some flag.
- *
- *@param flag_type Flag to set
- *@param flag_value Value to assign to flag
- *@see #getFlag
+ * @inheritDoc
*/
- public void setFlag(int flag_type, boolean flag_value)
+ @Override
+ public void setFlag(int mask, boolean value)
{
- flags[flag_type] = flag_value;
- notifyChanged();
+ // set/unset a bit in the flags value
+ if (value)
+ flags |= mask;
+ else
+ flags &= ~(mask);
+ notifyChanged();
}
- /**
- * Returns the value of some flag.
- *
- *@param flag_type Flag to retrieve the value of
- *@return true if the flag <code>flag_type</code> is set
- *@see #setFlag
- */
- public boolean getFlag(int flag_type)
+ /**
+ * @inheritDoc
+ */
+ @Override
+ public boolean getFlag(int mask)
{
- return flags[flag_type];
+ return (flags & mask) != 0;
}
- /**
+ /**
+ * @inheritDoc
+ */
+ @Override
+ public Short getFlagValue() {
+ return flags;
+ }
+
+
+ /**
* Sets the properties of this object.
*
*@param properties a Hashtable specifying the property values
@@ -414,7 +418,8 @@ public void setProperties(Map<Object,Object> properties)
* @see #getFlags
*/
public void setFlags(boolean[] flagsNew){
- flags=flagsNew;
+ for(int i = 0; i < flagsNew.length ; i++)
+ setFlag(CDKConstants.FLAG_MASKS[i], flagsNew[i]);
notifyChanged();
}
@@ -425,7 +430,13 @@ public void setFlags(boolean[] flagsNew){
*@see #setFlags
*/
public boolean[] getFlags(){
- return(flags);
+ // could use a list a invoke .toArray() on the return
+ boolean[] flagArray = new boolean[CDKConstants.MAX_FLAG_INDEX + 1];
+ for(int i = 0 ; i < CDKConstants.FLAG_MASKS.length; i++){
+ int mask = CDKConstants.FLAG_MASKS[i];
+ flagArray[i] = getFlag(mask);
+ }
+ return flagArray;
}
/**
@@ -60,6 +60,7 @@ protected NaturalElement(String element, Integer atomicNumber) {
// unsupported methods
+ @Override public Number getFlagValue() { return null; }
@Override public void setProperty(Object description, Object property) {}
@Override public void removeProperty(Object description) {}
@Override public Object getProperty(Object description) { return null; }
@@ -437,6 +437,17 @@ public boolean getFlag(int flagType) {
return null;
}
+
+ /**
+ * This field is not used by this immutable hydrogen.
+ *
+ * @return null.
+ */
+ @Override
+ public Number getFlagValue() {
+ return null;
+ }
+
/** {@inheritDoc}} */
/**
* This field is not used by this immutable hydrogen.
@@ -153,23 +153,42 @@
public void setID(String identifier);
/**
- * Sets the value of some flag.
- *
- * @param flag_type Flag to set
- * @param flag_value Value to assign to flag
- * @see #getFlag
+ * Sets the value of some flag. The flag is a mask from a given
+ * CDKConstant (e.g. {@link org.openscience.cdk.CDKConstants#ISAROMATIC}
+ * or {@link org.openscience.cdk.CDKConstants#VISITED}).
+ *
+ * <pre>{@code
+ * // set this chem object to be aromatic
+ * chemObject.setFlag(CDKConstants.ISAROMATIC, Boolean.TRUE);
+ * // ...
+ * // indicate we have visited this chem object
+ * chemObject.setFlag(CDKConstants.VISITED, Boolean.TRUE);
+ * }</pre>
+ *
+ * @param mask flag to set the value for
+ * @param value value to assign to flag
+ * @see #getFlag
+ * @see org.openscience.cdk.CDKConstants
*/
- public void setFlag(int flag_type, boolean flag_value);
+ public void setFlag(int mask, boolean value);
/**
- * Returns the value of some flag.
+ * Returns the value of a given flag. The flag is a mask from a given
+ * CDKConstant (e.g. {@link org.openscience.cdk.CDKConstants#ISAROMATIC}).
+ *
+ * <pre>{@code
+ * if(chemObject.getFlag(CDKConstants.ISAROMATIC)){
+ * // handle aromatic flag on this chem object
+ * }
+ * }</pre>
*
- * @param flag_type Flag to retrieve the value of
- * @return true if the flag <code>flag_type</code> is set
- * @see #setFlag
+ * @param mask flag to retrieve the value of
+ * @return true if the flag <code>flag_type</code> is set
+ * @see #setFlag
+ * @see org.openscience.cdk.CDKConstants
*/
- public boolean getFlag(int flag_type);
+ public boolean getFlag(int mask);
/**
* Sets the properties of this object.
@@ -180,22 +199,39 @@
public void setProperties(Map<Object,Object> properties);
/**
- * Sets the whole set of flags.
+ * Sets the whole set of flags. This set will iteratively invoke
+ * {@link #setFlag(int, boolean)} for each value in the array and
+ * use {@link org.openscience.cdk.CDKConstants#FLAG_MASKS} to look
+ * up the correct mask. If only a single flag is being set it is a lot
+ * faster to use {@link #setFlag(int, boolean)}.
*
- * @param flagsNew the new flags.
+ * @param newFlags the new flags to set.
+ * @see #setFlag(int, boolean)
* @see #getFlags
*/
- public void setFlags(boolean[] flagsNew);
+ public void setFlags(boolean[] newFlags);
/**
- * Returns the whole set of flags.
+ * Returns the whole set of flags. This method will create a new array on
+ * each invocation and it is recommend you use {@link #getFlagValue()}
+ * if you need all the flags. For individual flags please use {@link #getFlag(int)}
*
* @return the flags.
* @see #setFlags
+ * @see #getFlag(int)
+ * @see #getFlagValue()
*/
public boolean[] getFlags();
/**
+ * Access the internal value used to store the flags. The flags are stored
+ * on a single numeric value and are set/cleared.
+ *
+ * @return numeric representation of the flags
+ */
+ public Number getFlagValue();
+
+ /**
* Returns a one line description of this IChemObject.
*
* @return a String representation of this object
@@ -28,6 +28,7 @@
import org.openscience.cdk.CDKConstants;
import org.openscience.cdk.interfaces.IAtom;
+import org.openscience.cdk.interfaces.IChemObject;
import org.openscience.cdk.interfaces.IChemObjectBuilder;
import org.openscience.cdk.interfaces.IChemObjectChangeEvent;
import org.openscience.cdk.interfaces.IChemObjectListener;
@@ -36,7 +37,7 @@
* @cdk.module isomorphism
* @cdk.githash
*/
-public class QueryChemObject {
+public class QueryChemObject implements IChemObject {
/**
* List for listener administration.
@@ -61,10 +62,9 @@
* flag array with self-defined constants (flags[VISITED] = true). 100 flags
* per object should be more than enough.
*/
- private boolean[] flags;
+ private short flags; // flags are currently stored as a single short value MAX_FLAG_INDEX < 16
public QueryChemObject() {
- flags = new boolean[CDKConstants.MAX_FLAG_INDEX + 1];
chemObjectListeners = null;
properties = null;
identifier = null;
@@ -272,28 +272,26 @@ public void setID(String identifier)
}
/**
- * Sets the value of some flag.
- *
- *@param flag_type Flag to set
- *@param flag_value Value to assign to flag
- *@see #getFlag
+ * @inheritDoc
*/
- public void setFlag(int flag_type, boolean flag_value)
+ @Override
+ public void setFlag(int mask, boolean value)
{
- flags[flag_type] = flag_value;
+ // set/unset a bit in the flags value
+ if (value)
+ flags |= mask;
+ else
+ flags &= ~(mask);
notifyChanged();
}
/**
- * Returns the value of some flag.
- *
- *@param flag_type Flag to retrieve the value of
- *@return true if the flag <code>flag_type</code> is set
- *@see #setFlag
+ * @inheritDoc
*/
- public boolean getFlag(int flag_type)
+ @Override
+ public boolean getFlag(int mask)
{
- return flags[flag_type];
+ return (flags & mask) != 0;
}
/**
@@ -316,23 +314,35 @@ public void setProperties(Map<Object,Object> properties)
private boolean doNotification = true;
/**
- * Sets the whole set of flags.
- *
- * @param flagsNew the new flags.
- * @see #getFlags
+ * @inheritDoc
*/
+ @Override
public void setFlags(boolean[] flagsNew){
- flags=flagsNew;
+ for(int i = 0; i < flagsNew.length ; i++)
+ setFlag(CDKConstants.FLAG_MASKS[i], flagsNew[i]);
}
/**
- * Returns the whole set of flags.
- *
- *@return the flags.
- *@see #setFlags
+ * @inheritDoc
*/
+ @Override
public boolean[] getFlags(){
- return(flags);
+ // could use a list a invoke .toArray() on the return
+ boolean[] flagArray = new boolean[CDKConstants.MAX_FLAG_INDEX + 1];
+ for(int i = 0 ; i < CDKConstants.FLAG_MASKS.length; i++){
+ int mask = CDKConstants.FLAG_MASKS[i];
+ flagArray[i] = getFlag(mask);
+ }
+ return flagArray;
+ }
+
+
+ /**
+ * @inheritDoc
+ */
+ @Override
+ public Short getFlagValue(){
+ return flags;
}
public void setNotification(boolean bool) {
Oops, something went wrong.

0 comments on commit 1a1b03d

Please sign in to comment.