All Downloads are FREE. Search and download functionalities are using the official Maven repository.

ai.platon.pulsar.common.OrderedIntDoubleMapping Maven / Gradle / Ivy

There is a newer version: 2.1.0
Show newest version
/**
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 * 

* http://www.apache.org/licenses/LICENSE-2.0 *

* Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package ai.platon.pulsar.common; import org.apache.commons.math3.linear.OpenMapRealVector; import org.apache.commons.math3.linear.SparseRealVector; import java.io.Serializable; import java.util.Optional; /** * From mahout * * @link {http://mahout.apache.org/docs/0.13.0/api/docs/mahout-math/index.html?org/apache/mahout/math/map/OpenIntDoubleHashMap.html} * @author vincent * @version $Id: $Id */ public final class OrderedIntDoubleMapping implements Serializable, Cloneable { public static final double DEFAULT_VALUE = 0.0; public static final OrderedIntDoubleMapping EMPTY = new OrderedIntDoubleMapping(0); private int[] indices; private double[] values; private int numMappings; // If true, doesn't allow DEFAULT_VALUEs in the mapping (adding a zero discards it). Otherwise, a DEFAULT_VALUE is // treated like any other value. private boolean noDefault = true; /** *

Constructor for OrderedIntDoubleMapping.

* * @param noDefault a boolean. */ public OrderedIntDoubleMapping(boolean noDefault) { this(); this.noDefault = noDefault; } /** *

Constructor for OrderedIntDoubleMapping.

*/ public OrderedIntDoubleMapping() { // no-arg constructor for deserializer this(11); } /** *

Constructor for OrderedIntDoubleMapping.

* * @param capacity a int. */ public OrderedIntDoubleMapping(int capacity) { indices = new int[capacity]; values = new double[capacity]; numMappings = 0; } /** *

Constructor for OrderedIntDoubleMapping.

* * @param indices an array of {@link int} objects. * @param values an array of {@link double} objects. * @param numMappings a int. */ public OrderedIntDoubleMapping(int[] indices, double[] values, int numMappings) { this.indices = indices; this.values = values; this.numMappings = numMappings; } /** *

isEmpty.

* * @return a boolean. */ public boolean isEmpty() { return this == EMPTY || (indices.length == 0 && values.length == 0 && numMappings == 0); } /** *

Getter for the field indices.

* * @return an array of {@link int} objects. */ public int[] getIndices() { return indices; } /** *

indexAt.

* * @param offset a int. * @return a int. */ public int indexAt(int offset) { return indices[offset]; } /** *

setIndexAt.

* * @param offset a int. * @param index a int. */ public void setIndexAt(int offset, int index) { indices[offset] = index; } /** *

Getter for the field values.

* * @return an array of {@link double} objects. */ public double[] getValues() { return values; } /** *

setValueAt.

* * @param offset a int. * @param value a double. */ public void setValueAt(int offset, double value) { values[offset] = value; } /** *

Getter for the field numMappings.

* * @return a int. */ public int getNumMappings() { return numMappings; } /** *

toSparseVector.

* * @param dimension a int. * @return a {@link org.apache.commons.math3.linear.SparseRealVector} object. */ public SparseRealVector toSparseVector(int dimension) { OpenMapRealVector vector = new OpenMapRealVector(dimension); for (int index : indices) { vector.setEntry(index, get(index)); } return vector; } /** *

toArray.

* * @param dim a int. * @return an array of {@link double} objects. */ public double[] toArray(int dim) { double[] values = new double[dim]; for (int i = 0; i < dim; i++) { values[i] = get(i); } return values; } private void growTo(int newCapacity) { if (newCapacity > indices.length) { int[] newIndices = new int[newCapacity]; System.arraycopy(indices, 0, newIndices, 0, numMappings); indices = newIndices; double[] newValues = new double[newCapacity]; System.arraycopy(values, 0, newValues, 0, numMappings); values = newValues; } } private int find(int index) { int low = 0; int high = numMappings - 1; while (low <= high) { int mid = low + (high - low >>> 1); int midVal = indices[mid]; if (midVal < index) { low = mid + 1; } else if (midVal > index) { high = mid - 1; } else { return mid; } } return -(low + 1); } /** *

get.

* * @param index a int. * @return a double. */ public double get(int index) { int offset = find(index); return offset >= 0 ? values[offset] : DEFAULT_VALUE; } /** *

set.

* * @param index a int. * @param value a double. */ public void set(int index, double value) { if (numMappings == 0 || index > indices[numMappings - 1]) { if (!noDefault || value != DEFAULT_VALUE) { if (numMappings >= indices.length) { growTo(Math.max((int) (1.2 * numMappings), numMappings + 1)); } indices[numMappings] = index; values[numMappings] = value; ++numMappings; } } else { int offset = find(index); if (offset >= 0) { insertOrUpdateValueIfPresent(offset, value); } else { insertValueIfNotDefault(index, offset, value); } } } /** * Merges the updates in linear time by allocating new arrays and iterating through the existing indices and values * and the updates' indices and values at the same time while selecting the minimum index to set at each step. * * @param updates another list of mappings to be merged in. */ public void merge(OrderedIntDoubleMapping updates) { int[] updateIndices = updates.getIndices(); double[] updateValues = updates.getValues(); int newNumMappings = numMappings + updates.getNumMappings(); int newCapacity = Math.max((int) (1.2 * newNumMappings), newNumMappings + 1); int[] newIndices = new int[newCapacity]; double[] newValues = new double[newCapacity]; int k = 0; int i = 0, j = 0; for (; i < numMappings && j < updates.getNumMappings(); ++k) { if (indices[i] < updateIndices[j]) { newIndices[k] = indices[i]; newValues[k] = values[i]; ++i; } else if (indices[i] > updateIndices[j]) { newIndices[k] = updateIndices[j]; newValues[k] = updateValues[j]; ++j; } else { newIndices[k] = updateIndices[j]; newValues[k] = updateValues[j]; ++i; ++j; } } for (; i < numMappings; ++i, ++k) { newIndices[k] = indices[i]; newValues[k] = values[i]; } for (; j < updates.getNumMappings(); ++j, ++k) { newIndices[k] = updateIndices[j]; newValues[k] = updateValues[j]; } indices = newIndices; values = newValues; numMappings = k; } /** {@inheritDoc} */ @Override public int hashCode() { int result = 0; for (int i = 0; i < numMappings; i++) { result = 31 * result + indices[i]; result = 31 * result + (int) Double.doubleToRawLongBits(values[i]); } return result; } /** {@inheritDoc} */ @Override public boolean equals(Object o) { if (this == o) { return true; } if (o instanceof OrderedIntDoubleMapping) { OrderedIntDoubleMapping other = (OrderedIntDoubleMapping) o; if (numMappings == other.numMappings) { for (int i = 0; i < numMappings; i++) { if (indices[i] != other.indices[i] || values[i] != other.values[i]) { return false; } } return true; } } return false; } /** {@inheritDoc} */ @Override public String toString() { StringBuilder result = new StringBuilder(10 * numMappings); for (int i = 0; i < numMappings; i++) { result.append('('); result.append(indices[i]); result.append(','); result.append(values[i]); result.append(')'); } return result.toString(); } /** {@inheritDoc} */ @SuppressWarnings("CloneDoesntCallSuperClone") @Override public OrderedIntDoubleMapping clone() { return new OrderedIntDoubleMapping(indices.clone(), values.clone(), numMappings); } /** *

increment.

* * @param index a int. * @param increment a double. */ public void increment(int index, double increment) { int offset = find(index); if (offset >= 0) { double newValue = values[offset] + increment; insertOrUpdateValueIfPresent(offset, newValue); } else { insertValueIfNotDefault(index, offset, increment); } } private void insertValueIfNotDefault(int index, int offset, double value) { if (!noDefault || value != DEFAULT_VALUE) { if (numMappings >= indices.length) { growTo(Math.max((int) (1.2 * numMappings), numMappings + 1)); } int at = -offset - 1; if (numMappings > at) { for (int i = numMappings - 1, j = numMappings; i >= at; i--, j--) { indices[j] = indices[i]; values[j] = values[i]; } } indices[at] = index; values[at] = value; numMappings++; } } private void insertOrUpdateValueIfPresent(int offset, double newValue) { if (noDefault && newValue == DEFAULT_VALUE) { for (int i = offset + 1, j = offset; i < numMappings; i++, j++) { indices[j] = indices[i]; values[j] = values[i]; } numMappings--; } else { values[offset] = newValue; } } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy