/// <summary>
        /// Determina a soma de duas matrizes multidimensionais.
        /// </summary>
        /// <param name="right">A matriz multidimensional a ser somada.</param>
        /// <param name="semiGroup">O semi-grupo responsável pelas operações sobre os coeficientes.</param>
        /// <returns>O resultado da soma.</returns>
        /// <exception cref="ArgumentNullException">Se um dos argumentos for nulo.</exception>
        public MultiDimensionalMathRange <T> Sum(MultiDimensionalMathRange <T> right, ISemigroup <T> semiGroup)
        {
            if (right == null)
            {
                throw new ArgumentNullException("right");
            }

            if (semiGroup == null)
            {
                throw new ArgumentNullException("Semi group structure is needed.");
            }

            if (!this.CheckDimension(right.configuration))
            {
                throw new MathematicsException("Can only sum ranges with the same dimensions.");
            }

            var result = new MultiDimensionalMathRange <T>();

            Array.Copy(this.configuration, result.configuration, this.configuration.Length);
            var p = 1;

            for (int i = 0; i < this.configuration.Length; ++i)
            {
                p *= this.configuration[i];
            }

            result.elements = new T[p];
            for (int i = 0; i < this.elements.Length; ++i)
            {
                result.elements[i] = semiGroup.Add(this.elements[i], right.elements[i]);
            }

            return(result);
        }
Пример #2
0
        /// <summary>
        /// Obtém a soma da matriz corrente com outra matriz.
        /// </summary>
        /// <param name="right">A outra matriz.</param>
        /// <param name="semigroup">O semigrupo.</param>
        /// <returns>O resultado da soma.</returns>
        public ArrayMathMatrix <ObjectType> Add(ArrayMathMatrix <ObjectType> right, ISemigroup <ObjectType> semigroup)
        {
            if (right == null)
            {
                throw new ArgumentNullException("right");
            }
            else if (semigroup == null)
            {
                throw new ArgumentNullException("semigroup");
            }
            else
            {
                if (this.numberOfLines == right.numberOfLines &&
                    this.numberOfColumns == right.numberOfColumns)
                {
                    var result = new ArrayMathMatrix <ObjectType>(
                        this.numberOfLines,
                        this.numberOfColumns);
                    for (int i = 0; i < this.numberOfLines; ++i)
                    {
                        for (int j = 0; j < this.numberOfColumns; ++j)
                        {
                            result.elements[i][j] = semigroup.Add(
                                this.elements[i][j],
                                right.elements[i][j]);
                        }
                    }

                    return(result);
                }
                else
                {
                    throw new ArgumentException("Matrices don't have the same dimensions.");
                }
            }
        }
        /// <summary>
        /// Determina a contracção da matriz corrente segundo os índices espcificados.
        /// </summary>
        /// <param name="contractionIndices">A matriz multidimensional a ser somada.</param>
        /// <param name="semiGroup">O objeto responsável pelas operações sobre os coeficientes.</param>
        /// <returns>O resultado do produto.</returns>
        /// <exception cref="ArgumentNullException">Se um dos argumentos for nulo.</exception>
        public MultiDimensionalMathRange <T> Contract(int[] contractionIndices, ISemigroup <T> semiGroup)
        {
            if (contractionIndices == null)
            {
                throw new ArgumentNullException("contractionIndices");
            }

            if (semiGroup == null)
            {
                throw new MathematicsException("Parameter semiGroup can't be null.");
            }

            var result = new MultiDimensionalMathRange <T>();

            this.CheckConversion(contractionIndices);
            if (contractionIndices.Length == this.configuration.Length)
            {
                result.elements = new T[1];
                var advance = 0;
                for (int i = this.configuration.Length - 1; i > 0; --i)
                {
                    advance *= this.configuration[i];
                    advance += 1;
                }

                var pos = advance;
                for (int i = 1; i < this.configuration.Length; ++i)
                {
                    result.elements[0] = semiGroup.Add(result.elements[0], this.elements[pos]);
                    pos += advance;
                }

                result.configuration = new[] { 0 };
            }
            else
            {
                var contractionMask       = new int[this.configuration.Length];
                var newConfigurationCount = 0;
                for (int i = 0; i < this.configuration.Length; ++i)
                {
                    if (!contractionIndices.Contains(i))
                    {
                        contractionMask[i] = 1;
                    }
                    else
                    {
                        ++newConfigurationCount;
                    }
                }

                var newSize = 1;
                result.configuration = new int[newConfigurationCount];
                var pointer = 0;
                for (int i = 0; i < this.configuration.Length; ++i)
                {
                    if (contractionMask[i] == 1)
                    {
                        newSize *= this.configuration[i];
                        result.configuration[pointer++] = this.configuration[i];
                    }
                }

                var oldAdvances = new int[this.configuration.Length - newConfigurationCount];
                var oldConfig   = new int[oldAdvances.Length];
                pointer = oldAdvances.Length;
                var advance = 1;
                for (int i = 0; i < this.configuration.Length; ++i)
                {
                    if (contractionMask[i] == 0)
                    {
                        oldConfig[pointer]     = this.configuration[i];
                        oldAdvances[pointer++] = advance;
                    }

                    advance *= this.configuration[i];
                }

                advance = 0;
                for (int i = this.configuration.Length - 1; i > 0; --i)
                {
                    advance *= this.configuration[i];
                    advance += contractionMask[i];
                }

                result.elements = new T[newSize];
                var oldCoords = new int[oldConfig.Length];
                pointer = 0;
                for (int i = 0; i < newSize; ++i)
                {
                    result.elements[i] = this.elements[pointer];
                    while (pointer < this.elements.Length)
                    {
                        result.elements[i] = semiGroup.Add(result.elements[i], result.elements[pointer]);
                        pointer           += advance;
                    }

                    pointer = this.Increment(oldCoords, oldConfig, oldAdvances);
                }
            }

            return(result);
        }