Return-Path: X-Original-To: archive-asf-public-internal@cust-asf2.ponee.io Delivered-To: archive-asf-public-internal@cust-asf2.ponee.io Received: from cust-asf.ponee.io (cust-asf.ponee.io [163.172.22.183]) by cust-asf2.ponee.io (Postfix) with ESMTP id 60D59200C7B for ; Fri, 14 Apr 2017 17:51:04 +0200 (CEST) Received: by cust-asf.ponee.io (Postfix) id 5F52B160B80; Fri, 14 Apr 2017 15:51:04 +0000 (UTC) Delivered-To: archive-asf-public@cust-asf.ponee.io Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by cust-asf.ponee.io (Postfix) with SMTP id E868B160BA3 for ; Fri, 14 Apr 2017 17:51:01 +0200 (CEST) Received: (qmail 46404 invoked by uid 500); 14 Apr 2017 15:51:01 -0000 Mailing-List: contact commits-help@ignite.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@ignite.apache.org Delivered-To: mailing list commits@ignite.apache.org Received: (qmail 46298 invoked by uid 99); 14 Apr 2017 15:51:00 -0000 Received: from git1-us-west.apache.org (HELO git1-us-west.apache.org) (140.211.11.23) by apache.org (qpsmtpd/0.29) with ESMTP; Fri, 14 Apr 2017 15:51:00 +0000 Received: by git1-us-west.apache.org (ASF Mail Server at git1-us-west.apache.org, from userid 33) id 27DE4E93E1; Fri, 14 Apr 2017 15:51:00 +0000 (UTC) Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit From: av@apache.org To: commits@ignite.apache.org Date: Fri, 14 Apr 2017 15:51:06 -0000 Message-Id: In-Reply-To: <0b1063d4bce14dfe90e596512f497ab6@git.apache.org> References: <0b1063d4bce14dfe90e596512f497ab6@git.apache.org> X-Mailer: ASF-Git Admin Mailer Subject: [07/13] ignite git commit: IGNITE-4572 Machine Learning: Develop distributed algebra support for dense and sparse data sets. archived-at: Fri, 14 Apr 2017 15:51:04 -0000 http://git-wip-us.apache.org/repos/asf/ignite/blob/acd21fb8/modules/math/src/main/java/org/apache/ignite/math/impls/storage/vector/RandomVectorStorage.java ---------------------------------------------------------------------- diff --git a/modules/math/src/main/java/org/apache/ignite/math/impls/storage/vector/RandomVectorStorage.java b/modules/math/src/main/java/org/apache/ignite/math/impls/storage/vector/RandomVectorStorage.java new file mode 100644 index 0000000..58f0fb4 --- /dev/null +++ b/modules/math/src/main/java/org/apache/ignite/math/impls/storage/vector/RandomVectorStorage.java @@ -0,0 +1,152 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.ignite.math.impls.storage.vector; + +import java.io.IOException; +import java.io.ObjectInput; +import java.io.ObjectOutput; +import java.nio.ByteBuffer; +import java.util.Random; +import org.apache.ignite.math.MurmurHash; +import org.apache.ignite.math.VectorStorage; +import org.apache.ignite.math.exceptions.UnsupportedOperationException; + +/** + * {@link VectorStorage} implementation with random values in the vector elements. + */ +public class RandomVectorStorage implements VectorStorage { + /** */ + private static final long SCALE = 1L << 32; + /** */ + private static final int PRIME = 104047; + + /** Random generation seed. */ + private int seed; + + /** Vector size. */ + private int size; + + /** Whether fast hash is used, in {@link #get(int)}. */ + private boolean fastHash; + + /** */ + public RandomVectorStorage() { + // No-op. + } + + /** + * @param size Size of the storage. + * @param fastHash Whether or not to use fast hashing or Murmur hashing. + */ + public RandomVectorStorage(int size, boolean fastHash) { + assert size > 0; + + this.size = size; + this.fastHash = fastHash; + + seed = new Random().nextInt(); + } + + /** {@inheritDoc} */ + @Override public int size() { + return size; + } + + /** {@inheritDoc} */ + @Override public double get(int i) { + if (!fastHash) { + ByteBuffer buf = ByteBuffer.allocate(4); + + buf.putInt(i); + buf.flip(); + + return (MurmurHash.hash64A(buf, seed) & (SCALE - 1)) / (double)SCALE; + } + else + // This isn't a fantastic random number generator, but it is just fine for random projections. + return (((i * PRIME) & 8) * 0.25) - 1; + } + + /** {@inheritDoc} */ + @Override public void set(int i, double v) { + throw new UnsupportedOperationException("Random vector storage is a read-only storage."); + } + + /** {@inheritDoc} */ + @Override public void writeExternal(ObjectOutput out) throws IOException { + out.writeInt(size); + out.writeInt(seed); + out.writeBoolean(fastHash); + } + + /** {@inheritDoc} */ + @Override public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException { + size = in.readInt(); + seed = in.readInt(); + fastHash = in.readBoolean(); + } + + /** {@inheritDoc} */ + @Override public boolean isSequentialAccess() { + return true; + } + + /** {@inheritDoc} */ + @Override public boolean isDense() { + return true; + } + + /** {@inheritDoc} */ + @Override public boolean isRandomAccess() { + return true; + } + + /** {@inheritDoc} */ + @Override public boolean isDistributed() { + return false; + } + + /** {@inheritDoc} */ + @Override public boolean isArrayBased() { + return false; + } + + /** {@inheritDoc} */ + @Override public int hashCode() { + int res = 1; + + res = res * 37 + Boolean.hashCode(fastHash); + res = res * 37 + seed; + res = res * 37 + size; + + return res; + } + + /** {@inheritDoc} */ + @Override public boolean equals(Object o) { + if (this == o) + return true; + + if (o == null || getClass() != o.getClass()) + return false; + + RandomVectorStorage that = (RandomVectorStorage)o; + + return size == that.size && seed == that.seed && fastHash == that.fastHash; + } +} http://git-wip-us.apache.org/repos/asf/ignite/blob/acd21fb8/modules/math/src/main/java/org/apache/ignite/math/impls/storage/vector/SingleElementVectorDelegateStorage.java ---------------------------------------------------------------------- diff --git a/modules/math/src/main/java/org/apache/ignite/math/impls/storage/vector/SingleElementVectorDelegateStorage.java b/modules/math/src/main/java/org/apache/ignite/math/impls/storage/vector/SingleElementVectorDelegateStorage.java new file mode 100644 index 0000000..c5a4350 --- /dev/null +++ b/modules/math/src/main/java/org/apache/ignite/math/impls/storage/vector/SingleElementVectorDelegateStorage.java @@ -0,0 +1,145 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.ignite.math.impls.storage.vector; + +import java.io.IOException; +import java.io.ObjectInput; +import java.io.ObjectOutput; +import org.apache.ignite.math.Vector; +import org.apache.ignite.math.VectorStorage; +import org.apache.ignite.math.exceptions.UnsupportedOperationException; + +/** + * Single value view storage over another vector. + */ +public class SingleElementVectorDelegateStorage implements VectorStorage { + /** */ private int idx; + /** */ private Vector vec; + + /** + * + */ + public SingleElementVectorDelegateStorage() { + // No-op. + } + + /** + * @param vec Parent vector. + * @param idx Element index. + */ + public SingleElementVectorDelegateStorage(Vector vec, int idx) { + assert vec != null; + assert idx >= 0; + + this.vec = vec; + this.idx = idx; + } + + /** + * + * + */ + public int index() { + return idx; + } + + /** + * + * + */ + public Vector delegate() { + return vec; + } + + /** {@inheritDoc} */ + @Override public int size() { + return vec.size(); + } + + /** {@inheritDoc} */ + @Override public double get(int i) { + return i == idx ? vec.get(i) : 0.0; + } + + /** {@inheritDoc} */ + @Override public void set(int i, double v) { + if (i == idx) + vec.set(i, v); + else + throw new UnsupportedOperationException("Can't set element outside of index: " + idx); + } + + /** {@inheritDoc} */ + @Override public void writeExternal(ObjectOutput out) throws IOException { + out.writeObject(vec); + out.writeInt(idx); + } + + /** {@inheritDoc} */ + @Override public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException { + vec = (Vector)in.readObject(); + idx = in.readInt(); + } + + /** {@inheritDoc} */ + @Override public boolean isSequentialAccess() { + return true; + } + + /** {@inheritDoc} */ + @Override public boolean isDense() { + return true; + } + + /** {@inheritDoc} */ + @Override public boolean isRandomAccess() { + return true; + } + + /** {@inheritDoc} */ + @Override public boolean isDistributed() { + return false; + } + + /** {@inheritDoc} */ + @Override public boolean isArrayBased() { + return false; + } + + /** {@inheritDoc} */ + @Override public boolean equals(Object o) { + if (this == o) + return true; + + if (o == null || getClass() != o.getClass()) + return false; + + SingleElementVectorDelegateStorage that = (SingleElementVectorDelegateStorage)o; + + return idx == that.idx && (vec != null ? vec.equals(that.vec) : that.vec == null); + } + + /** {@inheritDoc} */ + @Override public int hashCode() { + int res = idx; + + res = 31 * res + (vec != null ? vec.hashCode() : 0); + + return res; + } +} http://git-wip-us.apache.org/repos/asf/ignite/blob/acd21fb8/modules/math/src/main/java/org/apache/ignite/math/impls/storage/vector/SingleElementVectorStorage.java ---------------------------------------------------------------------- diff --git a/modules/math/src/main/java/org/apache/ignite/math/impls/storage/vector/SingleElementVectorStorage.java b/modules/math/src/main/java/org/apache/ignite/math/impls/storage/vector/SingleElementVectorStorage.java new file mode 100644 index 0000000..3378817 --- /dev/null +++ b/modules/math/src/main/java/org/apache/ignite/math/impls/storage/vector/SingleElementVectorStorage.java @@ -0,0 +1,143 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.ignite.math.impls.storage.vector; + +import java.io.IOException; +import java.io.ObjectInput; +import java.io.ObjectOutput; +import org.apache.ignite.math.VectorStorage; +import org.apache.ignite.math.exceptions.UnsupportedOperationException; + +/** + * Vector storage holding a single non-zero value at some index. + */ +public class SingleElementVectorStorage implements VectorStorage { + /** */ private int idx; + /** */ private double val; + /** */ private int size; + + /** + * + */ + public SingleElementVectorStorage() { + // No-op. + } + + /** + * @param size Parent vector size. + * @param idx Element index in the parent vector. + * @param val Value of the element. + */ + public SingleElementVectorStorage(int size, int idx, double val) { + assert size > 0; + assert idx >= 0; + + this.size = size; + this.idx = idx; + this.val = val; + } + + /** + * + * @return Index of the element in the parent vector. + */ + public int index() { + return idx; + } + + /** {@inheritDoc} */ + @Override public int size() { + return size; + } + + /** {@inheritDoc} */ + @Override public double get(int i) { + return i == idx ? val : 0.0; + } + + /** {@inheritDoc} */ + @Override public void set(int i, double v) { + if (i == idx) + val = v; + else + throw new UnsupportedOperationException("Can't set element outside of index: " + idx); + } + + /** {@inheritDoc} */ + @Override public void writeExternal(ObjectOutput out) throws IOException { + out.writeInt(size); + out.writeInt(idx); + out.writeDouble(val); + } + + /** {@inheritDoc} */ + @Override public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException { + size = in.readInt(); + idx = in.readInt(); + val = in.readDouble(); + } + + /** {@inheritDoc} */ + @Override public boolean isSequentialAccess() { + return true; + } + + /** {@inheritDoc} */ + @Override public boolean isDense() { + return true; + } + + /** {@inheritDoc} */ + @Override public boolean isRandomAccess() { + return true; + } + + /** {@inheritDoc} */ + @Override public boolean isDistributed() { + return false; + } + + /** {@inheritDoc} */ + @Override public boolean isArrayBased() { + return false; + } + + /** {@inheritDoc} */ + @Override public boolean equals(Object o) { + if (this == o) + return true; + + if (o == null || getClass() != o.getClass()) + return false; + + SingleElementVectorStorage that = (SingleElementVectorStorage)o; + + return idx == that.idx && Double.compare(that.val, val) == 0 && size == that.size; + } + + /** {@inheritDoc} */ + @Override public int hashCode() { + int res = idx; + long temp = Double.doubleToLongBits(val); + + res = 31 * res + (int)(temp ^ (temp >>> 32)); + res = 31 * res + size; + + return res; + } +} http://git-wip-us.apache.org/repos/asf/ignite/blob/acd21fb8/modules/math/src/main/java/org/apache/ignite/math/impls/storage/vector/SparseLocalOffHeapVectorStorage.java ---------------------------------------------------------------------- diff --git a/modules/math/src/main/java/org/apache/ignite/math/impls/storage/vector/SparseLocalOffHeapVectorStorage.java b/modules/math/src/main/java/org/apache/ignite/math/impls/storage/vector/SparseLocalOffHeapVectorStorage.java new file mode 100644 index 0000000..9b912cb --- /dev/null +++ b/modules/math/src/main/java/org/apache/ignite/math/impls/storage/vector/SparseLocalOffHeapVectorStorage.java @@ -0,0 +1,148 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.ignite.math.impls.storage.vector; + +import java.io.IOException; +import java.io.ObjectInput; +import java.io.ObjectOutput; +import java.nio.ByteBuffer; +import org.apache.ignite.internal.util.offheap.GridOffHeapMap; +import org.apache.ignite.internal.util.offheap.GridOffHeapMapFactory; +import org.apache.ignite.math.VectorStorage; +import org.apache.ignite.math.exceptions.UnsupportedOperationException; + +/** + * {@link VectorStorage} implementation for {@link org.apache.ignite.math.impls.vector.SparseLocalOffHeapVector}. + */ +public class SparseLocalOffHeapVectorStorage implements VectorStorage { + /** Assume 10% density. */ + private static final int INIT_DENSITY = 10; + /** Storage capacity. */ + private int size; + /** Local off heap map. */ + private GridOffHeapMap gridOffHeapMap; + + /** */ + public SparseLocalOffHeapVectorStorage() { + //No-op. + } + + /** */ + public SparseLocalOffHeapVectorStorage(int cap) { + assert cap > 0; + + gridOffHeapMap = GridOffHeapMapFactory.unsafeMap(cap / INIT_DENSITY); + size = cap; + } + + /** {@inheritDoc} */ + @Override public int size() { + return size; + } + + /** {@inheritDoc} */ + @Override public double get(int i) { + byte[] bytes = gridOffHeapMap.get(hash(i), intToByteArray(i)); + return bytes == null ? 0 : ByteBuffer.wrap(bytes).getDouble(); + } + + /** {@inheritDoc} */ + @Override public void set(int i, double v) { + if (v != 0.0) + gridOffHeapMap.put(hash(i), intToByteArray(i), doubleToByteArray(v)); + else if (gridOffHeapMap.contains(hash(i), intToByteArray(i))) + gridOffHeapMap.remove(hash(i), intToByteArray(i)); + } + + /** {@inheritDoc} */ + @Override public void writeExternal(ObjectOutput out) throws IOException { + throw new UnsupportedOperationException(); // TODO: add externalization support. + } + + /** {@inheritDoc} */ + @Override public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException { + throw new UnsupportedOperationException(); + } + + /** {@inheritDoc} */ + @Override public boolean isSequentialAccess() { + return false; + } + + /** {@inheritDoc} */ + @Override public boolean isRandomAccess() { + return true; + } + + /** {@inheritDoc} */ + @Override public boolean isDense() { + return false; + } + + /** {@inheritDoc} */ + @Override public boolean isArrayBased() { + return false; + } + + /** {@inheritDoc} */ + @Override public boolean isDistributed() { + return false; + } + + /** {@inheritDoc} */ + @Override public void destroy() { + gridOffHeapMap.destruct(); + } + + /** */ + private int hash(int h) { + // Apply base step of MurmurHash; see http://code.google.com/p/smhasher/ + // Despite two multiplies, this is often faster than others + // with comparable bit-spread properties. + h ^= h >>> 16; + h *= 0x85ebca6b; + h ^= h >>> 13; + h *= 0xc2b2ae35; + + return (h >>> 16) ^ h; + } + + /** */ + private byte[] intToByteArray(int val) { + return new byte[] { + (byte)(val >>> 24), + (byte)(val >>> 16), + (byte)(val >>> 8), + (byte)val}; + } + + /** */ + private byte[] doubleToByteArray(double val) { + long l = Double.doubleToRawLongBits(val); + return new byte[] { + (byte)((l >> 56) & 0xff), + (byte)((l >> 48) & 0xff), + (byte)((l >> 40) & 0xff), + (byte)((l >> 32) & 0xff), + (byte)((l >> 24) & 0xff), + (byte)((l >> 16) & 0xff), + (byte)((l >> 8) & 0xff), + (byte)((l) & 0xff), + }; + } +} http://git-wip-us.apache.org/repos/asf/ignite/blob/acd21fb8/modules/math/src/main/java/org/apache/ignite/math/impls/storage/vector/SparseLocalOnHeapVectorStorage.java ---------------------------------------------------------------------- diff --git a/modules/math/src/main/java/org/apache/ignite/math/impls/storage/vector/SparseLocalOnHeapVectorStorage.java b/modules/math/src/main/java/org/apache/ignite/math/impls/storage/vector/SparseLocalOnHeapVectorStorage.java new file mode 100644 index 0000000..b3a8a3c --- /dev/null +++ b/modules/math/src/main/java/org/apache/ignite/math/impls/storage/vector/SparseLocalOnHeapVectorStorage.java @@ -0,0 +1,152 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.ignite.math.impls.storage.vector; + +import it.unimi.dsi.fastutil.ints.Int2DoubleOpenHashMap; +import it.unimi.dsi.fastutil.ints.Int2DoubleRBTreeMap; +import java.io.IOException; +import java.io.ObjectInput; +import java.io.ObjectOutput; +import java.util.Map; +import org.apache.ignite.math.StorageConstants; +import org.apache.ignite.math.VectorStorage; + +/** + * Sparse, local, on-heap vector storage. + */ +public class SparseLocalOnHeapVectorStorage implements VectorStorage, StorageConstants { + /** */ private int size; + /** */ private int acsMode; + + /** Actual map storage. */ + private Map sto; + + /** + * + */ + public SparseLocalOnHeapVectorStorage() { + // No-op. + } + + /** + * @param size Vector size. + * @param acsMode Access mode. + */ + public SparseLocalOnHeapVectorStorage(int size, int acsMode) { + assert size > 0; + assertAccessMode(acsMode); + + this.size = size; + this.acsMode = acsMode; + + if (acsMode == SEQUENTIAL_ACCESS_MODE) + sto = new Int2DoubleRBTreeMap(); + else + sto = new Int2DoubleOpenHashMap(); + } + + /** + * + * + */ + public int getAccessMode() { + return acsMode; + } + + /** {@inheritDoc} */ + @Override public int size() { + return size; + } + + /** {@inheritDoc} */ + @Override public double get(int i) { + return sto.getOrDefault(i, 0.0); + } + + /** {@inheritDoc} */ + @Override public void set(int i, double v) { + if (v != 0.0) + sto.put(i, v); + else if (sto.containsKey(i)) + sto.remove(i); + + } + + /** {@inheritDoc} */ + @Override public void writeExternal(ObjectOutput out) throws IOException { + out.writeInt(size); + out.writeInt(acsMode); + out.writeObject(sto); + } + + /** {@inheritDoc} */ + @SuppressWarnings({"unchecked"}) + @Override public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException { + size = in.readInt(); + acsMode = in.readInt(); + sto = (Map)in.readObject(); + } + + /** {@inheritDoc} */ + @Override public boolean isSequentialAccess() { + return acsMode == SEQUENTIAL_ACCESS_MODE; + } + + /** {@inheritDoc} */ + @Override public boolean isDense() { + return false; + } + + /** {@inheritDoc} */ + @Override public boolean isRandomAccess() { + return true; + } + + /** {@inheritDoc} */ + @Override public boolean isDistributed() { + return false; + } + + /** {@inheritDoc} */ + @Override public boolean isArrayBased() { + return false; + } + + /** {@inheritDoc} */ + @Override public boolean equals(Object o) { + if (this == o) + return true; + + if (o == null || getClass() != o.getClass()) + return false; + + SparseLocalOnHeapVectorStorage that = (SparseLocalOnHeapVectorStorage)o; + + return size == that.size && acsMode == that.acsMode && (sto != null ? sto.equals(that.sto) : that.sto == null); + } + + /** {@inheritDoc} */ + @Override public int hashCode() { + int res = size; + + res = 31 * res + acsMode; + res = 31 * res + (sto != null ? sto.hashCode() : 0); + + return res; + } +} http://git-wip-us.apache.org/repos/asf/ignite/blob/acd21fb8/modules/math/src/main/java/org/apache/ignite/math/impls/storage/vector/package-info.java ---------------------------------------------------------------------- diff --git a/modules/math/src/main/java/org/apache/ignite/math/impls/storage/vector/package-info.java b/modules/math/src/main/java/org/apache/ignite/math/impls/storage/vector/package-info.java new file mode 100644 index 0000000..a716e6a --- /dev/null +++ b/modules/math/src/main/java/org/apache/ignite/math/impls/storage/vector/package-info.java @@ -0,0 +1,22 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * + * Contains specific implementations for vector storage models. + */ +package org.apache.ignite.math.impls.storage.vector; \ No newline at end of file http://git-wip-us.apache.org/repos/asf/ignite/blob/acd21fb8/modules/math/src/main/java/org/apache/ignite/math/impls/vector/AbstractReadOnlyVector.java ---------------------------------------------------------------------- diff --git a/modules/math/src/main/java/org/apache/ignite/math/impls/vector/AbstractReadOnlyVector.java b/modules/math/src/main/java/org/apache/ignite/math/impls/vector/AbstractReadOnlyVector.java new file mode 100644 index 0000000..58c583a --- /dev/null +++ b/modules/math/src/main/java/org/apache/ignite/math/impls/vector/AbstractReadOnlyVector.java @@ -0,0 +1,108 @@ +package org.apache.ignite.math.impls.vector; + +import org.apache.ignite.math.Matrix; +import org.apache.ignite.math.Vector; +import org.apache.ignite.math.VectorStorage; +import org.apache.ignite.math.functions.IgniteBiFunction; +import org.apache.ignite.math.functions.IgniteDoubleFunction; +import org.apache.ignite.math.impls.matrix.FunctionMatrix; + +/** + * This class provides a helper implementation of the read-only implementation of {@link Vector} + * interface to minimize the effort required to implement it. + * Subclasses may override some of the implemented methods if a more + * specific or optimized implementation is desirable. + */ +public abstract class AbstractReadOnlyVector extends AbstractVector { + /** */ + public AbstractReadOnlyVector() { + // No-op. + } + + /** + * @param sto Storage. + */ + public AbstractReadOnlyVector(VectorStorage sto) { + super(true, sto); + } + + /** {@inheritDoc} */ + @Override public Matrix cross(Vector vec) { + return new FunctionMatrix(size(), vec.size(), + (row, col) -> vec.get(col) * get(row)); + } + + /** {@inheritDoc} */ + @Override public Matrix toMatrix(boolean rowLike) { + return new FunctionMatrix(rowLike ? 1 : size(), rowLike ? size() : 1, + (row, col) -> rowLike ? get(col) : get(row)); + } + + /** {@inheritDoc} */ + @Override public Matrix toMatrixPlusOne(boolean rowLike, double zeroVal) { + return new FunctionMatrix(rowLike ? 1 : size() + 1, rowLike ? size() + 1 : 1, (row, col) -> { + if (row == 0 && col == 0) + return zeroVal; + + return rowLike ? get(col - 1) : get(row - 1); + }); + } + + /** {@inheritDoc} */ + @Override public Vector copy() { + return this; // This exploits read-only feature of this type vector. + } + + /** {@inheritDoc} */ + @Override public Vector logNormalize() { + return logNormalize(2.0, Math.sqrt(getLengthSquared())); + } + + /** {@inheritDoc} */ + @Override public Vector logNormalize(double power) { + return logNormalize(power, kNorm(power)); + } + + /** {@inheritDoc} */ + @Override public Vector map(IgniteDoubleFunction fun) { + return new FunctionVector(size(), (i) -> fun.apply(get(i))); + } + + /** {@inheritDoc} */ + @Override public Vector map(Vector vec, IgniteBiFunction fun) { + checkCardinality(vec); + + return new FunctionVector(size(), (i) -> fun.apply(get(i), vec.get(i))); + } + + /** {@inheritDoc} */ + @Override public Vector map(IgniteBiFunction fun, double y) { + return new FunctionVector(size(), (i) -> fun.apply(get(i), y)); + } + + /** {@inheritDoc} */ + @Override public Vector divide(double x) { + if (x == 1.0) + return this; + + return new FunctionVector(size(), (i) -> get(i) / x); + } + + /** {@inheritDoc} */ + @Override public Vector times(double x) { + return x == 0 ? new ConstantVector(size(), 0) : new FunctionVector(size(), (i) -> get(i) * x); + } + + /** + * @param power Power. + * @param normLen Normalized length. + * @return logNormalized value. + */ + private Vector logNormalize(double power, double normLen) { + assert !(Double.isInfinite(power) || power <= 1.0); + + double denominator = normLen * Math.log(power); + + return new FunctionVector(size(), (idx) -> Math.log1p(get(idx)) / denominator); + } +} http://git-wip-us.apache.org/repos/asf/ignite/blob/acd21fb8/modules/math/src/main/java/org/apache/ignite/math/impls/vector/AbstractVector.java ---------------------------------------------------------------------- diff --git a/modules/math/src/main/java/org/apache/ignite/math/impls/vector/AbstractVector.java b/modules/math/src/main/java/org/apache/ignite/math/impls/vector/AbstractVector.java new file mode 100644 index 0000000..d84c0f3 --- /dev/null +++ b/modules/math/src/main/java/org/apache/ignite/math/impls/vector/AbstractVector.java @@ -0,0 +1,903 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.ignite.math.impls.vector; + +import java.io.IOException; +import java.io.ObjectInput; +import java.io.ObjectOutput; +import java.util.Arrays; +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; +import java.util.NoSuchElementException; +import java.util.Spliterator; +import java.util.function.Consumer; +import java.util.function.IntToDoubleFunction; +import org.apache.ignite.lang.IgniteUuid; +import org.apache.ignite.math.Matrix; +import org.apache.ignite.math.Vector; +import org.apache.ignite.math.VectorStorage; +import org.apache.ignite.math.exceptions.CardinalityException; +import org.apache.ignite.math.exceptions.IndexException; +import org.apache.ignite.math.exceptions.UnsupportedOperationException; +import org.apache.ignite.math.functions.Functions; +import org.apache.ignite.math.functions.IgniteBiFunction; +import org.apache.ignite.math.functions.IgniteDoubleFunction; +import org.apache.ignite.math.impls.matrix.MatrixView; +import org.jetbrains.annotations.NotNull; + +/** + * This class provides a helper implementation of the {@link Vector} + * interface to minimize the effort required to implement it. + * Subclasses may override some of the implemented methods if a more + * specific or optimized implementation is desirable. + */ +public abstract class AbstractVector implements Vector { + /** Vector storage implementation. */ + private VectorStorage sto; + + /** Meta attribute storage. */ + private Map meta = new HashMap<>(); + + /** Vector's GUID. */ + private IgniteUuid guid = IgniteUuid.randomUuid(); + + /** Cached value for length squared. */ + private double lenSq = 0.0; + + /** Maximum cached element. */ + private Element maxElm = null; + /** Minimum cached element. */ + private Element minElm = null; + + /** Readonly flag (false by default). */ + private boolean readOnly = false; + + /** Read-only error message. */ + private static final String RO_MSG = "Vector is read-only."; + + /** + * + */ + private void ensureReadOnly() { + if (readOnly) + throw new UnsupportedOperationException(RO_MSG); + } + + /** + * @param sto Storage. + */ + public AbstractVector(VectorStorage sto) { + this(false, sto); + } + + /** + * @param readOnly Is read only. + * @param sto Storage. + */ + public AbstractVector(boolean readOnly, VectorStorage sto) { + assert sto != null; + + this.readOnly = readOnly; + this.sto = sto; + } + + /** + * + */ + public AbstractVector() { + // No-op. + } + + /** + * Set storage. + * + * @param sto Storage. + */ + protected void setStorage(VectorStorage sto) { + this.sto = sto; + } + + /** + * @param i Index. + * @param v Value. + */ + protected void storageSet(int i, double v) { + ensureReadOnly(); + + sto.set(i, v); + + // Reset cached values. + lenSq = 0.0; + maxElm = minElm = null; + } + + /** + * @param i Index. + * @return Value. + */ + protected double storageGet(int i) { + return sto.get(i); + } + + /** {@inheritDoc} */ + @Override public int size() { + return sto.size(); + } + + /** + * Check index bounds. + * + * @param idx Index to check. + */ + protected void checkIndex(int idx) { + if (idx < 0 || idx >= sto.size()) + throw new IndexException(idx); + } + + /** {@inheritDoc} */ + @Override public double get(int idx) { + checkIndex(idx); + + return storageGet(idx); + } + + /** {@inheritDoc} */ + @Override public double getX(int idx) { + return storageGet(idx); + } + + /** {@inheritDoc} */ + @Override public boolean isArrayBased() { + return sto.isArrayBased(); + } + + /** {@inheritDoc} */ + @Override public Vector sort() { + if (isArrayBased()) + Arrays.parallelSort(sto.data()); + else + throw new UnsupportedOperationException(); + + return this; + } + + /** {@inheritDoc} */ + @Override public Vector map(IgniteDoubleFunction fun) { + if (sto.isArrayBased()) { + double[] data = sto.data(); + + Arrays.setAll(data, (idx) -> fun.apply(data[idx])); + } + else { + int len = size(); + + for (int i = 0; i < len; i++) + storageSet(i, fun.apply(storageGet(i))); + } + + return this; + } + + /** {@inheritDoc} */ + @Override public Vector map(Vector vec, IgniteBiFunction fun) { + checkCardinality(vec); + + int len = size(); + + for (int i = 0; i < len; i++) + storageSet(i, fun.apply(storageGet(i), vec.get(i))); + + return this; + } + + /** {@inheritDoc} */ + @Override public Vector map(IgniteBiFunction fun, double y) { + int len = size(); + + for (int i = 0; i < len; i++) + storageSet(i, fun.apply(storageGet(i), y)); + + return this; + } + + /** + * @param idx Index. + * @return Value. + */ + protected Element makeElement(int idx) { + checkIndex(idx); + + return new Element() { + /** {@inheritDoc} */ + @Override public double get() { + return storageGet(idx); + } + + /** {@inheritDoc} */ + @Override public int index() { + return idx; + } + + /** {@inheritDoc} */ + @Override public void set(double val) { + storageSet(idx, val); + } + }; + } + + /** {@inheritDoc} */ + @Override public Element minElement() { + if (minElm == null) { + int minIdx = 0; + int len = size(); + + for (int i = 0; i < len; i++) + if (storageGet(i) < storageGet(minIdx)) + minIdx = i; + + minElm = makeElement(minIdx); + } + + return minElm; + } + + /** {@inheritDoc} */ + @Override public Element maxElement() { + if (maxElm == null) { + int maxIdx = 0; + int len = size(); + + for (int i = 0; i < len; i++) + if (storageGet(i) > storageGet(maxIdx)) + maxIdx = i; + + maxElm = makeElement(maxIdx); + } + + return maxElm; + } + + /** {@inheritDoc} */ + @Override public double minValue() { + return minElement().get(); + } + + /** {@inheritDoc} */ + @Override public double maxValue() { + return maxElement().get(); + } + + /** {@inheritDoc} */ + @Override public Vector set(int idx, double val) { + checkIndex(idx); + + storageSet(idx, val); + + return this; + } + + /** {@inheritDoc} */ + @Override public Vector setX(int idx, double val) { + storageSet(idx, val); + + return this; + } + + /** {@inheritDoc} */ + @Override public Vector increment(int idx, double val) { + checkIndex(idx); + + storageSet(idx, storageGet(idx) + val); + + return this; + } + + /** {@inheritDoc} */ + @Override public Vector incrementX(int idx, double val) { + storageSet(idx, storageGet(idx) + val); + + return this; + } + + /** + * Tests if given value is considered a zero value. + * + * @param val Value to check. + */ + protected boolean isZero(double val) { + return val == 0.0; + } + + /** {@inheritDoc} */ + @Override public double sum() { + double sum = 0; + int len = size(); + + for (int i = 0; i < len; i++) + sum += storageGet(i); + + return sum; + } + + /** {@inheritDoc} */ + @Override public IgniteUuid guid() { + return guid; + } + + /** {@inheritDoc} */ + @Override public Iterable all() { + return new Iterable() { + private int idx = 0; + + /** {@inheritDoc} */ + @NotNull + @Override public Iterator iterator() { + return new Iterator() { + /** {@inheritDoc} */ + @Override public boolean hasNext() { + return size() > 0 && idx < size(); + } + + /** {@inheritDoc} */ + @Override public Element next() { + if (hasNext()) + return getElement(idx++); + + throw new NoSuchElementException(); + } + }; + } + }; + } + + /** {@inheritDoc} */ + @Override public int nonZeroElements() { + int cnt = 0; + + for (Element ignored : nonZeroes()) + cnt++; + + return cnt; + } + + /** {@inheritDoc} */ + @Override public T foldMap(IgniteBiFunction foldFun, IgniteDoubleFunction mapFun, + T zeroVal) { + T res = zeroVal; + int len = size(); + + for (int i = 0; i < len; i++) + res = foldFun.apply(res, mapFun.apply(storageGet(i))); + + return res; + } + + /** {@inheritDoc} */ + @Override public T foldMap(Vector vec, IgniteBiFunction foldFun, + IgniteBiFunction combFun, T zeroVal) { + checkCardinality(vec); + + T res = zeroVal; + int len = size(); + + for (int i = 0; i < len; i++) + res = foldFun.apply(res, combFun.apply(storageGet(i), vec.getX(i))); + + return res; + } + + /** {@inheritDoc} */ + @Override public Iterable nonZeroes() { + return new Iterable() { + private int idx = 0; + private int idxNext = -1; + + /** {@inheritDoc} */ + @NotNull + @Override public Iterator iterator() { + return new Iterator() { + @Override public boolean hasNext() { + findNext(); + + return !over(); + } + + @Override public Element next() { + if (hasNext()) { + idx = idxNext; + + return getElement(idxNext); + } + + throw new NoSuchElementException(); + } + + private void findNext() { + if (over()) + return; + + if (idxNextInitialized() && idx != idxNext) + return; + + if (idxNextInitialized()) + idx = idxNext + 1; + + while (idx < size() && isZero(get(idx))) + idx++; + + idxNext = idx++; + } + + private boolean over() { + return idxNext >= size(); + } + + private boolean idxNextInitialized() { + return idxNext != -1; + } + }; + } + }; + } + + /** {@inheritDoc} */ + @Override public Map getMetaStorage() { + return meta; + } + + /** {@inheritDoc} */ + @Override public Vector assign(double val) { + if (sto.isArrayBased()) { + ensureReadOnly(); + + Arrays.fill(sto.data(), val); + } + else { + int len = size(); + + for (int i = 0; i < len; i++) + storageSet(i, val); + } + + return this; + } + + /** {@inheritDoc} */ + @Override public Vector assign(double[] vals) { + checkCardinality(vals); + + if (sto.isArrayBased()) { + ensureReadOnly(); + + System.arraycopy(vals, 0, sto.data(), 0, vals.length); + + lenSq = 0.0; + } + else { + int len = size(); + + for (int i = 0; i < len; i++) + storageSet(i, vals[i]); + } + + return this; + } + + /** {@inheritDoc} */ + @Override public Vector assign(Vector vec) { + checkCardinality(vec); + + for (Vector.Element x : vec.all()) + storageSet(x.index(), x.get()); + + return this; + } + + /** {@inheritDoc} */ + @Override public Vector assign(IntToDoubleFunction fun) { + assert fun != null; + + if (sto.isArrayBased()) { + ensureReadOnly(); + + Arrays.setAll(sto.data(), fun); + } + else { + int len = size(); + + for (int i = 0; i < len; i++) + storageSet(i, fun.applyAsDouble(i)); + } + + return this; + } + + /** {@inheritDoc} */ + @Override public Spliterator allSpliterator() { + return new Spliterator() { + /** {@inheritDoc} */ + @Override public boolean tryAdvance(Consumer act) { + int len = size(); + + for (int i = 0; i < len; i++) + act.accept(storageGet(i)); + + return true; + } + + /** {@inheritDoc} */ + @Override public Spliterator trySplit() { + return null; // No Splitting. + } + + /** {@inheritDoc} */ + @Override public long estimateSize() { + return size(); + } + + /** {@inheritDoc} */ + @Override public int characteristics() { + return ORDERED | SIZED; + } + }; + } + + /** {@inheritDoc} */ + @Override public Spliterator nonZeroSpliterator() { + return new Spliterator() { + /** {@inheritDoc} */ + @Override public boolean tryAdvance(Consumer act) { + int len = size(); + + for (int i = 0; i < len; i++) { + double val = storageGet(i); + + if (!isZero(val)) + act.accept(val); + } + + return true; + } + + /** {@inheritDoc} */ + @Override public Spliterator trySplit() { + return null; // No Splitting. + } + + /** {@inheritDoc} */ + @Override public long estimateSize() { + return nonZeroElements(); + } + + /** {@inheritDoc} */ + @Override public int characteristics() { + return ORDERED | SIZED; + } + }; + } + + /** {@inheritDoc} */ + @Override public double dot(Vector vec) { + checkCardinality(vec); + + double sum = 0.0; + int len = size(); + + for (int i = 0; i < len; i++) + sum += storageGet(i) * vec.getX(i); + + return sum; + } + + /** {@inheritDoc} */ + @Override public double getLengthSquared() { + if (lenSq == 0.0) + lenSq = dotSelf(); + + return lenSq; + } + + /** {@inheritDoc} */ + @Override public boolean isDense() { + return sto.isDense(); + } + + /** {@inheritDoc} */ + @Override public boolean isSequentialAccess() { + return sto.isSequentialAccess(); + } + + /** {@inheritDoc} */ + @Override public boolean isRandomAccess() { + return sto.isRandomAccess(); + } + + /** {@inheritDoc} */ + @Override public boolean isDistributed() { + return sto.isDistributed(); + } + + /** {@inheritDoc} */ + @Override public VectorStorage getStorage() { + return sto; + } + + /** {@inheritDoc} */ + @Override public Vector viewPart(int off, int len) { + return new VectorView(this, off, len); + } + + /** {@inheritDoc} */ + @Override public Matrix cross(Vector vec) { + Matrix res = likeMatrix(size(), vec.size()); + + if (res == null) + return null; + + for (Element e : nonZeroes()) { + int row = e.index(); + + res.assignRow(row, vec.times(getX(row))); + } + + return res; + } + + /** {@inheritDoc} */ + @Override public Matrix toMatrix(boolean rowLike) { + Matrix res = likeMatrix(rowLike ? 1 : size(), rowLike ? size() : 1); + + if (res == null) + return null; + + if (rowLike) + res.assignRow(0, this); + else + res.assignColumn(0, this); + + return res; + } + + /** {@inheritDoc} */ + @Override public Matrix toMatrixPlusOne(boolean rowLike, double zeroVal) { + Matrix res = likeMatrix(rowLike ? 1 : size() + 1, rowLike ? size() + 1 : 1); + + if (res == null) + return null; + + res.set(0, 0, zeroVal); + + if (rowLike) + new MatrixView(res, 0, 1, 1, size()).assignRow(0, this); + else + new MatrixView(res, 1, 0, size(), 1).assignColumn(0, this); + + return res; + } + + /** {@inheritDoc} */ + @Override public double getDistanceSquared(Vector vec) { + checkCardinality(vec); + + double thisLenSq = getLengthSquared(); + double thatLenSq = vec.getLengthSquared(); + double dot = dot(vec); + double distEst = thisLenSq + thatLenSq - 2 * dot; + + if (distEst > 1.0e-3 * (thisLenSq + thatLenSq)) + // The vectors are far enough from each other that the formula is accurate. + return Math.max(distEst, 0); + else + return foldMap(vec, Functions.PLUS, Functions.MINUS_SQUARED, 0d); + } + + /** */ + protected void checkCardinality(Vector vec) { + if (vec.size() != size()) + throw new CardinalityException(size(), vec.size()); + } + + /** */ + protected void checkCardinality(double[] vec) { + if (vec.length != size()) + throw new CardinalityException(size(), vec.length); + } + + /** */ + protected void checkCardinality(int[] arr) { + if (arr.length != size()) + throw new CardinalityException(size(), arr.length); + } + + /** {@inheritDoc} */ + @Override public Vector minus(Vector vec) { + checkCardinality(vec); + + Vector cp = copy(); + + return cp.map(vec, Functions.MINUS); + } + + /** {@inheritDoc} */ + @Override public Vector plus(double x) { + Vector cp = copy(); + + return x != 0.0 ? cp.map(Functions.plus(x)) : cp; + } + + /** {@inheritDoc} */ + @Override public Vector divide(double x) { + Vector cp = copy(); + + if (x != 1.0) + for (Element element : cp.all()) + element.set(element.get() / x); + + return cp; + } + + /** {@inheritDoc} */ + @Override public Vector times(double x) { + if (x == 0.0) + return like(size()); + else + return copy().map(Functions.mult(x)); + } + + /** {@inheritDoc} */ + @Override public Vector times(Vector vec) { + checkCardinality(vec); + + return copy().map(vec, Functions.MULT); + } + + /** {@inheritDoc} */ + @Override public Vector plus(Vector vec) { + checkCardinality(vec); + + Vector cp = copy(); + + return cp.map(vec, Functions.PLUS); + } + + /** {@inheritDoc} */ + @Override public Vector logNormalize() { + return logNormalize(2.0, Math.sqrt(getLengthSquared())); + } + + /** {@inheritDoc} */ + @Override public Vector logNormalize(double power) { + return logNormalize(power, kNorm(power)); + } + + /** + * @param power Power. + * @param normLen Normalized length. + * @return logNormalized value. + */ + private Vector logNormalize(double power, double normLen) { + assert !(Double.isInfinite(power) || power <= 1.0); + + double denominator = normLen * Math.log(power); + + Vector cp = copy(); + + for (Element element : cp.all()) + element.set(Math.log1p(element.get()) / denominator); + + return cp; + } + + /** {@inheritDoc} */ + @Override public double kNorm(double power) { + assert power >= 0.0; + + // Special cases. + if (Double.isInfinite(power)) + return foldMap(Math::max, Math::abs, 0d); + else if (power == 2.0) + return Math.sqrt(getLengthSquared()); + else if (power == 1.0) + return foldMap(Functions.PLUS, Math::abs, 0d); + else if (power == 0.0) + return nonZeroElements(); + else + // Default case. + return Math.pow(foldMap(Functions.PLUS, Functions.pow(power), 0d), 1.0 / power); + } + + /** {@inheritDoc} */ + @Override public Vector normalize() { + return divide(Math.sqrt(getLengthSquared())); + } + + /** {@inheritDoc} */ + @Override public Vector normalize(double power) { + return divide(kNorm(power)); + } + + /** {@inheritDoc} */ + @Override public Vector copy() { + return like(size()).assign(this); + } + + /** + * @return Result of dot with self. + */ + protected double dotSelf() { + double sum = 0.0; + int len = size(); + + for (int i = 0; i < len; i++) { + double v = storageGet(i); + + sum += v * v; + } + + return sum; + } + + /** {@inheritDoc} */ + @Override public Element getElement(int idx) { + return makeElement(idx); + } + + /** {@inheritDoc} */ + @Override public void writeExternal(ObjectOutput out) throws IOException { + out.writeObject(sto); + out.writeObject(meta); + out.writeObject(guid); + out.writeBoolean(readOnly); + } + + /** {@inheritDoc} */ + @SuppressWarnings("unchecked") + @Override public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException { + sto = (VectorStorage)in.readObject(); + meta = (Map)in.readObject(); + guid = (IgniteUuid)in.readObject(); + readOnly = in.readBoolean(); + } + + /** {@inheritDoc} */ + @Override public void destroy() { + sto.destroy(); + } + + /** {@inheritDoc} */ + @Override public int hashCode() { + int res = 1; + res += res * 37 + guid.hashCode(); + res += sto == null ? 0 : res * 37 + sto.hashCode(); + return res; + } + + /** {@inheritDoc} */ + @Override public boolean equals(Object obj) { + if (this == obj) + return true; + + if (obj == null || getClass() != obj.getClass()) + return false; + + AbstractVector that = (AbstractVector)obj; + + return (sto != null ? sto.equals(that.sto) : that.sto == null); + } +} http://git-wip-us.apache.org/repos/asf/ignite/blob/acd21fb8/modules/math/src/main/java/org/apache/ignite/math/impls/vector/CacheVector.java ---------------------------------------------------------------------- diff --git a/modules/math/src/main/java/org/apache/ignite/math/impls/vector/CacheVector.java b/modules/math/src/main/java/org/apache/ignite/math/impls/vector/CacheVector.java new file mode 100644 index 0000000..0e9b26f --- /dev/null +++ b/modules/math/src/main/java/org/apache/ignite/math/impls/vector/CacheVector.java @@ -0,0 +1,140 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.ignite.math.impls.vector; + +import org.apache.ignite.IgniteCache; +import org.apache.ignite.math.Matrix; +import org.apache.ignite.math.ValueMapper; +import org.apache.ignite.math.Vector; +import org.apache.ignite.math.VectorKeyMapper; +import org.apache.ignite.math.exceptions.UnsupportedOperationException; +import org.apache.ignite.math.functions.IgniteBiFunction; +import org.apache.ignite.math.functions.IgniteDoubleFunction; +import org.apache.ignite.math.functions.IgniteFunction; +import org.apache.ignite.math.impls.CacheUtils; +import org.apache.ignite.math.impls.storage.vector.CacheVectorStorage; + +/** + * Vector based on existing cache and index and value mapping functions. + */ +public class CacheVector extends AbstractVector { + /** + * + */ + public CacheVector() { + // No-op. + } + + /** + * Creates new vector over existing cache. + * + * @param size + * @param cache + * @param keyFunc + * @param valMapper + */ + public CacheVector( + int size, + IgniteCache cache, + VectorKeyMapper keyFunc, + ValueMapper valMapper) { + setStorage(new CacheVectorStorage<>(size, cache, keyFunc, valMapper)); + } + + /** + * @param mapper + */ + private Vector mapOverCache(IgniteFunction mapper) { + CacheVectorStorage sto = storage(); + + CacheUtils.map(sto.cache().getName(), sto.keyMapper(), sto.valueMapper(), mapper); + + return this; + } + + /** {@inheritDoc} */ + @Override public double minValue() { + CacheVectorStorage sto = storage(); + + return CacheUtils.min(sto.cache().getName(), sto.keyMapper(), sto.valueMapper()); + } + + /** {@inheritDoc} */ + @Override public double maxValue() { + CacheVectorStorage sto = storage(); + + return CacheUtils.max(sto.cache().getName(), sto.keyMapper(), sto.valueMapper()); + } + + /** {@inheritDoc} */ + @Override public Vector map(IgniteDoubleFunction fun) { + return mapOverCache(fun::apply); + } + + /** {@inheritDoc} */ + @Override public Vector map(IgniteBiFunction fun, double y) { + // TODO: provide cache-optimized implementation. + return super.map(fun, y); // TODO + } + + /** {@inheritDoc} */ + @Override public double sum() { + CacheVectorStorage sto = storage(); + + return CacheUtils.sum(sto.cache().getName(), sto.keyMapper(), sto.valueMapper()); + } + + /** {@inheritDoc} */ + @Override public Vector assign(double val) { + return mapOverCache((Double d) -> val); + } + + /** {@inheritDoc} */ + @Override public Vector plus(double x) { + return mapOverCache((Double d) -> d + x); + } + + /** {@inheritDoc} */ + @Override public Vector divide(double x) { + return mapOverCache((Double d) -> d / x); + } + + /** {@inheritDoc} */ + @Override public Vector times(double x) { + return mapOverCache((Double d) -> d * x); + } + + /** + * + * + */ + @SuppressWarnings({"unchecked"}) + private CacheVectorStorage storage() { + return (CacheVectorStorage)getStorage(); + } + + /** {@inheritDoc} */ + @Override public Vector like(int crd) { + throw new UnsupportedOperationException(); + } + + /** {@inheritDoc} */ + @Override public Matrix likeMatrix(int rows, int cols) { + throw new UnsupportedOperationException(); + } +} http://git-wip-us.apache.org/repos/asf/ignite/blob/acd21fb8/modules/math/src/main/java/org/apache/ignite/math/impls/vector/ConstantVector.java ---------------------------------------------------------------------- diff --git a/modules/math/src/main/java/org/apache/ignite/math/impls/vector/ConstantVector.java b/modules/math/src/main/java/org/apache/ignite/math/impls/vector/ConstantVector.java new file mode 100644 index 0000000..0fddfd6 --- /dev/null +++ b/modules/math/src/main/java/org/apache/ignite/math/impls/vector/ConstantVector.java @@ -0,0 +1,84 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.ignite.math.impls.vector; + +import org.apache.ignite.math.Matrix; +import org.apache.ignite.math.Vector; +import org.apache.ignite.math.VectorStorage; +import org.apache.ignite.math.exceptions.UnsupportedOperationException; +import org.apache.ignite.math.impls.storage.vector.ConstantVectorStorage; + +/** + * Constant value, read-only vector. + */ +public class ConstantVector extends AbstractReadOnlyVector { + /** + * + */ + public ConstantVector() { + // No-op. + } + + /** + * @param size + * @param val + */ + public ConstantVector(int size, double val) { + super(new ConstantVectorStorage(size, val)); + } + + /** + * + * + */ + private ConstantVectorStorage storage() { + return (ConstantVectorStorage)getStorage(); + } + + /** {@inheritDoc} */ + @Override public Vector copy() { + ConstantVectorStorage sto = storage(); + + return new ConstantVector(sto.size(), sto.constant()); + } + + /** {@inheritDoc} */ + @Override public Vector like(int crd) { + return new ConstantVector(crd, storage().constant()); + } + + /** {@inheritDoc} */ + @Override public Matrix likeMatrix(int rows, int cols) { + throw new UnsupportedOperationException(); + } + + /** {@inheritDoc} */ + @Override public boolean equals(Object o) { + if (this == o) + return true; + + if (o == null || getClass() != o.getClass()) + return false; + + ConstantVector that = (ConstantVector)o; + + VectorStorage sto = getStorage(); + + return (sto != null ? sto.equals(that.getStorage()) : that.getStorage() == null); + } +} http://git-wip-us.apache.org/repos/asf/ignite/blob/acd21fb8/modules/math/src/main/java/org/apache/ignite/math/impls/vector/DelegatingVector.java ---------------------------------------------------------------------- diff --git a/modules/math/src/main/java/org/apache/ignite/math/impls/vector/DelegatingVector.java b/modules/math/src/main/java/org/apache/ignite/math/impls/vector/DelegatingVector.java new file mode 100644 index 0000000..a10fa45 --- /dev/null +++ b/modules/math/src/main/java/org/apache/ignite/math/impls/vector/DelegatingVector.java @@ -0,0 +1,391 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.ignite.math.impls.vector; + +import java.io.IOException; +import java.io.ObjectInput; +import java.io.ObjectOutput; +import java.util.HashMap; +import java.util.Map; +import java.util.Spliterator; +import java.util.function.IntToDoubleFunction; +import org.apache.ignite.lang.IgniteUuid; +import org.apache.ignite.math.Matrix; +import org.apache.ignite.math.Vector; +import org.apache.ignite.math.VectorStorage; +import org.apache.ignite.math.functions.IgniteBiFunction; +import org.apache.ignite.math.functions.IgniteDoubleFunction; + +/** + * Convenient class that can be used to add decorations to an existing vector. Subclasses + * can add weights, indices, etc. while maintaining full vector functionality. + */ +public class DelegatingVector implements Vector { + /** Delegating vector. */ + private Vector dlg; + + /** Meta attribute storage. */ + private Map meta = new HashMap<>(); + + /** GUID. */ + private IgniteUuid guid = IgniteUuid.randomUuid(); + + /** */ + public DelegatingVector() { + // No-op. + } + + /** + * @param dlg + */ + public DelegatingVector(Vector dlg) { + assert dlg != null; + + this.dlg = dlg; + } + + /** {@inheritDoc} */ + @Override public void writeExternal(ObjectOutput out) throws IOException { + out.writeObject(dlg); + out.writeObject(meta); + out.writeObject(guid); + } + + /** {@inheritDoc} */ + @SuppressWarnings("unchecked") + @Override public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException { + dlg = (Vector)in.readObject(); + meta = (Map)in.readObject(); + guid = (IgniteUuid)in.readObject(); + } + + /** {@inheritDoc} */ + @Override public Map getMetaStorage() { + return meta; + } + + /** {@inheritDoc} */ + @Override public Matrix likeMatrix(int rows, int cols) { + return dlg.likeMatrix(rows, cols); + } + + /** {@inheritDoc} */ + @Override public Matrix toMatrix(boolean rowLike) { + return dlg.toMatrix(rowLike); + } + + /** {@inheritDoc} */ + @Override public Matrix toMatrixPlusOne(boolean rowLike, double zeroVal) { + return dlg.toMatrixPlusOne(rowLike, zeroVal); + } + + /** {@inheritDoc} */ + @Override public int size() { + return dlg.size(); + } + + /** {@inheritDoc} */ + @Override public boolean isDense() { + return dlg.isDense(); + } + + /** {@inheritDoc} */ + @Override public double minValue() { + return dlg.minValue(); + } + + /** {@inheritDoc} */ + @Override public double maxValue() { + return dlg.maxValue(); + } + + /** {@inheritDoc} */ + @Override public boolean isSequentialAccess() { + return dlg.isSequentialAccess(); + } + + /** {@inheritDoc} */ + @Override public boolean isArrayBased() { + return dlg.isArrayBased(); + } + + /** {@inheritDoc} */ + @Override public Vector copy() { + return new DelegatingVector(dlg); + } + + /** {@inheritDoc} */ + @Override public Iterable all() { + return dlg.all(); + } + + /** {@inheritDoc} */ + @Override public Iterable nonZeroes() { + return dlg.nonZeroes(); + } + + /** {@inheritDoc} */ + @Override public Vector sort() { + return dlg.sort(); + } + + /** {@inheritDoc} */ + @Override public Spliterator allSpliterator() { + return dlg.allSpliterator(); + } + + /** {@inheritDoc} */ + @Override public Spliterator nonZeroSpliterator() { + return dlg.nonZeroSpliterator(); + } + + /** {@inheritDoc} */ + @Override public Element getElement(int idx) { + return dlg.getElement(idx); + } + + /** {@inheritDoc} */ + @Override public Vector assign(double val) { + return dlg.assign(val); + } + + /** {@inheritDoc} */ + @Override public Vector assign(double[] vals) { + return dlg.assign(vals); + } + + /** {@inheritDoc} */ + @Override public Vector assign(Vector vec) { + return dlg.assign(vec); + } + + /** {@inheritDoc} */ + @Override public Vector assign(IntToDoubleFunction fun) { + return dlg.assign(fun); + } + + /** {@inheritDoc} */ + @Override public Vector map(IgniteDoubleFunction fun) { + return dlg.map(fun); + } + + /** {@inheritDoc} */ + @Override public Vector map(Vector vec, IgniteBiFunction fun) { + return dlg.map(vec, fun); + } + + /** {@inheritDoc} */ + @Override public Vector map(IgniteBiFunction fun, double y) { + return dlg.map(fun, y); + } + + /** {@inheritDoc} */ + @Override public Vector divide(double x) { + return dlg.divide(x); + } + + /** {@inheritDoc} */ + @Override public double dot(Vector vec) { + return dlg.dot(vec); + } + + /** {@inheritDoc} */ + @Override public double get(int idx) { + return dlg.get(idx); + } + + /** {@inheritDoc} */ + @Override public double getX(int idx) { + return dlg.getX(idx); + } + + /** {@inheritDoc} */ + @Override public Vector like(int crd) { + return dlg.like(crd); + } + + /** {@inheritDoc} */ + @Override public Vector minus(Vector vec) { + return dlg.minus(vec); + } + + /** {@inheritDoc} */ + @Override public Vector normalize() { + return dlg.normalize(); + } + + /** {@inheritDoc} */ + @Override public Vector normalize(double power) { + return dlg.normalize(power); + } + + /** {@inheritDoc} */ + @Override public Vector logNormalize() { + return dlg.logNormalize(); + } + + /** {@inheritDoc} */ + @Override public Vector logNormalize(double power) { + return dlg.logNormalize(power); + } + + /** {@inheritDoc} */ + @Override public double kNorm(double power) { + return dlg.kNorm(power); + } + + /** {@inheritDoc} */ + @Override public Element minElement() { + return dlg.minElement(); + } + + /** {@inheritDoc} */ + @Override public Element maxElement() { + return dlg.maxElement(); + } + + /** {@inheritDoc} */ + @Override public Vector plus(double x) { + return dlg.plus(x); + } + + /** {@inheritDoc} */ + @Override public Vector plus(Vector vec) { + return dlg.plus(vec); + } + + /** {@inheritDoc} */ + @Override public Vector set(int idx, double val) { + return dlg.set(idx, val); + } + + /** {@inheritDoc} */ + @Override public Vector setX(int idx, double val) { + return dlg.setX(idx, val); + } + + /** {@inheritDoc} */ + @Override public Vector incrementX(int idx, double val) { + return dlg.incrementX(idx, val); + } + + /** {@inheritDoc} */ + @Override public Vector increment(int idx, double val) { + return dlg.increment(idx, val); + } + + /** {@inheritDoc} */ + @Override public int nonZeroElements() { + return dlg.nonZeroElements(); + } + + /** {@inheritDoc} */ + @Override public Vector times(double x) { + return dlg.times(x); + } + + /** {@inheritDoc} */ + @Override public Vector times(Vector vec) { + return dlg.times(vec); + } + + /** {@inheritDoc} */ + @Override public Vector viewPart(int off, int len) { + return dlg.viewPart(off, len); + } + + /** {@inheritDoc} */ + @Override public VectorStorage getStorage() { + return dlg.getStorage(); + } + + /** {@inheritDoc} */ + @Override public double sum() { + return dlg.sum(); + } + + /** {@inheritDoc} */ + @Override public Matrix cross(Vector vec) { + return dlg.cross(vec); + } + + /** {@inheritDoc} */ + @Override public T foldMap(IgniteBiFunction foldFun, IgniteDoubleFunction mapFun, + T zeroVal) { + return dlg.foldMap(foldFun, mapFun, zeroVal); + } + + /** {@inheritDoc} */ + @Override public T foldMap(Vector vec, IgniteBiFunction foldFun, + IgniteBiFunction combFun, T zeroVal) { + return dlg.foldMap(vec, foldFun, combFun, zeroVal); + } + + /** {@inheritDoc} */ + @Override public double getLengthSquared() { + return dlg.getLengthSquared(); + } + + /** {@inheritDoc} */ + @Override public double getDistanceSquared(Vector vec) { + return dlg.getDistanceSquared(vec); + } + + /** {@inheritDoc} */ + @Override public boolean isRandomAccess() { + return dlg.isRandomAccess(); + } + + /** {@inheritDoc} */ + @Override public boolean isDistributed() { + return dlg.isDistributed(); + } + + /** {@inheritDoc} */ + @Override public IgniteUuid guid() { + return guid; + } + + /** {@inheritDoc} */ + @Override public void destroy() { + dlg.destroy(); + } + + /** {@inheritDoc} */ + @Override public int hashCode() { + int res = 1; + + res = res * 37 + meta.hashCode(); + res = res * 37 + dlg.hashCode(); + + return res; + } + + /** {@inheritDoc} */ + @Override public boolean equals(Object o) { + if (this == o) + return true; + + if (o == null || getClass() != o.getClass()) + return false; + + DelegatingVector that = (DelegatingVector)o; + + return meta.equals(that.meta) && dlg.equals(that.dlg); + } +} http://git-wip-us.apache.org/repos/asf/ignite/blob/acd21fb8/modules/math/src/main/java/org/apache/ignite/math/impls/vector/DenseLocalOffHeapVector.java ---------------------------------------------------------------------- diff --git a/modules/math/src/main/java/org/apache/ignite/math/impls/vector/DenseLocalOffHeapVector.java b/modules/math/src/main/java/org/apache/ignite/math/impls/vector/DenseLocalOffHeapVector.java new file mode 100644 index 0000000..4e7eb21 --- /dev/null +++ b/modules/math/src/main/java/org/apache/ignite/math/impls/vector/DenseLocalOffHeapVector.java @@ -0,0 +1,89 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.ignite.math.impls.vector; + +import java.util.stream.IntStream; +import org.apache.ignite.math.Matrix; +import org.apache.ignite.math.Vector; +import org.apache.ignite.math.impls.matrix.DenseLocalOffHeapMatrix; +import org.apache.ignite.math.impls.storage.vector.DenseLocalOffHeapVectorStorage; + +/** + * Implementation for {@link Vector} assuming dense logic and local offheap JVM storage. + * It is suitable for data sets where local, non-distributed execution is satisfactory and on-heap JVM storage + * is not enough to keep the entire data set. + */ +public class DenseLocalOffHeapVector extends AbstractVector { + /** */ + public DenseLocalOffHeapVector() { + // No-op. + } + + /** */ + private void makeOffheapStorage(int size) { + setStorage(new DenseLocalOffHeapVectorStorage(size)); + } + + /** + * @param arr Array to copy to offheap storage. + */ + public DenseLocalOffHeapVector(double[] arr) { + makeOffheapStorage(arr.length); + + assign(arr); + } + + /** + * @param size Vector cardinality. + */ + public DenseLocalOffHeapVector(int size) { + makeOffheapStorage(size); + } + + /** {@inheritDoc} */ + @Override public Vector assign(Vector vec) { + checkCardinality(vec); + + IntStream.range(0, size()).parallel().forEach(idx -> set(idx, vec.get(idx))); + + return this; + } + + /** {@inheritDoc} */ + @Override public Vector times(double x) { + if (x == 0.0) + return like(size()).assign(0); + else + return super.times(x); + } + + /** {@inheritDoc} */ + @Override public Vector like(int crd) { + return new DenseLocalOffHeapVector(crd); + } + + /** {@inheritDoc} */ + @Override public Matrix likeMatrix(int rows, int cols) { + return new DenseLocalOffHeapMatrix(rows, cols); + } + + /** {@inheritDoc} */ + @Override public boolean equals(Object o) { + return o != null && getClass().equals(o.getClass()) && (getStorage().equals(((Vector)o).getStorage())); + } +} http://git-wip-us.apache.org/repos/asf/ignite/blob/acd21fb8/modules/math/src/main/java/org/apache/ignite/math/impls/vector/DenseLocalOnHeapVector.java ---------------------------------------------------------------------- diff --git a/modules/math/src/main/java/org/apache/ignite/math/impls/vector/DenseLocalOnHeapVector.java b/modules/math/src/main/java/org/apache/ignite/math/impls/vector/DenseLocalOnHeapVector.java new file mode 100644 index 0000000..5827998 --- /dev/null +++ b/modules/math/src/main/java/org/apache/ignite/math/impls/vector/DenseLocalOnHeapVector.java @@ -0,0 +1,104 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.ignite.math.impls.vector; + +import java.util.Map; +import org.apache.ignite.math.Matrix; +import org.apache.ignite.math.Vector; +import org.apache.ignite.math.VectorStorage; +import org.apache.ignite.math.exceptions.UnsupportedOperationException; +import org.apache.ignite.math.impls.matrix.DenseLocalOnHeapMatrix; +import org.apache.ignite.math.impls.storage.vector.ArrayVectorStorage; + +/** + * Basic implementation for vector. + *

