From f7d00bbd69759b47264dd6f62a9659f55de61422 Mon Sep 17 00:00:00 2001 From: kaifox Date: Mon, 3 Jul 2017 17:02:29 +0200 Subject: [PATCH 1/4] Put in place a new (currently empty) interface for new methods. --- .../org/tensorics/core/tensor/MapableTensor.java | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 src/java/org/tensorics/core/tensor/MapableTensor.java diff --git a/src/java/org/tensorics/core/tensor/MapableTensor.java b/src/java/org/tensorics/core/tensor/MapableTensor.java new file mode 100644 index 000000000..73cf473c8 --- /dev/null +++ b/src/java/org/tensorics/core/tensor/MapableTensor.java @@ -0,0 +1,15 @@ +package org.tensorics.core.tensor; + +/** + * Enhances the tensor interface by a method to view the tensor as a map from + * position to values. This interface is intended to be used by utility methods + * in order to avoid unnecessary calls. + * + * @author kaifox + * + * @param + * the type of the values of the tensors + */ +public interface MapableTensor extends Tensor { + +} From ba0372b8936a28ab200bfb99f5914c5028002509 Mon Sep 17 00:00:00 2001 From: kaifox Date: Mon, 3 Jul 2017 17:37:40 +0200 Subject: [PATCH 2/4] No asMap() method in tensor interface anymore --- .../meteo/simple/SimpleMeteoExample.java | 2 +- .../org/tensorics/core/lang/Tensorics.java | 710 ++++----- .../core/tensor/AbstractTensorBuilder.java | 4 +- .../core/tensor/BroadcastedTensorView.java | 2 +- .../core/tensor/ImmutableTensor.java | 8 +- .../tensorics/core/tensor/MapableTensor.java | 4 + .../org/tensorics/core/tensor/Tensor.java | 8 - .../lang/OngoingDimensionFlattening.java | 3 +- .../tensor/lang/OngoingTensorFiltering.java | 3 +- .../lang/OngoingTensorManipulation.java | 3 +- .../core/tensor/lang/QuantityTensors.java | 13 +- .../core/tensor/lang/TensorStructurals.java | 5 +- .../core/tensor/operations/OngoingMapOut.java | 2 +- .../tensor/operations/TensorInternals.java | 67 +- .../tensor/operations/TensorReduction.java | 2 +- .../ImmutableDoubleArrayBackedTensor.java | 3 +- .../core/tensor/stream/TensorStreams.java | 3 +- ...bstractDiscreteFunctionVs1DTensorTest.java | 5 +- .../core/lang/TensorCalculationsTest.java | 1269 +++++++++-------- .../core/tensor/ImmutableTensorTest.java | 4 +- .../AbstractTensorbackedTest.java | 185 ++- .../tensorbacked/TensorbackedBuilderTest.java | 228 +-- 22 files changed, 1292 insertions(+), 1241 deletions(-) diff --git a/src/examples/org/tensorics/core/examples/meteo/simple/SimpleMeteoExample.java b/src/examples/org/tensorics/core/examples/meteo/simple/SimpleMeteoExample.java index 6a0e7325e..4bfe6cd53 100644 --- a/src/examples/org/tensorics/core/examples/meteo/simple/SimpleMeteoExample.java +++ b/src/examples/org/tensorics/core/examples/meteo/simple/SimpleMeteoExample.java @@ -41,7 +41,7 @@ private void getByStaticMethodsWithStaticImports() { private void loopThroughEntries() { // tag::loopThroughEntries[] - for (Entry entry : temperatures.asMap().entrySet()) { + for (Entry entry : Tensorics.mapFrom(temperatures).entrySet()) { Position position = entry.getKey(); double value = entry.getValue(); System.out.println(position + "\t->\t" + value); diff --git a/src/java/org/tensorics/core/lang/Tensorics.java b/src/java/org/tensorics/core/lang/Tensorics.java index e03204c74..2a2f3b215 100644 --- a/src/java/org/tensorics/core/lang/Tensorics.java +++ b/src/java/org/tensorics/core/lang/Tensorics.java @@ -57,11 +57,14 @@ import com.google.common.base.Optional; /** - * The main entry point for constructing and structural manipulation of tensorics. If mathematical operations are - * required, then you should either inherit from {@link TensoricSupport} (or one of its convenience implementations) or - * use the {@link #using(ExtendedField)} method (only recommended for one-liners). + * The main entry point for constructing and structural manipulation of + * tensorics. If mathematical operations are required, then you should either + * inherit from {@link TensoricSupport} (or one of its convenience + * implementations) or use the {@link #using(ExtendedField)} method (only + * recommended for one-liners). *

- * Additional utilities for supporting classes can be found in the corresponding utility classes. E.g. + * Additional utilities for supporting classes can be found in the corresponding + * utility classes. E.g. *

    *
  • {@link org.tensorics.core.tensor.Positions} *
  • {@link org.tensorics.core.tensor.Shapes} @@ -73,348 +76,361 @@ */ public final class Tensorics { - /** - * private constructor to avoid instantiation - */ - private Tensorics() { - /* only static methods */ - } - - /** - * Creates an instance of a 'support' type class, which provides methods as starting points for the 'fluent' API for - * tensor manipulation. - * - * @param field the (mathematical construct) field which defines the operations for the tensor elements. - * @return a tensoric support, which provides the starting methods for the tensoric fluent API. - * @param the types of values in the field - */ - public static TensoricSupport using(ExtendedField field) { - return new TensoricSupport<>(EnvironmentImpl.of(field, ManipulationOptions.defaultOptions(field))); - } - - public static Tensor merge(Iterable> tensors) { - return TensorStructurals.merge(tensors); - } - - /** - * @see TensorStructurals#mergeContextIntoShape(Tensor) - */ - public static Tensor mergeContextIntoShape(Tensor tensor) { - return TensorStructurals.mergeContextIntoShape(tensor); - } - - /** - * @see ImmutableTensor#builder(Set) - */ - public static TensorBuilder builder(Set> dimensions) { - return ImmutableTensor.builder(dimensions); - } - - /** - * @see ImmutableTensor#builder(Class...) - */ - public static TensorBuilder builder(Class... dimensions) { - return ImmutableTensor.builder(dimensions); - } - - /** - * @see ImmutableTensor#fromMap(Set, Map) - */ - public static Tensor fromMap(Set> dimensions, Map map) { - return ImmutableTensor.fromMap(dimensions, map); - } - - /** - * @see ImmutableTensor#copyOf(Tensor) - */ - public static Tensor copyOf(Tensor tensor) { - return ImmutableTensor.copyOf(tensor); - } - - /** - * @see ImmutableTensor#builderFrom(Tensor) - */ - public static TensorBuilder builderFrom(Tensor tensor) { - return ImmutableTensor.builderFrom(tensor); - } - - /** - * @see ImmutableTensor#zeroDimensionalOf(Object) - */ - public static Tensor zeroDimensionalOf(T value) { - return ImmutableTensor.zeroDimensionalOf(value); - } - - /** - * @see ImmutableQuantifiedValue#of(Object, Unit) - */ - public static ImmutableQuantifiedValue quantityOf(V value, Unit unit) { - return ImmutableQuantifiedValue.of(value, unit); - } - - /** - * Convenience method to create a quantity directly from a jscience unit. - * - * @param value the of the quantity - * @param unit the unit of the quantity - * @return a new instance of the quantity - * @see Tensorics#quantityOf(Object, Unit) - */ - public static ImmutableQuantifiedValue quantityOf(V value, javax.measure.unit.Unit unit) { - return quantityOf(value, JScienceUnit.of(unit)); - } - - /** - * @see Tensorbackeds#builderFor(Class) - */ - public static > TensorbackedBuilder builderFor(Class tensorbackedClass) { - return Tensorbackeds.builderFor(tensorbackedClass); - } - - /** - * @see Tensorbackeds#sizeOf(Tensorbacked) - */ - public static > int sizeOf(TB tensorbacked) { - return Tensorbackeds.sizeOf(tensorbacked); - } - - /** - * @see Tensorbackeds#dimensionalityOf(Tensorbacked) - */ - public static > int dimensionalityOf(TB tensorbacked) { - return Tensorbackeds.dimensionalityOf(tensorbacked); - } - - /** - * @see Tensorbackeds#empty(Class) - */ - public static > TB empty(Class tensorbackedClass) { - return Tensorbackeds.empty(tensorbackedClass); - } - - /** - * @see Tensorbackeds#validitiesOf(Tensorbacked) - */ - public static Tensor validitiesOf(Tensorbacked> tensorbacked) { - return Tensorbackeds.validitiesOf(tensorbacked); - } - - /** - * @see Tensorbackeds#valuesOf(Tensorbacked) - */ - public static Tensor valuesOf(Tensorbacked> tensorbacked) { - return Tensorbackeds.valuesOf(tensorbacked); - } - - /** - * @see Tensorbackeds#errorsOf(Tensorbacked) - */ - public static Tensor> errorsOf(Tensorbacked> tensorbacked) { - return Tensorbackeds.errorsOf(tensorbacked); - } - - /** - * @see Tensorbackeds#positionsOf(Tensorbacked) - */ - public static Set positionsOf(Tensorbacked tensorbacked) { - return Tensorbackeds.positionsOf(tensorbacked); - } - - /** - * @deprecated use renamed method {@link #quantityTensorOf(Tensor, Unit)} - */ - @Deprecated - public static Tensor> convertToQuantified(Tensor tensor, Unit unit) { - return QuantityTensors.quantityTensorOf(tensor, unit); - } - - /** - * @see QuantityTensors#quantityTensorOf(Tensor, Unit) - */ - public static Tensor> quantityTensorOf(Tensor tensor, Unit unit) { - return QuantityTensors.quantityTensorOf(tensor, unit); - } - - /** - * @see QuantityTensors#unitOf(Tensor) - */ - public static Unit unitOf(Tensor> tensor) { - return QuantityTensors.unitOf(tensor); - } - - /** - * @see Tensorbackeds#unitOf(Tensorbacked) - */ - public static Unit unitOf(Tensorbacked> tensorbacked) { - return Tensorbackeds.unitOf(tensorbacked); - } - - /** - * @see Tensorbackeds#shapeOf(Tensorbacked) - */ - public static Shape shapeOf(Tensorbacked tensorbacked) { - return Tensorbackeds.shapeOf(tensorbacked); - } - - public static Set> dimensionsOf(Tensorbacked tensorbacked) { - return Tensorbackeds.shapeOf(tensorbacked).dimensionSet(); - } - - /** - * @see TensorStructurals#from(Tensor) - */ - public static OngoingTensorManipulation from(Tensor tensor) { - return TensorStructurals.from(tensor); - } - - public static OngoingTensorManipulation from(Tensorbacked tensorbacked) { - return TensorStructurals.from(tensorbacked.tensor()); - } - - public static Set> dimensionsOf(Tensor tensor) { - return tensor.shape().dimensionSet(); - } - - public static Set positionsOf(Tensor tensor) { - return tensor.shape().positionSet(); - } - - public static Tensor validitiesOf(Tensor> tensor) { - return QuantityTensors.validitiesOf(tensor); - } - - public static Tensor valuesOf(Tensor> tensor) { - return QuantityTensors.valuesOf(tensor); - } - - public static Tensor> errorsOf(Tensor> tensor) { - return QuantityTensors.errorsOf(tensor); - } - - public static Tensor errorsOfOr(Tensor> tensor, S defaultValue) { - return QuantityTensors.errorsOfOr(tensor, defaultValue); - } - - public static OngoingFlattening flatten(Tensor tensor) { - return TensorStructurals.flatten(tensor); - } - - public static OngoingFlattening flatten(Tensorbacked tensorbacked) { - return Tensorbackeds.flatten(tensorbacked); - } - - public static Tensor sameValues(Shape shape, S value) { - return TensorInternals.sameValues(shape, value); - } - - public static Tensor createFrom(Shape shape, Supplier supplier) { - return TensorInternals.createFrom(shape, supplier); - } - - public static Tensor createFrom(Shape shape, Function function) { - return TensorInternals.createFrom(shape, function); - } - - public static OngoingCompletion complete(Tensor tensor) { - return TensorStructurals.complete(tensor); - } - - public static Tensor transformEntries(Tensor tensor, Function, T> function) { - return TensorStructurals.transformEntries(tensor, function); - } - - public static Tensor map(Tensor tensor, Function function) { - return TensorStructurals.transformScalars(tensor, function); - } - - public static final Tensor> zeroDimensionalOf(double value, - javax.measure.unit.Unit unit) { - QuantifiedValue quantity = quantityOf(value, unit); - return zeroDimensionalOf(quantity); - } - - public static final Tensor> zeroDimensionalOf(double value, Unit unit) { - QuantifiedValue quantity = quantityOf(value, unit); - return zeroDimensionalOf(quantity); - } - - /** - * @see Tensorbackeds#tensorsOf(Iterable) - */ - public static Iterable> tensorsOf(Iterable> tensorbackeds) { - return Tensorbackeds.tensorsOf(tensorbackeds); - } - - /** - * @see Tensorbackeds#construct(Class) - */ - public static > OngoingTensorbackedConstruction construct( - Class tensorbackedClass) { - return Tensorbackeds.construct(tensorbackedClass); - } - - /** - * @see Tensorbackeds#stripContext(Tensorbacked) - */ - public static > TB stripContext(TB tensorbacked) { - return Tensorbackeds.stripContext(tensorbacked); - } - - /** - * @see TensorStructurals#stripContext(Tensor) - */ - public static Tensor stripContext(Tensor tensor) { - return TensorStructurals.stripContext(tensor); - } - - /** - * @see TensorStructurals#filter(Tensor) - */ - public static OngoingTensorFiltering filter(Tensor tensor) { - return TensorStructurals.filter(tensor); - } - - /** - * @see Tensorbackeds#filter(Tensorbacked) - */ - public static > OngoingTensorbackedFiltering filter(TB tensorbacked) { - return Tensorbackeds.filter(tensorbacked); - } - - public static Tensor setContext(Tensor tensor, Position context) { - return TensorStructurals.setContext(tensor, context); - } - - public static > TB setContext(TB tensorbacked, Position context) { - return Tensorbackeds.setContext(tensorbacked, context); - } - - /** - * @see TensorStreams#tensorEntryStream(Tensor) - */ - public static Stream> stream(Tensor tensor) { - return TensorStreams.tensorEntryStream(tensor); - } - - /** - * @see TensorStreams#tensorEntryStream(Tensor) - */ - public static Stream> stream(Tensorbacked tensorBacked) { - return TensorStreams.tensorEntryStream(tensorBacked.tensor()); - } - - /** - * @see Tensorbackeds#shapeOf(Tensorbacked) - */ - public static > Iterable shapesOf(Iterable tensorbackeds) { - return Tensorbackeds.shapesOf(tensorbackeds); - } - - /** - * @see Tensorbackeds#complete(Tensorbacked) - */ - public static > OngoingTensorbackedCompletion complete(TB tensorbacked) { - return Tensorbackeds.complete(tensorbacked); - } + /** + * private constructor to avoid instantiation + */ + private Tensorics() { + /* only static methods */ + } + + /** + * Creates an instance of a 'support' type class, which provides methods as + * starting points for the 'fluent' API for tensor manipulation. + * + * @param field + * the (mathematical construct) field which defines the + * operations for the tensor elements. + * @return a tensoric support, which provides the starting methods for the + * tensoric fluent API. + * @param + * the types of values in the field + */ + public static TensoricSupport using(ExtendedField field) { + return new TensoricSupport<>(EnvironmentImpl.of(field, ManipulationOptions.defaultOptions(field))); + } + + public static Tensor merge(Iterable> tensors) { + return TensorStructurals.merge(tensors); + } + + /** + * @see TensorStructurals#mergeContextIntoShape(Tensor) + */ + public static Tensor mergeContextIntoShape(Tensor tensor) { + return TensorStructurals.mergeContextIntoShape(tensor); + } + + /** + * @see ImmutableTensor#builder(Set) + */ + public static TensorBuilder builder(Set> dimensions) { + return ImmutableTensor.builder(dimensions); + } + + /** + * @see ImmutableTensor#builder(Class...) + */ + public static TensorBuilder builder(Class... dimensions) { + return ImmutableTensor.builder(dimensions); + } + + /** + * @see ImmutableTensor#fromMap(Set, Map) + */ + public static Tensor fromMap(Set> dimensions, Map map) { + return ImmutableTensor.fromMap(dimensions, map); + } + + /** + * @see ImmutableTensor#copyOf(Tensor) + */ + public static Tensor copyOf(Tensor tensor) { + return ImmutableTensor.copyOf(tensor); + } + + /** + * @see ImmutableTensor#builderFrom(Tensor) + */ + public static TensorBuilder builderFrom(Tensor tensor) { + return ImmutableTensor.builderFrom(tensor); + } + + /** + * @see ImmutableTensor#zeroDimensionalOf(Object) + */ + public static Tensor zeroDimensionalOf(T value) { + return ImmutableTensor.zeroDimensionalOf(value); + } + + /** + * @see ImmutableQuantifiedValue#of(Object, Unit) + */ + public static ImmutableQuantifiedValue quantityOf(V value, Unit unit) { + return ImmutableQuantifiedValue.of(value, unit); + } + + /** + * Convenience method to create a quantity directly from a jscience unit. + * + * @param value + * the of the quantity + * @param unit + * the unit of the quantity + * @return a new instance of the quantity + * @see Tensorics#quantityOf(Object, Unit) + */ + public static ImmutableQuantifiedValue quantityOf(V value, javax.measure.unit.Unit unit) { + return quantityOf(value, JScienceUnit.of(unit)); + } + + /** + * @see Tensorbackeds#builderFor(Class) + */ + public static > TensorbackedBuilder builderFor(Class tensorbackedClass) { + return Tensorbackeds.builderFor(tensorbackedClass); + } + + /** + * @see Tensorbackeds#sizeOf(Tensorbacked) + */ + public static > int sizeOf(TB tensorbacked) { + return Tensorbackeds.sizeOf(tensorbacked); + } + + /** + * @see Tensorbackeds#dimensionalityOf(Tensorbacked) + */ + public static > int dimensionalityOf(TB tensorbacked) { + return Tensorbackeds.dimensionalityOf(tensorbacked); + } + + /** + * @see Tensorbackeds#empty(Class) + */ + public static > TB empty(Class tensorbackedClass) { + return Tensorbackeds.empty(tensorbackedClass); + } + + /** + * @see Tensorbackeds#validitiesOf(Tensorbacked) + */ + public static Tensor validitiesOf(Tensorbacked> tensorbacked) { + return Tensorbackeds.validitiesOf(tensorbacked); + } + + /** + * @see Tensorbackeds#valuesOf(Tensorbacked) + */ + public static Tensor valuesOf(Tensorbacked> tensorbacked) { + return Tensorbackeds.valuesOf(tensorbacked); + } + + /** + * @see Tensorbackeds#errorsOf(Tensorbacked) + */ + public static Tensor> errorsOf(Tensorbacked> tensorbacked) { + return Tensorbackeds.errorsOf(tensorbacked); + } + + /** + * @see Tensorbackeds#positionsOf(Tensorbacked) + */ + public static Set positionsOf(Tensorbacked tensorbacked) { + return Tensorbackeds.positionsOf(tensorbacked); + } + + /** + * @deprecated use renamed method {@link #quantityTensorOf(Tensor, Unit)} + */ + @Deprecated + public static Tensor> convertToQuantified(Tensor tensor, Unit unit) { + return QuantityTensors.quantityTensorOf(tensor, unit); + } + + /** + * @see QuantityTensors#quantityTensorOf(Tensor, Unit) + */ + public static Tensor> quantityTensorOf(Tensor tensor, Unit unit) { + return QuantityTensors.quantityTensorOf(tensor, unit); + } + + /** + * @see QuantityTensors#unitOf(Tensor) + */ + public static Unit unitOf(Tensor> tensor) { + return QuantityTensors.unitOf(tensor); + } + + /** + * @see Tensorbackeds#unitOf(Tensorbacked) + */ + public static Unit unitOf(Tensorbacked> tensorbacked) { + return Tensorbackeds.unitOf(tensorbacked); + } + + /** + * @see Tensorbackeds#shapeOf(Tensorbacked) + */ + public static Shape shapeOf(Tensorbacked tensorbacked) { + return Tensorbackeds.shapeOf(tensorbacked); + } + + public static Set> dimensionsOf(Tensorbacked tensorbacked) { + return Tensorbackeds.shapeOf(tensorbacked).dimensionSet(); + } + + /** + * @see TensorStructurals#from(Tensor) + */ + public static OngoingTensorManipulation from(Tensor tensor) { + return TensorStructurals.from(tensor); + } + + public static OngoingTensorManipulation from(Tensorbacked tensorbacked) { + return TensorStructurals.from(tensorbacked.tensor()); + } + + public static Set> dimensionsOf(Tensor tensor) { + return tensor.shape().dimensionSet(); + } + + public static Set positionsOf(Tensor tensor) { + return tensor.shape().positionSet(); + } + + public static Tensor validitiesOf(Tensor> tensor) { + return QuantityTensors.validitiesOf(tensor); + } + + public static Tensor valuesOf(Tensor> tensor) { + return QuantityTensors.valuesOf(tensor); + } + + public static Tensor> errorsOf(Tensor> tensor) { + return QuantityTensors.errorsOf(tensor); + } + + public static Tensor errorsOfOr(Tensor> tensor, S defaultValue) { + return QuantityTensors.errorsOfOr(tensor, defaultValue); + } + + public static OngoingFlattening flatten(Tensor tensor) { + return TensorStructurals.flatten(tensor); + } + + public static OngoingFlattening flatten(Tensorbacked tensorbacked) { + return Tensorbackeds.flatten(tensorbacked); + } + + public static Tensor sameValues(Shape shape, S value) { + return TensorInternals.sameValues(shape, value); + } + + public static Tensor createFrom(Shape shape, Supplier supplier) { + return TensorInternals.createFrom(shape, supplier); + } + + public static Tensor createFrom(Shape shape, Function function) { + return TensorInternals.createFrom(shape, function); + } + + public static OngoingCompletion complete(Tensor tensor) { + return TensorStructurals.complete(tensor); + } + + public static Tensor transformEntries(Tensor tensor, Function, T> function) { + return TensorStructurals.transformEntries(tensor, function); + } + + public static Tensor map(Tensor tensor, Function function) { + return TensorStructurals.transformScalars(tensor, function); + } + + public static final Tensor> zeroDimensionalOf(double value, + javax.measure.unit.Unit unit) { + QuantifiedValue quantity = quantityOf(value, unit); + return zeroDimensionalOf(quantity); + } + + public static final Tensor> zeroDimensionalOf(double value, Unit unit) { + QuantifiedValue quantity = quantityOf(value, unit); + return zeroDimensionalOf(quantity); + } + + /** + * @see Tensorbackeds#tensorsOf(Iterable) + */ + public static Iterable> tensorsOf(Iterable> tensorbackeds) { + return Tensorbackeds.tensorsOf(tensorbackeds); + } + + /** + * @see Tensorbackeds#construct(Class) + */ + public static > OngoingTensorbackedConstruction construct( + Class tensorbackedClass) { + return Tensorbackeds.construct(tensorbackedClass); + } + + /** + * @see Tensorbackeds#stripContext(Tensorbacked) + */ + public static > TB stripContext(TB tensorbacked) { + return Tensorbackeds.stripContext(tensorbacked); + } + + /** + * @see TensorStructurals#stripContext(Tensor) + */ + public static Tensor stripContext(Tensor tensor) { + return TensorStructurals.stripContext(tensor); + } + + /** + * @see TensorStructurals#filter(Tensor) + */ + public static OngoingTensorFiltering filter(Tensor tensor) { + return TensorStructurals.filter(tensor); + } + + /** + * @see Tensorbackeds#filter(Tensorbacked) + */ + public static > OngoingTensorbackedFiltering filter(TB tensorbacked) { + return Tensorbackeds.filter(tensorbacked); + } + + public static Tensor setContext(Tensor tensor, Position context) { + return TensorStructurals.setContext(tensor, context); + } + + public static > TB setContext(TB tensorbacked, Position context) { + return Tensorbackeds.setContext(tensorbacked, context); + } + + /** + * @see TensorStreams#tensorEntryStream(Tensor) + */ + public static Stream> stream(Tensor tensor) { + return TensorStreams.tensorEntryStream(tensor); + } + + /** + * @see TensorStreams#tensorEntryStream(Tensor) + */ + public static Stream> stream(Tensorbacked tensorBacked) { + return TensorStreams.tensorEntryStream(tensorBacked.tensor()); + } + + /** + * @see Tensorbackeds#shapeOf(Tensorbacked) + */ + public static > Iterable shapesOf(Iterable tensorbackeds) { + return Tensorbackeds.shapesOf(tensorbackeds); + } + + /** + * @see Tensorbackeds#complete(Tensorbacked) + */ + public static > OngoingTensorbackedCompletion complete(TB tensorbacked) { + return Tensorbackeds.complete(tensorbacked); + } + + /** + * @see TensorInternals#mapFrom(Tensor) + */ + public static Map mapFrom(Tensor tensor) { + return TensorInternals.mapFrom(tensor); + } } diff --git a/src/java/org/tensorics/core/tensor/AbstractTensorBuilder.java b/src/java/org/tensorics/core/tensor/AbstractTensorBuilder.java index c5d52ed2d..332dc34c3 100644 --- a/src/java/org/tensorics/core/tensor/AbstractTensorBuilder.java +++ b/src/java/org/tensorics/core/tensor/AbstractTensorBuilder.java @@ -27,6 +27,8 @@ import java.util.Map.Entry; import java.util.Set; +import org.tensorics.core.tensor.operations.TensorInternals; + import com.google.common.base.Preconditions; import com.google.common.collect.ImmutableSet; @@ -125,7 +127,7 @@ public final OngoingPut at(Object... coordinates) { public final void putAllAt(Tensor tensor, Position position) { checkNotNull(tensor, "The tensor must not be null!"); checkNotNull(position, "The position must not be null!"); - for (Entry entry : tensor.asMap().entrySet()) { + for (Entry entry : TensorInternals.mapFrom(tensor).entrySet()) { putAt(entry.getValue(), Positions.union(position, entry.getKey())); } } diff --git a/src/java/org/tensorics/core/tensor/BroadcastedTensorView.java b/src/java/org/tensorics/core/tensor/BroadcastedTensorView.java index a974a8123..ba00ff8df 100644 --- a/src/java/org/tensorics/core/tensor/BroadcastedTensorView.java +++ b/src/java/org/tensorics/core/tensor/BroadcastedTensorView.java @@ -46,7 +46,7 @@ * @author kfuchsbe * @param the type of the values of the tensor */ -public final class BroadcastedTensorView implements Tensor { +public final class BroadcastedTensorView implements MapableTensor { /** The original (smaller) tensor */ private final Tensor originalTensor; diff --git a/src/java/org/tensorics/core/tensor/ImmutableTensor.java b/src/java/org/tensorics/core/tensor/ImmutableTensor.java index 0f8c935e1..bb3d42d24 100644 --- a/src/java/org/tensorics/core/tensor/ImmutableTensor.java +++ b/src/java/org/tensorics/core/tensor/ImmutableTensor.java @@ -29,6 +29,8 @@ import java.util.NoSuchElementException; import java.util.Set; +import org.tensorics.core.tensor.operations.TensorInternals; + import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableMultiset; @@ -48,7 +50,7 @@ * @author agorzaws, kfuchsbe * @param type of values in Tensor. */ -public class ImmutableTensor implements Tensor, Serializable { +public class ImmutableTensor implements MapableTensor, Serializable { private static final long serialVersionUID = 1L; @@ -161,7 +163,7 @@ public static final Tensor zeroDimensionalOf(T value) { */ public static final Tensor copyOf(Tensor tensor) { Builder builder = builder(tensor.shape().dimensionSet()); - builder.putAllMap(tensor.asMap()); + builder.putAllMap(TensorInternals.mapFrom(tensor)); builder.context(tensor.context()); return builder.build(); } @@ -175,7 +177,7 @@ public static final Tensor copyOf(Tensor tensor) { */ public static Builder builderFrom(Tensor tensor) { Builder builder = builder(tensor.shape().dimensionSet()); - builder.putAllMap(tensor.asMap()); + builder.putAllMap(TensorInternals.mapFrom(tensor)); return builder; } diff --git a/src/java/org/tensorics/core/tensor/MapableTensor.java b/src/java/org/tensorics/core/tensor/MapableTensor.java index 73cf473c8..f7d3c2530 100644 --- a/src/java/org/tensorics/core/tensor/MapableTensor.java +++ b/src/java/org/tensorics/core/tensor/MapableTensor.java @@ -1,5 +1,7 @@ package org.tensorics.core.tensor; +import java.util.Map; + /** * Enhances the tensor interface by a method to view the tensor as a map from * position to values. This interface is intended to be used by utility methods @@ -11,5 +13,7 @@ * the type of the values of the tensors */ public interface MapableTensor extends Tensor { + + public Map asMap(); } diff --git a/src/java/org/tensorics/core/tensor/Tensor.java b/src/java/org/tensorics/core/tensor/Tensor.java index 0e2333116..e9eb769f8 100644 --- a/src/java/org/tensorics/core/tensor/Tensor.java +++ b/src/java/org/tensorics/core/tensor/Tensor.java @@ -22,7 +22,6 @@ package org.tensorics.core.tensor; -import java.util.Map; /** * The top interface for {@link Tensor} like objects. @@ -57,13 +56,6 @@ public interface Tensor { */ E get(Object... coordinates); - /** - * @return all the entries as a map of Position to value. There is no - * guarantee about the thread safety or mutability of the returned - * {@link Map}. - */ - Map asMap(); - /** * Retrieves the shape of the tensor. As shape we understand simply the * structure of a tensor: Its dimensions and the available positions. diff --git a/src/java/org/tensorics/core/tensor/lang/OngoingDimensionFlattening.java b/src/java/org/tensorics/core/tensor/lang/OngoingDimensionFlattening.java index dc98123ce..896416549 100644 --- a/src/java/org/tensorics/core/tensor/lang/OngoingDimensionFlattening.java +++ b/src/java/org/tensorics/core/tensor/lang/OngoingDimensionFlattening.java @@ -29,6 +29,7 @@ import org.tensorics.core.tensor.Positions; import org.tensorics.core.tensor.Positions.DimensionStripper; import org.tensorics.core.tensor.Tensor; +import org.tensorics.core.tensor.operations.TensorInternals; import com.google.common.collect.ImmutableSetMultimap; import com.google.common.collect.Multimaps; @@ -54,7 +55,7 @@ public Tensor> intoTensorOfSets() { private SetMultimap intoSetMultimap() { ImmutableSetMultimap.Builder builder = ImmutableSetMultimap.builder(); DimensionStripper dimensionStripper = Positions.stripping(dimensionsToFlatten); - for (java.util.Map.Entry entry : tensor.asMap().entrySet()) { + for (java.util.Map.Entry entry : TensorInternals.mapFrom(tensor).entrySet()) { Position newPosition = dimensionStripper.apply(entry.getKey()); builder.put(newPosition, entry.getValue()); } diff --git a/src/java/org/tensorics/core/tensor/lang/OngoingTensorFiltering.java b/src/java/org/tensorics/core/tensor/lang/OngoingTensorFiltering.java index 1c810bf94..b7858e113 100644 --- a/src/java/org/tensorics/core/tensor/lang/OngoingTensorFiltering.java +++ b/src/java/org/tensorics/core/tensor/lang/OngoingTensorFiltering.java @@ -28,6 +28,7 @@ import org.tensorics.core.tensor.ImmutableTensor; import org.tensorics.core.tensor.Position; import org.tensorics.core.tensor.Tensor; +import org.tensorics.core.tensor.operations.TensorInternals; import com.google.common.collect.Range; @@ -52,7 +53,7 @@ public > Tensor by(Class coordinateClass, Range ImmutableTensor.Builder builder = ImmutableTensor.builder(tensor.shape().dimensionSet()); builder.context(tensor.context()); - for (Entry entry : tensor.asMap().entrySet()) { + for (Entry entry : TensorInternals.mapFrom(tensor).entrySet()) { if (coordinateRange.contains(entry.getKey().coordinateFor(coordinateClass))) { builder.putAt(entry.getValue(), entry.getKey()); } diff --git a/src/java/org/tensorics/core/tensor/lang/OngoingTensorManipulation.java b/src/java/org/tensorics/core/tensor/lang/OngoingTensorManipulation.java index aa975a4b8..fbef4baf9 100644 --- a/src/java/org/tensorics/core/tensor/lang/OngoingTensorManipulation.java +++ b/src/java/org/tensorics/core/tensor/lang/OngoingTensorManipulation.java @@ -34,6 +34,7 @@ import org.tensorics.core.tensor.ImmutableTensor.Builder; import org.tensorics.core.tensor.Position; import org.tensorics.core.tensor.Tensor; +import org.tensorics.core.tensor.operations.TensorInternals; /** * Part of the tensoric fluent API which provides methods to describe misc manipulations on a given tensor. @@ -60,7 +61,7 @@ public class OngoingTensorManipulation { */ public Tensor extractWhereTrue(Tensor mask) { Builder tensorBuilder = ImmutableTensor.builder(tensor.shape().dimensionSet()); - for (java.util.Map.Entry entry : tensor.asMap().entrySet()) { + for (java.util.Map.Entry entry : TensorInternals.mapFrom(tensor).entrySet()) { if (mask.get(entry.getKey()).booleanValue()) { tensorBuilder.at(entry.getKey()).put(entry.getValue()); } diff --git a/src/java/org/tensorics/core/tensor/lang/QuantityTensors.java b/src/java/org/tensorics/core/tensor/lang/QuantityTensors.java index 0f07da287..457f24f20 100644 --- a/src/java/org/tensorics/core/tensor/lang/QuantityTensors.java +++ b/src/java/org/tensorics/core/tensor/lang/QuantityTensors.java @@ -28,6 +28,7 @@ import org.tensorics.core.tensor.ImmutableTensor.Builder; import org.tensorics.core.tensor.Position; import org.tensorics.core.tensor.Tensor; +import org.tensorics.core.tensor.operations.TensorInternals; import org.tensorics.core.units.Unit; import com.google.common.base.Optional; @@ -49,7 +50,7 @@ private QuantityTensors() { public static Tensor valuesOf(Tensor> tensor) { Builder builder = ImmutableTensor.builder(tensor.shape().dimensionSet()); builder.context(tensor.context()); - for (java.util.Map.Entry> entry : tensor.asMap().entrySet()) { + for (java.util.Map.Entry> entry : TensorInternals.mapFrom(tensor).entrySet()) { builder.at(entry.getKey()).put(entry.getValue().value()); } return builder.build(); @@ -58,7 +59,7 @@ public static Tensor valuesOf(Tensor> tensor) { public static Tensor> errorsOf(Tensor> tensor) { Builder> builder = ImmutableTensor.builder(tensor.shape().dimensionSet()); builder.context(tensor.context()); - for (java.util.Map.Entry> entry : tensor.asMap().entrySet()) { + for (java.util.Map.Entry> entry : TensorInternals.mapFrom(tensor).entrySet()) { builder.at(entry.getKey()).put(entry.getValue().error()); } return builder.build(); @@ -67,7 +68,7 @@ public static Tensor> errorsOf(Tensor> tensor public static Tensor errorsOfOr(Tensor> tensor, S defaultValue) { Builder builder = ImmutableTensor.builder(tensor.shape().dimensionSet()); builder.context(tensor.context()); - for (java.util.Map.Entry> entry : tensor.asMap().entrySet()) { + for (java.util.Map.Entry> entry : TensorInternals.mapFrom(tensor).entrySet()) { builder.at(entry.getKey()).put(entry.getValue().error().or(defaultValue)); } return builder.build(); @@ -76,7 +77,7 @@ public static Tensor errorsOfOr(Tensor> tensor, S defa public static Tensor validitiesOf(Tensor> tensor) { Builder builder = ImmutableTensor.builder(tensor.shape().dimensionSet()); builder.context(tensor.context()); - for (java.util.Map.Entry> entry : tensor.asMap().entrySet()) { + for (java.util.Map.Entry> entry : TensorInternals.mapFrom(tensor).entrySet()) { builder.at(entry.getKey()).put(entry.getValue().validity()); } return builder.build(); @@ -86,7 +87,7 @@ public static Unit unitOf(Tensor> tensor) { /* * XXX this is nasty! Even an empty tensor should have a correct unit ...probably? */ - for (java.util.Map.Entry> entry : tensor.asMap().entrySet()) { + for (java.util.Map.Entry> entry : TensorInternals.mapFrom(tensor).entrySet()) { return entry.getValue().unit(); } throw new IllegalArgumentException("No entries in the given tensor! Cannot find out what is the unit."); @@ -95,7 +96,7 @@ public static Unit unitOf(Tensor> tensor) { public static Tensor> quantityTensorOf(Tensor tensor, Unit unit) { Builder> builder = ImmutableTensor.builder(tensor.shape().dimensionSet()); builder.context(tensor.context()); - for (java.util.Map.Entry entry : tensor.asMap().entrySet()) { + for (java.util.Map.Entry entry : TensorInternals.mapFrom(tensor).entrySet()) { builder.at(entry.getKey()).put(ImmutableQuantifiedValue.of(entry.getValue(), unit)); } return builder.build(); diff --git a/src/java/org/tensorics/core/tensor/lang/TensorStructurals.java b/src/java/org/tensorics/core/tensor/lang/TensorStructurals.java index 3c8e485a8..73e7aa1ec 100644 --- a/src/java/org/tensorics/core/tensor/lang/TensorStructurals.java +++ b/src/java/org/tensorics/core/tensor/lang/TensorStructurals.java @@ -35,6 +35,7 @@ import org.tensorics.core.tensor.Shape; import org.tensorics.core.tensor.Shapes; import org.tensorics.core.tensor.Tensor; +import org.tensorics.core.tensor.operations.TensorInternals; import com.google.common.collect.Iterables; import com.google.common.collect.Sets; @@ -125,7 +126,7 @@ public static final OngoingCompletion complete(Tensor tensor) { public static Tensor transformEntries(Tensor tensor, Function, T> function) { Builder builder = ImmutableTensor.builder(tensor.shape().dimensionSet()); - for (Entry entry : tensor.asMap().entrySet()) { + for (Entry entry : TensorInternals.mapFrom(tensor).entrySet()) { builder.putAt(function.apply(entry), entry.getKey()); } return builder.build(); @@ -134,7 +135,7 @@ public static Tensor transformEntries(Tensor tensor, Function Tensor transformScalars(Tensor tensor, Function function) { Builder builder = ImmutableTensor.builder(tensor.shape().dimensionSet()); builder.context(tensor.context()); - for (Entry entry : tensor.asMap().entrySet()) { + for (Entry entry : TensorInternals.mapFrom(tensor).entrySet()) { builder.putAt(function.apply(entry.getValue()), entry.getKey()); } return builder.build(); diff --git a/src/java/org/tensorics/core/tensor/operations/OngoingMapOut.java b/src/java/org/tensorics/core/tensor/operations/OngoingMapOut.java index 7d2555ac6..274ad0574 100644 --- a/src/java/org/tensorics/core/tensor/operations/OngoingMapOut.java +++ b/src/java/org/tensorics/core/tensor/operations/OngoingMapOut.java @@ -59,7 +59,7 @@ public Tensor> inDirectionOf(Class dimension) { tensorBuilder.context(tensor.context()); // XXX IS this correct? - Multimap, Entry> fullEntries = groupBy(tensor.asMap().entrySet(), dimension); + Multimap, Entry> fullEntries = groupBy(TensorInternals.mapFrom(tensor).entrySet(), dimension); for (Set key : fullEntries.keySet()) { Map values = mapByDimension(fullEntries.get(key), dimension); tensorBuilder.at(Position.of(key)).put(values); diff --git a/src/java/org/tensorics/core/tensor/operations/TensorInternals.java b/src/java/org/tensorics/core/tensor/operations/TensorInternals.java index 75a0a2d5a..9c8c1a70b 100644 --- a/src/java/org/tensorics/core/tensor/operations/TensorInternals.java +++ b/src/java/org/tensorics/core/tensor/operations/TensorInternals.java @@ -22,17 +22,22 @@ package org.tensorics.core.tensor.operations; +import static java.util.Objects.requireNonNull; import static org.tensorics.core.tensor.operations.PositionFunctions.forSupplier; +import java.util.Map; import java.util.Map.Entry; import java.util.Set; import java.util.function.Function; import java.util.function.Supplier; +import org.tensorics.core.tensor.MapableTensor; import org.tensorics.core.tensor.Position; import org.tensorics.core.tensor.Shape; import org.tensorics.core.tensor.Tensor; +import com.google.common.collect.ImmutableMap; + /** * Utility methods for tensors which are not exposed to the public API * @@ -40,28 +45,54 @@ */ public final class TensorInternals { - private TensorInternals() { - /* only static methods */ - } + private TensorInternals() { + /* only static methods */ + } + + public static OngoingMapOut mapOut(Tensor tensor) { + return new OngoingMapOut<>(tensor); + } - public static OngoingMapOut mapOut(Tensor tensor) { - return new OngoingMapOut<>(tensor); - } + public static Set> entrySetOf(Tensor tensor) { + return mapFrom(tensor).entrySet(); + } - public static Set> entrySetOf(Tensor tensor) { - return tensor.asMap().entrySet(); - } + public static Tensor sameValues(Shape shape, S value) { + return new SingleValueTensorCreationOperation(shape, value).perform(); + } - public static Tensor sameValues(Shape shape, S value) { - return new SingleValueTensorCreationOperation(shape, value).perform(); - } + public static Tensor createFrom(Shape shape, Supplier supplier) { + return new FunctionTensorCreationOperation<>(shape, forSupplier(supplier)).perform(); + } - public static Tensor createFrom(Shape shape, Supplier supplier) { - return new FunctionTensorCreationOperation<>(shape, forSupplier(supplier)).perform(); - } + public static Tensor createFrom(Shape shape, Function function) { + return new FunctionTensorCreationOperation<>(shape, function).perform(); + } - public static Tensor createFrom(Shape shape, Function function) { - return new FunctionTensorCreationOperation<>(shape, function).perform(); - } + /** + * Returns a map representing the content of the given tensor. The concrete + * instance of the map might differ depending on the implementation of the + * passed in tensor: Tensor implementations can offer a more efficient way + * to retrieve a map from them, by implementing the {@link MapableTensor} + * interface. If this interface is present, then its + * {@link MapableTensor#asMapOld()} method will be called. Otherwise, as a + * fallback, a new immutable map will be created from information from the + * shape of the passed in tensor and its values. + * + * @param tensor + * the tensor from which a map should be returned + * @return a map representing the context of the tensor + */ + public static Map mapFrom(Tensor tensor) { + requireNonNull(tensor, "tensor must not be null"); + if (tensor instanceof MapableTensor) { + return ((MapableTensor) tensor).asMap(); + } + ImmutableMap.Builder builder = ImmutableMap.builder(); + for (Position position : tensor.shape().positionSet()) { + builder.put(position, tensor.get(position)); + } + return builder.build(); + } } diff --git a/src/java/org/tensorics/core/tensor/operations/TensorReduction.java b/src/java/org/tensorics/core/tensor/operations/TensorReduction.java index 69239745a..6186f2d1b 100644 --- a/src/java/org/tensorics/core/tensor/operations/TensorReduction.java +++ b/src/java/org/tensorics/core/tensor/operations/TensorReduction.java @@ -59,7 +59,7 @@ public Tensor apply(Tensor value) { Builder builder = ImmutableTensor.builder(mapped.shape().dimensionSet()); builder.context(reductionStrategy.context(value.context())); - for (Entry> entry : mapped.asMap().entrySet()) { + for (Entry> entry : TensorInternals.mapFrom(mapped).entrySet()) { R reducedValue = reductionStrategy.reduce(entry.getValue(), entry.getKey()); if (reducedValue != null) { builder.at(entry.getKey()).put(reducedValue); diff --git a/src/java/org/tensorics/core/tensor/specific/ImmutableDoubleArrayBackedTensor.java b/src/java/org/tensorics/core/tensor/specific/ImmutableDoubleArrayBackedTensor.java index 9bb33d488..9d3515c80 100644 --- a/src/java/org/tensorics/core/tensor/specific/ImmutableDoubleArrayBackedTensor.java +++ b/src/java/org/tensorics/core/tensor/specific/ImmutableDoubleArrayBackedTensor.java @@ -25,6 +25,7 @@ import java.util.Map; import org.tensorics.core.tensor.AbstractTensorBuilder; +import org.tensorics.core.tensor.MapableTensor; import org.tensorics.core.tensor.Position; import org.tensorics.core.tensor.Shape; import org.tensorics.core.tensor.Tensor; @@ -38,7 +39,7 @@ * * @author kaifox */ -public class ImmutableDoubleArrayBackedTensor implements Tensor { +public class ImmutableDoubleArrayBackedTensor implements MapableTensor { private final PositionIndexer indexer; private final double[] values; diff --git a/src/java/org/tensorics/core/tensor/stream/TensorStreams.java b/src/java/org/tensorics/core/tensor/stream/TensorStreams.java index d5b7ad1cd..3fb2b13c4 100644 --- a/src/java/org/tensorics/core/tensor/stream/TensorStreams.java +++ b/src/java/org/tensorics/core/tensor/stream/TensorStreams.java @@ -27,6 +27,7 @@ import org.tensorics.core.tensor.Position; import org.tensorics.core.tensor.Tensor; +import org.tensorics.core.tensor.operations.TensorInternals; import org.tensorics.core.tensorbacked.Tensorbacked; /** @@ -46,7 +47,7 @@ private TensorStreams() { * @return */ public static Stream> tensorEntryStream(Tensor tensor) { - return tensor.asMap().entrySet().stream(); + return TensorInternals.mapFrom(tensor).entrySet().stream(); } diff --git a/src/test/org/tensorics/core/function/AbstractDiscreteFunctionVs1DTensorTest.java b/src/test/org/tensorics/core/function/AbstractDiscreteFunctionVs1DTensorTest.java index 418fc9b37..fa708c591 100644 --- a/src/test/org/tensorics/core/function/AbstractDiscreteFunctionVs1DTensorTest.java +++ b/src/test/org/tensorics/core/function/AbstractDiscreteFunctionVs1DTensorTest.java @@ -92,12 +92,11 @@ public void testTensorStd() { } private void assertThatAllTensorElementsEqualTo(Tensor tensor, T value) { - - assertTrue(tensor.asMap().values().stream().allMatch(value::equals)); + assertTrue(Tensorics.mapFrom(tensor).values().stream().allMatch(value::equals)); } private void assertTensorNotEmpty(Tensor tensor) { - assertFalse(tensor.asMap().isEmpty()); + assertFalse(Tensorics.mapFrom(tensor).isEmpty()); } private void assertThatTensorContainsCoordinatesOfTwoOperands(Tensor tensorResult, Tensor operand1, diff --git a/src/test/org/tensorics/core/lang/TensorCalculationsTest.java b/src/test/org/tensorics/core/lang/TensorCalculationsTest.java index ef8e830db..ca2a559da 100644 --- a/src/test/org/tensorics/core/lang/TensorCalculationsTest.java +++ b/src/test/org/tensorics/core/lang/TensorCalculationsTest.java @@ -65,639 +65,640 @@ */ public class TensorCalculationsTest { - private static final int Z_COOR_NUMBER = 1; - private static final int Y_COOR_NUMBER = 2; - private static final int X_COOR_NUMBER = 512; - - private Tensor tensor1; - private Tensor tensor1Flags; - private Tensor tensor2; - private Tensor tensor3Big; - private TensoricSupport tensoricFieldUsage; - - @Before - public void setUp() throws Exception { - tensoricFieldUsage = Tensorics.using(Structures.doubles()); - tensor1 = prepareValues(1.0); - tensor1Flags = prepareOnlyEvenValuesTrueFlag(); - tensor2 = prepareValues(2.5); - System.out.println("============== <<<<<<<<<< NEXT TEST >>>>>>>>>> ============="); - } - - @Test - public void averageOverOneDimensionOnValue1() { - YCoordinate y = YCoordinate.of(1); - Tensor averagedOverX = TensorStructurals.from(tensor1).reduce(XCoordinate.class) - .byAveragingIn(doubles()); - assertEquals(4.5, averagedOverX.get(Position.of(y)), 0.0); - } - - @Test - public void averageOverOneDimensionKeepingOther() { - Tensor averageOverYCoordinte = TensorStructurals.from(tensor1).reduce(XCoordinate.class) - .byAveragingIn(doubles()); - assertEquals(tensor1.shape().dimensionSet().size() - 1, averageOverYCoordinte.shape().dimensionSet().size()); - Set coordinateValues = TensorStructurals.from(averageOverYCoordinte) - .extractCoordinatesOfType(YCoordinate.class); - assertEquals(10, coordinateValues.size()); - } - - @Test - public void testMultiplyByNumber() { - YCoordinate y = YCoordinate.of(1); - XCoordinate x = XCoordinate.of(3); - Tensor tensor = tensoricFieldUsage.calculate(tensor1).elementTimesV(-1.0); - assertEquals(-3, tensor.get(x, y).doubleValue(), 0.0); - } - - @Test - public void testDivideByNumber() { - YCoordinate y = YCoordinate.of(1); - XCoordinate x = XCoordinate.of(3); - Tensor tensor = tensoricFieldUsage.calculate(tensor1).elementDividedByV(2.0); - assertEquals(1.5, tensor.get(x, y).doubleValue(), 0.0); - } - - @Test - public void testRMSCalculation() { - YCoordinate y = YCoordinate.of(1); - double rms = TensorStructurals.from(tensor1).reduce(XCoordinate.class).byRmsIn(doubles()).get(y); - - assertEquals(5.33, rms, 0.01); - double rms2 = TensorStructurals.from(tensor1).reduce(XCoordinate.class).byRmsIn(doubles()).get(Position.of(y)); - assertEquals(5.33, rms2, 0.01); - } - - @Test(expected = IllegalArgumentException.class) - public void testRMSCalculationTooManyCoordiantes() { - YCoordinate y = YCoordinate.of(1); - XCoordinate x = XCoordinate.of(2); - TensorStructurals.from(tensor1).reduce(XCoordinate.class).byRmsIn(doubles()).get(x, y); - } - - @Test - public void testMeanCalculation() { - YCoordinate y = YCoordinate.of(1); - double mean2 = TensorStructurals.from(TensorStructurals.from(tensor1).extract(y)).reduce(XCoordinate.class) - .byAveragingIn(doubles()).get(Position.empty()); - assertEquals(4.5, mean2, 0.0); - } - - @Test - public void testAddition() { - YCoordinate y = YCoordinate.of(2); - XCoordinate x = XCoordinate.of(6); - Tensor tensor = tensoricFieldUsage.calculate(tensor1).plus(tensor1); - assertEquals(24.0, tensor.get(x, y).doubleValue(), 0.0); - } - - @Test - public void testSubtraction() { - YCoordinate y = YCoordinate.of(2); - XCoordinate x = XCoordinate.of(6); - Tensor tensor = tensoricFieldUsage.calculate(tensor1).minus(tensor1); - assertEquals(0.0, tensor.get(x, y).doubleValue(), 0.0); - } - - @Test - public void testFluentAddition() { - YCoordinate y = YCoordinate.of(2); - XCoordinate x = XCoordinate.of(6); - Tensor tensor = tensoricFieldUsage.calculate(tensor1).plus(tensor1); - assertEquals(24.0, tensor.get(x, y).doubleValue(), 0.0); - } - - @Test - public void testAdditionOf2elementsTo100WithResult2() { - YCoordinate y = YCoordinate.of(2); - XCoordinate x = XCoordinate.of(6); - XCoordinate x2 = XCoordinate.of(3); - - Builder builder = ImmutableTensor.builder(ImmutableSet.of(y.getClass(), x.getClass())); - builder.at(Position.of(ImmutableSet.of(x, y))).put(13.2); - builder.at(Position.of(ImmutableSet.of(x2, y))).put(-1.2); - Tensor testTensor = builder.build(); - - Tensor tensor = tensoricFieldUsage.calculate(tensor1).plus(testTensor); - assertEquals(25.2, tensor.get(x, y).doubleValue(), 0.0); - } - - @Test - public void testAdditionOf2elementsTo2() { - YCoordinate y = YCoordinate.of(2); - XCoordinate x = XCoordinate.of(6); - XCoordinate x2 = XCoordinate.of(3); - - Builder builder = ImmutableTensor.builder(ImmutableSet.of(y.getClass(), x.getClass())); - builder.at(Position.of(ImmutableSet.of(x, y))).put(13.2); - builder.at(Position.of(ImmutableSet.of(x2, y))).put(-1.2); - Tensor testTensor = builder.build(); - - Builder builder2 = ImmutableTensor.builder(ImmutableSet.of(y.getClass(), x.getClass())); - builder2.at(Position.of(ImmutableSet.of(x, y))).put(1.2); - builder2.at(Position.of(ImmutableSet.of(x2, y))).put(1.2); - Tensor testTensor2 = builder2.build(); - Tensor tensor = tensoricFieldUsage.calculate(testTensor).plus(testTensor2); - assertEquals(14.4, tensor.get(x, y).doubleValue(), 0.001); - } - - @Test - public void testFlagApplience() { - Tensor tensor = from(tensor1).extractWhereTrue(tensor1Flags); - YCoordinate y = YCoordinate.of(2); - XCoordinate x = XCoordinate.of(6); - assertEquals(12.0, tensor.get(Position.of(ImmutableSet.of(x, y))).doubleValue(), 0.0); - assertEquals(5, TensorStructurals.from(tensor).extractCoordinatesOfType(x.getClass()).size()); - } - - @Test(expected = NoSuchElementException.class) - public void testFlagApplienceFailure() { - Tensor tensor = from(tensor1).extractWhereTrue(tensor1Flags); - YCoordinate y = YCoordinate.of(2); - XCoordinate x = XCoordinate.of(7); - assertEquals(14.0, tensor.get(x, y).doubleValue(), 0.0); - } - - @Test - public void testAdditionFrom2elementsTo100WithWrongShapes() { - XCoordinate x = XCoordinate.of(6); - XCoordinate x2 = XCoordinate.of(3); - Builder builder = ImmutableTensor.builder(ImmutableSet.of(x.getClass())); - double x1Add = 13.2; - double x2Add = -1.2; - builder.at(Position.of(x)).put(x1Add); - builder.at(Position.of(x2)).put(x2Add); - Tensor testTensor = builder.build(); - Tensor result = tensoricFieldUsage.calculate(tensor1).plus(testTensor); - - /* - * from broadcasting the y dimension of the test tensor to the values of tensor1 (10 values) together with the - * two x-coordinates, we expect a tensor of sixe 20. - */ - assertEquals(20, result.shape().size()); - - checkCorrectlyAdded(x, x1Add, result); - checkCorrectlyAdded(x2, x2Add, result); - } - - private void checkCorrectlyAdded(XCoordinate x, double x1Add, Tensor result) { - for (java.util.Map.Entry entry : result.asMap().entrySet()) { - Position position = entry.getKey(); - if (x.equals(position.coordinateFor(XCoordinate.class))) { - assertEquals(tensor1.get(position) + x1Add, entry.getValue(), 0.0000001); - } - } - } - - @Test(expected = IllegalArgumentException.class) - public void testReductionOnNonExistingCoordinate() { - TensorStructurals.from(tensor1).extract(ZCoordinate.of(1)); - } - - @Test - public void testOperationsOnBig512x2x1Tensor() { - long totalDiff = calculateOnTensor(X_COOR_NUMBER, Y_COOR_NUMBER, Z_COOR_NUMBER, true); - assertTrue(totalDiff < 800); - } - - @Test - @Ignore - public void profileTensorPreparation() { - int maxY = 1000; - int step = 100; - int nX = 100; - int nZ = 1; - populateCaches(maxY); - populatePositionCache(nX, maxY, nZ); - List results = new ArrayList<>(); - for (int nY = step; nY <= maxY; nY += step) { - results.add(profileTensorPreparation(nX, nY, nZ)); - } - printProfileResult(results); - } - - @Test - @Ignore - public void profileDoubleTensorPreparation() { - int maxY = 1000; - int step = 100; - int nX = 100; - int nZ = 1; - populateCaches(maxY); - populatePositionCache(nX, maxY, nZ); - List results = new ArrayList<>(); - for (int nY = step; nY <= maxY; nY += step) { - results.add(profileDoubleTensorPreparation(nX, nY, nZ)); - } - printProfileResult(results); - } - - private void printProfileResult(List results) { - System.out.println("Step \tSize \ttime [ms] \tmem [byte]"); - int step = 0; - for (ProfileResult result : results) { - SystemState stateDiff = result.systemStateDiff; - System.out.println(step++ + "\t" + result.tensorSize + "\t" + stateDiff.getTimeInMillis() + "\t" - + stateDiff.getMemoryUsageInB()); - } - } - - @Ignore - @Test - public void profilePositionMapPreparation() { - int maxY = 1000; - int step = 100; - int nX = 100; - int nZ = 1; - populateCaches(maxY); - populatePositionCache(nX, maxY, nZ); - List results = new ArrayList<>(); - for (int nY = step; nY <= maxY; nY += step) { - results.add(profileMapPreparation(nX, nY, nZ)); - } - printProfileResult(results); - } - - @Test - @Ignore - public void profileSimpleMapPopulation() { - int maxValue = 100000; - int step = 10000; - populateCaches(maxValue); - List results = new ArrayList<>(); - for (int i = step; i <= maxValue; i += step) { - results.add(profileXCoordinateMap(i)); - } - printProfileResult(results); - } - - private ProfileResult profileXCoordinateMap(int size) { - System.out.println("Map preparation preparation of size=" + size + ":"); - SystemState initialState = currentTimeAfterGc(); - Map map = createImmutableMapOfSize(size); - SystemState stateDiff = currentTimeAfterGc().minus(initialState); - stateDiff.printToStdOut(); - return new ProfileResult(map.size(), stateDiff); - - } - - private Map createImmutableMapOfSize(int size) { - ImmutableMap.Builder builder = ImmutableMap.builder(); - for (int i = 0; i < size; i++) { - builder.put(XCoordinate.of(i), valueForBig(i, i, i, 2.0)); - } - return builder.build(); - } - - private void populateCaches(int maxValue) { - for (int i = 0; i <= maxValue; i++) { - XCoordinate.of(i); - YCoordinate.of(i); - ZCoordinate.of(i); - } - } - - private void populatePositionCache(int nX, int nY, int nZ) { - for (int i = 0; i <= nX; i++) { - for (int j = 0; j <= nY; j++) { - for (int k = 0; k <= nZ; k++) { - Position.of(coordinatesFor(i, j, k)); - } - } - } - } - - private ProfileResult profileTensorPreparation(int nX, int nY, int nZ) { - System.out.println("Tensor preparation for " + nX + "x" + nY + "x" + nZ + ":"); - SystemState initialState = currentTimeAfterGc(); - Tensor tensor = prepareValuesForBig(nX, nY, nZ, 2.0); - SystemState stateDiff = currentTimeBeforeGc().minus(initialState); - stateDiff.printToStdOut(); - System.out.println("Tensor size:" + tensor.shape().size()); - return new ProfileResult(tensor.shape().size(), stateDiff); - } - - private ProfileResult profileMapPreparation(int nX, int nY, int nZ) { - System.out.println("Map preparation for " + nX + "x" + nY + "x" + nZ + ":"); - SystemState initialState = currentTimeAfterGc(); - Map map = prepareMap(nX, nY, nZ); - SystemState stateDiff = currentTimeAfterGc().minus(initialState); - stateDiff.printToStdOut(); - System.out.println("Map size:" + map.size()); - return new ProfileResult(map.size(), stateDiff); - } - - private ProfileResult profileDoubleTensorPreparation(int nX, int nY, int nZ) { - System.out.println("Tensor preparation for " + nX + "x" + nY + "x" + nZ + ":"); - SystemState initialState = currentTimeAfterGc(); - Tensor tensor = prepareValuesForBigDouble(nX, nY, nZ, 2.0); - SystemState stateDiff = currentTimeBeforeGc().minus(initialState); - stateDiff.printToStdOut(); - System.out.println("Tensor size:" + tensor.shape().size()); - return new ProfileResult(tensor.shape().size(), stateDiff); - } - - @Ignore - @Test - public void profileRepetitiveMap() { - List results = profileMapNTimes(10); - printProfileResult(results); - } - - @Ignore - @Test - public void profileSimpleRepetitiveTensor() { - CoordinateRange range = CoordinateRange.fromSize(TensorSize.ofXYZ(400, 500, 1)); - System.out.println("Created range"); - - List results = profileTensorCreationNTimes(5, range, new ValueFactory() { - - @Override - public Double create(int x, int y, int z) { - return valueForBig(x, y, z, 2.0); - } - }); - printProfileResult(results); - } - - @Ignore - @Test - public void profileQuantifiedRepetitiveTensor() { - final Unit unit = JScienceUnit.of(SI.METER); - CoordinateRange range = CoordinateRange.fromSize(TensorSize.ofXYZ(100, 1000, 1)); - - List results = profileTensorCreationNTimes(10, range, - new ValueFactory>() { - - @Override - public QuantifiedValue create(int x, int y, int z) { - return Tensorics.quantityOf(valueForBig(x, y, z, 2.0), unit).withError(0.0); - } - }); - printProfileResult(results); - } - - public List profileMapNTimes(int nTimes) { - List> maps = new ArrayList<>(); - List results = new ArrayList<>(); - for (int i = 0; i < nTimes; i++) { - SystemState initialState = currentTimeAfterGc(); - Map map = prepareMap(100, 1000, 1); - SystemState stateDiff = currentTimeAfterGc().minus(initialState); - stateDiff.printToStdOut(); - System.out.println("Map size:" + map.size()); - results.add(new ProfileResult(map.size(), stateDiff)); - maps.add(map); - } - return results; - } - - public List profileTensorCreationNTimes(int nTimes, CoordinateRange range, - ValueFactory factory) { - List> tensors = new ArrayList<>(); - List results = new ArrayList<>(); - for (int i = 0; i < nTimes; i++) { - SystemState initialState = currentTimeAfterGc(); - Tensor tensor = createTensor(range, factory); - SystemState stateDiff = currentTimeBeforeGc().minus(initialState); - stateDiff.printToStdOut(); - int size = tensor.shape().size(); - System.out.println("Tensor size:" + size); - results.add(new ProfileResult(size, stateDiff)); - tensors.add(tensor); - } - return results; - } - - private Map prepareMap(int nX, int nY, int nZ) { - Map map = new HashMap<>(); - for (int i = 0; i < nX; i++) { - for (int j = 0; j < nY; j++) { - for (int k = 0; k < nZ; k++) { - map.put(Position.of(coordinatesFor(i, j, k)), valueForBig(i, j, k, 2.0)); - } - } - } - return map; - } - - private static class ProfileResult { - private final SystemState systemStateDiff; - private final int tensorSize; - - public ProfileResult(int tensorSize, SystemState systemStateDiff) { - super(); - this.tensorSize = tensorSize; - this.systemStateDiff = systemStateDiff; - } - } - - @Test - public void testOperationsOnBig1024x2x2Tensor() { - long totalDiff = calculateOnTensor(X_COOR_NUMBER * 2, Y_COOR_NUMBER, Z_COOR_NUMBER * 2, true); - assertTrue(totalDiff < 4000); - } - - @Test - public void testSimpleTensoricsTask() { - - Tensor result = new TensoricTask>( - EnvironmentImpl.of(doubles(), ManipulationOptions.defaultOptions(doubles()))) { - - @Override - public Tensor run() { - return calculate(tensor1).plus(tensor2); - } - - }.run(); - assertEquals(100, result.shape().size()); - } - - private long calculateOnTensor(int xCoorNumber, int yCoorNumber, int zCoorNumber, boolean printLog) { - long memoryBefore = getMemoryUsage(); - - SimpleDateFormat sdf = new SimpleDateFormat("hh:MM:ss.SSS"); - Date date = new Date(); - int nbOfElements = xCoorNumber * yCoorNumber * zCoorNumber; - if (printLog) { - System.out.println(" Creation of [" + xCoorNumber + "," + yCoorNumber + "," + zCoorNumber - + "] (total nb of elements: " + nbOfElements + ")\t" + sdf.format(date)); - } - tensor3Big = prepareValuesForBig(xCoorNumber, yCoorNumber, zCoorNumber, 1.0); - - System.out.println("used memory :" + (getMemoryUsage() - memoryBefore)); - - YCoordinate y = YCoordinate.of(0); - XCoordinate x = XCoordinate.of(0); - ZCoordinate z = ZCoordinate.of(0); - Date date2 = new Date(); - if (printLog) { - System.out.println("done after (" + (date2.getTime() - date.getTime()) + "ms); \n Multiplying (base*(-1))\t" - + sdf.format(date2)); - } - Tensor inversedTensor = tensoricFieldUsage.negativeOf(tensor3Big); - Date date3 = new Date(); - if (printLog) { - System.out.println("done after (" + (date3.getTime() - date2.getTime()) - + "ms); \n Adding (base*(-1) to base)\t" + sdf.format(date3)); - } - Tensor tensorOut = tensoricFieldUsage.calculate(tensor3Big).plus(inversedTensor); - - Date date4 = new Date(); - if (printLog) { - System.out.println("Done \t" + sdf.format(date4) + " (" + (date4.getTime() - date3.getTime()) + "ms)"); - } - assertEquals(0.0, tensorOut.get(x, y, z).doubleValue(), 0.0); - Date date5 = new Date(); - if (printLog) { - System.out.println("get value at [0,0,0] \t" + sdf.format(date5) + " done after (" - + (date5.getTime() - date4.getTime()) + "ms)"); - } - - TensorStructurals.from(TensorStructurals.from(tensorOut).extract(z, y)).reduce(XCoordinate.class) - .byAveragingIn(doubles()); - - Date date6 = new Date(); - if (printLog) { - System.out.println("get mean on [x,0,0] \t" + sdf.format(date6) + " done after (" - + (date6.getTime() - date5.getTime()) + "ms)"); - } - // Tensors.getRmsOf(tensorOut).slicingAt(ImmutableSet.of(y, z)); - TensorStructurals.from(tensorOut).reduce(XCoordinate.class).byRmsIn(doubles()).get(y, z); - - Date date7 = new Date(); - if (printLog) { - System.out.println("get rms on [x,0,0] \t" + sdf.format(date7) + " done after (" - + (date7.getTime() - date6.getTime()) + "ms)"); - } - long totalDiff = date7.getTime() - date2.getTime(); - if (printLog) { - System.out.println("Total (since first calc) done after (" + totalDiff + "ms)"); - System.out.println("used memory :" + (getMemoryUsage() - memoryBefore)); - System.out.println("====================================="); - } - return totalDiff; - } - - public long getMemoryUsage() { - for (int i = 0; i < 10; i++) { - System.gc(); // NOSONAR - } - - int kb = 1024; - Runtime runtime = Runtime.getRuntime(); - - // Print used memory - long usedMemoryinKb = (runtime.totalMemory() - runtime.freeMemory()) / kb; - return usedMemoryinKb; - } - - @SuppressWarnings("boxing") - private Tensor prepareValues(double factor) { - ImmutableSet> dimensions = ImmutableSet.of(XCoordinate.class, YCoordinate.class); - Builder builder = ImmutableTensor.builder(dimensions); - for (int i = 0; i < 10; i++) { - for (int j = 0; j < 10; j++) { - builder.at(Position.of(coordinatesFor(i, j))).put(valueFor(i, j, factor)); - } - } - return builder.build(); - } - - private Tensor prepareOnlyEvenValuesTrueFlag() { - ImmutableSet> dimensions = ImmutableSet.of(XCoordinate.class, YCoordinate.class); - Builder builder = ImmutableTensor.builder(dimensions); - for (int i = 0; i < 10; i++) { - for (int j = 0; j < 10; j++) { - builder.at(Position.of(coordinatesFor(i, j))).put(flagFor(i, j)); - } - } - return builder.build(); - } - - private Boolean flagFor(int i, int j) { - if (i % 2 == 0 && j % 2 == 0) { - return Boolean.TRUE; - } - return Boolean.FALSE; - } - - private double valueFor(int i, int j, double factor) { - return j * i * factor; - } - - private Set coordinatesFor(int i, int j) { - Set coordinates = new HashSet<>(); - coordinates.add(XCoordinate.of(i)); - coordinates.add(YCoordinate.of(j)); - return coordinates; - } - - private Set coordinatesFor(int i, int j, int k) { - Set coordinates = coordinatesFor(i, j); - coordinates.add(ZCoordinate.of(k)); - return coordinates; - } - - @SuppressWarnings("boxing") - private Tensor prepareValuesForBig(int Nx, int Ny, int Nz, final double factor) { - final CoordinateRange range = CoordinateRange.fromSize(TensorSize.ofXYZ(Nx, Ny, Nz)); - return createTensor(range, new ValueFactory() { - @Override - public Double create(int x, int y, int z) { - return valueForBig(x, y, z, factor); - } - }); - } - - private Tensor createTensor(CoordinateRange range, ValueFactory factory) { - ImmutableSet> dimensions = ImmutableSet.of(XCoordinate.class, YCoordinate.class, ZCoordinate.class); - Builder builder = ImmutableTensor.builder(dimensions); - for (XCoordinate x : range.getxCoordinates()) { - for (YCoordinate y : range.getyCoordinates()) { - for (ZCoordinate z : range.getzCoordinates()) { - builder.putAt(factory.create(x.getValue(), y.getValue(), z.getValue()), Position.of(x, y, z)); - } - } - } - return builder.build(); - } - - private Tensor prepareValuesForBigDouble(int Nx, int Ny, int Nz, final double factor) { - final CoordinateRange range = CoordinateRange.fromSize(TensorSize.ofXYZ(Nx, Ny, Nz)); - return createDoubleTensor(range, new ValueFactory() { - @Override - public Double create(int x, int y, int z) { - return valueForBig(x, y, z, factor); - } - }); - } - - private Tensor createDoubleTensor(CoordinateRange range, ValueFactory factory) { - PositionIndexer.Builder indexerBuilder = PositionIndexer.builder(); - indexerBuilder.put(XCoordinate.class, range.getxCoordinates()); - indexerBuilder.put(YCoordinate.class, range.getyCoordinates()); - indexerBuilder.put(ZCoordinate.class, range.getzCoordinates()); - PositionIndexer indexer = indexerBuilder.build(); - - ImmutableDoubleArrayBackedTensor.Builder builder = ImmutableDoubleArrayBackedTensor.builder(indexer); - for (XCoordinate x : range.getxCoordinates()) { - for (YCoordinate y : range.getyCoordinates()) { - for (ZCoordinate z : range.getzCoordinates()) { - builder.putUncheckedAt(factory.create(x.getValue(), y.getValue(), z.getValue()), - Position.of(x, y, z)); - } - } - } - return builder.build(); - } - - interface ValueFactory { - V create(int x, int y, int z); - } - - private double valueForBig(int i, int j, int k, double factor) { - return j * i * k * factor; - } + private static final int Z_COOR_NUMBER = 1; + private static final int Y_COOR_NUMBER = 2; + private static final int X_COOR_NUMBER = 512; + + private Tensor tensor1; + private Tensor tensor1Flags; + private Tensor tensor2; + private Tensor tensor3Big; + private TensoricSupport tensoricFieldUsage; + + @Before + public void setUp() throws Exception { + tensoricFieldUsage = Tensorics.using(Structures.doubles()); + tensor1 = prepareValues(1.0); + tensor1Flags = prepareOnlyEvenValuesTrueFlag(); + tensor2 = prepareValues(2.5); + System.out.println("============== <<<<<<<<<< NEXT TEST >>>>>>>>>> ============="); + } + + @Test + public void averageOverOneDimensionOnValue1() { + YCoordinate y = YCoordinate.of(1); + Tensor averagedOverX = TensorStructurals.from(tensor1).reduce(XCoordinate.class) + .byAveragingIn(doubles()); + assertEquals(4.5, averagedOverX.get(Position.of(y)), 0.0); + } + + @Test + public void averageOverOneDimensionKeepingOther() { + Tensor averageOverYCoordinte = TensorStructurals.from(tensor1).reduce(XCoordinate.class) + .byAveragingIn(doubles()); + assertEquals(tensor1.shape().dimensionSet().size() - 1, averageOverYCoordinte.shape().dimensionSet().size()); + Set coordinateValues = TensorStructurals.from(averageOverYCoordinte) + .extractCoordinatesOfType(YCoordinate.class); + assertEquals(10, coordinateValues.size()); + } + + @Test + public void testMultiplyByNumber() { + YCoordinate y = YCoordinate.of(1); + XCoordinate x = XCoordinate.of(3); + Tensor tensor = tensoricFieldUsage.calculate(tensor1).elementTimesV(-1.0); + assertEquals(-3, tensor.get(x, y).doubleValue(), 0.0); + } + + @Test + public void testDivideByNumber() { + YCoordinate y = YCoordinate.of(1); + XCoordinate x = XCoordinate.of(3); + Tensor tensor = tensoricFieldUsage.calculate(tensor1).elementDividedByV(2.0); + assertEquals(1.5, tensor.get(x, y).doubleValue(), 0.0); + } + + @Test + public void testRMSCalculation() { + YCoordinate y = YCoordinate.of(1); + double rms = TensorStructurals.from(tensor1).reduce(XCoordinate.class).byRmsIn(doubles()).get(y); + + assertEquals(5.33, rms, 0.01); + double rms2 = TensorStructurals.from(tensor1).reduce(XCoordinate.class).byRmsIn(doubles()).get(Position.of(y)); + assertEquals(5.33, rms2, 0.01); + } + + @Test(expected = IllegalArgumentException.class) + public void testRMSCalculationTooManyCoordiantes() { + YCoordinate y = YCoordinate.of(1); + XCoordinate x = XCoordinate.of(2); + TensorStructurals.from(tensor1).reduce(XCoordinate.class).byRmsIn(doubles()).get(x, y); + } + + @Test + public void testMeanCalculation() { + YCoordinate y = YCoordinate.of(1); + double mean2 = TensorStructurals.from(TensorStructurals.from(tensor1).extract(y)).reduce(XCoordinate.class) + .byAveragingIn(doubles()).get(Position.empty()); + assertEquals(4.5, mean2, 0.0); + } + + @Test + public void testAddition() { + YCoordinate y = YCoordinate.of(2); + XCoordinate x = XCoordinate.of(6); + Tensor tensor = tensoricFieldUsage.calculate(tensor1).plus(tensor1); + assertEquals(24.0, tensor.get(x, y).doubleValue(), 0.0); + } + + @Test + public void testSubtraction() { + YCoordinate y = YCoordinate.of(2); + XCoordinate x = XCoordinate.of(6); + Tensor tensor = tensoricFieldUsage.calculate(tensor1).minus(tensor1); + assertEquals(0.0, tensor.get(x, y).doubleValue(), 0.0); + } + + @Test + public void testFluentAddition() { + YCoordinate y = YCoordinate.of(2); + XCoordinate x = XCoordinate.of(6); + Tensor tensor = tensoricFieldUsage.calculate(tensor1).plus(tensor1); + assertEquals(24.0, tensor.get(x, y).doubleValue(), 0.0); + } + + @Test + public void testAdditionOf2elementsTo100WithResult2() { + YCoordinate y = YCoordinate.of(2); + XCoordinate x = XCoordinate.of(6); + XCoordinate x2 = XCoordinate.of(3); + + Builder builder = ImmutableTensor.builder(ImmutableSet.of(y.getClass(), x.getClass())); + builder.at(Position.of(ImmutableSet.of(x, y))).put(13.2); + builder.at(Position.of(ImmutableSet.of(x2, y))).put(-1.2); + Tensor testTensor = builder.build(); + + Tensor tensor = tensoricFieldUsage.calculate(tensor1).plus(testTensor); + assertEquals(25.2, tensor.get(x, y).doubleValue(), 0.0); + } + + @Test + public void testAdditionOf2elementsTo2() { + YCoordinate y = YCoordinate.of(2); + XCoordinate x = XCoordinate.of(6); + XCoordinate x2 = XCoordinate.of(3); + + Builder builder = ImmutableTensor.builder(ImmutableSet.of(y.getClass(), x.getClass())); + builder.at(Position.of(ImmutableSet.of(x, y))).put(13.2); + builder.at(Position.of(ImmutableSet.of(x2, y))).put(-1.2); + Tensor testTensor = builder.build(); + + Builder builder2 = ImmutableTensor.builder(ImmutableSet.of(y.getClass(), x.getClass())); + builder2.at(Position.of(ImmutableSet.of(x, y))).put(1.2); + builder2.at(Position.of(ImmutableSet.of(x2, y))).put(1.2); + Tensor testTensor2 = builder2.build(); + Tensor tensor = tensoricFieldUsage.calculate(testTensor).plus(testTensor2); + assertEquals(14.4, tensor.get(x, y).doubleValue(), 0.001); + } + + @Test + public void testFlagApplience() { + Tensor tensor = from(tensor1).extractWhereTrue(tensor1Flags); + YCoordinate y = YCoordinate.of(2); + XCoordinate x = XCoordinate.of(6); + assertEquals(12.0, tensor.get(Position.of(ImmutableSet.of(x, y))).doubleValue(), 0.0); + assertEquals(5, TensorStructurals.from(tensor).extractCoordinatesOfType(x.getClass()).size()); + } + + @Test(expected = NoSuchElementException.class) + public void testFlagApplienceFailure() { + Tensor tensor = from(tensor1).extractWhereTrue(tensor1Flags); + YCoordinate y = YCoordinate.of(2); + XCoordinate x = XCoordinate.of(7); + assertEquals(14.0, tensor.get(x, y).doubleValue(), 0.0); + } + + @Test + public void testAdditionFrom2elementsTo100WithWrongShapes() { + XCoordinate x = XCoordinate.of(6); + XCoordinate x2 = XCoordinate.of(3); + Builder builder = ImmutableTensor.builder(ImmutableSet.of(x.getClass())); + double x1Add = 13.2; + double x2Add = -1.2; + builder.at(Position.of(x)).put(x1Add); + builder.at(Position.of(x2)).put(x2Add); + Tensor testTensor = builder.build(); + Tensor result = tensoricFieldUsage.calculate(tensor1).plus(testTensor); + + /* + * from broadcasting the y dimension of the test tensor to the values of + * tensor1 (10 values) together with the two x-coordinates, we expect a + * tensor of sixe 20. + */ + assertEquals(20, result.shape().size()); + + checkCorrectlyAdded(x, x1Add, result); + checkCorrectlyAdded(x2, x2Add, result); + } + + private void checkCorrectlyAdded(XCoordinate x, double x1Add, Tensor result) { + for (java.util.Map.Entry entry : Tensorics.mapFrom(result).entrySet()) { + Position position = entry.getKey(); + if (x.equals(position.coordinateFor(XCoordinate.class))) { + assertEquals(tensor1.get(position) + x1Add, entry.getValue(), 0.0000001); + } + } + } + + @Test(expected = IllegalArgumentException.class) + public void testReductionOnNonExistingCoordinate() { + TensorStructurals.from(tensor1).extract(ZCoordinate.of(1)); + } + + @Test + public void testOperationsOnBig512x2x1Tensor() { + long totalDiff = calculateOnTensor(X_COOR_NUMBER, Y_COOR_NUMBER, Z_COOR_NUMBER, true); + assertTrue(totalDiff < 800); + } + + @Test + @Ignore + public void profileTensorPreparation() { + int maxY = 1000; + int step = 100; + int nX = 100; + int nZ = 1; + populateCaches(maxY); + populatePositionCache(nX, maxY, nZ); + List results = new ArrayList<>(); + for (int nY = step; nY <= maxY; nY += step) { + results.add(profileTensorPreparation(nX, nY, nZ)); + } + printProfileResult(results); + } + + @Test + @Ignore + public void profileDoubleTensorPreparation() { + int maxY = 1000; + int step = 100; + int nX = 100; + int nZ = 1; + populateCaches(maxY); + populatePositionCache(nX, maxY, nZ); + List results = new ArrayList<>(); + for (int nY = step; nY <= maxY; nY += step) { + results.add(profileDoubleTensorPreparation(nX, nY, nZ)); + } + printProfileResult(results); + } + + private void printProfileResult(List results) { + System.out.println("Step \tSize \ttime [ms] \tmem [byte]"); + int step = 0; + for (ProfileResult result : results) { + SystemState stateDiff = result.systemStateDiff; + System.out.println(step++ + "\t" + result.tensorSize + "\t" + stateDiff.getTimeInMillis() + "\t" + + stateDiff.getMemoryUsageInB()); + } + } + + @Ignore + @Test + public void profilePositionMapPreparation() { + int maxY = 1000; + int step = 100; + int nX = 100; + int nZ = 1; + populateCaches(maxY); + populatePositionCache(nX, maxY, nZ); + List results = new ArrayList<>(); + for (int nY = step; nY <= maxY; nY += step) { + results.add(profileMapPreparation(nX, nY, nZ)); + } + printProfileResult(results); + } + + @Test + @Ignore + public void profileSimpleMapPopulation() { + int maxValue = 100000; + int step = 10000; + populateCaches(maxValue); + List results = new ArrayList<>(); + for (int i = step; i <= maxValue; i += step) { + results.add(profileXCoordinateMap(i)); + } + printProfileResult(results); + } + + private ProfileResult profileXCoordinateMap(int size) { + System.out.println("Map preparation preparation of size=" + size + ":"); + SystemState initialState = currentTimeAfterGc(); + Map map = createImmutableMapOfSize(size); + SystemState stateDiff = currentTimeAfterGc().minus(initialState); + stateDiff.printToStdOut(); + return new ProfileResult(map.size(), stateDiff); + + } + + private Map createImmutableMapOfSize(int size) { + ImmutableMap.Builder builder = ImmutableMap.builder(); + for (int i = 0; i < size; i++) { + builder.put(XCoordinate.of(i), valueForBig(i, i, i, 2.0)); + } + return builder.build(); + } + + private void populateCaches(int maxValue) { + for (int i = 0; i <= maxValue; i++) { + XCoordinate.of(i); + YCoordinate.of(i); + ZCoordinate.of(i); + } + } + + private void populatePositionCache(int nX, int nY, int nZ) { + for (int i = 0; i <= nX; i++) { + for (int j = 0; j <= nY; j++) { + for (int k = 0; k <= nZ; k++) { + Position.of(coordinatesFor(i, j, k)); + } + } + } + } + + private ProfileResult profileTensorPreparation(int nX, int nY, int nZ) { + System.out.println("Tensor preparation for " + nX + "x" + nY + "x" + nZ + ":"); + SystemState initialState = currentTimeAfterGc(); + Tensor tensor = prepareValuesForBig(nX, nY, nZ, 2.0); + SystemState stateDiff = currentTimeBeforeGc().minus(initialState); + stateDiff.printToStdOut(); + System.out.println("Tensor size:" + tensor.shape().size()); + return new ProfileResult(tensor.shape().size(), stateDiff); + } + + private ProfileResult profileMapPreparation(int nX, int nY, int nZ) { + System.out.println("Map preparation for " + nX + "x" + nY + "x" + nZ + ":"); + SystemState initialState = currentTimeAfterGc(); + Map map = prepareMap(nX, nY, nZ); + SystemState stateDiff = currentTimeAfterGc().minus(initialState); + stateDiff.printToStdOut(); + System.out.println("Map size:" + map.size()); + return new ProfileResult(map.size(), stateDiff); + } + + private ProfileResult profileDoubleTensorPreparation(int nX, int nY, int nZ) { + System.out.println("Tensor preparation for " + nX + "x" + nY + "x" + nZ + ":"); + SystemState initialState = currentTimeAfterGc(); + Tensor tensor = prepareValuesForBigDouble(nX, nY, nZ, 2.0); + SystemState stateDiff = currentTimeBeforeGc().minus(initialState); + stateDiff.printToStdOut(); + System.out.println("Tensor size:" + tensor.shape().size()); + return new ProfileResult(tensor.shape().size(), stateDiff); + } + + @Ignore + @Test + public void profileRepetitiveMap() { + List results = profileMapNTimes(10); + printProfileResult(results); + } + + @Ignore + @Test + public void profileSimpleRepetitiveTensor() { + CoordinateRange range = CoordinateRange.fromSize(TensorSize.ofXYZ(400, 500, 1)); + System.out.println("Created range"); + + List results = profileTensorCreationNTimes(5, range, new ValueFactory() { + + @Override + public Double create(int x, int y, int z) { + return valueForBig(x, y, z, 2.0); + } + }); + printProfileResult(results); + } + + @Ignore + @Test + public void profileQuantifiedRepetitiveTensor() { + final Unit unit = JScienceUnit.of(SI.METER); + CoordinateRange range = CoordinateRange.fromSize(TensorSize.ofXYZ(100, 1000, 1)); + + List results = profileTensorCreationNTimes(10, range, + new ValueFactory>() { + + @Override + public QuantifiedValue create(int x, int y, int z) { + return Tensorics.quantityOf(valueForBig(x, y, z, 2.0), unit).withError(0.0); + } + }); + printProfileResult(results); + } + + public List profileMapNTimes(int nTimes) { + List> maps = new ArrayList<>(); + List results = new ArrayList<>(); + for (int i = 0; i < nTimes; i++) { + SystemState initialState = currentTimeAfterGc(); + Map map = prepareMap(100, 1000, 1); + SystemState stateDiff = currentTimeAfterGc().minus(initialState); + stateDiff.printToStdOut(); + System.out.println("Map size:" + map.size()); + results.add(new ProfileResult(map.size(), stateDiff)); + maps.add(map); + } + return results; + } + + public List profileTensorCreationNTimes(int nTimes, CoordinateRange range, + ValueFactory factory) { + List> tensors = new ArrayList<>(); + List results = new ArrayList<>(); + for (int i = 0; i < nTimes; i++) { + SystemState initialState = currentTimeAfterGc(); + Tensor tensor = createTensor(range, factory); + SystemState stateDiff = currentTimeBeforeGc().minus(initialState); + stateDiff.printToStdOut(); + int size = tensor.shape().size(); + System.out.println("Tensor size:" + size); + results.add(new ProfileResult(size, stateDiff)); + tensors.add(tensor); + } + return results; + } + + private Map prepareMap(int nX, int nY, int nZ) { + Map map = new HashMap<>(); + for (int i = 0; i < nX; i++) { + for (int j = 0; j < nY; j++) { + for (int k = 0; k < nZ; k++) { + map.put(Position.of(coordinatesFor(i, j, k)), valueForBig(i, j, k, 2.0)); + } + } + } + return map; + } + + private static class ProfileResult { + private final SystemState systemStateDiff; + private final int tensorSize; + + public ProfileResult(int tensorSize, SystemState systemStateDiff) { + super(); + this.tensorSize = tensorSize; + this.systemStateDiff = systemStateDiff; + } + } + + @Test + public void testOperationsOnBig1024x2x2Tensor() { + long totalDiff = calculateOnTensor(X_COOR_NUMBER * 2, Y_COOR_NUMBER, Z_COOR_NUMBER * 2, true); + assertTrue(totalDiff < 4000); + } + + @Test + public void testSimpleTensoricsTask() { + + Tensor result = new TensoricTask>( + EnvironmentImpl.of(doubles(), ManipulationOptions.defaultOptions(doubles()))) { + + @Override + public Tensor run() { + return calculate(tensor1).plus(tensor2); + } + + }.run(); + assertEquals(100, result.shape().size()); + } + + private long calculateOnTensor(int xCoorNumber, int yCoorNumber, int zCoorNumber, boolean printLog) { + long memoryBefore = getMemoryUsage(); + + SimpleDateFormat sdf = new SimpleDateFormat("hh:MM:ss.SSS"); + Date date = new Date(); + int nbOfElements = xCoorNumber * yCoorNumber * zCoorNumber; + if (printLog) { + System.out.println(" Creation of [" + xCoorNumber + "," + yCoorNumber + "," + zCoorNumber + + "] (total nb of elements: " + nbOfElements + ")\t" + sdf.format(date)); + } + tensor3Big = prepareValuesForBig(xCoorNumber, yCoorNumber, zCoorNumber, 1.0); + + System.out.println("used memory :" + (getMemoryUsage() - memoryBefore)); + + YCoordinate y = YCoordinate.of(0); + XCoordinate x = XCoordinate.of(0); + ZCoordinate z = ZCoordinate.of(0); + Date date2 = new Date(); + if (printLog) { + System.out.println("done after (" + (date2.getTime() - date.getTime()) + "ms); \n Multiplying (base*(-1))\t" + + sdf.format(date2)); + } + Tensor inversedTensor = tensoricFieldUsage.negativeOf(tensor3Big); + Date date3 = new Date(); + if (printLog) { + System.out.println("done after (" + (date3.getTime() - date2.getTime()) + + "ms); \n Adding (base*(-1) to base)\t" + sdf.format(date3)); + } + Tensor tensorOut = tensoricFieldUsage.calculate(tensor3Big).plus(inversedTensor); + + Date date4 = new Date(); + if (printLog) { + System.out.println("Done \t" + sdf.format(date4) + " (" + (date4.getTime() - date3.getTime()) + "ms)"); + } + assertEquals(0.0, tensorOut.get(x, y, z).doubleValue(), 0.0); + Date date5 = new Date(); + if (printLog) { + System.out.println("get value at [0,0,0] \t" + sdf.format(date5) + " done after (" + + (date5.getTime() - date4.getTime()) + "ms)"); + } + + TensorStructurals.from(TensorStructurals.from(tensorOut).extract(z, y)).reduce(XCoordinate.class) + .byAveragingIn(doubles()); + + Date date6 = new Date(); + if (printLog) { + System.out.println("get mean on [x,0,0] \t" + sdf.format(date6) + " done after (" + + (date6.getTime() - date5.getTime()) + "ms)"); + } + // Tensors.getRmsOf(tensorOut).slicingAt(ImmutableSet.of(y, z)); + TensorStructurals.from(tensorOut).reduce(XCoordinate.class).byRmsIn(doubles()).get(y, z); + + Date date7 = new Date(); + if (printLog) { + System.out.println("get rms on [x,0,0] \t" + sdf.format(date7) + " done after (" + + (date7.getTime() - date6.getTime()) + "ms)"); + } + long totalDiff = date7.getTime() - date2.getTime(); + if (printLog) { + System.out.println("Total (since first calc) done after (" + totalDiff + "ms)"); + System.out.println("used memory :" + (getMemoryUsage() - memoryBefore)); + System.out.println("====================================="); + } + return totalDiff; + } + + public long getMemoryUsage() { + for (int i = 0; i < 10; i++) { + System.gc(); // NOSONAR + } + + int kb = 1024; + Runtime runtime = Runtime.getRuntime(); + + // Print used memory + long usedMemoryinKb = (runtime.totalMemory() - runtime.freeMemory()) / kb; + return usedMemoryinKb; + } + + @SuppressWarnings("boxing") + private Tensor prepareValues(double factor) { + ImmutableSet> dimensions = ImmutableSet.of(XCoordinate.class, YCoordinate.class); + Builder builder = ImmutableTensor.builder(dimensions); + for (int i = 0; i < 10; i++) { + for (int j = 0; j < 10; j++) { + builder.at(Position.of(coordinatesFor(i, j))).put(valueFor(i, j, factor)); + } + } + return builder.build(); + } + + private Tensor prepareOnlyEvenValuesTrueFlag() { + ImmutableSet> dimensions = ImmutableSet.of(XCoordinate.class, YCoordinate.class); + Builder builder = ImmutableTensor.builder(dimensions); + for (int i = 0; i < 10; i++) { + for (int j = 0; j < 10; j++) { + builder.at(Position.of(coordinatesFor(i, j))).put(flagFor(i, j)); + } + } + return builder.build(); + } + + private Boolean flagFor(int i, int j) { + if (i % 2 == 0 && j % 2 == 0) { + return Boolean.TRUE; + } + return Boolean.FALSE; + } + + private double valueFor(int i, int j, double factor) { + return j * i * factor; + } + + private Set coordinatesFor(int i, int j) { + Set coordinates = new HashSet<>(); + coordinates.add(XCoordinate.of(i)); + coordinates.add(YCoordinate.of(j)); + return coordinates; + } + + private Set coordinatesFor(int i, int j, int k) { + Set coordinates = coordinatesFor(i, j); + coordinates.add(ZCoordinate.of(k)); + return coordinates; + } + + @SuppressWarnings("boxing") + private Tensor prepareValuesForBig(int Nx, int Ny, int Nz, final double factor) { + final CoordinateRange range = CoordinateRange.fromSize(TensorSize.ofXYZ(Nx, Ny, Nz)); + return createTensor(range, new ValueFactory() { + @Override + public Double create(int x, int y, int z) { + return valueForBig(x, y, z, factor); + } + }); + } + + private Tensor createTensor(CoordinateRange range, ValueFactory factory) { + ImmutableSet> dimensions = ImmutableSet.of(XCoordinate.class, YCoordinate.class, ZCoordinate.class); + Builder builder = ImmutableTensor.builder(dimensions); + for (XCoordinate x : range.getxCoordinates()) { + for (YCoordinate y : range.getyCoordinates()) { + for (ZCoordinate z : range.getzCoordinates()) { + builder.putAt(factory.create(x.getValue(), y.getValue(), z.getValue()), Position.of(x, y, z)); + } + } + } + return builder.build(); + } + + private Tensor prepareValuesForBigDouble(int Nx, int Ny, int Nz, final double factor) { + final CoordinateRange range = CoordinateRange.fromSize(TensorSize.ofXYZ(Nx, Ny, Nz)); + return createDoubleTensor(range, new ValueFactory() { + @Override + public Double create(int x, int y, int z) { + return valueForBig(x, y, z, factor); + } + }); + } + + private Tensor createDoubleTensor(CoordinateRange range, ValueFactory factory) { + PositionIndexer.Builder indexerBuilder = PositionIndexer.builder(); + indexerBuilder.put(XCoordinate.class, range.getxCoordinates()); + indexerBuilder.put(YCoordinate.class, range.getyCoordinates()); + indexerBuilder.put(ZCoordinate.class, range.getzCoordinates()); + PositionIndexer indexer = indexerBuilder.build(); + + ImmutableDoubleArrayBackedTensor.Builder builder = ImmutableDoubleArrayBackedTensor.builder(indexer); + for (XCoordinate x : range.getxCoordinates()) { + for (YCoordinate y : range.getyCoordinates()) { + for (ZCoordinate z : range.getzCoordinates()) { + builder.putUncheckedAt(factory.create(x.getValue(), y.getValue(), z.getValue()), + Position.of(x, y, z)); + } + } + } + return builder.build(); + } + + interface ValueFactory { + V create(int x, int y, int z); + } + + private double valueForBig(int i, int j, int k, double factor) { + return j * i * k * factor; + } } diff --git a/src/test/org/tensorics/core/tensor/ImmutableTensorTest.java b/src/test/org/tensorics/core/tensor/ImmutableTensorTest.java index 859ad6ef6..8b761479d 100644 --- a/src/test/org/tensorics/core/tensor/ImmutableTensorTest.java +++ b/src/test/org/tensorics/core/tensor/ImmutableTensorTest.java @@ -101,13 +101,13 @@ public void sameDimensionTwiceThrowsImmediately() { @Test public void fromMapWithOneEntry() { Map map = ImmutableMap.of(Position.of(42), 0); - assertEquals(Tensorics.fromMap(ImmutableSet.of(Integer.class), map).asMap(), map); + assertEquals(Tensorics.mapFrom(Tensorics.fromMap(ImmutableSet.of(Integer.class), map)), map); } @Test public void fromEmptyMap() { Map map = ImmutableMap.of(); - assertEquals(Tensorics.fromMap(ImmutableSet.of(), map).asMap(), map); + assertEquals(Tensorics.mapFrom(Tensorics.fromMap(ImmutableSet.of(), map)), map); } @Test diff --git a/src/test/org/tensorics/core/tensorbacked/AbstractTensorbackedTest.java b/src/test/org/tensorics/core/tensorbacked/AbstractTensorbackedTest.java index d1acbf54a..d9fc97c07 100644 --- a/src/test/org/tensorics/core/tensorbacked/AbstractTensorbackedTest.java +++ b/src/test/org/tensorics/core/tensorbacked/AbstractTensorbackedTest.java @@ -17,102 +17,99 @@ import org.tensorics.core.lang.Tensorics; import org.tensorics.core.tensor.Tensor; import org.tensorics.core.tensor.TensorBuilder; +import org.tensorics.core.tensor.operations.TensorInternals; import org.tensorics.core.tensorbacked.annotation.Dimensions; public class AbstractTensorbackedTest { - public interface FirstCoordinateInterface { - /* marker interface */ - } - - public enum FirstCoordinate implements FirstCoordinateInterface { - FIRST_1, - FIRST_2, - FIRST_3; - } - - public enum SecondCoordinate { - SECOND_1, - SECOND_2; - } - - @Dimensions({ FirstCoordinate.class, SecondCoordinate.class }) - public static class LeafClassTensorbacked extends AbstractTensorbacked { - private static final long serialVersionUID = 1L; - - public LeafClassTensorbacked(Tensor tensor) { - super(tensor); - } - } - - @Dimensions({ FirstCoordinateInterface.class, SecondCoordinate.class }) - public static class InterfaceTensorbacked extends AbstractTensorbacked { - private static final long serialVersionUID = 1L; - - public InterfaceTensorbacked(Tensor tensor) { - super(tensor); - } - } - - private Tensor buildTensorFor(Class... dimensions) { - TensorBuilder builder = Tensorics.builder(dimensions); - builder.putAt(11.0, FirstCoordinate.FIRST_1, SecondCoordinate.SECOND_1); - builder.putAt(12.0, FirstCoordinate.FIRST_1, SecondCoordinate.SECOND_2); - builder.putAt(21.0, FirstCoordinate.FIRST_2, SecondCoordinate.SECOND_1); - return builder.build(); - } - - private final Tensor leafClassTensor = buildTensorFor(FirstCoordinate.class, SecondCoordinate.class); - private final Tensor interfaceTensor = buildTensorFor(FirstCoordinateInterface.class, - SecondCoordinate.class); - - @Test - public void canConstructLeafClassTensorbackedFromLeafClassTensor() { - LeafClassTensorbacked tb = new LeafClassTensorbacked(leafClassTensor); - assertEquals(tb.tensor().asMap(), leafClassTensor.asMap()); - assertEquals(TensorbackedInternals.dimensionsOf(LeafClassTensorbacked.class), - tb.tensor().shape().dimensionSet()); - } - - @Test(expected = IllegalArgumentException.class) - public void canNotConstructLeafClassTensorbackedFromInterfaceClassTensor() { - LeafClassTensorbacked tb = new LeafClassTensorbacked(interfaceTensor); - assertEquals(tb.tensor().asMap(), interfaceTensor.asMap()); - } - - public void canConstructInterfaceTensorbackedFromLeafClassTensor() { - InterfaceTensorbacked tb = new InterfaceTensorbacked(leafClassTensor); - assertEquals(tb.tensor().asMap(), leafClassTensor.asMap()); - assertEquals(TensorbackedInternals.dimensionsOf(InterfaceTensorbacked.class), - tb.tensor().shape().dimensionSet()); - } - - @Test - public void canNotConstructInterfaceTensorbackedFromInterfaceClassTensor() { - InterfaceTensorbacked tb = new InterfaceTensorbacked(interfaceTensor); - assertEquals(tb.tensor().asMap(), interfaceTensor.asMap()); - } - - @Test - public void interfaceTensorbackedCalculationTest() { - InterfaceTensorbacked tb = new InterfaceTensorbacked(interfaceTensor); - InterfaceTensorbacked result = DoubleTensorics.calculate(tb).plus(tb); - - assertResultOfCalculation(result); - } - - @Test - public void leafClassTensorbackedCalculationTest() { - LeafClassTensorbacked tb = new LeafClassTensorbacked(leafClassTensor); - LeafClassTensorbacked result = DoubleTensorics.calculate(tb).plus(tb); - - assertResultOfCalculation(result); - - } - - private void assertResultOfCalculation(AbstractTensorbacked result) { - Assertions.assertThat(result.tensor().get(FIRST_1, SECOND_1)).isEqualTo(valueOf(22)); - Assertions.assertThat(result.tensor().get(FIRST_1, SECOND_2)).isEqualTo(valueOf(24)); - Assertions.assertThat(result.tensor().get(FIRST_2, SECOND_1)).isEqualTo(valueOf(42)); - } + public interface FirstCoordinateInterface { + /* marker interface */ + } + + public enum FirstCoordinate implements FirstCoordinateInterface { + FIRST_1, FIRST_2, FIRST_3; + } + + public enum SecondCoordinate { + SECOND_1, SECOND_2; + } + + @Dimensions({ FirstCoordinate.class, SecondCoordinate.class }) + public static class LeafClassTensorbacked extends AbstractTensorbacked { + private static final long serialVersionUID = 1L; + + public LeafClassTensorbacked(Tensor tensor) { + super(tensor); + } + } + + @Dimensions({ FirstCoordinateInterface.class, SecondCoordinate.class }) + public static class InterfaceTensorbacked extends AbstractTensorbacked { + private static final long serialVersionUID = 1L; + + public InterfaceTensorbacked(Tensor tensor) { + super(tensor); + } + } + + private Tensor buildTensorFor(Class... dimensions) { + TensorBuilder builder = Tensorics.builder(dimensions); + builder.putAt(11.0, FirstCoordinate.FIRST_1, SecondCoordinate.SECOND_1); + builder.putAt(12.0, FirstCoordinate.FIRST_1, SecondCoordinate.SECOND_2); + builder.putAt(21.0, FirstCoordinate.FIRST_2, SecondCoordinate.SECOND_1); + return builder.build(); + } + + private final Tensor leafClassTensor = buildTensorFor(FirstCoordinate.class, SecondCoordinate.class); + private final Tensor interfaceTensor = buildTensorFor(FirstCoordinateInterface.class, + SecondCoordinate.class); + + @Test + public void canConstructLeafClassTensorbackedFromLeafClassTensor() { + LeafClassTensorbacked tb = new LeafClassTensorbacked(leafClassTensor); + assertEquals(TensorInternals.mapFrom(tb.tensor()), TensorInternals.mapFrom(leafClassTensor)); + assertEquals(TensorbackedInternals.dimensionsOf(LeafClassTensorbacked.class), + tb.tensor().shape().dimensionSet()); + } + + @Test(expected = IllegalArgumentException.class) + public void canNotConstructLeafClassTensorbackedFromInterfaceClassTensor() { + LeafClassTensorbacked tb = new LeafClassTensorbacked(interfaceTensor); + assertEquals(Tensorics.mapFrom(tb.tensor()), TensorInternals.mapFrom(interfaceTensor)); + } + + public void canConstructInterfaceTensorbackedFromLeafClassTensor() { + InterfaceTensorbacked tb = new InterfaceTensorbacked(leafClassTensor); + assertEquals(Tensorics.mapFrom(tb.tensor()), TensorInternals.mapFrom(leafClassTensor)); + assertEquals(TensorbackedInternals.dimensionsOf(InterfaceTensorbacked.class), + tb.tensor().shape().dimensionSet()); + } + + @Test + public void canNotConstructInterfaceTensorbackedFromInterfaceClassTensor() { + InterfaceTensorbacked tb = new InterfaceTensorbacked(interfaceTensor); + assertEquals(Tensorics.mapFrom(tb.tensor()), TensorInternals.mapFrom(interfaceTensor)); + } + + @Test + public void interfaceTensorbackedCalculationTest() { + InterfaceTensorbacked tb = new InterfaceTensorbacked(interfaceTensor); + InterfaceTensorbacked result = DoubleTensorics.calculate(tb).plus(tb); + + assertResultOfCalculation(result); + } + + @Test + public void leafClassTensorbackedCalculationTest() { + LeafClassTensorbacked tb = new LeafClassTensorbacked(leafClassTensor); + LeafClassTensorbacked result = DoubleTensorics.calculate(tb).plus(tb); + + assertResultOfCalculation(result); + } + + private void assertResultOfCalculation(AbstractTensorbacked result) { + Assertions.assertThat(result.tensor().get(FIRST_1, SECOND_1)).isEqualTo(valueOf(22)); + Assertions.assertThat(result.tensor().get(FIRST_1, SECOND_2)).isEqualTo(valueOf(24)); + Assertions.assertThat(result.tensor().get(FIRST_2, SECOND_1)).isEqualTo(valueOf(42)); + } } diff --git a/src/test/org/tensorics/core/tensorbacked/TensorbackedBuilderTest.java b/src/test/org/tensorics/core/tensorbacked/TensorbackedBuilderTest.java index b907c1336..dbd877e66 100644 --- a/src/test/org/tensorics/core/tensorbacked/TensorbackedBuilderTest.java +++ b/src/test/org/tensorics/core/tensorbacked/TensorbackedBuilderTest.java @@ -39,119 +39,119 @@ public class TensorbackedBuilderTest { - private static final double TESTVALUE_1_0 = 1.0; - private static final Bpm BPM_A = new Bpm("A"); - private static final Position POS_A_H = Position.of(BPM_A, Plane.H); - - @Test - public void emptyTensorbackedHasCorrectDimensionality() { - assertThat(Tensorics.dimensionalityOf(emptyOrbit()), equalTo(2)); - } - - @Test - public void emptyTensorHasSizeZero() { - assertThat(Tensorics.sizeOf(emptyOrbit()), equalTo(0)); - } - - @Test(expected = IllegalArgumentException.class) - public void putInsufficientCoordinateThrows() { - newBuilder().at(BPM_A).put(1.0); - } - - @Test - public void putOneCorrectValueWorks() { - TensorbackedBuilder builder = newBuilder(); - builder.at(BPM_A, Plane.H).put(1.0); - SinglebeamOrbit orbit = builder.build(); - assertThat(Tensorics.sizeOf(orbit), equalTo(1)); - } - - @Test(expected = IllegalArgumentException.class) - public void putAtOnePositionWithWrongCoordinatesThrows() { - newBuilder().at(Position.of(BPM_A)).put(TESTVALUE_1_0); - } - - @Test - public void putOneAtPositionHasCorrectSize() { - assertThat(Tensorics.sizeOf(oneValuePosAH()), equalTo(1)); - } - - @Test - public void putOneAtPositionHasCorrectValue() { - assertThat(oneValuePosAH().tensor().get(POS_A_H), equalTo(TESTVALUE_1_0)); - } - - @Test - public void putOneValueByCoordinatesHasCorrectValue() { - assertThat(oneValueCoordinatesAH().tensor().get(POS_A_H), equalTo(TESTVALUE_1_0)); - } - - @Test - public void oneValueCoordinatesEqualsOneValuePos() { - assertThat(oneValueCoordinatesAH(), equalTo(oneValuePosAH())); - } - - @Test(expected = NullPointerException.class) - public void putNullEntryThrows() { - java.util.Map.Entry toPut = null; - newBuilder().put(toPut); - } - - @Test - public void putOneEntryIsEqualToOriginal() { - TensorbackedBuilder builder = newBuilder(); - builder.put(Iterables.getFirst(oneValuePosAH().tensor().asMap().entrySet(), null)); - assertThat(builder.build(), equalTo(oneValuePosAH())); - } - - @Test(expected = NullPointerException.class) - public void putNullEntriesThrows() { - Set> toPut = null; - newBuilder().putAll(toPut); - } - - @Test - public void putEmptyCollectionResultsInEmptyTensor() { - TensorbackedBuilder builder = newBuilder(); - builder.putAll(Collections.> emptySet()); - assertThat(Tensorics.sizeOf(builder.build()), equalTo(0)); - } - - @Test - public void copyByEntryEqualsToOriginal() { - assertThat(oneValuePosCopied(), equalTo(oneValuePosAH())); - } - - @Test - public void copyByEntryEqualsHasCorrectSize() { - assertThat(Tensorics.sizeOf(oneValuePosCopied()), equalTo(1)); - } - - private SinglebeamOrbit oneValuePosCopied() { - TensorbackedBuilder builder = newBuilder(); - builder.putAll(oneValuePosAH().tensor().asMap().entrySet()); - SinglebeamOrbit copiedOrbit = builder.build(); - return copiedOrbit; - } - - private SinglebeamOrbit oneValueCoordinatesAH() { - TensorbackedBuilder builder = newBuilder(); - builder.at(POS_A_H.coordinates()).put(TESTVALUE_1_0); - return builder.build(); - } - - private SinglebeamOrbit oneValuePosAH() { - TensorbackedBuilder builder = newBuilder(); - builder.at(POS_A_H).put(TESTVALUE_1_0); - return builder.build(); - } - - private TensorbackedBuilder newBuilder() { - return Tensorics.builderFor(SinglebeamOrbit.class); - } - - private SinglebeamOrbit emptyOrbit() { - return newBuilder().build(); - } + private static final double TESTVALUE_1_0 = 1.0; + private static final Bpm BPM_A = new Bpm("A"); + private static final Position POS_A_H = Position.of(BPM_A, Plane.H); + + @Test + public void emptyTensorbackedHasCorrectDimensionality() { + assertThat(Tensorics.dimensionalityOf(emptyOrbit()), equalTo(2)); + } + + @Test + public void emptyTensorHasSizeZero() { + assertThat(Tensorics.sizeOf(emptyOrbit()), equalTo(0)); + } + + @Test(expected = IllegalArgumentException.class) + public void putInsufficientCoordinateThrows() { + newBuilder().at(BPM_A).put(1.0); + } + + @Test + public void putOneCorrectValueWorks() { + TensorbackedBuilder builder = newBuilder(); + builder.at(BPM_A, Plane.H).put(1.0); + SinglebeamOrbit orbit = builder.build(); + assertThat(Tensorics.sizeOf(orbit), equalTo(1)); + } + + @Test(expected = IllegalArgumentException.class) + public void putAtOnePositionWithWrongCoordinatesThrows() { + newBuilder().at(Position.of(BPM_A)).put(TESTVALUE_1_0); + } + + @Test + public void putOneAtPositionHasCorrectSize() { + assertThat(Tensorics.sizeOf(oneValuePosAH()), equalTo(1)); + } + + @Test + public void putOneAtPositionHasCorrectValue() { + assertThat(oneValuePosAH().tensor().get(POS_A_H), equalTo(TESTVALUE_1_0)); + } + + @Test + public void putOneValueByCoordinatesHasCorrectValue() { + assertThat(oneValueCoordinatesAH().tensor().get(POS_A_H), equalTo(TESTVALUE_1_0)); + } + + @Test + public void oneValueCoordinatesEqualsOneValuePos() { + assertThat(oneValueCoordinatesAH(), equalTo(oneValuePosAH())); + } + + @Test(expected = NullPointerException.class) + public void putNullEntryThrows() { + java.util.Map.Entry toPut = null; + newBuilder().put(toPut); + } + + @Test + public void putOneEntryIsEqualToOriginal() { + TensorbackedBuilder builder = newBuilder(); + builder.put(Iterables.getFirst(Tensorics.mapFrom(oneValuePosAH().tensor()).entrySet(), null)); + assertThat(builder.build(), equalTo(oneValuePosAH())); + } + + @Test(expected = NullPointerException.class) + public void putNullEntriesThrows() { + Set> toPut = null; + newBuilder().putAll(toPut); + } + + @Test + public void putEmptyCollectionResultsInEmptyTensor() { + TensorbackedBuilder builder = newBuilder(); + builder.putAll(Collections.>emptySet()); + assertThat(Tensorics.sizeOf(builder.build()), equalTo(0)); + } + + @Test + public void copyByEntryEqualsToOriginal() { + assertThat(oneValuePosCopied(), equalTo(oneValuePosAH())); + } + + @Test + public void copyByEntryEqualsHasCorrectSize() { + assertThat(Tensorics.sizeOf(oneValuePosCopied()), equalTo(1)); + } + + private SinglebeamOrbit oneValuePosCopied() { + TensorbackedBuilder builder = newBuilder(); + builder.putAll(Tensorics.mapFrom(oneValuePosAH().tensor()).entrySet()); + SinglebeamOrbit copiedOrbit = builder.build(); + return copiedOrbit; + } + + private SinglebeamOrbit oneValueCoordinatesAH() { + TensorbackedBuilder builder = newBuilder(); + builder.at(POS_A_H.coordinates()).put(TESTVALUE_1_0); + return builder.build(); + } + + private SinglebeamOrbit oneValuePosAH() { + TensorbackedBuilder builder = newBuilder(); + builder.at(POS_A_H).put(TESTVALUE_1_0); + return builder.build(); + } + + private TensorbackedBuilder newBuilder() { + return Tensorics.builderFor(SinglebeamOrbit.class); + } + + private SinglebeamOrbit emptyOrbit() { + return newBuilder().build(); + } } From 7690e72df094b1f752855c71600ac8c6d10edefe Mon Sep 17 00:00:00 2001 From: kaifox Date: Mon, 3 Jul 2017 18:16:18 +0200 Subject: [PATCH 3/4] Some tests and cleanup --- .../core/tensor/BroadcastedTensorView.java | 135 +++++++++--------- .../core/tensor/ImmutableTensor.java | 2 +- .../tensorics/core/tensor/MapableTensor.java | 19 --- .../tensorics/core/tensor/MappableTensor.java | 40 ++++++ .../tensor/operations/TensorInternals.java | 14 +- .../ImmutableDoubleArrayBackedTensor.java | 14 +- .../tensorics/core/tensor/PositionTest.java | 1 - .../operations/TensorInternalsTest.java | 47 ++++++ 8 files changed, 163 insertions(+), 109 deletions(-) delete mode 100644 src/java/org/tensorics/core/tensor/MapableTensor.java create mode 100644 src/java/org/tensorics/core/tensor/MappableTensor.java create mode 100644 src/test/org/tensorics/core/tensor/operations/TensorInternalsTest.java diff --git a/src/java/org/tensorics/core/tensor/BroadcastedTensorView.java b/src/java/org/tensorics/core/tensor/BroadcastedTensorView.java index ba00ff8df..a0fa590a7 100644 --- a/src/java/org/tensorics/core/tensor/BroadcastedTensorView.java +++ b/src/java/org/tensorics/core/tensor/BroadcastedTensorView.java @@ -25,83 +25,80 @@ import static org.tensorics.core.tensor.Positions.stripping; import static org.tensorics.core.tensor.Shapes.outerProduct; -import java.util.Map; - import org.tensorics.core.tensor.Positions.DimensionStripper; -import com.google.common.collect.ImmutableMap; - /** - * Lets a tensors appear as a tensor with a bigger shape. The final ('broadcasted') shape of the tensor has more - * dimensions as the original tensor and is the outer product of the original shape and an additional shape passed into - * the view. The original set and the passed in shape have to be disjunct in dimensions, i.e. there must be no dimension - * which appears in both of them. + * Lets a tensors appear as a tensor with a bigger shape. The final + * ('broadcasted') shape of the tensor has more dimensions as the original + * tensor and is the outer product of the original shape and an additional shape + * passed into the view. The original set and the passed in shape have to be + * disjunct in dimensions, i.e. there must be no dimension which appears in both + * of them. *

    - * The values are broadcasted such that the values will be the same for all coordinates of the new dimensions. + * The values are broadcasted such that the values will be the same for all + * coordinates of the new dimensions. *

    - * The resulting view will still be backed by the original tensor. Since the broadcasted shape will never be updated - * from the original tensor, the results might be unpredictable, if the original tensor would be mutable. + * The resulting view will still be backed by the original tensor. Since the + * broadcasted shape will never be updated from the original tensor, the results + * might be unpredictable, if the original tensor would be mutable. * * @author agorzaws * @author kfuchsbe - * @param the type of the values of the tensor + * @param + * the type of the values of the tensor */ -public final class BroadcastedTensorView implements MapableTensor { - - /** The original (smaller) tensor */ - private final Tensor originalTensor; - - /** The shape, how the tensor will appear */ - private final Shape broadcastedShape; - - /** - * The stripper instance to be used for the position-transformation from the bigger shape to the original - */ - private final DimensionStripper dimensionStripper; - - /** - * Constructs a view of the given original tensor, broadcasted to the additional shape. - * - * @param originalTensor the original tensor - * @param extendingShape the shape by which the original tensor shape has to be enlarged - */ - public BroadcastedTensorView(Tensor originalTensor, Shape extendingShape) { - this.originalTensor = originalTensor; - this.broadcastedShape = outerProduct(originalTensor.shape(), extendingShape); - this.dimensionStripper = stripping(extendingShape.dimensionSet()); - } - - @Override - public V get(Position position) { - return originalTensor.get(toOriginal(position)); - } - - @Override - public V get(Object... coordinates) { - return get(Position.of(coordinates)); - } - - @Override - public Map asMap() { - ImmutableMap.Builder builder = ImmutableMap.builder(); - for (Position position : broadcastedShape.positionSet()) { - builder.put(position, get(position)); - } - return builder.build(); - } - - private Position toOriginal(Position position) { - return dimensionStripper.apply(position); - } - - @Override - public Shape shape() { - return this.broadcastedShape; - } - - @Override - public Position context() { - return originalTensor.context(); - } +public final class BroadcastedTensorView implements Tensor { + + /** The original (smaller) tensor */ + private final Tensor originalTensor; + + /** The shape, how the tensor will appear */ + private final Shape broadcastedShape; + + /** + * The stripper instance to be used for the position-transformation from the + * bigger shape to the original + */ + private final DimensionStripper dimensionStripper; + + /** + * Constructs a view of the given original tensor, broadcasted to the + * additional shape. + * + * @param originalTensor + * the original tensor + * @param extendingShape + * the shape by which the original tensor shape has to be + * enlarged + */ + public BroadcastedTensorView(Tensor originalTensor, Shape extendingShape) { + this.originalTensor = originalTensor; + this.broadcastedShape = outerProduct(originalTensor.shape(), extendingShape); + this.dimensionStripper = stripping(extendingShape.dimensionSet()); + } + + @Override + public V get(Position position) { + return originalTensor.get(toOriginal(position)); + } + + @Override + public V get(Object... coordinates) { + return get(Position.of(coordinates)); + } + + private Position toOriginal(Position position) { + return dimensionStripper.apply(position); + } + + @Override + public Shape shape() { + return this.broadcastedShape; + } + + @Override + public Position context() { + return originalTensor.context(); + } } diff --git a/src/java/org/tensorics/core/tensor/ImmutableTensor.java b/src/java/org/tensorics/core/tensor/ImmutableTensor.java index bb3d42d24..6d97a5fb9 100644 --- a/src/java/org/tensorics/core/tensor/ImmutableTensor.java +++ b/src/java/org/tensorics/core/tensor/ImmutableTensor.java @@ -50,7 +50,7 @@ * @author agorzaws, kfuchsbe * @param type of values in Tensor. */ -public class ImmutableTensor implements MapableTensor, Serializable { +public class ImmutableTensor implements MappableTensor, Serializable { private static final long serialVersionUID = 1L; diff --git a/src/java/org/tensorics/core/tensor/MapableTensor.java b/src/java/org/tensorics/core/tensor/MapableTensor.java deleted file mode 100644 index f7d3c2530..000000000 --- a/src/java/org/tensorics/core/tensor/MapableTensor.java +++ /dev/null @@ -1,19 +0,0 @@ -package org.tensorics.core.tensor; - -import java.util.Map; - -/** - * Enhances the tensor interface by a method to view the tensor as a map from - * position to values. This interface is intended to be used by utility methods - * in order to avoid unnecessary calls. - * - * @author kaifox - * - * @param - * the type of the values of the tensors - */ -public interface MapableTensor extends Tensor { - - public Map asMap(); - -} diff --git a/src/java/org/tensorics/core/tensor/MappableTensor.java b/src/java/org/tensorics/core/tensor/MappableTensor.java new file mode 100644 index 000000000..a1d6a9f58 --- /dev/null +++ b/src/java/org/tensorics/core/tensor/MappableTensor.java @@ -0,0 +1,40 @@ +package org.tensorics.core.tensor; + +import java.util.Map; + +/** + * Enhances the tensor interface by a method to view the tensor as a map from + * position to values. This interface is intended to be used by utility methods + * in order to avoid unnecessary calls. + * + * @author kaifox + * + * @param + * the type of the values of the tensors + */ +public interface MappableTensor extends Tensor { + + /** + * By implementing this method, a tensor can provide an efficient way to + * convert the tensor to a map from position to values. Implementing + * instances must follow the following contract: + *

      + *
    • this method must not return {@code null} + *
    • It is recommended to return either a copy or an immutable map. + * Despite clients are not supposed to manipulate the returned maps, it + * cannot be guaranteed and this could lead to unexpected results. + *
    + * Usually, clients will not use this method directly, but should use + * {@link org.tensorics.core.tensor.operations.TensorInternals#mapFrom(Tensor)} + * (internal clients) or + * {@link org.tensorics.core.lang.Tensorics#mapFrom(Tensor)} (external + * clients) + * + * @see org.tensorics.core.tensor.operations.TensorInternals#mapFrom(Tensor) + * @see org.tensorics.core.lang.Tensorics#mapFrom(Tensor) + * @return a (preferrably immutable) map representing the content of the + * tensor + */ + public Map asMap(); + +} diff --git a/src/java/org/tensorics/core/tensor/operations/TensorInternals.java b/src/java/org/tensorics/core/tensor/operations/TensorInternals.java index 9c8c1a70b..5e8833d8e 100644 --- a/src/java/org/tensorics/core/tensor/operations/TensorInternals.java +++ b/src/java/org/tensorics/core/tensor/operations/TensorInternals.java @@ -31,7 +31,7 @@ import java.util.function.Function; import java.util.function.Supplier; -import org.tensorics.core.tensor.MapableTensor; +import org.tensorics.core.tensor.MappableTensor; import org.tensorics.core.tensor.Position; import org.tensorics.core.tensor.Shape; import org.tensorics.core.tensor.Tensor; @@ -73,20 +73,22 @@ public static Tensor createFrom(Shape shape, Function functi * Returns a map representing the content of the given tensor. The concrete * instance of the map might differ depending on the implementation of the * passed in tensor: Tensor implementations can offer a more efficient way - * to retrieve a map from them, by implementing the {@link MapableTensor} + * to retrieve a map from them, by implementing the {@link MappableTensor} * interface. If this interface is present, then its - * {@link MapableTensor#asMapOld()} method will be called. Otherwise, as a + * {@link MappableTensor#asMapOld()} method will be called. Otherwise, as a * fallback, a new immutable map will be created from information from the * shape of the passed in tensor and its values. * * @param tensor * the tensor from which a map should be returned - * @return a map representing the context of the tensor + * @return a map representing the content of the tensor + * @throws NullPointerException + * in case the passed in tensor is {@code null} */ public static Map mapFrom(Tensor tensor) { requireNonNull(tensor, "tensor must not be null"); - if (tensor instanceof MapableTensor) { - return ((MapableTensor) tensor).asMap(); + if (tensor instanceof MappableTensor) { + return ((MappableTensor) tensor).asMap(); } ImmutableMap.Builder builder = ImmutableMap.builder(); for (Position position : tensor.shape().positionSet()) { diff --git a/src/java/org/tensorics/core/tensor/specific/ImmutableDoubleArrayBackedTensor.java b/src/java/org/tensorics/core/tensor/specific/ImmutableDoubleArrayBackedTensor.java index 9d3515c80..9f0a3f075 100644 --- a/src/java/org/tensorics/core/tensor/specific/ImmutableDoubleArrayBackedTensor.java +++ b/src/java/org/tensorics/core/tensor/specific/ImmutableDoubleArrayBackedTensor.java @@ -25,13 +25,10 @@ import java.util.Map; import org.tensorics.core.tensor.AbstractTensorBuilder; -import org.tensorics.core.tensor.MapableTensor; import org.tensorics.core.tensor.Position; import org.tensorics.core.tensor.Shape; import org.tensorics.core.tensor.Tensor; -import com.google.common.collect.ImmutableMap; - /** * A specific implementation of a tensor, that contains double values. It is * backed by a simple double array to minimize memory usage and improve @@ -39,7 +36,7 @@ * * @author kaifox */ -public class ImmutableDoubleArrayBackedTensor implements MapableTensor { +public class ImmutableDoubleArrayBackedTensor implements Tensor { private final PositionIndexer indexer; private final double[] values; @@ -61,15 +58,6 @@ public Double get(Object... coordinates) { return get(Position.of(coordinates)); } - @Override - public Map asMap() { - ImmutableMap.Builder builder = ImmutableMap.builder(); - for (Position position : indexer.allPositions()) { - builder.put(position, get(position)); - } - return builder.build(); - } - @Override public Shape shape() { return Shape.viewOf(indexer.dimensions(), indexer.allPositions()); diff --git a/src/test/org/tensorics/core/tensor/PositionTest.java b/src/test/org/tensorics/core/tensor/PositionTest.java index 535fddd5c..35f7228a9 100644 --- a/src/test/org/tensorics/core/tensor/PositionTest.java +++ b/src/test/org/tensorics/core/tensor/PositionTest.java @@ -51,7 +51,6 @@ public void assertConsistentWithCorrectSet() { @Test public void assertConsistentWithWrongSetThrows() { thrown.expect(IllegalArgumentException.class); - //thrown.expectMessage("coordinates are not consistent"); thrown.expectMessage("assignable"); assertConsistentDimensions(POS_A, ImmutableSet.of(Integer.class)); } diff --git a/src/test/org/tensorics/core/tensor/operations/TensorInternalsTest.java b/src/test/org/tensorics/core/tensor/operations/TensorInternalsTest.java new file mode 100644 index 000000000..a331ea9f8 --- /dev/null +++ b/src/test/org/tensorics/core/tensor/operations/TensorInternalsTest.java @@ -0,0 +1,47 @@ +package org.tensorics.core.tensor.operations; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import java.util.Map; + +import org.junit.Test; +import org.tensorics.core.tensor.MappableTensor; +import org.tensorics.core.tensor.Position; +import org.tensorics.core.tensor.Shape; +import org.tensorics.core.tensor.Tensor; + +import com.google.common.collect.ImmutableMap; + +public class TensorInternalsTest { + + private final static Shape SHAPE_TO_RETURN = Shape.zeroDimensional(); + private final static String VALUE_TO_RETURN = "aValue"; + private final static Map MAP_TO_RETURN = ImmutableMap.of(Position.empty(), VALUE_TO_RETURN); + + @Test + public void mapFromCallsAsMapFromMapableTensor() { + @SuppressWarnings("unchecked") + MappableTensor mapableTensor = mock(MappableTensor.class); + when(mapableTensor.asMap()).thenReturn(MAP_TO_RETURN); + + Map returned = TensorInternals.mapFrom(mapableTensor); + assertThat(returned).isEqualTo(MAP_TO_RETURN); + verify(mapableTensor, times(1)).asMap(); + } + + @Test + public void mapIsConstructedFromShape() { + @SuppressWarnings("unchecked") + Tensor tensor = mock(Tensor.class); + when(tensor.shape()).thenReturn(SHAPE_TO_RETURN); + when(tensor.get(Position.empty())).thenReturn(VALUE_TO_RETURN); + + Map returned = TensorInternals.mapFrom(tensor); + assertThat(returned).isEqualTo(MAP_TO_RETURN); + } + +} From 9084f31ef6dcaca1f9e3c70948a04f79dfc8fda9 Mon Sep 17 00:00:00 2001 From: kaifox Date: Tue, 4 Jul 2017 00:21:49 +0200 Subject: [PATCH 4/4] fixed wrong reference --- .../org/tensorics/core/tensor/operations/TensorInternals.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/java/org/tensorics/core/tensor/operations/TensorInternals.java b/src/java/org/tensorics/core/tensor/operations/TensorInternals.java index 5e8833d8e..6c3e309e8 100644 --- a/src/java/org/tensorics/core/tensor/operations/TensorInternals.java +++ b/src/java/org/tensorics/core/tensor/operations/TensorInternals.java @@ -75,7 +75,7 @@ public static Tensor createFrom(Shape shape, Function functi * passed in tensor: Tensor implementations can offer a more efficient way * to retrieve a map from them, by implementing the {@link MappableTensor} * interface. If this interface is present, then its - * {@link MappableTensor#asMapOld()} method will be called. Otherwise, as a + * {@link MappableTensor#asMap()} method will be called. Otherwise, as a * fallback, a new immutable map will be created from information from the * shape of the passed in tensor and its values. *