/// <summary>
        /// Divides a tensor by a scalar
        /// </summary>
        /// <param name="Input">The tensor to divide from</param>
        /// <param name="Scalar">The scalar to divide by</param>
        public static Tensor Tensor_Divide(Tensor Input, double Scalar)
        {
            //Create a flat tensor from the input and another one for the result
            FlatTensor Flat = FlatTensor.FromTensor(Input);
            FlatTensor Result = new FlatTensor(Flat.Count);

            //For each value in the flat tensor:
            for (int i = 0; i < Flat.Count; i++)
            {
                //Divide the value of the tensor by the scalar and add it to the result
                Result[i] = Flat[i] / Scalar;
            }

            //Return the result
            return Result.ToTensor();
        }
        /// <summary>
        /// Negates all of the values of a tensor (flips the sign of each value in the tensor).
        /// </summary>
        /// <param name="Input">The tensor to negate</param>
        public static Tensor Tensor_Negate(Tensor Input)
        {
            //The best way to accomplish this, is to unfold the tensor, multiply each value by -1, and then fold the tensor
            FlatTensor Flat = FlatTensor.FromTensor(Input);
            FlatTensor Result = new FlatTensor(Flat.Count);

            //For each value in the flat tensor:
            for (int i = 0; i < Flat.Count; i++)
            {
                //Multiply the value by -1 and add it to the result
                Result[i] = Flat[i] * -1.0;
            }

            //Return the result
            return Result.ToTensor();
        }
        /// <summary>
        /// Creates a sub-tensor from a given tensor between a pair of array dimensions (inclusive).
        /// The resulting tensor will have a rank equal to (EndRank - StartRank) + 1.
        /// </summary>
        /// <param name="Input">The tensor to decompose</param>
        /// <param name="StartRank">The starting sub-rank (array dimension) (inclusive)</param>
        /// <param name="EndRank">The ending sub-rank (array dimension) (inclusive)</param>
        public static Tensor Tensor_ToSubTensor(Tensor Input, int StartRank, int EndRank)
        {
            //If the starting sub-rank is greater than the end sub-rank, complain
            if (StartRank > EndRank) throw new Exception("Invalid start/end sub-ranks.");

            //If the starting and ending subrank are the same:
            if (StartRank == EndRank)
            {
                //Obtain the underlying dimensionality of the origional at the starting (and thus ending) rank
                int UnderlyingDim = Input.ObtainDimensionality(StartRank);

                //Create a new rank one tensor with the same dimensionality as the start (and end) rank
                Tensor ReturnTensor = new Tensor(1, UnderlyingDim);

                //Create an access key
                int[] Key = new int[Input.Rank];

                //For each underlying dimension:
                for (int i = 0; i < UnderlyingDim; i++)
                {
                    //Copy over the value
                    Key[StartRank] = i;
                    ReturnTensor[Key] = Input[Key];
                }

                //Return the newly created tensor
                return ReturnTensor;
            }
            else //Otherwise if they are not the same:
            {

            }
            throw new System.NotImplementedException();
        }
        /// <summary>
        /// Copies all of the values in a tensor to a new one.
        /// </summary>
        /// <param name="Input">The tensor to copy</param>
        public static Tensor Tensor_Copy(Tensor Input)
        {
            if (Input.Rank > 0)
            {
                //Create a flat tensor from the input and another one for the result
                FlatTensor Flat = FlatTensor.FromTensor(Input);
                FlatTensor Result = new FlatTensor(Flat.Count);

                //For each value in the flat tensor:
                for (int i = 0; i < Flat.Count; i++)
                {
                    //Copy the value to the result
                    Result[i] = Flat[i];
                }

                //Return the result
                return Result.ToTensor();
            }
            else
            {
                //We are working with a scalar
                Tensor ScalarTensor = new Tensor(0, 0);
                ScalarTensor.Data = (double)Input.Data;
                return ScalarTensor;
            }
        }
        /// <summary>
        /// Computes the subtraction of two tensors of the same rank and underlying dimensionalities.
        /// </summary>
        /// <param name="Tensor1">The tensor to subtract from</param>
        /// <param name="Tensor2">The tensor to subtract</param>
        public static Tensor Tensor_Subtract(Tensor Tensor1, Tensor Tensor2)
        {
            //Only two tensors of the same rank may be subtracted
            if (Tensor1.Rank != Tensor2.Rank) throw new Exception("Tensors must be the same rank!");

            //To subtract two tensors, first we want to unfold each into a flat tensor
            FlatTensor Flat1 = FlatTensor.FromTensor(Tensor1);
            FlatTensor Flat2 = FlatTensor.FromTensor(Tensor2);

            //Make sure the resulting flat tensors are the same length
            if (Flat1.Count != Flat2.Count) throw new Exception("Tensors must have the same underlying dimensionality at each sub-rank!");

            //Now subtract them like we would two vectors
            FlatTensor Result = new FlatTensor(Flat1.Count);
            for (int i = 0; i < Flat1.Count; i++)
            {
                Result[i] = Flat1[i] - Flat2[i];
            }

            //Finally, fold the resulting flat tensor back into a regular tensor
            return Result.ToTensor();
        }