org.openscience.cdk.hash.AbstractHashGenerator Maven / Gradle / Ivy
/*
* Copyright (c) 2013 John May
*
* Contact: [email protected]
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
* as published by the Free Software Foundation; either version 2.1
* of the License, or (at your option) any later version.
* All we ask is that proper credit is given for our work, which includes
* - but is not limited to - adding the above copyright notice to the beginning
* of your source code files, and to any copyright notice that you may distribute
* with programs based on this work.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 U
*/
package org.openscience.cdk.hash;
import org.openscience.cdk.interfaces.IAtomContainer;
import org.openscience.cdk.interfaces.IBond;
import java.util.Arrays;
/**
* An abstract hash function providing several utility methods to be used by
* other hashing functions.
*
* @author John May
* @cdk.module hash
* @cdk.githash
*/
class AbstractHashGenerator {
/* pseudorandom number generator */
private final Pseudorandom pseudorandom;
/**
* Construct an abstract hash function providing the pseudorandom number
* generator.
*
* @param pseudorandom a pseudorandom number generator
* @throws NullPointerException the pseudorandom number generator was null
*/
public AbstractHashGenerator(Pseudorandom pseudorandom) {
if (pseudorandom == null) throw new NullPointerException("null pseduorandom number generator provided");
this.pseudorandom = pseudorandom;
}
/**
* Create a copy of the array of long values.
*
* @param src original values
* @return copy of the original values
* @see Arrays#copyOf(long[], int)
*/
static long[] copy(long[] src) {
return Arrays.copyOf(src, src.length);
}
/**
* Copy the values from the source (src) array to the destination (dest).
*
* @param src source values
* @param dest destination of the source copy
* @see System#arraycopy(Object, int, Object, int, int);
*/
static void copy(long[] src, long[] dest) {
System.arraycopy(src, 0, dest, 0, dest.length);
}
/**
* Generate the next random number.
*
* @param seed a {@literal long} value to seed a pseudorandom number
* generator
* @return next pseudorandom number
*/
long rotate(long seed) {
return pseudorandom.next(seed);
}
/**
* Rotate a value, n times. The rotation uses a pseudorandom
* number generator to sequentially generate values seed on the previous
* value.
*
* @param value the {@literal long} value to rotate
* @param n the number of times to rotate the value
* @return the {@literal long} value rotated the specified number of times
*/
long rotate(long value, int n) {
while (n-- > 0)
value = pseudorandom.next(value);
return value;
}
/**
* Returns the value of the lowest three bits. This value is between 0 and 7
* inclusive.
*
* @param value a {@literal long} value
* @return the {@literal int} value of the lowest three bits.
*/
static int lowestThreeBits(long value) {
return (int) (value & 0x7);
}
/**
* Distribute the provided value across the set of {@literal long} values.
*
* @param value a {@literal long} value to distribute
* @return the {@literal long} value distributed a set amount
*/
long distribute(long value) {
// rotate 1-8 times
return rotate(value, 1 + lowestThreeBits(value));
}
/**
* Convert an IAtomContainer to an adjacency list.
*
* @param container the container to convert
* @return adjacency list representation
*/
static int[][] toAdjList(IAtomContainer container) {
if (container == null) throw new IllegalArgumentException("atom container was null");
int n = container.getAtomCount();
int[][] graph = new int[n][16];
int[] degree = new int[n];
for (IBond bond : container.bonds()) {
int v = container.getAtomNumber(bond.getAtom(0));
int w = container.getAtomNumber(bond.getAtom(1));
if (v < 0 || w < 0)
throw new IllegalArgumentException("bond at index " + container.getBondNumber(bond)
+ " contained an atom not pressent in molecule");
graph[v][degree[v]++] = w;
graph[w][degree[w]++] = v;
// if the vertex degree of v or w reaches capacity, double the size
if (degree[v] == graph[v].length) graph[v] = Arrays.copyOf(graph[v], degree[v] * 2);
if (degree[w] == graph[w].length) graph[w] = Arrays.copyOf(graph[w], degree[w] * 2);
}
for (int v = 0; v < n; v++) {
graph[v] = Arrays.copyOf(graph[v], degree[v]);
}
return graph;
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy