| /*=============================================================================# |
| # Copyright (c) 2009, 2021 Stephan Wahlbrink and others. |
| # |
| # This program and the accompanying materials are made available under the |
| # terms of the Eclipse Public License 2.0 which is available at |
| # https://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0 |
| # which is available at https://www.apache.org/licenses/LICENSE-2.0. |
| # |
| # SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 |
| # |
| # Contributors: |
| # Stephan Wahlbrink <sw@wahlbrink.eu> - initial API and implementation |
| #=============================================================================*/ |
| |
| package org.eclipse.statet.rj.data; |
| |
| import org.eclipse.statet.jcommons.lang.NonNullByDefault; |
| import org.eclipse.statet.jcommons.lang.Nullable; |
| |
| |
| @NonNullByDefault |
| public class RDataUtils { |
| |
| /** |
| * Returns the common abbreviation for the type of the given data store. |
| * These are the abbreviations used by the R function <code>str(x)</code>. |
| * If there is no abbreviation for the given type, it return the class name |
| * of an R vector with data of this type. |
| * |
| * @param store the data store |
| * @return an abbreviation |
| */ |
| public static final String getStoreAbbr(final RStore<?> store) { |
| switch (store.getStoreType()) { |
| case RStore.LOGICAL: |
| return "logi"; |
| case RStore.INTEGER: |
| return "int"; |
| case RStore.NUMERIC: |
| return "num"; |
| case RStore.CHARACTER: |
| return "chr"; |
| case RStore.COMPLEX: |
| return "cplx"; |
| case RStore.RAW: |
| return "raw"; |
| case RStore.FACTOR: |
| return ((RFactorStore) store).isOrdered() ? RObject.CLASSNAME_ORDERED : RObject.CLASSNAME_FACTOR; |
| default: |
| return ""; |
| } |
| } |
| |
| /** |
| * Returns the class name of an R vector with data of the type of the given data store. |
| * |
| * @param store the data store |
| * @return an class name |
| */ |
| public static final String getStoreClass(final RStore<?> store) { |
| switch (store.getStoreType()) { |
| case RStore.LOGICAL: |
| return RObject.CLASSNAME_LOGICAL; |
| case RStore.INTEGER: |
| return RObject.CLASSNAME_INTEGER; |
| case RStore.NUMERIC: |
| return RObject.CLASSNAME_NUMERIC; |
| case RStore.CHARACTER: |
| return RObject.CLASSNAME_CHARACTER; |
| case RStore.COMPLEX: |
| return RObject.CLASSNAME_COMPLEX; |
| case RStore.RAW: |
| return RObject.CLASSNAME_RAW; |
| case RStore.FACTOR: |
| return ((RFactorStore) store).isOrdered() ? RObject.CLASSNAME_ORDERED : RObject.CLASSNAME_FACTOR; |
| default: |
| return ""; |
| } |
| } |
| |
| public static final String getStoreMode(final int storeType) { |
| switch (storeType) { |
| case RStore.LOGICAL: |
| return "logical"; |
| case RStore.INTEGER: |
| case RStore.FACTOR: |
| return "integer"; |
| case RStore.NUMERIC: |
| return "numeric"; |
| case RStore.CHARACTER: |
| return "character"; |
| case RStore.COMPLEX: |
| return "complex"; |
| case RStore.RAW: |
| return "raw"; |
| default: |
| return ""; |
| } |
| } |
| |
| public static final String getObjectTypeName(final byte type) { |
| switch (type) { |
| case RObject.TYPE_NULL: |
| return "RNull"; |
| case RObject.TYPE_VECTOR: |
| return "RVector"; |
| case RObject.TYPE_ARRAY: |
| return "RArray"; |
| case RObject.TYPE_LIST: |
| return "RList"; |
| case RObject.TYPE_DATAFRAME: |
| return "RDataFrame"; |
| case RObject.TYPE_S4OBJECT: |
| return "RS4Object"; |
| case RObject.TYPE_ENVIRONMENT: |
| return "REnvironment"; |
| case RObject.TYPE_LANGUAGE: |
| return "RLanguage"; |
| case RObject.TYPE_FUNCTION: |
| return "RFunction"; |
| case RObject.TYPE_REFERENCE: |
| return "RReference"; |
| case RObject.TYPE_OTHER: |
| return "<other>"; |
| case RObject.TYPE_MISSING: |
| return "RMissing"; |
| case RObject.TYPE_PROMISE: |
| return "RPromise"; |
| default: |
| return "<unkown>"; |
| } |
| } |
| |
| public static final long computeLengthFromDim(final int[] dims) { |
| if (dims.length == 0) { |
| return 0; |
| } |
| long length= 1; |
| for (int i= 0; i < dims.length; i++) { |
| length *= dims[i]; |
| } |
| return length; |
| } |
| |
| public static final long getDataIdx(final int[] dims, final int... idxs) { |
| assert (dims.length > 0); |
| assert (dims.length == idxs.length); |
| |
| long dataIdx= idxs[0]; |
| long step= dims[0]; |
| // alt: idx=0; step=1; i=0; |
| for (int i= 1; i < dims.length; i++) { |
| dataIdx+= step*idxs[i]; |
| step *= dims[i]; |
| } |
| return dataIdx; |
| } |
| |
| public static final long getDataIdx(final RStore<?> dims, final int... idxs) { |
| assert (dims.getLength() > 0); |
| assert (dims.getLength() == idxs.length); |
| |
| long dataIdx= idxs[0]; |
| long step= dims.getInt(0); |
| // alt: idx=0; step=1; i=0; |
| for (int i= 1; i < dims.getLength(); i++) { |
| dataIdx+= step * idxs[i]; |
| step *= dims.getInt(i); |
| } |
| return dataIdx; |
| } |
| |
| /** |
| * Computes the index of a data value in a store of a matrix / 2 dimensional arrays |
| * specified by its column and row indexes. |
| * |
| * @param rowCount count of rows of the matrix |
| * @param rowIdx row index (zero-based) of the matrix |
| * @param columnIdx column index (zero-based) of the matrix |
| * @return the index in the data store |
| * |
| * @see #getDataIdx(int[], int...) |
| */ |
| public static final long getDataIdx(final long rowCount, final long rowIdx, final long columnIdx) { |
| return rowIdx + rowCount * columnIdx; |
| } |
| |
| public static final int[] getDataIdxs(final int[] dims, final int dim, final int idx) { |
| assert (dims.length > 0); |
| assert (0 <= dim && dim < dims.length); |
| assert (0 <= idx && idx < dims[dim]); |
| |
| final int size; |
| final int dimsCount= dims.length; |
| if (dimsCount == 1) { |
| size= 1; |
| } |
| else if (dimsCount == 2) { |
| size= dims[(dim == 0) ? 1 : 0]; |
| } |
| else { |
| int counter= 1; |
| for (int dimIdx= 0; dimIdx < dimsCount; dimIdx++) { |
| if (dimIdx != dim) { |
| counter *= dims[dimIdx]; |
| } |
| } |
| size= counter; |
| } |
| |
| final int[] dataIdxs= new int[size]; |
| int step= 1; |
| int stepCount= 1; |
| for (int dimIdx= 0; dimIdx < dimsCount; dimIdx++) { |
| final int dimSize= dims[dimIdx]; |
| if (dimIdx == dim) { |
| final int add= step*idx; |
| for (int i= 0; i < size; i++) { |
| dataIdxs[i]+= add; |
| } |
| } |
| else { |
| for (int i= 0, idxInDim= 0; i < size; idxInDim++) { |
| if (idxInDim == dimSize) { |
| idxInDim= 0; |
| } |
| final int add= step*idxInDim; |
| for (int j= 0; j < stepCount && i < size; i++,j++) { |
| dataIdxs[i]+= add; |
| } |
| } |
| stepCount *= dimSize; |
| } |
| step *= dimSize; |
| } |
| return dataIdxs; |
| } |
| |
| |
| private static final RStore<?> requireObjectData(final RObject obj) throws UnexpectedRDataException { |
| final RStore<?> store= obj.getData(); |
| if (store == null) { |
| throw new UnexpectedRDataException("Unexpected R object type: " + getObjectTypeName(obj.getRObjectType()) + " (without R data)"); |
| } |
| return store; |
| } |
| |
| private static final RLogicalStore requireRLogicalStore(final RStore<?> store) throws UnexpectedRDataException { |
| if (store.getStoreType() != RStore.LOGICAL) { |
| throw new UnexpectedRDataException("Unexpected R data type: " + getStoreAbbr(store)); |
| } |
| return (RLogicalStore)store; |
| } |
| |
| private static final RIntegerStore requireRIntegerStore(final RStore<?> store) throws UnexpectedRDataException { |
| if (store.getStoreType() != RStore.INTEGER) { |
| throw new UnexpectedRDataException("Unexpected R data type: " + getStoreAbbr(store)); |
| } |
| return (RIntegerStore)store; |
| } |
| |
| private static final RNumericStore requireRNumericStore(final RStore<?> store) throws UnexpectedRDataException { |
| if (store.getStoreType() != RStore.NUMERIC) { |
| throw new UnexpectedRDataException("Unexpected R data type: " + getStoreAbbr(store)); |
| } |
| return (RNumericStore)store; |
| } |
| |
| private static final RCharacterStore requireRCharacterStore(final RStore<?> store) throws UnexpectedRDataException { |
| if (store.getStoreType() != RStore.CHARACTER) { |
| throw new UnexpectedRDataException("Unexpected R data type: " + getStoreAbbr(store)); |
| } |
| return (RCharacterStore)store; |
| } |
| |
| private static final RRawStore requireRRawStore(final RStore<?> store) throws UnexpectedRDataException { |
| if (store.getStoreType() != RStore.RAW) { |
| throw new UnexpectedRDataException("Unexpected R data type: " + getStoreAbbr(store)); |
| } |
| return (RRawStore)store; |
| } |
| |
| private static final void requireLengthEqual1(final RStore<?> store) throws UnexpectedRDataException { |
| if (store.getLength() != 1) { |
| throw new UnexpectedRDataException("Unexpected R data length: " + store.getLength() + ", but == 1 expected."); |
| } |
| } |
| |
| |
| public static final RVector<?> checkRVector(final @Nullable RObject obj) throws UnexpectedRDataException { |
| if (obj == null) { |
| throw new UnexpectedRDataException("Missing R object."); |
| } |
| if (obj.getRObjectType() != RObject.TYPE_VECTOR) { |
| throw new UnexpectedRDataException("Unexpected R object type: " + getObjectTypeName(obj.getRObjectType())); |
| } |
| return (RVector<?>)obj; |
| } |
| |
| @SuppressWarnings("unchecked") |
| public static final RVector<RLogicalStore> checkRLogiVector(final @Nullable RObject obj) throws UnexpectedRDataException { |
| if (obj == null) { |
| throw new UnexpectedRDataException("Missing R object."); |
| } |
| if (obj.getRObjectType() != RObject.TYPE_VECTOR) { |
| throw new UnexpectedRDataException("Unexpected R object type: " + getObjectTypeName(obj.getRObjectType())); |
| } |
| requireRLogicalStore(requireObjectData(obj)); |
| return (RVector<RLogicalStore>)obj; |
| } |
| |
| @SuppressWarnings("unchecked") |
| public static final RVector<RIntegerStore> checkRIntVector(final @Nullable RObject obj) throws UnexpectedRDataException { |
| if (obj == null) { |
| throw new UnexpectedRDataException("Missing R object."); |
| } |
| if (obj.getRObjectType() != RObject.TYPE_VECTOR) { |
| throw new UnexpectedRDataException("Unexpected R object type: " + getObjectTypeName(obj.getRObjectType())); |
| } |
| requireRIntegerStore(requireObjectData(obj)); |
| return (RVector<RIntegerStore>)obj; |
| } |
| |
| @SuppressWarnings("unchecked") |
| public static final RVector<RNumericStore> checkRNumVector(final @Nullable RObject obj) throws UnexpectedRDataException { |
| if (obj == null) { |
| throw new UnexpectedRDataException("Missing R object."); |
| } |
| if (obj.getRObjectType() != RObject.TYPE_VECTOR) { |
| throw new UnexpectedRDataException("Unexpected R object type: " + getObjectTypeName(obj.getRObjectType())); |
| } |
| requireRNumericStore(requireObjectData(obj)); |
| return (RVector<RNumericStore>)obj; |
| } |
| |
| @SuppressWarnings("unchecked") |
| public static final RVector<RCharacterStore> checkRCharVector(final @Nullable RObject obj) throws UnexpectedRDataException { |
| if (obj == null) { |
| throw new UnexpectedRDataException("Missing R object."); |
| } |
| if (obj.getRObjectType() != RObject.TYPE_VECTOR) { |
| throw new UnexpectedRDataException("Unexpected R object type: " + getObjectTypeName(obj.getRObjectType())); |
| } |
| requireRCharacterStore(requireObjectData(obj)); |
| return (RVector<RCharacterStore>)obj; |
| } |
| |
| @SuppressWarnings("unchecked") |
| public static final RVector<RRawStore> checkRRawVector(final @Nullable RObject obj) throws UnexpectedRDataException { |
| if (obj == null) { |
| throw new UnexpectedRDataException("Missing R object."); |
| } |
| if (obj.getRObjectType() != RObject.TYPE_VECTOR) { |
| throw new UnexpectedRDataException("Unexpected R object type: " + getObjectTypeName(obj.getRObjectType())); |
| } |
| requireRRawStore(requireObjectData(obj)); |
| return (RVector<RRawStore>) obj; |
| } |
| |
| |
| public static final RArray<?> checkRArray(final @Nullable RObject obj) throws UnexpectedRDataException { |
| if (obj == null) { |
| throw new UnexpectedRDataException("Missing R object."); |
| } |
| if (obj.getRObjectType() != RObject.TYPE_ARRAY) { |
| throw new UnexpectedRDataException("Unexpected R object type: " + getObjectTypeName(obj.getRObjectType())); |
| } |
| return (RArray<?>)obj; |
| } |
| |
| public static final RArray<?> checkRArray(final @Nullable RObject obj, final int dim) throws UnexpectedRDataException { |
| if (obj == null) { |
| throw new UnexpectedRDataException("Missing R object."); |
| } |
| if (obj.getRObjectType() != RObject.TYPE_ARRAY) { |
| throw new UnexpectedRDataException("Unexpected R object type: " + getObjectTypeName(obj.getRObjectType())); |
| } |
| final RArray<?> array= (RArray<?>) obj; |
| if (dim > 0) { |
| if (dim != array.getDim().getLength()) { |
| throw new UnexpectedRDataException("Unexpected R array dimension: " + array.getDim().getLength()); |
| } |
| } |
| return array; |
| } |
| |
| public static final RArray<?> checkRArray(final @Nullable RObject obj, final long dim) throws UnexpectedRDataException { |
| if (obj == null) { |
| throw new UnexpectedRDataException("Missing R object."); |
| } |
| if (obj.getRObjectType() != RObject.TYPE_ARRAY) { |
| throw new UnexpectedRDataException("Unexpected R object type: " + getObjectTypeName(obj.getRObjectType())); |
| } |
| final RArray<?> array= (RArray<?>) obj; |
| if (dim > 0) { |
| if (dim != array.getDim().getLength()) { |
| throw new UnexpectedRDataException("Unexpected R array dimension: " + array.getDim().getLength()); |
| } |
| } |
| return array; |
| } |
| |
| @SuppressWarnings("unchecked") |
| public static final RArray<RCharacterStore> checkRCharArray(final @Nullable RObject obj, final int dim) throws UnexpectedRDataException { |
| if (obj == null) { |
| throw new UnexpectedRDataException("Missing R object."); |
| } |
| if (obj.getRObjectType() != RObject.TYPE_ARRAY) { |
| throw new UnexpectedRDataException("Unexpected R object type: " + getObjectTypeName(obj.getRObjectType())); |
| } |
| requireRCharacterStore(requireObjectData(obj)); |
| final RArray<RCharacterStore> array= (RArray<RCharacterStore>)obj; |
| if (dim > 0) { |
| if (dim != array.getDim().getLength()) { |
| throw new UnexpectedRDataException("Unexpected R array dimension: " + array.getDim().getLength()); |
| } |
| } |
| return array; |
| } |
| |
| @SuppressWarnings("unchecked") |
| public static final RArray<RRawStore> checkRRawArray(final @Nullable RObject obj, final int dim) throws UnexpectedRDataException { |
| if (obj == null) { |
| throw new UnexpectedRDataException("Missing R object."); |
| } |
| if (obj.getRObjectType() != RObject.TYPE_ARRAY) { |
| throw new UnexpectedRDataException("Unexpected R object type: " + getObjectTypeName(obj.getRObjectType())); |
| } |
| requireRRawStore(requireObjectData(obj)); |
| final var array= (RArray<RRawStore>)obj; |
| if (dim > 0) { |
| if (dim != array.getDim().getLength()) { |
| throw new UnexpectedRDataException("Unexpected R array dimension: " + array.getDim().getLength()); |
| } |
| } |
| return array; |
| } |
| |
| |
| public static final RList checkRList(final @Nullable RObject obj) throws UnexpectedRDataException { |
| if (obj == null) { |
| throw new UnexpectedRDataException("Missing R object."); |
| } |
| if (obj.getRObjectType() != RObject.TYPE_LIST) { |
| throw new UnexpectedRDataException("Unexpected R object type: " + getObjectTypeName(obj.getRObjectType())); |
| } |
| return (RList) obj; |
| } |
| |
| public static final RDataFrame checkRDataFrame(final @Nullable RObject obj) throws UnexpectedRDataException { |
| if (obj == null) { |
| throw new UnexpectedRDataException("Missing R object."); |
| } |
| if (obj.getRObjectType() != RObject.TYPE_DATAFRAME) { |
| throw new UnexpectedRDataException("Unexpected R object type: " + getObjectTypeName(obj.getRObjectType())); |
| } |
| return (RDataFrame) obj; |
| } |
| |
| public static final RDataFrame checkRDataFrame(final @Nullable RObject obj, final long length) throws UnexpectedRDataException { |
| if (obj == null) { |
| throw new UnexpectedRDataException("Missing R object."); |
| } |
| if (obj.getRObjectType() != RObject.TYPE_DATAFRAME) { |
| throw new UnexpectedRDataException("Unexpected R object type: " + getObjectTypeName(obj.getRObjectType())); |
| } |
| if (obj.getLength() != length) { |
| throw new UnexpectedRDataException("Unexpected R dataframe column count: " + obj.getLength()); |
| } |
| return (RDataFrame) obj; |
| } |
| |
| public static final RReference checkRReference(final @Nullable RObject obj) throws UnexpectedRDataException { |
| if (obj == null) { |
| throw new UnexpectedRDataException("Missing R object."); |
| } |
| if (obj.getRObjectType() != RObject.TYPE_REFERENCE) { |
| throw new UnexpectedRDataException( |
| "Unexpected R object type: " + getObjectTypeName(obj.getRObjectType()) ); |
| } |
| return (RReference) obj; |
| } |
| |
| public static final RReference checkRReference(final @Nullable RObject obj, final byte referencedObjectType) |
| throws UnexpectedRDataException { |
| if (obj == null) { |
| throw new UnexpectedRDataException("Missing R object."); |
| } |
| if (obj.getRObjectType() != RObject.TYPE_REFERENCE) { |
| throw new UnexpectedRDataException( |
| "Unexpected R object type: " + getObjectTypeName(obj.getRObjectType()) ); |
| } |
| final RReference reference= (RReference) obj; |
| if (reference.getReferencedRObjectType() != referencedObjectType) { |
| throw new UnexpectedRDataException( |
| "Unexpected referenced R object type: " + getObjectTypeName(obj.getRObjectType()) + |
| ", but " + getObjectTypeName(referencedObjectType) + " expected." ); |
| } |
| return (RReference) obj; |
| } |
| |
| public static final RLanguage checkRLanguage(final @Nullable RObject obj) throws UnexpectedRDataException { |
| if (obj == null) { |
| throw new UnexpectedRDataException("Missing R object."); |
| } |
| if (obj.getRObjectType() != RObject.TYPE_LANGUAGE) { |
| throw new UnexpectedRDataException("Unexpected R object type: " + getObjectTypeName(obj.getRObjectType())); |
| } |
| return (RLanguage) obj; |
| } |
| |
| |
| public static final boolean isSingleLogi(final @Nullable RObject obj) { |
| final RStore<?> data; |
| return (obj != null && (data= obj.getData()) != null |
| && data.getStoreType() == RStore.LOGICAL |
| && data.getLength() == 1 ); |
| } |
| |
| public static final @Nullable Boolean checkSingleLogi(final @Nullable RObject obj) throws UnexpectedRDataException { |
| if (obj == null) { |
| throw new UnexpectedRDataException("Missing R object."); |
| } |
| final RLogicalStore data= requireRLogicalStore(requireObjectData(obj)); |
| requireLengthEqual1(data); |
| |
| return data.get(0); |
| } |
| |
| public static final boolean checkSingleLogiValue(final @Nullable RObject obj) throws UnexpectedRDataException { |
| if (obj == null) { |
| throw new UnexpectedRDataException("Missing R object."); |
| } |
| final RLogicalStore data= requireRLogicalStore(requireObjectData(obj)); |
| requireLengthEqual1(data); |
| if (data.isNA(0)) { |
| throw new UnexpectedRDataException("Unexpected R data value: NA"); |
| } |
| |
| return data.getLogi(0); |
| } |
| |
| public static final boolean isSingleInt(final @Nullable RObject obj) { |
| final RStore<?> data; |
| return (obj != null && (data= obj.getData()) != null |
| && data.getStoreType() == RStore.INTEGER |
| && data.getLength() == 1 ); |
| } |
| |
| public static final @Nullable Integer checkSingleInt(final @Nullable RObject obj) throws UnexpectedRDataException { |
| if (obj == null) { |
| throw new UnexpectedRDataException("Missing R object."); |
| } |
| final RIntegerStore data= requireRIntegerStore(requireObjectData(obj)); |
| requireLengthEqual1(data); |
| |
| return data.get(0); |
| } |
| |
| public static final int checkSingleIntValue(final @Nullable RObject obj) throws UnexpectedRDataException { |
| if (obj == null) { |
| throw new UnexpectedRDataException("Missing R object."); |
| } |
| final RIntegerStore data= requireRIntegerStore(requireObjectData(obj)); |
| requireLengthEqual1(data); |
| if (data.isNA(0)) { |
| throw new UnexpectedRDataException("Unexpected R data value: NA"); |
| } |
| |
| return data.getInt(0); |
| } |
| |
| public static final boolean isSingleNum(final @Nullable RObject obj) { |
| final RStore<?> data; |
| return (obj != null && (data= obj.getData()) != null |
| && data.getStoreType() == RStore.NUMERIC |
| && data.getLength() == 1 ); |
| } |
| |
| public static final @Nullable Double checkSingleNum(final @Nullable RObject obj) throws UnexpectedRDataException { |
| if (obj == null) { |
| throw new UnexpectedRDataException("Missing R object."); |
| } |
| final RNumericStore data= requireRNumericStore(requireObjectData(obj)); |
| requireLengthEqual1(data); |
| |
| return data.get(0); |
| } |
| |
| public static final double checkSingleNumValue(final @Nullable RObject obj) throws UnexpectedRDataException { |
| if (obj == null) { |
| throw new UnexpectedRDataException("Missing R object."); |
| } |
| final RNumericStore data= requireRNumericStore(requireObjectData(obj)); |
| requireLengthEqual1(data); |
| if (data.isNA(0)) { |
| throw new UnexpectedRDataException("Unexpected R data value: NA"); |
| } |
| |
| return data.getNum(0); |
| } |
| |
| public static final boolean isSingleChar(final @Nullable RObject obj) { |
| final RStore<?> data; |
| return (obj != null && (data= obj.getData()) != null |
| && data.getStoreType() == RStore.CHARACTER |
| && data.getLength() == 1 ); |
| } |
| |
| @Deprecated |
| public static final boolean isSingleString(final @Nullable RObject obj) { |
| return isSingleChar(obj); |
| } |
| |
| public static final @Nullable String checkSingleChar(final @Nullable RObject obj) throws UnexpectedRDataException { |
| if (obj == null) { |
| throw new UnexpectedRDataException("Missing R object."); |
| } |
| final RCharacterStore data= requireRCharacterStore(requireObjectData(obj)); |
| requireLengthEqual1(data); |
| |
| return data.get(0); |
| } |
| |
| public static final String checkSingleCharValue(final @Nullable RObject obj) throws UnexpectedRDataException { |
| if (obj == null) { |
| throw new UnexpectedRDataException("Missing R object."); |
| } |
| final RCharacterStore data= requireRCharacterStore(requireObjectData(obj)); |
| requireLengthEqual1(data); |
| if (data.isNA(0)) { |
| throw new UnexpectedRDataException("Unexpected R data value: NA"); |
| } |
| |
| return data.getChar(0); |
| } |
| |
| public static final boolean isSingleRaw(final @Nullable RObject obj) { |
| final RStore<?> data; |
| return (obj != null && (data= obj.getData()) != null |
| && data.getStoreType() == RStore.RAW |
| && data.getLength() == 1 ); |
| } |
| |
| public static final Byte checkSingleRaw(final @Nullable RObject obj) throws UnexpectedRDataException { |
| if (obj == null) { |
| throw new UnexpectedRDataException("Missing R object."); |
| } |
| final RRawStore data= requireRRawStore(requireObjectData(obj)); |
| requireLengthEqual1(data); |
| |
| return data.get(0); |
| } |
| |
| public static final byte checkSingleRawValue(final @Nullable RObject obj) throws UnexpectedRDataException { |
| if (obj == null) { |
| throw new UnexpectedRDataException("Missing R object."); |
| } |
| final RRawStore data= requireRRawStore(requireObjectData(obj)); |
| requireLengthEqual1(data); |
| |
| return data.getRaw(0); |
| } |
| |
| |
| public static final RObject checkType(final @Nullable RObject obj, final byte objectType) throws UnexpectedRDataException { |
| if (obj == null) { |
| throw new UnexpectedRDataException("Missing R object."); |
| } |
| if (obj.getRObjectType() != objectType) { |
| throw new UnexpectedRDataException( |
| "Unexpected R object type: " + getObjectTypeName(obj.getRObjectType()) + |
| ", but " + getObjectTypeName(objectType) + " expected." ); |
| } |
| return obj; |
| } |
| |
| public static final RStore<?> checkData(final RStore<?> data, final byte storeType) throws UnexpectedRDataException { |
| if (data.getStoreType() != storeType) { |
| throw new UnexpectedRDataException("Unexpected R data type: " + getStoreAbbr(data) + ", but " + storeType + " expected."); |
| } |
| return data; |
| } |
| |
| |
| public static final int checkIntLength(final RObject obj) throws UnexpectedRDataException { |
| return checkIntLength(obj.getLength()); |
| } |
| |
| public static final int checkIntLength(final RStore<?> data) throws UnexpectedRDataException { |
| return checkIntLength(data.getLength()); |
| } |
| |
| public static final int checkIntLength(final long length) throws UnexpectedRDataException { |
| if (length < 0 || length > Integer.MAX_VALUE) { |
| throw new UnexpectedRDataException("Unexpected R data length: " + length + ", but <= 2^31-1 expected."); |
| } |
| return (int)length; |
| } |
| |
| public static final int checkIntIdx(final long idx) throws UnexpectedRDataException { |
| if (idx < 0 || idx >= Integer.MAX_VALUE) { |
| throw new UnexpectedRDataException("Unexpected R data index: " + idx + ", but < 2^31-1 expected."); |
| } |
| return (int)idx; |
| } |
| |
| public static final <T extends RObject> T checkLengthEqual(final T obj, final long length) throws UnexpectedRDataException { |
| if (obj.getLength() != length) { |
| throw new UnexpectedRDataException("Unexpected R object length: " + obj.getLength() + ", but == " + length + " expected."); |
| } |
| return obj; |
| } |
| |
| public static final <TData extends RStore<?>> TData checkLengthEqual(final TData data, |
| final long length) |
| throws UnexpectedRDataException { |
| if (data.getLength() != length) { |
| throw new UnexpectedRDataException("Unexpected R data length: " + data.getLength() + ", but == " + length + " expected."); |
| } |
| return data; |
| } |
| |
| public static final <TData extends RStore<?>> TData checkLengthGreaterOrEqual(final TData data, |
| final long length) |
| throws UnexpectedRDataException { |
| if (data.getLength() < length) { |
| throw new UnexpectedRDataException("Unexpected R data length: " + data.getLength() + ", but >= " + length + " expected."); |
| } |
| return data; |
| } |
| |
| public static final <P> P checkValue(final RStore<P> data, final int idx) throws UnexpectedRDataException { |
| final P value= data.get(idx); |
| if (value == null) { |
| throw new UnexpectedRDataException("Unexpected R data value: NA"); |
| } |
| return value; |
| } |
| |
| public static final <P> P checkValue(final RStore<P> data, final long idx) throws UnexpectedRDataException { |
| final P value= data.get(idx); |
| if (value == null) { |
| throw new UnexpectedRDataException("Unexpected R data value: NA"); |
| } |
| return value; |
| } |
| |
| public static final <P> P getValue(final RStore<P> data, final int idx, final P na) { |
| final P value= data.get(idx); |
| return (value != null) ? value : na; |
| } |
| |
| public static final <P> P getValue(final RStore<P> data, final long idx, final P na) { |
| final P value= data.get(idx); |
| return (value != null) ? value : na; |
| } |
| |
| |
| /*-- 2d --*/ |
| |
| public static final int getRowCount(final RArray<?> array) throws UnexpectedRDataException { |
| return array.getDim().getInt(0); |
| } |
| |
| public static final void checkRowCountEqual(final RArray<?> array, final int count) throws UnexpectedRDataException { |
| if (array.getDim().getInt(0) != count) { |
| throw new UnexpectedRDataException("Unexpected R matrix row count: " + array.getDim().getInt(0) + ", but == " + count + " expected."); |
| } |
| } |
| |
| public static final void checkRowCountEqual(final RDataFrame dataframe, final long count) throws UnexpectedRDataException { |
| if (dataframe.getRowCount() != count) { |
| throw new UnexpectedRDataException("Unexpected R dataframe row count: " + dataframe.getRowCount() + ", but == " + count + " expected."); |
| } |
| } |
| |
| public static final int getColumnCount(final RArray<?> array) throws UnexpectedRDataException { |
| return array.getDim().getInt(1); |
| } |
| |
| public static final void checkColumnCountEqual(final RArray<?> array, final int count) throws UnexpectedRDataException { |
| if (array.getDim().getInt(1) != count) { |
| throw new UnexpectedRDataException("Unexpected R matrix column count: " + array.getDim().getInt(1) + ", but == " + count + " expected."); |
| } |
| } |
| |
| public static final long checkColumnName(final RArray<?> array, final String name) throws UnexpectedRDataException { |
| final long idx= array.getNames(1).indexOf(name); |
| if (idx < 0) { |
| throw new UnexpectedRDataException("Missing R matrix column: " + name); |
| } |
| return idx; |
| } |
| |
| public static final void checkColumnCountEqual(final RDataFrame dataframe, final long count) throws UnexpectedRDataException { |
| if (dataframe.getColumnCount() != count) { |
| throw new UnexpectedRDataException("Unexpected R dataframe column count: " + dataframe.getColumnCount() + ", but == " + count + " expected."); |
| } |
| } |
| |
| |
| /*-- int --*/ |
| |
| public static final long binarySearch(final RVector<?> vector, final int value) { |
| final RStore<?> data= vector.getData(); |
| return binarySearch(data, 0, data.getLength(), value); |
| } |
| |
| public static final long binarySearch(final RStore<?> data, final int value) { |
| return binarySearch(data, 0, data.getLength(), value); |
| } |
| |
| public static final int binarySearch(final RStore<?> data, final int fromIdx, final int toIdx, final int value) { |
| if (fromIdx < 0 || fromIdx > data.getLength() |
| || toIdx < 0 || toIdx > data.getLength()) { |
| throw new IndexOutOfBoundsException(Long.toString(fromIdx)); |
| } |
| if (fromIdx > toIdx) { |
| throw new IllegalArgumentException(); |
| } |
| |
| return doBinarySearch(data, fromIdx, toIdx - 1, value); |
| } |
| |
| private static int doBinarySearch(final RStore<?> data, int low, int high, final int value) { |
| while (low <= high) { |
| final int mid= (low + high) >>> 1; |
| final int midValue= data.getInt(mid); |
| if (midValue < value) { |
| low= mid + 1; |
| } |
| else if (midValue > value) { |
| high= mid - 1; |
| } |
| else { |
| return mid; // key found |
| } |
| } |
| return -(low + 1); // key not found. |
| } |
| |
| public static final long binarySearch(final RStore<?> data, final long fromIdx, final long toIdx, final int value) { |
| if (fromIdx < 0 || fromIdx > data.getLength() |
| || toIdx < 0 || toIdx > data.getLength()) { |
| throw new IndexOutOfBoundsException(Long.toString(fromIdx)); |
| } |
| if (fromIdx > toIdx) { |
| throw new IllegalArgumentException(); |
| } |
| if (toIdx <= Integer.MAX_VALUE) { |
| return doBinarySearch(data, (int)fromIdx, (int)toIdx - 1, value); |
| } |
| |
| return doBinarySearch(data, fromIdx, toIdx - 1, value); |
| } |
| |
| private static long doBinarySearch(final RStore<?> data, long low, long high, final int value) { |
| while (low <= high) { |
| final long mid= (low + high) >>> 1; |
| final int midValue= data.getInt(mid); |
| if (midValue < value) { |
| low= mid + 1; |
| } |
| else if (midValue > value) { |
| high= mid - 1; |
| } |
| else { |
| return mid; // key found |
| } |
| } |
| return -(low + 1); // key not found. |
| } |
| |
| public static final int binarySearch(final RStore<?> data, |
| final long[] fromIdxs, final int length, final int[] values) { |
| if (fromIdxs.length > values.length) { |
| throw new IllegalArgumentException(); |
| } |
| if (length < 0 || length > data.getLength()) { |
| throw new IllegalArgumentException(); |
| } |
| for (int i= 0; i < fromIdxs.length; i++) { |
| if (fromIdxs[i] < 0 || fromIdxs[i] + length > data.getLength()) { |
| throw new IndexOutOfBoundsException(Long.toString(fromIdxs[i])); |
| } |
| } |
| |
| int low= 0; |
| int high= length - 1; |
| ITER_IDX: while (low <= high) { |
| final int mid= (low + high) >>> 1; |
| for (int i= 0; i < fromIdxs.length; i++) { |
| final int midValue= data.getInt(fromIdxs[i] + mid); |
| if (midValue < values[i]) { |
| low= mid + 1; |
| continue ITER_IDX; |
| } |
| if (midValue > values[i]) { |
| high= mid - 1; |
| continue ITER_IDX; |
| } |
| } |
| return mid; // key found |
| } |
| return -(low + 1); // key not found. |
| } |
| |
| public static final int compare(final int[] values1, final int[] values2) { |
| for (int i= 0; i < values1.length; i++) { |
| if (values1[i] < values2[i]) { |
| return -1; |
| } |
| if (values1[i] > values2[i]) { |
| return +1; |
| } |
| } |
| return 0; // equal |
| } |
| |
| |
| /*-- long ~ num -- */ |
| |
| public static final long binarySearch(final RStore<?> data, final long value) { |
| return binarySearch(data, 0, data.getLength(), value); |
| } |
| |
| public static final int binarySearch(final RStore<?> data, final int fromIdx, final int toIdx, final long value) { |
| if (fromIdx < 0 || fromIdx > data.getLength() |
| || toIdx < 0 || toIdx > data.getLength()) { |
| throw new IndexOutOfBoundsException(Long.toString(fromIdx)); |
| } |
| if (fromIdx > toIdx) { |
| throw new IllegalArgumentException(); |
| } |
| |
| return doBinarySearch(data, fromIdx, toIdx - 1, value); |
| } |
| |
| private static int doBinarySearch(final RStore<?> data, int low, int high, final long value) { |
| while (low <= high) { |
| final int mid= (low + high) >>> 1; |
| final double midValue= data.getNum(mid); |
| if (midValue < value) { |
| low= mid + 1; |
| } |
| else if (midValue > value) { |
| high= mid - 1; |
| } |
| else { |
| return mid; // key found |
| } |
| } |
| return -(low + 1); // key not found. |
| } |
| |
| public static final long binarySearch(final RStore<?> data, final long fromIdx, final long toIdx, final long value) { |
| if (fromIdx < 0 || fromIdx > data.getLength() |
| || toIdx < 0 || toIdx > data.getLength()) { |
| throw new IndexOutOfBoundsException(Long.toString(fromIdx)); |
| } |
| if (fromIdx > toIdx) { |
| throw new IllegalArgumentException(); |
| } |
| if (toIdx <= Integer.MAX_VALUE) { |
| return doBinarySearch(data, (int)fromIdx, (int)toIdx - 1, value); |
| } |
| |
| return doBinarySearch(data, fromIdx, toIdx - 1, value); |
| } |
| |
| private static long doBinarySearch(final RStore<?> data, long low, long high, final long value) { |
| while (low <= high) { |
| final long mid= (low + high) >>> 1; |
| final double midValue= data.getNum(mid); |
| if (midValue < value) { |
| low= mid + 1; |
| } |
| else if (midValue > value) { |
| high= mid - 1; |
| } |
| else { |
| return mid; // key found |
| } |
| } |
| return -(low + 1); // key not found. |
| } |
| |
| public static final int binarySearch(final RStore<?> data, |
| final long[] fromIdxs, final int length, final long[] values) { |
| if (fromIdxs.length > values.length) { |
| throw new IllegalArgumentException(); |
| } |
| if (length < 0 || length > data.getLength()) { |
| throw new IllegalArgumentException(); |
| } |
| for (int i= 0; i < fromIdxs.length; i++) { |
| if (fromIdxs[i] < 0 || fromIdxs[i] + length > data.getLength()) { |
| throw new IndexOutOfBoundsException(Long.toString(fromIdxs[i])); |
| } |
| } |
| |
| int low= 0; |
| int high= length - 1; |
| ITER_IDX: while (low <= high) { |
| final int mid= (low + high) >>> 1; |
| for (int i= 0; i < fromIdxs.length; i++) { |
| final double midValue= data.getNum(fromIdxs[i] + mid); |
| if (midValue < values[i]) { |
| low= mid + 1; |
| continue ITER_IDX; |
| } |
| if (midValue > values[i]) { |
| high= mid - 1; |
| continue ITER_IDX; |
| } |
| } |
| return mid; // key found |
| } |
| return -(low + 1); // key not found. |
| } |
| |
| public static final int compare(final long[] values1, final long[] values2) { |
| for (int i= 0; i < values1.length; i++) { |
| if (values1[i] < values2[i]) { |
| return -1; |
| } |
| if (values1[i] > values2[i]) { |
| return +1; |
| } |
| } |
| return 0; // equal |
| } |
| |
| |
| public static final byte[] encodeLongToRaw(final long id) { |
| final byte[] raw= new byte[8]; |
| encodeLongToRaw(id, raw, 0); |
| return raw; |
| } |
| |
| public static final void encodeLongToRaw(final long id, final byte[] raw, int idx) { |
| raw[idx++]= (byte) (id >>> 56); |
| raw[idx++]= (byte) (id >>> 48); |
| raw[idx++]= (byte) (id >>> 40); |
| raw[idx++]= (byte) (id >>> 32); |
| raw[idx++]= (byte) (id >>> 24); |
| raw[idx++]= (byte) (id >>> 16); |
| raw[idx++]= (byte) (id >>> 8); |
| raw[idx]= (byte) (id); |
| } |
| |
| public static final long decodeLongFromRaw(final byte[] raw) { |
| return decodeLongFromRaw(raw, 0); |
| } |
| |
| public static final long decodeLongFromRaw(final byte[] raw, int idx) { |
| return( ((long)(raw[idx++] & 0xff) << 56) | |
| ((long)(raw[idx++] & 0xff) << 48) | |
| ((long)(raw[idx++] & 0xff) << 40) | |
| ((long)(raw[idx++] & 0xff) << 32) | |
| ((long)(raw[idx++] & 0xff) << 24) | |
| ((raw[idx++] & 0xff) << 16) | |
| ((raw[idx++] & 0xff) << 8) | |
| ((raw[idx] & 0xff)) ); |
| } |
| |
| } |