+ * This is a trivial implementation for vector assuming dense logic, local on-heap JVM storage + * based on {@code double[]} array. It is only suitable for data sets where + * local, non-distributed execution is satisfactory and on-heap JVM storage is enough + * to keep the entire data set. + */ +public class DenseLocalOnHeapVector extends AbstractVector { + /** + * @param size Vector cardinality. + */ + private VectorStorage mkStorage(int size) { + return new ArrayVectorStorage(size); + } + + /** + * @param arr Source array. + * @param cp {@code true} to clone array, reuse it otherwise. + */ + private VectorStorage mkStorage(double[] arr, boolean cp) { + assert arr != null; + + return new ArrayVectorStorage(cp ? arr.clone() : arr); + } + + /** + * @param args Parameters for new Vector. + */ + public DenseLocalOnHeapVector(Map args) { + assert args != null; + + if (args.containsKey("size")) + setStorage(mkStorage((int)args.get("size"))); + else if (args.containsKey("arr") && args.containsKey("copy")) + setStorage(mkStorage((double[])args.get("arr"), (boolean)args.get("copy"))); + else + throw new UnsupportedOperationException("Invalid constructor argument(s)."); + } + + /** */ + public DenseLocalOnHeapVector() { + // No-op. + } + + /** + * @param size Vector cardinality. + */ + public DenseLocalOnHeapVector(int size) { + setStorage(mkStorage(size)); + } + + /** + * @param arr Source array. + * @param shallowCp {@code true} to use shallow copy. + */ + public DenseLocalOnHeapVector(double[] arr, boolean shallowCp) { + setStorage(mkStorage(arr, shallowCp)); + } + + /** + * @param arr Source array. + */ + public DenseLocalOnHeapVector(double[] arr) { + this(arr, false); + } + + /** {@inheritDoc} */ + @Override public Matrix likeMatrix(int rows, int cols) { + return new DenseLocalOnHeapMatrix(rows, cols); + } + + /** {@inheritDoc} */ + @Override public Vector like(int crd) { + return new DenseLocalOnHeapVector(crd); + } +} http://git-wip-us.apache.org/repos/asf/ignite/blob/acd21fb8/modules/math/src/main/java/org/apache/ignite/math/impls/vector/FunctionVector.java ---------------------------------------------------------------------- diff --git a/modules/math/src/main/java/org/apache/ignite/math/impls/vector/FunctionVector.java b/modules/math/src/main/java/org/apache/ignite/math/impls/vector/FunctionVector.java new file mode 100644 index 0000000..0e7cfad --- /dev/null +++ b/modules/math/src/main/java/org/apache/ignite/math/impls/vector/FunctionVector.java @@ -0,0 +1,112 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.ignite.math.impls.vector; + +import java.util.Map; +import org.apache.ignite.math.Matrix; +import org.apache.ignite.math.Vector; +import org.apache.ignite.math.exceptions.UnsupportedOperationException; +import org.apache.ignite.math.functions.IgniteFunction; +import org.apache.ignite.math.functions.IntDoubleToVoidFunction; +import org.apache.ignite.math.impls.storage.vector.FunctionVectorStorage; + +/** + * Implementation of {@link Vector} that maps vector element index to {@link java.util.function} interfaces. + */ +public class FunctionVector extends AbstractVector { + /** + * + */ + public FunctionVector() { + // No-op. + } + + /** + * Creates read-write or read-only function vector. + * + * @param size Vector size. + * @param getFunc Function that returns value corresponding to given element index. + * @param setFunc Set function. If {@code null} - this will be a read-only vector. + */ + public FunctionVector(int size, IgniteFunction getFunc, IntDoubleToVoidFunction setFunc) { + setStorage(new FunctionVectorStorage(size, getFunc, setFunc)); + } + + /** + * Creates read-only function vector. + * + * @param size Vector size. + * @param getFunc Function that returns value corresponding to given element index. + */ + public FunctionVector(int size, IgniteFunction getFunc) { + setStorage(new FunctionVectorStorage(size, getFunc)); + } + + /** + * @param args Arguments for vector constructor. + */ + public FunctionVector(Map args) { + assert args != null; + + if (args.containsKey("size") && args.containsKey("getFunc") && args.containsKey("setFunc")) { + @SuppressWarnings("unchecked") + IgniteFunction getFunc = (IgniteFunction)args.get("getFunc"); + IntDoubleToVoidFunction setFunc = (IntDoubleToVoidFunction)args.get("setFunc"); + int size = (int)args.get("size"); + + setStorage(new FunctionVectorStorage(size, getFunc, setFunc)); + } + else if (args.containsKey("size") && args.containsKey("getFunc")) { + @SuppressWarnings("unchecked") + IgniteFunction getFunc = (IgniteFunction)args.get("getFunc"); + int size = (int)args.get("size"); + + setStorage(new FunctionVectorStorage(size, getFunc)); + } + else + throw new UnsupportedOperationException("Invalid constructor argument(s)."); + } + + /** + * + * + */ + private FunctionVectorStorage storage() { + return (FunctionVectorStorage)getStorage(); + } + + /** {@inheritDoc} */ + @Override public org.apache.ignite.math.Vector like(int crd) { + FunctionVectorStorage sto = storage(); + + return new FunctionVector(crd, sto.getFunction(), sto.setFunction()); + } + + /** {@inheritDoc} */ + @Override public Matrix likeMatrix(int rows, int cols) { + throw new UnsupportedOperationException(); + } + + /** {@inheritDoc} */ + @Override public Vector times(double x) { + if (x == 0.0) + return like(size()).assign(0); + else + return super.times(x); + } +}