Browse Source

LA: Vector SetValues SubVector SetSubVector #96

v2
Christoph Ruegg 14 years ago
parent
commit
c77483a4d0
  1. 61
      src/Numerics/LinearAlgebra/Complex/DenseVector.cs
  2. 61
      src/Numerics/LinearAlgebra/Complex/SparseVector.cs
  3. 61
      src/Numerics/LinearAlgebra/Complex32/DenseVector.cs
  4. 61
      src/Numerics/LinearAlgebra/Complex32/SparseVector.cs
  5. 61
      src/Numerics/LinearAlgebra/Double/DenseVector.cs
  6. 61
      src/Numerics/LinearAlgebra/Double/SparseVector.cs
  7. 2
      src/Numerics/LinearAlgebra/Generic/Matrix.cs
  8. 56
      src/Numerics/LinearAlgebra/Generic/Vector.cs
  9. 61
      src/Numerics/LinearAlgebra/Single/DenseVector.cs
  10. 61
      src/Numerics/LinearAlgebra/Single/SparseVector.cs
  11. 2
      src/UnitTests/LinearAlgebraTests/Complex/VectorTests.cs
  12. 2
      src/UnitTests/LinearAlgebraTests/Complex32/VectorTests.cs
  13. 2
      src/UnitTests/LinearAlgebraTests/Double/VectorTests.cs
  14. 2
      src/UnitTests/LinearAlgebraTests/Single/VectorTests.cs

61
src/Numerics/LinearAlgebra/Complex/DenseVector.cs

@ -599,67 +599,6 @@ namespace MathNet.Numerics.LinearAlgebra.Complex
return index; return index;
} }
/// <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<Complex> SubVector(int index, int length)
{
if (index < 0 || index >= _length)
{
throw new ArgumentOutOfRangeException("index");
}
if (length <= 0)
{
throw new ArgumentOutOfRangeException("length");
}
if (index + length > _length)
{
throw new ArgumentOutOfRangeException("length");
}
var result = new DenseVector(length);
CommonParallel.For(
index,
index + length,
i => result._values[i - index] = _values[i]);
return result;
}
/// <summary>
/// Set the values of this vector to the given values.
/// </summary>
/// <param name="values">The array containing the values to use.</param>
/// <exception cref="ArgumentNullException">If <paramref name="values"/> is <see langword="null" />.</exception>
/// <exception cref="ArgumentException">If <paramref name="values"/> is not the same size as this vector.</exception>
public override void SetValues(Complex[] values)
{
if (values == null)
{
throw new ArgumentNullException("values");
}
if (values.Length != _length)
{
throw new ArgumentException(Resources.ArgumentVectorsSameLength, "values");
}
CommonParallel.For(
0,
values.Length,
i => _values[i] = values[i]);
}
/// <summary> /// <summary>
/// Computes the sum of the vector's elements. /// Computes the sum of the vector's elements.
/// </summary> /// </summary>

61
src/Numerics/LinearAlgebra/Complex/SparseVector.cs

@ -815,67 +815,6 @@ namespace MathNet.Numerics.LinearAlgebra.Complex
return _storage.Indices[index]; return _storage.Indices[index];
} }
/// <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<Complex> 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;
}
/// <summary>
/// Set the values of this vector to the given values.
/// </summary>
/// <param name="values">The array containing the values to use.</param>
/// <exception cref="ArgumentNullException">If <paramref name="values"/> is <see langword="null" />.</exception>
/// <exception cref="ArgumentException">If <paramref name="values"/> is not the same size as this vector.</exception>
public override void SetValues(Complex[] values)
{
if (values == null)
{
throw new ArgumentNullException("values");
}
if (values.Length != Count)
{
throw new ArgumentException(Resources.ArgumentVectorsSameLength, "values");
}
for (var i = 0; i < values.Length; i++)
{
At(i, values[i]);
}
}
/// <summary> /// <summary>
/// Computes the sum of the vector's elements. /// Computes the sum of the vector's elements.
/// </summary> /// </summary>

61
src/Numerics/LinearAlgebra/Complex32/DenseVector.cs

