using System; using MathNet.Numerics.Properties; namespace MathNet.Numerics.LinearAlgebra.Storage { public abstract partial class VectorStorage : IEquatable> where T : struct, IEquatable, IFormattable { // [ruegg] public fields are OK here public readonly int Length; protected VectorStorage(int length) { if (length <= 0) { throw new ArgumentOutOfRangeException(Resources.ArgumentMustBePositive); } Length = length; } /// /// Gets or sets the value at the given index, with range checking. /// /// /// The index of the element. /// /// The value to get or set. /// This method is ranged checked. and /// to get and set values without range checking. public T this[int index] { get { ValidateRange(index); return At(index); } set { ValidateRange(index); At(index, value); } } /// /// Retrieves the requested element without range checking. /// /// The index of the element. /// The requested element. /// Not range-checked. public abstract T At(int index); /// /// Sets the element without range checking. /// /// The index of the element. /// The value to set the element to. /// WARNING: This method is not thread safe. Use "lock" with it and be sure to avoid deadlocks. public abstract void At(int index, T value); /// /// True if all fields of this vector can be set to any value. /// False if some fields are fixed. /// public virtual bool IsFullyMutable { get { return true; } } /// /// True if the specified field can be set to any value. /// False if the field is fixed. /// public virtual bool IsMutable(int index) { return true; } public virtual void Clear() { for (var i = 0; i < Length; i++) { At(i, default(T)); } } public virtual void Clear(int index, int count) { for (var i = index; i < index + count; i++) { At(i, default(T)); } } /// /// Indicates whether the current object is equal to another object of the same type. /// /// /// An object to compare with this object. /// /// /// true if the current object is equal to the parameter; otherwise, false. /// public virtual bool Equals(VectorStorage other) { // Reject equality when the argument is null or has a different shape. if (other == null) { return false; } if (Length != other.Length) { return false; } // Accept if the argument is the same object as this. if (ReferenceEquals(this, other)) { return true; } // If all else fails, perform element wise comparison. for (var index = 0; index < Length; index++) { if (!At(index).Equals(other.At(index))) { return false; } } return true; } /// /// Determines whether the specified is equal to the current . /// /// /// true if the specified is equal to the current ; otherwise, false. /// /// The to compare with the current . public override sealed bool Equals(object obj) { return Equals(obj as MatrixStorage); } /// /// Serves as a hash function for a particular type. /// /// /// A hash code for the current . /// public override int GetHashCode() { var hashNum = Math.Min(Length, 25); int hash = 17; unchecked { for (var i = 0; i < hashNum; i++) { hash = hash*31 + At(i).GetHashCode(); } } return hash; } /// Parameters assumed to be validated already. public virtual void CopyTo(VectorStorage target, bool skipClearing = false) { for (int i = 0; i < Length; i++) { target.At(i, At(i)); } } public virtual void CopySubVectorTo(VectorStorage target, int sourceIndex, int targetIndex, int count, bool skipClearing = false) { if (target == null) { throw new ArgumentNullException("target"); } if (ReferenceEquals(this, target)) { throw new NotSupportedException(); } ValidateSubVectorRange(target, sourceIndex, targetIndex, count); for (int i = sourceIndex, ii = targetIndex; i < sourceIndex + count; i++, ii++) { target.At(ii, At(i)); } } } }