internal override void Map2ToUnchecked(VectorStorage <T> target, VectorStorage <T> other, Func <T, T, T> f,
                                               Zeros zeros, ExistingData existingData)
        {
            if (target is SparseVectorStorage <T> )
            {
                // Recursive to dense target at first, since the operation is
                // effectively dense anyway because at least one operand is dense
                var intermediate = new DenseVectorStorage <T>(target.Length);
                Map2ToUnchecked(intermediate, other, f, zeros, ExistingData.AssumeZeros);
                intermediate.CopyTo(target, existingData);
                return;
            }

            var denseTarget = target as DenseVectorStorage <T>;
            var denseOther  = other as DenseVectorStorage <T>;

            if (denseTarget != null && denseOther != null)
            {
                CommonParallel.For(0, Data.Length, 4096, (a, b) =>
                {
                    for (var i = a; i < b; i++)
                    {
                        denseTarget.Data[i] = f(Data[i], denseOther.Data[i]);
                    }
                });

                return;
            }

            var sparseOther = other as SparseVectorStorage <T>;

            if (denseTarget != null && sparseOther != null)
            {
                var targetData      = denseTarget.Data;
                var otherIndices    = sparseOther.Indices;
                var otherValues     = sparseOther.Values;
                var otherValueCount = sparseOther.ValueCount;

                var k = 0;
                for (var i = 0; i < Data.Length; i++)
                {
                    if (k < otherValueCount && otherIndices[k] == i)
                    {
                        targetData[i] = f(Data[i], otherValues[k]);
                        k++;
                    }
                    else
                    {
                        targetData[i] = f(Data[i], Zero);
                    }
                }

                return;
            }

            base.Map2ToUnchecked(target, other, f, zeros, existingData);
        }
Esempio n. 2
0
        internal override void Map2ToUnchecked(VectorStorage <T> target, VectorStorage <T> other, Func <T, T, T> f, Zeros zeros, ExistingData existingData)
        {
            var processZeros = zeros == Zeros.Include || !Zero.Equals(f(Zero, Zero));

            var denseTarget = target as DenseVectorStorage <T>;
            var denseOther  = other as DenseVectorStorage <T>;

            if (denseTarget == null && (denseOther != null || processZeros))
            {
                // The handling is effectively dense but we're supposed to push
                // to a sparse target. Let's use a dense target instead,
                // then copy it normalized back to the sparse target.
                var intermediate = new DenseVectorStorage <T>(target.Length);
                Map2ToUnchecked(intermediate, other, f, zeros, ExistingData.AssumeZeros);
                intermediate.CopyTo(target, existingData);
                return;
            }

            if (denseOther != null)
            {
                T[] targetData = denseTarget.Data;
                T[] otherData  = denseOther.Data;

                int k = 0;
                for (int i = 0; i < otherData.Length; i++)
                {
                    if (k < ValueCount && Indices[k] == i)
                    {
                        targetData[i] = f(Values[k], otherData[i]);
                        k++;
                    }
                    else
                    {
                        targetData[i] = f(Zero, otherData[i]);
                    }
                }

                return;
            }

            var sparseOther = other as SparseVectorStorage <T>;

            if (sparseOther != null && denseTarget != null)
            {
                T[]   targetData      = denseTarget.Data;
                int[] otherIndices    = sparseOther.Indices;
                T[]   otherValues     = sparseOther.Values;
                int   otherValueCount = sparseOther.ValueCount;

                if (processZeros)
                {
                    int p = 0, q = 0;
                    for (int i = 0; i < targetData.Length; i++)
                    {
                        var left  = p < ValueCount && Indices[p] == i ? Values[p++] : Zero;
                        var right = q < otherValueCount && otherIndices[q] == i ? otherValues[q++] : Zero;
                        targetData[i] = f(left, right);
                    }
                }
                else
                {
                    if (existingData == ExistingData.Clear)
                    {
                        denseTarget.Clear();
                    }

                    int p = 0, q = 0;
                    while (p < ValueCount || q < otherValueCount)
                    {
                        if (q >= otherValueCount || p < ValueCount && Indices[p] < otherIndices[q])
                        {
                            targetData[Indices[p]] = f(Values[p], Zero);
                            p++;
                        }
                        else if (p >= ValueCount || q < otherValueCount && Indices[p] > otherIndices[q])
                        {
                            targetData[otherIndices[q]] = f(Zero, otherValues[q]);
                            q++;
                        }
                        else
                        {
                            Debug.Assert(Indices[p] == otherIndices[q]);
                            targetData[Indices[p]] = f(Values[p], otherValues[q]);
                            p++;
                            q++;
                        }
                    }
                }

                return;
            }

            var sparseTarget = target as SparseVectorStorage <T>;

            if (sparseOther != null && sparseTarget != null)
            {
                var   indices         = new List <int>();
                var   values          = new List <T>();
                int[] otherIndices    = sparseOther.Indices;
                T[]   otherValues     = sparseOther.Values;
                int   otherValueCount = sparseOther.ValueCount;

                int p = 0, q = 0;
                while (p < ValueCount || q < otherValueCount)
                {
                    if (q >= otherValueCount || p < ValueCount && Indices[p] < otherIndices[q])
                    {
                        var value = f(Values[p], Zero);
                        if (!Zero.Equals(value))
                        {
                            indices.Add(Indices[p]);
                            values.Add(value);
                        }

                        p++;
                    }
                    else if (p >= ValueCount || q < otherValueCount && Indices[p] > otherIndices[q])
                    {
                        var value = f(Zero, otherValues[q]);
                        if (!Zero.Equals(value))
                        {
                            indices.Add(otherIndices[q]);
                            values.Add(value);
                        }

                        q++;
                    }
                    else
                    {
                        var value = f(Values[p], otherValues[q]);
                        if (!Zero.Equals(value))
                        {
                            indices.Add(Indices[p]);
                            values.Add(value);
                        }

                        p++;
                        q++;
                    }
                }

                sparseTarget.Indices    = indices.ToArray();
                sparseTarget.Values     = values.ToArray();
                sparseTarget.ValueCount = values.Count;
                return;
            }

            // FALL BACK

            base.Map2ToUnchecked(target, other, f, zeros, existingData);
        }