@ -599,67 +599,6 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32
return index; return index;
} }
/// <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<Complex32> SubVector(int index, int length)
{
if (index < 0 || index >= _length)
{
throw new ArgumentOutOfRangeException("index");
}
if (length <= 0)
{
throw new ArgumentOutOfRangeException("length");
}
if (index + length > _length)
{
throw new ArgumentOutOfRangeException("length");
}
var result = new DenseVector(length);
CommonParallel.For(
index,
index + length,
i => result._values[i - index] = _values[i]);
return result;
}
/// <summary>
/// Set the values of this vector to the given values.
/// </summary>
/// <param name="values">The array containing the values to use.</param>
/// <exception cref="ArgumentNullException">If <paramref name="values"/> is <see langword="null" />.</exception>
/// <exception cref="ArgumentException">If <paramref name="values"/> is not the same size as this vector.</exception>
public override void SetValues(Complex32[] values)
{
if (values == null)
{
throw new ArgumentNullException("values");
}
if (values.Length != _length)
{
throw new ArgumentException(Resources.ArgumentVectorsSameLength, "values");
}
CommonParallel.For(
0,
values.Length,
i => _values[i] = values[i]);
}
/// <summary> /// <summary>
/// Computes the sum of the vector's elements. /// Computes the sum of the vector's elements.
/// </summary> /// </summary>

61
src/Numerics/LinearAlgebra/Complex32/SparseVector.cs

@ -815,67 +815,6 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32
return _storage.Indices[index]; return _storage.Indices[index];
} }
/// <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<Complex32> 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;
}
/// <summary>
/// Set the values of this vector to the given values.
/// </summary>
/// <param name="values">The array containing the values to use.</param>
/// <exception cref="ArgumentNullException">If <paramref name="values"/> is <see langword="null" />.</exception>
/// <exception cref="ArgumentException">If <paramref name="values"/> is not the same size as this vector.</exception>
public override void SetValues(Complex32[] values)
{
if (values == null)
{
throw new ArgumentNullException("values");
}
if (values.Length != Count)
{
throw new ArgumentException(Resources.ArgumentVectorsSameLength, "values");
}
for (var i = 0; i < values.Length; i++)
{
At(i, values[i]);
}
}
/// <summary> /// <summary>
/// Computes the sum of the vector's elements. /// Computes the sum of the vector's elements.
/// </summary> /// </summary>

61
src/Numerics/LinearAlgebra/Double/DenseVector.cs

@ -640,67 +640,6 @@ namespace MathNet.Numerics.LinearAlgebra.Double
return index; return index;
} }
/// <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 >= _length)
{
throw new ArgumentOutOfRangeException("index");
}
if (length <= 0)
{
throw new ArgumentOutOfRangeException("length");
}
if (index + length > _length)
{
throw new ArgumentOutOfRangeException("length");
}
var result = new DenseVector(length);
CommonParallel.For(
index,
index + length,
i => result._values[i - index] = _values[i]);
return result;
}
/// <summary>
/// Set the values of this vector to the given values.
/// </summary>
/// <param name="values">The array containing the values to use.</param>
/// <exception cref="ArgumentNullException">If <paramref name="values"/> is <see langword="null" />.</exception>
/// <exception cref="ArgumentException">If <paramref name="values"/> is not the same size as this vector.</exception>
public override void SetValues(double[] values)
{
if (values == null)
{
throw new ArgumentNullException("values");
}
if (values.Length != _length)
{
throw new ArgumentException(Resources.ArgumentVectorsSameLength, "values");
}
CommonParallel.For(
0,
values.Length,
i => _values[i] = values[i]);
}
/// <summary> /// <summary>
/// Returns the index of the absolute maximum element. /// Returns the index of the absolute maximum element.
/// </summary> /// </summary>

61
src/Numerics/LinearAlgebra/Double/SparseVector.cs

@ -819,67 +819,6 @@ namespace MathNet.Numerics.LinearAlgebra.Double
return _storage.Indices[index]; return _storage.Indices[index];
} }
/// <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;
}
/// <summary>
/// Set the values of this vector to the given values.
/// </summary>
/// <param name="values">The array containing the values to use.</param>
/// <exception cref="ArgumentNullException">If <paramref name="values"/> is <see langword="null" />.</exception>
/// <exception cref="ArgumentException">If <paramref name="values"/> is not the same size as this vector.</exception>
public override void SetValues(double[] values)
{
if (values == null)
{
throw new ArgumentNullException("values");
}
if (values.Length != Count)
{
throw new ArgumentException(Resources.ArgumentVectorsSameLength, "values");
}
for (var i = 0; i < values.Length; i++)
{
At(i, values[i]);
}
}
/// <summary> /// <summary>
/// Returns the index of the absolute maximum element. /// Returns the index of the absolute maximum element.
/// </summary> /// </summary>

2
src/Numerics/LinearAlgebra/Generic/Matrix.cs

