/// <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> /// Combines the values in a list using a semigroup combinator /// </summary> /// <typeparam name="X">The value type</typeparam> /// <param name="g"></param> /// <param name="list"></param> /// <returns></returns> public static X combine <X>(ISemigroup <X> g, Lst <X> list) => Lst.combine(g.combine, list);
/// <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); }
/// <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); }