package de.lmu.ifi.dbs.elki.utilities.datastructures.arraylike; /* This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures Copyright (C) 2014 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. 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 Affero General Public License for more details. You should have received a copy of the GNU Affero General Public License along with this program. If not, see . */ import java.util.List; import de.lmu.ifi.dbs.elki.data.FeatureVector; import de.lmu.ifi.dbs.elki.data.NumberVector; import de.lmu.ifi.dbs.elki.math.linearalgebra.Vector; /** * Utility class that allows plug-in use of various "array-like" types such as * lists in APIs that can take any kind of array to safe the cost of * reorganizing the objects into a real array. * * @author Erich Schubert * * @apiviz.landmark * @apiviz.composedOf ArrayAdapter */ public final class ArrayLikeUtil { /** * Static instance for lists. */ private static final ListArrayAdapter LISTADAPTER = new ListArrayAdapter<>(); /** * Static instance for lists of numbers. */ private static final NumberListArrayAdapter NUMBERLISTADAPTER = new NumberListArrayAdapter<>(); /** * Static instance. */ private static final IdentityArrayAdapter IDENTITYADAPTER = new IdentityArrayAdapter<>(); /** * Static instance. */ public static final FeatureVectorAdapter FEATUREVECTORADAPTER = new FeatureVectorAdapter(); /** * Use a number vector in the array API. */ public static final NumberVectorAdapter NUMBERVECTORADAPTER = new NumberVectorAdapter(); /** * Adapter for matrixes, reinterpreted as flat arrays. */ public static final FlatMatrixAdapter FLATMATRIXADAPTER = new FlatMatrixAdapter(); /** * Use a double array in the array API. */ public static final NumberArrayAdapter DOUBLEARRAYADAPTER = new DoubleArrayAdapter(); /** * Use a float array in the array API. */ public static final NumberArrayAdapter FLOATARRAYADAPTER = new FloatArrayAdapter(); /** * Use a Trove double list as array. */ public static final TDoubleListAdapter TDOUBLELISTADAPTER = new TDoubleListAdapter(); /** * Use ArrayDBIDs as array. */ public static final ArrayDBIDsAdapter ARRAYDBIDADAPTER = new ArrayDBIDsAdapter(); /** * Adapter for vectors. */ public static final NumberArrayAdapter VECTORADAPTER = new VectorAdapter(); /** * Fake constructor. Do not instantiate! */ private ArrayLikeUtil() { // Do not instantiate } /** * Cast the static instance. * * @param dummy Dummy variable, for type inference * @return Static instance */ @SuppressWarnings("unchecked") public static ArrayAdapter> listAdapter(List dummy) { return (ListArrayAdapter) LISTADAPTER; } /** * Cast the static instance. * * @param dummy Dummy variable, for type inference * @return Static instance */ @SuppressWarnings("unchecked") public static NumberArrayAdapter> numberListAdapter(List dummy) { return (NumberListArrayAdapter) NUMBERLISTADAPTER; } /** * Get the static instance. * * @param dummy Dummy object for type inference * @return Static instance */ @SuppressWarnings("unchecked") public static IdentityArrayAdapter identityAdapter(T dummy) { return (IdentityArrayAdapter) IDENTITYADAPTER; } /** * Get the static instance. * * @param prototype Prototype value, for type inference * @return Instance */ @SuppressWarnings("unchecked") public static FeatureVectorAdapter featureVectorAdapter(FeatureVector prototype) { return (FeatureVectorAdapter) FEATUREVECTORADAPTER; } /** * Get the static instance. * * @param prototype Prototype value, for type inference * @return Instance */ public static NumberVectorAdapter numberVectorAdapter(NumberVector prototype) { return NUMBERVECTORADAPTER; } /** * Get the adapter for double arrays. * * @return double array adapter */ public static NumberArrayAdapter doubleArrayAdapter() { return DOUBLEARRAYADAPTER; } /** * Returns the index of the maximum of the given values. If no value is bigger * than the first, the index of the first entry is returned. * * @param array type * @param array Array to inspect * @param adapter API adapter class * @return the index of the maximum in the given values * @throws IndexOutOfBoundsException if the length of the array is 0. */ public static int getIndexOfMaximum(A array, NumberArrayAdapter adapter) throws IndexOutOfBoundsException { final int size = adapter.size(array); int index = 0; double max = adapter.getDouble(array, 0); for (int i = 1; i < size; i++) { double val = adapter.getDouble(array, i); if (val > max) { max = val; index = i; } } return index; } /** * Returns the index of the maximum of the given values. If no value is bigger * than the first, the index of the first entry is returned. * * @param array Array to inspect * @return the index of the maximum in the given values * @throws IndexOutOfBoundsException if the length of the array is 0. */ public static int getIndexOfMaximum(double[] array) throws IndexOutOfBoundsException { return getIndexOfMaximum(array, DOUBLEARRAYADAPTER); } /** * Convert a numeric array-like to a double[]. * * @param array Array-like * @param adapter Adapter * @return primitive double array */ public static double[] toPrimitiveDoubleArray(A array, NumberArrayAdapter adapter) { if (adapter == DOUBLEARRAYADAPTER) { return ((double[]) array).clone(); } double[] ret = new double[adapter.size(array)]; for (int i = 0; i < ret.length; i++) { ret[i] = adapter.getDouble(array, i); } return ret; } /** * Convert a list of numbers to double[]. * * @param array List of numbers * @return double array */ public static double[] toPrimitiveDoubleArray(List array) { return toPrimitiveDoubleArray(array, NUMBERLISTADAPTER); } /** * Convert a number vector to double[]. * * @param obj Object to convert * @return primitive double array */ public static double[] toPrimitiveDoubleArray(NumberVector obj) { return toPrimitiveDoubleArray(obj, numberVectorAdapter(obj)); } /** * Convert a numeric array-like to a float[]. * * @param array Array-like * @param adapter Adapter * @return primitive float array */ public static float[] toPrimitiveFloatArray(A array, NumberArrayAdapter adapter) { if (adapter == FLOATARRAYADAPTER) { return ((float[]) array).clone(); } float[] ret = new float[adapter.size(array)]; for (int i = 0; i < ret.length; i++) { ret[i] = adapter.getFloat(array, i); } return ret; } /** * Convert a list of numbers to float[]. * * @param array List of numbers * @return float array */ public static float[] toPrimitiveFloatArray(List array) { return toPrimitiveFloatArray(array, NUMBERLISTADAPTER); } /** * Convert a number vector to float[]. * * @param obj Object to convert * @return primitive float array */ public static float[] toPrimitiveFloatArray(NumberVector obj) { return toPrimitiveFloatArray(obj, numberVectorAdapter(obj)); } /** * Convert a numeric array-like to a int[]. * * @param array Array-like * @param adapter Adapter * @return primitive double array */ public static int[] toPrimitiveIntegerArray(A array, NumberArrayAdapter adapter) { int[] ret = new int[adapter.size(array)]; for (int i = 0; i < ret.length; i++) { ret[i] = adapter.getInteger(array, i); } return ret; } /** * Convert a list of numbers to int[]. * * @param array List of numbers * @return double array */ public static int[] toPrimitiveIntegerArray(List array) { return toPrimitiveIntegerArray(array, NUMBERLISTADAPTER); } /** * Convert a number vector to int[]. * * @param obj Object to convert * @return primitive double array */ public static int[] toPrimitiveIntegerArray(NumberVector obj) { return toPrimitiveIntegerArray(obj, numberVectorAdapter(obj)); } }