@ -632,7 +632,7 @@ namespace MathNet.Numerics.LinearAlgebra.Generic
public virtual Matrix<T> SubMatrix(int rowIndex, int rowCount, int columnIndex, int columnCount) public virtual Matrix<T> SubMatrix(int rowIndex, int rowCount, int columnIndex, int columnCount)
{ {
var target = CreateMatrix(rowCount, columnCount); var target = CreateMatrix(rowCount, columnCount);
Storage.CopySubMatrixTo(target.Storage, rowIndex, 0, rowCount, columnIndex, 0, columnCount); Storage.CopySubMatrixTo(target.Storage, rowIndex, 0, rowCount, columnIndex, 0, columnCount, skipClearing: true);
return target; return target;
} }

56
src/Numerics/LinearAlgebra/Generic/Vector.cs

@ -1285,37 +1285,35 @@ namespace MathNet.Numerics.LinearAlgebra.Generic
/// Creates a vector containing specified elements. /// Creates a vector containing specified elements.
/// </summary> /// </summary>
/// <param name="index">The first element to begin copying from.</param> /// <param name="index">The first element to begin copying from.</param>
/// <param name="length">The number of elements to copy.</param> /// <param name="count">The number of elements to copy.</param>
/// <returns>A vector containing a copy of the specified elements.</returns> /// <returns>A vector containing a copy of the specified elements.</returns>
/// <exception cref="ArgumentOutOfRangeException"><list><item>If <paramref name="index"/> is not positive or /// <exception cref="ArgumentOutOfRangeException"><list><item>If <paramref name="index"/> is not positive or
/// greater than or equal to the size of the vector.</item> /// 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> /// <item>If <paramref name="index"/> + <paramref name="length"/> is greater than or equal to the size of the vector.</item>
/// </list></exception> /// </list></exception>
/// <exception cref="ArgumentException">If <paramref name="length"/> is not positive.</exception> /// <exception cref="ArgumentException">If <paramref name="length"/> is not positive.</exception>
public virtual Vector<T> SubVector(int index, int length) public Vector<T> SubVector(int index, int count)
{ {
if (index < 0 || index >= Count) var target = CreateVector(count);
{ Storage.CopySubVectorTo(target.Storage, index, 0, count, skipClearing: true);
throw new ArgumentOutOfRangeException("index"); return target;
} }
if (length <= 0) /// <summary>
/// Copies the values of a given vector into a region in this vector.
/// </summary>
/// <param name="index">The field to start copying to</param>
/// <param name="count">The number of fields to cpy. Must be positive.</param>
/// <param name="subVector">The sub-vector to copy from.</param>
/// <exception cref="ArgumentNullException">If <paramref name="subVector"/> is <see langword="null" /></exception>
public void SetSubVector(int index, int count, Vector<T> subVector)
{
if (subVector == null)
{ {
throw new ArgumentOutOfRangeException("length"); throw new ArgumentNullException("subVector");
} }
if (index + length > Count) subVector.Storage.CopySubVectorTo(Storage, 0, index, count);
{
throw new ArgumentOutOfRangeException("index");
}
var result = CreateVector(length);
CommonParallel.For(
index,
index + length,
i => result[i - index] = this[i]);
return result;
} }
/// <summary> /// <summary>
@ -1324,22 +1322,10 @@ namespace MathNet.Numerics.LinearAlgebra.Generic
/// <param name="values">The array containing the values to use.</param> /// <param name="values">The array containing the values to use.</param>
/// <exception cref="ArgumentNullException">If <paramref name="values"/> is <see langword="null" />.</exception> /// <exception cref="ArgumentNullException">If <paramref name="values"/> is <see langword="null" />.</exception>
/// <exception cref="ArgumentException">If <paramref name="values"/> is not the same size as this vector.</exception> /// <exception cref="ArgumentException">If <paramref name="values"/> is not the same size as this vector.</exception>
public virtual void SetValues(T[] values) public void SetValues(T[] values)
{ {
if (values == null) var source = new DenseVectorStorage<T>(Count, values);
{ source.CopyTo(Storage);
throw new ArgumentNullException("values");
}
if (values.Length != Count)
{
throw new ArgumentException(Resources.ArgumentVectorsSameLength, "values");
}
CommonParallel.For(
0,
values.Length,
i => this[i] = values[i]);
} }
#endregion #endregion

61
src/Numerics/LinearAlgebra/Single/DenseVector.cs

