// // Math.NET Numerics, part of the Math.NET Project // http://numerics.mathdotnet.com // http://github.com/mathnet/mathnet-numerics // http://mathnetnumerics.codeplex.com // // Copyright (c) 2009-2013 Math.NET // // Permission is hereby granted, free of charge, to any person // obtaining a copy of this software and associated documentation // files (the "Software"), to deal in the Software without // restriction, including without limitation the rights to use, // copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the // Software is furnished to do so, subject to the following // conditions: // // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES // OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT // HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, // WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR // OTHER DEALINGS IN THE SOFTWARE. // using System; using System.Collections.Generic; using System.Linq; using MathNet.Numerics.Properties; using MathNet.Numerics.Threading; namespace MathNet.Numerics.LinearAlgebra.Storage { [Serializable] public class DenseVectorStorage : VectorStorage where T : struct, IEquatable, IFormattable { // [ruegg] public fields are OK here public readonly T[] Data; internal DenseVectorStorage(int length) : base(length) { Data = new T[length]; } internal DenseVectorStorage(int length, T[] data) : base(length) { if (data == null) { throw new ArgumentNullException("data"); } if (data.Length != length) { throw new ArgumentOutOfRangeException("data", string.Format(Resources.ArgumentArrayWrongLength, length)); } Data = data; } /// /// True if the vector storage format is dense. /// public override bool IsDense { get { return true; } } /// /// Retrieves the requested element without range checking. /// public override T At(int index) { return Data[index]; } /// /// Sets the element without range checking. /// public override void At(int index, T value) { Data[index] = value; } public override void Clear() { Array.Clear(Data, 0, Data.Length); } public override void Clear(int index, int count) { Array.Clear(Data, index, count); } // INITIALIZATION public static DenseVectorStorage OfVector(VectorStorage vector) { var storage = new DenseVectorStorage(vector.Length); vector.CopyToUnchecked(storage, skipClearing: true); return storage; } public static DenseVectorStorage OfInit(int length, Func init) { if (length < 1) { throw new ArgumentOutOfRangeException("length", string.Format(Resources.ArgumentLessThanOne, length)); } var data = new T[length]; CommonParallel.For(0, data.Length, 4096, (a, b) => { for (int i = a; i < b; i++) { data[i] = init(i); } }); return new DenseVectorStorage(length, data); } public static DenseVectorStorage OfEnumerable(IEnumerable data) { if (data == null) { throw new ArgumentNullException("data"); } var arrayData = data as T[]; if (arrayData != null) { var copy = new T[arrayData.Length]; Array.Copy(arrayData, copy, arrayData.Length); return new DenseVectorStorage(copy.Length, copy); } var array = data.ToArray(); return new DenseVectorStorage(array.Length, array); } public static DenseVectorStorage OfIndexedEnumerable(int length, IEnumerable> data) { if (data == null) { throw new ArgumentNullException("data"); } var array = new T[length]; foreach (var item in data) { array[item.Item1] = item.Item2; } return new DenseVectorStorage(array.Length, array); } // VECTOR COPY internal override void CopyToUnchecked(VectorStorage target, bool skipClearing = false) { var denseTarget = target as DenseVectorStorage; if (denseTarget != null) { if (!ReferenceEquals(this, denseTarget)) { Array.Copy(Data, 0, denseTarget.Data, 0, Data.Length); } return; } // FALL BACK for (int i = 0; i < Data.Length; i++) { target.At(i, Data[i]); } } // ROW COPY internal override void CopyToRowUnchecked(MatrixStorage target, int rowIndex, bool skipClearing = false) { var denseTarget = target as DenseColumnMajorMatrixStorage; if (denseTarget != null) { for (int j = 0; j < Data.Length; j++) { denseTarget.Data[j*target.RowCount + rowIndex] = Data[j]; } return; } // FALL BACK for (int j = 0; j < Length; j++) { target.At(rowIndex, j, Data[j]); } } // COLUMN COPY internal override void CopyToColumnUnchecked(MatrixStorage target, int columnIndex, bool skipClearing = false) { var denseTarget = target as DenseColumnMajorMatrixStorage; if (denseTarget != null) { Array.Copy(Data, 0, denseTarget.Data, columnIndex*denseTarget.RowCount, Data.Length); return; } // FALL BACK for (int i = 0; i < Length; i++) { target.At(i, columnIndex, Data[i]); } } // SUB-VECTOR COPY internal override void CopySubVectorToUnchecked(VectorStorage target, int sourceIndex, int targetIndex, int count, bool skipClearing = false) { var denseTarget = target as DenseVectorStorage; if (denseTarget != null) { Array.Copy(Data, sourceIndex, denseTarget.Data, targetIndex, count); return; } // FALL BACK base.CopySubVectorToUnchecked(target, sourceIndex, targetIndex, count, skipClearing); } // SUB-ROW COPY internal override void CopyToSubRowUnchecked(MatrixStorage target, int rowIndex, int sourceColumnIndex, int targetColumnIndex, int columnCount, bool skipClearing = false) { var denseTarget = target as DenseColumnMajorMatrixStorage; if (denseTarget != null) { for (int j = 0; j < Data.Length; j++) { denseTarget.Data[(j + targetColumnIndex)*target.RowCount + rowIndex] = Data[j + sourceColumnIndex]; } return; } // FALL BACK for (int j = sourceColumnIndex, jj = targetColumnIndex; j < sourceColumnIndex + columnCount; j++, jj++) { target.At(rowIndex, jj, Data[j]); } } // SUB-COLUMN COPY internal override void CopyToSubColumnUnchecked(MatrixStorage target, int columnIndex, int sourceRowIndex, int targetRowIndex, int rowCount, bool skipClearing = false) { var denseTarget = target as DenseColumnMajorMatrixStorage; if (denseTarget != null) { Array.Copy(Data, sourceRowIndex, denseTarget.Data, columnIndex*denseTarget.RowCount + targetRowIndex, rowCount); return; } // FALL BACK for (int i = sourceRowIndex, ii = targetRowIndex; i < sourceRowIndex + rowCount; i++, ii++) { target.At(ii, columnIndex, Data[i]); } } // ENUMERATION public override IEnumerable Enumerate() { return Data; } public override IEnumerable> EnumerateIndexed() { return Data.Select((t, i) => new Tuple(i, t)); } public override IEnumerable EnumerateNonZero() { return Data.Where(x => !Zero.Equals(x)); } public override IEnumerable> EnumerateNonZeroIndexed() { for (var i = 0; i < Data.Length; i++) { if (!Zero.Equals(Data[i])) { yield return new Tuple(i, Data[i]); } } } // FUNCTIONAL COMBINATORS internal override void MapToUnchecked(VectorStorage target, Func f, bool forceMapZeros = false, bool skipClearing = false) { var denseTarget = target as DenseVectorStorage; if (denseTarget != null) { CommonParallel.For(0, Data.Length, 4096, (a, b) => { for (int i = a; i < b; i++) { denseTarget.Data[i] = f(Data[i]); } }); return; } // FALL BACK for (int i = 0; i < Length; i++) { target.At(i, f(Data[i])); } } internal override void MapIndexedToUnchecked(VectorStorage target, Func f, bool forceMapZeros = false, bool skipClearing = false) { var denseTarget = target as DenseVectorStorage; if (denseTarget != null) { CommonParallel.For(0, Data.Length, 4096, (a, b) => { for (int i = a; i < b; i++) { denseTarget.Data[i] = f(i, Data[i]); } }); return; } // FALL BACK for (int i = 0; i < Length; i++) { target.At(i, f(i, Data[i])); } } } }