/// <summary>
        /// Returns a vector each of whose elements is the maximal from the corresponding
        /// ones of argument vectors. Note that dimensions of the arguments must match.
        /// </summary>
        /// <param name="v1">First vector</param>
        /// <param name="v2">Second vector</param>
        /// <returns>vector v3 such that for each i = 0...dim(v1) v3[i] = max( v1[i], v2[i] )</returns>
        public static WBVec Max(WBVec v1, WBVec v2)
        {
            double[] av1 = v1.v;
            double[] av2 = v2.v;

            if (av1 == null)
            {
                throw new ArgumentNullException("v1");
            }
            if (av2 == null)
            {
                throw new ArgumentNullException("v2");
            }

            if (av1.Length != av2.Length)
            {
                throw new ArgumentException("Vector lengths do not match");
            }
            WBVec y = WBVec.Zeros(av1.Length);

            for (int i = 0; i < av1.Length; i++)
            {
                y[i] = Math.Max(av1[i], av2[i]);
            }

            return(y);
        }
 /// <summary>
 /// Получить/назначть часть вектора, начиная с [fromInd-элекента и до toIndex-элемента] включительно
 /// </summary>
 /// <param name="fromInd">ОТ (начиная с StartIndex) индекс</param>
 /// <param name="toIndex">ДО ()</param>
 /// <returns></returns>
 public            WBVec this[int fromInd, int toIndex] {
     get {
         int length = toIndex - fromInd + 1;
         var res    = WBVec.Zeros(length);
         Array.Copy(this.v, fromInd - StartIndex, res.v, 0, length);
         return(res);
     }
     set {
         Array.Copy(value.v, 0, this.v, fromInd - StartIndex, toIndex - fromInd + 1);
     }
 }
        /// <summary>Performs scalar multiplication of two vectors</summary>
        /// <param name="a">First vector</param>
        /// <param name="b">Second vector</param>
        /// <returns>Result of scalar multiplication</returns>
        public static WBVec operator *(WBVec a, WBVec b)
        {
            if (a.Length != b.Length)
            {
                throw new InvalidOperationException("Cannot multy vectors of different length");
            }
            double[] res = WBVec.Zeros(a.Length);

            for (int i = 0; i < a.Length; i++)
            {
                res[i] = a[i] * b[i];
            }

            return(res);
        }
        /// <summary>
        /// Returns a vector whose elements are the absolute values of the given vector elements
        /// </summary>
        /// <param name="v">Vector to operate with</param>
        /// <returns>Vector v1 such that for each i = 0...dim(v) v1[i] = |v[i]|</returns>
        public WBVec Abs()
        {
            if (v == null)
            {
                return(new WBVec());
            }

            int   n = v.Length;
            WBVec y = WBVec.Zeros(n);

            for (int i = 0; i < n; i++)
            {
                y[i] = Math.Abs(v[i]);
            }
            return(y);
        }
        /// <summary>Performs element-wise division of two vectors</summary>
        /// <param name="a">Numerator vector</param>
        /// <param name="b">Denominator vector</param>
        /// <returns>Result of scalar multiplication</returns>
        public static WBVec operator /(WBVec a, WBVec b)
        {
            if (a.Length != b.Length)
            {
                throw new InvalidOperationException("Cannot element-wise divide vectors of different length");
            }
            double[] res = WBVec.Zeros(a.Length);

            for (int i = 0; i < a.Length; i++)
            {
                if (b[i] == 0.0d)
                {
                    throw new DivideByZeroException("Cannot divide by zero");
                }
                res[i] = a[i] / b[i];
            }

            return(res);
        }