@ -640,67 +640,6 @@ namespace MathNet.Numerics.LinearAlgebra.Single
return index; return index;
} }
/// <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<float> SubVector(int index, int length)
{
if (index < 0 || index >= _length)
{
throw new ArgumentOutOfRangeException("index");
}
if (length <= 0)
{
throw new ArgumentOutOfRangeException("length");
}
if (index + length > _length)
{
throw new ArgumentOutOfRangeException("length");
}
var result = new DenseVector(length);
CommonParallel.For(
index,
index + length,
i => result._values[i - index] = _values[i]);
return result;
}
/// <summary>
/// Set the values of this vector to the given values.
/// </summary>
/// <param name="values">The array containing the values to use.</param>
/// <exception cref="ArgumentNullException">If <paramref name="values"/> is <see langword="null" />.</exception>
/// <exception cref="ArgumentException">If <paramref name="values"/> is not the same size as this vector.</exception>
public override void SetValues(float[] values)
{
if (values == null)
{
throw new ArgumentNullException("values");
}
if (values.Length != _length)
{
throw new ArgumentException(Resources.ArgumentVectorsSameLength, "values");
}
CommonParallel.For(
0,
values.Length,
i => _values[i] = values[i]);
}
/// <summary> /// <summary>
/// Returns the index of the absolute maximum element. /// Returns the index of the absolute maximum element.
/// </summary> /// </summary>

61
src/Numerics/LinearAlgebra/Single/SparseVector.cs

@ -814,67 +814,6 @@ namespace MathNet.Numerics.LinearAlgebra.Single
return _storage.Indices[index]; return _storage.Indices[index];
} }
/// <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<float> 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[i - index] = this[i];
}
return result;
}
/// <summary>
/// Set the values of this vector to the given values.
/// </summary>
/// <param name="values">The array containing the values to use.</param>
/// <exception cref="ArgumentNullException">If <paramref name="values"/> is <see langword="null" />.</exception>
/// <exception cref="ArgumentException">If <paramref name="values"/> is not the same size as this vector.</exception>
public override void SetValues(float[] values)
{
if (values == null)
{
throw new ArgumentNullException("values");
}
if (values.Length != Count)
{
throw new ArgumentException(Resources.ArgumentVectorsSameLength, "values");
}
for (var i = 0; i < values.Length; i++)
{
At(i, values[i]);
}
}
/// <summary> /// <summary>
/// Returns the index of the absolute maximum element. /// Returns the index of the absolute maximum element.
/// </summary> /// </summary>

2
src/UnitTests/LinearAlgebraTests/Complex/VectorTests.cs

@ -467,7 +467,7 @@ namespace MathNet.Numerics.UnitTests.LinearAlgebraTests.Complex
public void SetValuesWithNonEqualDataLengthThrowsArgumentException() public void SetValuesWithNonEqualDataLengthThrowsArgumentException()
{ {
var vector = CreateVector(Data.Length + 2); var vector = CreateVector(Data.Length + 2);
Assert.Throws<ArgumentException>(() => vector.SetValues(Data)); Assert.Throws<ArgumentOutOfRangeException>(() => vector.SetValues(Data));
} }
/// <summary> /// <summary>

2
src/UnitTests/LinearAlgebraTests/Complex32/VectorTests.cs

@ -467,7 +467,7 @@ namespace MathNet.Numerics.UnitTests.LinearAlgebraTests.Complex32
public void SetValuesWithNonEqualDataLengthThrowsArgumentException() public void SetValuesWithNonEqualDataLengthThrowsArgumentException()
{ {
var vector = CreateVector(Data.Length + 2); var vector = CreateVector(Data.Length + 2);
Assert.Throws<ArgumentException>(() => vector.SetValues(Data)); Assert.Throws<ArgumentOutOfRangeException>(() => vector.SetValues(Data));
} }
/// <summary> /// <summary>

2
src/UnitTests/LinearAlgebraTests/Double/VectorTests.cs

@ -481,7 +481,7 @@ namespace MathNet.Numerics.UnitTests.LinearAlgebraTests.Double
public void SetValuesWithNonEqualDataLengthThrowsArgumentException() public void SetValuesWithNonEqualDataLengthThrowsArgumentException()
{ {
var vector = CreateVector(Data.Length + 2); var vector = CreateVector(Data.Length + 2);
Assert.Throws<ArgumentException>(() => vector.SetValues(Data)); Assert.Throws<ArgumentOutOfRangeException>(() => vector.SetValues(Data));
} }
/// <summary> /// <summary>

2
src/UnitTests/LinearAlgebraTests/Single/VectorTests.cs

@ -481,7 +481,7 @@ namespace MathNet.Numerics.UnitTests.LinearAlgebraTests.Single
public void SetValuesWithNonEqualDataLengthThrowsArgumentException() public void SetValuesWithNonEqualDataLengthThrowsArgumentException()
{ {
var vector = CreateVector(Data.Length + 2); var vector = CreateVector(Data.Length + 2);
Assert.Throws<ArgumentException>(() => vector.SetValues(Data)); Assert.Throws<ArgumentOutOfRangeException>(() => vector.SetValues(Data));
} }
/// <summary> /// <summary>

Loading…
Cancel
Save