public void TestVelocityOnPlane() { Frisbee.SimulationState st = new Frisbee.SimulationState { VX = 1, VY = 1, Theta = Math.PI / 4 }; Matrix<double> transformation = new SparseMatrix(new [,] { {st.CosTheta, st.SinTheta*st.SinPhi, -st.SinTheta*st.CosPhi}, {0, st.CosPhi, st.SinPhi}, {st.SinTheta, -st.CosTheta*st.SinPhi, st.CosTheta*st.CosPhi} }); SparseVector c3 = new SparseVector(transformation.Row(2)); SparseVector velocity = new SparseVector(new[] { st.VX, st.VY, st.VZ }); double velocityMagnitude = velocity.Norm(2); double velocityC3 = velocity.DotProduct(c3); Vector<double> vp = velocity.Subtract(c3.Multiply(velocityC3)); double vpMagnitude = vp.Norm(2); }
public static SparseVector Extract(this SparseVector vector, int[] rows) { var extractedVector = new SparseVector(rows.Length); for (int i = 0; i < rows.Length; i++) { extractedVector[i] = vector[rows[i]]; } return extractedVector; }
public static SparseVector MeanRowVector(this Matrix<double> matrix) { SparseVector meanVector = new SparseVector(matrix.RowCount); for (int i = 0; i < matrix.RowCount; i++) { SparseVector row = new SparseVector(SparseVectorStorage<double>.OfVector(matrix.Row(i).Storage)); double elements = row.NonZerosCount; if (elements > 0) { meanVector[i] = row.Sum() * (1 / elements); } else { meanVector[i] = 0; } } return meanVector; }
public static SparseVector MeanColumnVector(this Matrix<double> matrix) { SparseVector meanVector = new SparseVector(matrix.ColumnCount); for (int i = 0; i < matrix.ColumnCount; i++) { SparseVector column = new SparseVector(SparseVectorStorage<double>.OfVector(matrix.Column(i).Storage)); double elements = column.NonZerosCount; if (elements > 0) { double sum = column.Sum(); meanVector[i] = sum*(1/elements); } else { meanVector[i] = 0; } } return meanVector; }
/// <summary> /// Converts the string representation of a real sparse vector to double-precision sparse vector equivalent. /// A return value indicates whether the conversion succeeded or failed. /// </summary> /// <param name="value"> /// A string containing a real vector to convert. /// </param> /// <param name="formatProvider"> /// An <see cref="IFormatProvider"/> that supplies culture-specific formatting information about value. /// </param> /// <param name="result"> /// The parsed value. /// </param> /// <returns> /// If the conversion succeeds, the result will contain a complex number equivalent to value. /// Otherwise the result will be <c>null</c>. /// </returns> public static bool TryParse(string value, IFormatProvider formatProvider, out SparseVector result) { bool ret; try { result = Parse(value, formatProvider); ret = true; } catch (ArgumentNullException) { result = null; ret = false; } catch (FormatException) { result = null; ret = false; } return ret; }
/// <summary> /// Outer product of two vectors /// </summary> /// <param name="u">First vector</param> /// <param name="v">Second vector</param> /// <returns>Matrix M[i,j] = u[i]*v[j] </returns> /// <exception cref="ArgumentNullException">If the u vector is <see langword="null" />.</exception> /// <exception cref="ArgumentNullException">If the v vector is <see langword="null" />.</exception> public static Matrix<double> OuterProduct(SparseVector u, SparseVector v) { if (u == null) { throw new ArgumentNullException("u"); } if (v == null) { throw new ArgumentNullException("v"); } var matrix = new SparseMatrix(u.Count, v.Count); for (var i = 0; i < u._storage.ValueCount; i++) { for (var j = 0; j < v._storage.ValueCount; j++) { matrix.At(i, j, u._storage.Values[i] * v._storage.Values[j]); } } return matrix; }
/// <summary> /// Returns a negated vector. /// </summary> /// <returns>The negated vector.</returns> /// <remarks>Added as an alternative to the unary negation operator.</remarks> public override Vector Negate() { var result = new SparseVector(this.Count) { NonZeroValues = new double[this.NonZerosCount], NonZeroIndices = new int[this.NonZerosCount], NonZerosCount = this.NonZerosCount }; Buffer.BlockCopy(this.NonZeroIndices, 0, result.NonZeroIndices, 0, this.NonZerosCount * Constants.SizeOfInt); CommonParallel.For( 0, this.NonZerosCount, index => result.NonZeroValues[index] = -this.NonZeroValues[index]); return result; }
/// <summary> /// Initializes a new instance of the <see cref="SparseVector"/> class by /// copying the values from another. /// </summary> /// <param name="other"> /// The vector to create the new vector from. /// </param> public SparseVector(SparseVector other) : this(other.Count) { // Lets copy only needed data. Portion of needed data is determined by NonZerosCount value NonZeroValues = new double[other.NonZerosCount]; NonZeroIndices = new int[other.NonZerosCount]; NonZerosCount = other.NonZerosCount; Buffer.BlockCopy(other.NonZeroValues, 0, this.NonZeroValues, 0, other.NonZerosCount * Constants.SizeOfDouble); Buffer.BlockCopy(other.NonZeroIndices, 0, this.NonZeroIndices, 0, other.NonZerosCount * Constants.SizeOfInt); }
/// <summary> /// Tensor Product (Outer) of this and another vector. /// </summary> /// <param name="v">The vector to operate on.</param> /// <returns> /// Matrix M[i,j] = this[i] * v[j]. /// </returns> /// <seealso cref="OuterProduct"/> public Matrix TensorMultiply(SparseVector v) { return OuterProduct(this, v); }
private static double CosineR(SparseVector Vector_a, SparseVector Vector_b) { return Vector_a.DotProduct(Vector_b) / (Vector_a.L2Norm() * Vector_b.L2Norm()); //return Distance.Cosine(R.Row(a).ToArray(), R.Row(b).ToArray()); }
/// <summary> /// Outer product of this and another vector. /// </summary> /// <param name="v">The vector to operate on.</param> /// <returns> /// Matrix M[i,j] = this[i] * v[j]. /// </returns> public Matrix <double> OuterProduct(SparseVector v) { return(OuterProduct(this, v)); }
public void CheckSparseMechanismByZeroMultiply() { var vector = new SparseVector(10000); // Add non-zero elements vector[200] = 1.5; vector[500] = 3.5; vector[800] = 5.5; vector[0] = 7.5; // Multiply by 0 vector *= 0; var storage = (SparseVectorStorage<double>) vector.Storage; Assert.AreEqual(0, vector[200]); Assert.AreEqual(0, vector[500]); Assert.AreEqual(0, vector[800]); Assert.AreEqual(0, vector[0]); Assert.AreEqual(0, storage.ValueCount); }
public void CheckSparseMechanismBySettingValues() { var vector = new SparseVector(10000); var storage = (SparseVectorStorage<double>) vector.Storage; // Add non-zero elements vector[200] = 1.5; Assert.AreEqual(1.5, vector[200]); Assert.AreEqual(1, storage.ValueCount); vector[500] = 3.5; Assert.AreEqual(3.5, vector[500]); Assert.AreEqual(2, storage.ValueCount); vector[800] = 5.5; Assert.AreEqual(5.5, vector[800]); Assert.AreEqual(3, storage.ValueCount); vector[0] = 7.5; Assert.AreEqual(7.5, vector[0]); Assert.AreEqual(4, storage.ValueCount); // Remove non-zero elements vector[200] = 0; Assert.AreEqual(0, vector[200]); Assert.AreEqual(3, storage.ValueCount); vector[500] = 0; Assert.AreEqual(0, vector[500]); Assert.AreEqual(2, storage.ValueCount); vector[800] = 0; Assert.AreEqual(0, vector[800]); Assert.AreEqual(1, storage.ValueCount); vector[0] = 0; Assert.AreEqual(0, vector[0]); Assert.AreEqual(0, storage.ValueCount); }
public void CanScaleAVectorWhenSettingPreviousNonzeroElementsToZero() { var vector = new SparseVector(20); vector[10] = 1.0; vector[11] = 2.0; vector[11] = 0.0; var scaled = new SparseVector(20); vector.Multiply(3.0, scaled); Assert.AreEqual(3.0, scaled[10]); Assert.AreEqual(0.0, scaled[11]); }
public void CanPointwiseMultiplySparseVector() { var zeroArray = new[] {0.0, 1.0, 0.0, 1.0, 0.0}; var vector1 = SparseVector.OfEnumerable(Data); var vector2 = SparseVector.OfEnumerable(zeroArray); var result = new SparseVector(vector1.Count); vector1.PointwiseMultiply(vector2, result); for (var i = 0; i < vector1.Count; i++) { Assert.AreEqual(Data[i]*zeroArray[i], result[i]); } var resultStorage = (SparseVectorStorage<double>) result.Storage; Assert.AreEqual(2, resultStorage.ValueCount); }
public void CanDotProductOfTwoSparseVectors() { var vectorA = new SparseVector(10000); vectorA[200] = 1; vectorA[500] = 3; vectorA[800] = 5; vectorA[100] = 7; vectorA[900] = 9; var vectorB = new SparseVector(10000); vectorB[300] = 3; vectorB[500] = 5; vectorB[800] = 7; Assert.AreEqual(50.0, vectorA.DotProduct(vectorB)); }
/// <summary> /// Converts the string representation of a real sparse vector to double-precision sparse vector equivalent. /// A return value indicates whether the conversion succeeded or failed. /// </summary> /// <param name="value"> /// A string containing a real vector to convert. /// </param> /// <param name="result"> /// The parsed value. /// </param> /// <returns> /// If the conversion succeeds, the result will contain a complex number equivalent to value. /// Otherwise the result will be <c>null</c>. /// </returns> public static bool TryParse(string value, out SparseVector result) { return(TryParse(value, null, out result)); }
/// <summary> /// Creates a new instance of the Vector class. /// </summary> /// <param name="data">The array to create this vector from.</param> /// <returns>The new <c>Vector</c>.</returns> protected override Vector<double> CreateVector(IList<double> data) { var vector = new SparseVector(data.Count); for (var index = 0; index < data.Count; index++) { vector[index] = data[index]; } return vector; }
private static double PearsonR(SparseVector Vector_a, SparseVector Vector_b) { double correlation = Correlation.Pearson(Vector_a,Vector_b); if (double.IsNaN(correlation)) { // This means one of the row has 0 standard divation, // it does not correlate to anyone // so I assign the correlatino to be 0. however, strictly speaking, it should be left NaN correlation = 0; } return correlation; }
public void CanCreateSparseMatrix() { var vector = new SparseVector(3); var matrix = Matrix<double>.Build.SameAs(vector, 2, 3); Assert.IsInstanceOf<SparseMatrix>(matrix); Assert.AreEqual(2, matrix.RowCount); Assert.AreEqual(3, matrix.ColumnCount); }
/// <summary> /// Creates a vector containing specified elements. /// </summary> /// <param name="index">The first element to begin copying from.</param> /// <param name="length">The number of elements to copy.</param> /// <returns>A vector containing a copy of the specified elements.</returns> /// <exception cref="ArgumentOutOfRangeException"><list><item>If <paramref name="index"/> is not positive or /// greater than or equal to the size of the vector.</item> /// <item>If <paramref name="index"/> + <paramref name="length"/> is greater than or equal to the size of the vector.</item> /// </list></exception> /// <exception cref="ArgumentException">If <paramref name="length"/> is not positive.</exception> public override Vector SubVector(int index, int length) { if (index < 0 || index >= this.Count) { throw new ArgumentOutOfRangeException("index"); } if (length <= 0) { throw new ArgumentOutOfRangeException("length"); } if (index + length > this.Count) { throw new ArgumentOutOfRangeException("length"); } var result = new SparseVector(length); for (int i = index; i < index + length; i++) result[i - index] = this[i]; return result; }
public static Dictionary<int, List<int>> RecommendTopN(PrefRelations PR_train, int K, List<int> targetUsers, int topN) { Dictionary<int, List<int>> topNItemsByUser = new Dictionary<int, List<int>>(targetUsers.Count); int userCount = PR_train.UserCount; int itemCount = PR_train.ItemCount; SparseMatrix positionMatrix = PR_train.GetPositionMatrix(); // Make recommendations to each target user foreach (int indexOfUser in targetUsers) { Utils.PrintEpoch("Current user/total", indexOfUser, targetUsers.Count); // TODO: should have a default list of popular items in case of cold users Dictionary<int, double> topNItems = new Dictionary<int, double>(topN); // To store recommendations for indexOfUser Dictionary<int, double> topKNeighbors = KNNCore.GetTopKNeighborsByUser(PR_train.UserSimilarities, indexOfUser, K); SparseVector predictedPositionsOfUser = new SparseVector(itemCount); // Compute the predicted position of each item for indexOfUser for (int indexOfItem = 0; indexOfItem < itemCount; ++indexOfItem) { // Compute the position of this item for the user // by combining neighbors' positions on this item double weightedSum = 0; double weightSum = 0; int itemSeenCount = 0; foreach (KeyValuePair<int, double> neighbor in topKNeighbors) { int indexOfNeighbor = neighbor.Key; double similarityOfNeighbor = neighbor.Value; double itemPositionOfNeighbor = positionMatrix[indexOfNeighbor, indexOfItem]; // TODO: Zero means it is not seen by the neighbor but // it may also be the position value of 0 if (itemPositionOfNeighbor != 0) { weightSum += similarityOfNeighbor; weightedSum += itemPositionOfNeighbor * similarityOfNeighbor; itemSeenCount++; } } // If any neighbor has seen this item if (itemSeenCount != 0) { // TODO: Add user mean may improve the performance predictedPositionsOfUser[indexOfItem] = weightedSum / weightSum; } } List<int> indexesOfItemSortedByPosition = Enumerable.Range(0, itemCount).ToList(); Sorting.Sort(predictedPositionsOfUser, indexesOfItemSortedByPosition); indexesOfItemSortedByPosition.Reverse(); // Make it descending order by position // Add the top N items for user uid topNItemsByUser[indexOfUser] = indexesOfItemSortedByPosition.GetRange(0, topN); } return topNItemsByUser; #region Old version /* //===============Initialize variables================== // Recommendations are stored here indexed by user id Dictionary<int, List<int>> userRecommendations = new Dictionary<int, List<int>>(targetUsers.Count); int userCount = PR_train.UserCount; int itemCount = PR_train.ItemCount; // Build the item position matrix // each element indicates the position(kind of goodness) of an item to the user SparseMatrix itemPositions = new SparseMatrix(userCount, itemCount); Object lockMe = new Object(); Parallel.ForEach(PR_train.GetAllPreferenceRelations, pair => { int uid = pair.Key; Utilities.PrintEpoch("Current user/total", uid, userCount); SparseMatrix userPreferences = pair.Value; foreach (Tuple<int, Vector<double>> preferences in userPreferences.EnumerateRowsIndexed()) { int iid = preferences.Item1; SparseVector iidPreferences = SparseVector.OfVector(preferences.Item2); // The number of items that are preferred to item iid int preferredCount = 0; // The number of items that are less preferred to item iid int lessPreferredCount = 0; // The number of items (other than item iid) that are equally preferred to item iid // TODO: I'm not sure if we should count unknown preferences or not? int equallyPreferredCount = 0; // Note: don't use the Count() method it won't skip Zeros foreach (double preference in iidPreferences.Enumerate(Zeros.AllowSkip)) { if (preference == Config.Preferences.Preferred) ++preferredCount; else if (preference == Config.Preferences.LessPreferred) ++lessPreferredCount; else if (preference == Config.Preferences.EquallyPreferred) ++equallyPreferredCount; else { Debug.Assert(false, "We should not see any non-match value here."); } } double position = ((double)lessPreferredCount - preferredCount) / (preferredCount + lessPreferredCount + equallyPreferredCount); Debug.Assert(position >= -1 && position <= 1); // According to the paper if (position == 0) { Debug.Assert(preferredCount == lessPreferredCount); } // According to the paper lock (lockMe) { itemPositions[uid, iid] = position; } } }); // Need to cache the items appeared in each user's profile // as we won't consider unseen items as recommendations Dictionary<int, List<int>> seenItemsByUser = PR_train.GetSeenItemsByUser(); Matrix positionMatrix = PR_train.GetPositionMatrix(); Console.WriteLine("Recommending user/total"); // Make recommendations for each target user foreach (int uid in targetUsers) { Utilities.PrintEpoch("Current user/total", uid, targetUsers.Count); // TODO: should have a default list of popular items in case of cold users Dictionary<int, double> topN = new Dictionary<int, double>(topNCount); // To store recommendations for user uid Dictionary<int, double> topK = KNNCore.GetTopK(PR_train.UserSimilarities, uid, K); // Get a list of all candidate items List<int> candidateItems = new List<int>(); foreach (int uid_neighbor in topK.Keys) { // TODO: union will remove duplicates, seems to be expensive here candidateItems = candidateItems.Union(seenItemsByUser[uid_neighbor]).ToList(); } // Loop through all candidate items double minPosition = double.MinValue; int min_iid = int.MinValue; foreach (int iid in candidateItems) { // Compute the average position on item iid given // by the top K neighbors. Each position is weighted // by the similarity to the target user double weightedSum = 0; double weightSum = 0; foreach (KeyValuePair<int, double> neighbor in topK) { int uidNeighbor = neighbor.Key; double similarity = neighbor.Value; double iidPosition = itemPositions[uidNeighbor, iid]; // TODO: check the standard KNN, we should skip the unseen items somehow! //if (neighborRating != 0) // The weightSum serves as the normalization term // it needs abs() because some metric such as Pearson // may produce negative weights weightSum += Math.Abs(similarity); weightedSum += iidPosition * similarity; } double position_predicted = weightedSum / weightSum; // TODO: add some kind of user mean to improve? // TODO: should have a default list of popular items in case of cold users if (topN.Count < topNCount) // Fill the top N list untill it is full { topN[iid] = position_predicted; if (topN.Count == topNCount) { // Find the item with least position when we have N items in the list min_iid = topN.Aggregate((l, r) => l.Value < r.Value ? l : r).Key; minPosition = topN[min_iid]; } } else if (position_predicted > minPosition) { // Replace the least similar neighbor topN.Remove(min_iid); topN[iid] = position_predicted; // Find the item with least position min_iid = topN.Aggregate((l, r) => l.Value < r.Value ? l : r).Key; minPosition = topN[min_iid]; } } // Add the top N items for user uid userRecommendations[uid] = topN.Keys.ToList(); } return userRecommendations; */ #endregion }
private void AddScaledSparceVector(double alpha, SparseVector other) { if (other == null) { throw new ArgumentNullException("other"); } if (this.Count != other.Count) { throw new ArgumentException(Resources.ArgumentVectorsSameLength, "other"); } if (alpha == 0.0) { return; } // I don't use ILinearAlgebraProvider because we will get no benefit due to "lock" in this[index] // Possible fucniton in ILinearAlgebraProvider may be AddSparseVectorToScaledSparseVector(T[] y, int[] yIndices, T alpha, T[] x, int[] xIndices); // But it require to develop value setting algorithm and due to "lock" it will be even more greedy then implemented below if (ReferenceEquals(this, other)) { // Adding the same instance of sparse vector. That means if we modify "this" then "other" will be modified too. // To avoid such problem lets change values in internal storage of "this" if (alpha == 1.0) { for (int i = 0; i < this.NonZerosCount; i++) { this.NonZeroValues[i] += this.NonZeroValues[i]; } } else if (alpha == -1.0) { Clear(); // Vector is subtracted from itself return; } else { for (int i = 0; i < this.NonZerosCount; i++) { this.NonZeroValues[i] += alpha * this.NonZeroValues[i]; } } } else { // "this" and "other" are different objects, so by modifying "this" the "other" object will not be changed if (alpha == 1.0) { for (int i = 0; i < other.NonZerosCount; i++) { this[other.NonZeroIndices[i]] += other.NonZeroValues[i]; } } else { for (int i = 0; i < other.NonZerosCount; i++) { this[other.NonZeroIndices[i]] += alpha * other.NonZeroValues[i]; } } } }
/// <summary> /// Pointwise multiplies this vector with another vector. /// </summary> /// <param name="other">The vector to pointwise multiply with this one.</param> /// <returns>A new vector which is the pointwise multiplication of the two vectors.</returns> /// <exception cref="ArgumentNullException">If the other vector is <see langword="null" />.</exception> /// <exception cref="ArgumentException">If this vector and <paramref name="other"/> are not the same size.</exception> public override Vector PointwiseMultiply(Vector other) { if (other == null) { throw new ArgumentNullException("other"); } if (Count != other.Count) { throw new ArgumentException(Resources.ArgumentVectorsSameLength, "other"); } var copy = new SparseVector(Count); for (int i = 0; i < this._nonZeroIndices.Length; i++) { var d = this._nonZeroValues[i] * other[this._nonZeroIndices[i]]; if (d != 0.0) { copy[this._nonZeroIndices[i]] = d; } } return copy; }
/// <summary> /// Outer product of two vectors /// </summary> /// <param name="u">First vector</param> /// <param name="v">Second vector</param> /// <returns>Matrix M[i,j] = u[i]*v[j] </returns> /// <exception cref="ArgumentNullException">If the u vector is <see langword="null" />.</exception> /// <exception cref="ArgumentNullException">If the v vector is <see langword="null" />.</exception> /*SparseMatrix*/ public static Matrix OuterProduct(SparseVector u, SparseVector v) { if (u == null) { throw new ArgumentNullException("u"); } if (v == null) { throw new ArgumentNullException("v"); } throw new NotImplementedException(); //var matrix = new DenseMatrix(u.Count, v.Count); //CommonParallel.For( // 0, // u.Count, // i => // { // for (int j = 0; j < v.Count; j++) // { // matrix.At(i, j, u.Data[i] * v.Data[j]); // } // }); //return matrix; }
/// <summary> /// Outer product of two vectors /// </summary> /// <param name="u">First vector</param> /// <param name="v">Second vector</param> /// <returns>Matrix M[i,j] = u[i]*v[j] </returns> /// <exception cref="ArgumentNullException">If the u vector is <see langword="null" />.</exception> /// <exception cref="ArgumentNullException">If the v vector is <see langword="null" />.</exception> /*SparseMatrix*/ public static Matrix OuterProduct(SparseVector u, SparseVector v) { if (u == null) { throw new ArgumentNullException("u"); } if (v == null) { throw new ArgumentNullException("v"); } var matrix = new SparseMatrix(u.Count, v.Count); for (var i = 0; i < u.NonZerosCount; i++) { for (var j = 0; j < v.NonZerosCount; j++) { if (u._nonZeroIndices[i] == v._nonZeroIndices[j]) { matrix.At(i, j, u._nonZeroValues[i] * v._nonZeroValues[j]); } } } return matrix; }
public RatingVector(Vector<double> ratingVector) { this.ratingVector = ratingVector.Storage.IsDense ? SparseVector.OfVector(ratingVector) : (SparseVector)ratingVector; }
/// <summary> /// Multiplies a scalar to each element of the vector. /// </summary> /// <param name="scalar">The scalar to multiply.</param> /// <returns>A new vector that is the multiplication of the vector and the scalar.</returns> public override Vector<double> Multiply(double scalar) { if (scalar == 1.0) { return Clone(); } if (scalar == 0) { return new SparseVector(Count); } var copy = new SparseVector(this); Control.LinearAlgebraProvider.ScaleArray(scalar, copy._nonZeroValues, copy._nonZeroValues); return copy; }
/// <summary> /// Converts the string representation of a real sparse vector to double-precision sparse vector equivalent. /// A return value indicates whether the conversion succeeded or failed. /// </summary> /// <param name="value"> /// A string containing a real vector to convert. /// </param> /// <param name="result"> /// The parsed value. /// </param> /// <returns> /// If the conversion succeeds, the result will contain a complex number equivalent to value. /// Otherwise the result will be <c>null</c>. /// </returns> public static bool TryParse(string value, out SparseVector result) { return TryParse(value, null, out result); }
/// <summary> /// Returns a negated vector. /// </summary> /// <returns>The negated vector.</returns> /// <remarks>Added as an alternative to the unary negation operator.</remarks> public override Vector<double> Negate() { var result = new SparseVector(Count) { _nonZeroValues = new double[NonZerosCount], _nonZeroIndices = new int[NonZerosCount], NonZerosCount = NonZerosCount }; if (NonZerosCount != 0) { CommonParallel.For( 0, NonZerosCount, index => result._nonZeroValues[index] = -_nonZeroValues[index]); Buffer.BlockCopy(_nonZeroIndices, 0, result._nonZeroIndices, 0, NonZerosCount * Constants.SizeOfInt); } return result; }
/// <summary> /// Outer product of this and another vector. /// </summary> /// <param name="v">The vector to operate on.</param> /// <returns> /// Matrix M[i,j] = this[i] * v[j]. /// </returns> public Matrix<double> OuterProduct(SparseVector v) { return OuterProduct(this, v); }
/// <summary> /// Creates a vector containing specified elements. /// </summary> /// <param name="index">The first element to begin copying from.</param> /// <param name="length">The number of elements to copy.</param> /// <returns>A vector containing a copy of the specified elements.</returns> /// <exception cref="ArgumentOutOfRangeException"><list><item>If <paramref name="index"/> is not positive or /// greater than or equal to the size of the vector.</item> /// <item>If <paramref name="index"/> + <paramref name="length"/> is greater than or equal to the size of the vector.</item> /// </list></exception> /// <exception cref="ArgumentException">If <paramref name="length"/> is not positive.</exception> public override Vector<double> SubVector(int index, int length) { if (index < 0 || index >= Count) { throw new ArgumentOutOfRangeException("index"); } if (length <= 0) { throw new ArgumentOutOfRangeException("length"); } if (index + length > Count) { throw new ArgumentOutOfRangeException("length"); } var result = new SparseVector(length); for (var i = index; i < index + length; i++) { result.At(i - index, At(i)); } return result; }