text:
// Licensed to the Apache Software Foundation (ASF) under one or more
// contributor license agreements.  See the NOTICE file distributed with
// this work for additional information regarding copyright ownership.
// The ASF licenses this file to You under the Apache License, Version 2.0
// (the "License"); you may not use this file except in compliance with
// the License.  You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
using Math3.exception;
using Math3.exception.util;
using Math3.util;
using System;

namespace Math3.linear
{
    ///
    /// Cache-friendly implementation of FieldMatrix using a flat arrays to store
    /// square blocks of the matrix.
    /// <para>
    /// This implementation is specially designed to be cache-friendly. Square blocks are
    /// stored as small arrays and allow efficient traversal of data both in row major direction
    /// and columns major direction, one block at a time. This greatly increases performances
    /// for algorithms that use crossed directions loops like multiplication or transposition.
    /// </para>
    /// <para>
    /// The size of square blocks is a static parameter. It may be tuned according to the cache
    /// size of the target computer processor. As a rule of thumbs, it should be the largest
    /// value that allows three blocks to be simultaneously cached (this is necessary for example
    /// for matrix multiplication). The default value is to use 36x36 blocks.
    /// </para>
    /// <para>
    /// The regular blocks represent <see cref="BLOCK_SIZE"/> x <see cref="BLOCK_SIZE"/>
    /// squares. Blocks at right hand side and bottom side which may be smaller to fit matrix
    /// dimensions. The square blocks are flattened in row major order in single dimension arrays
    /// which are therefore <see cref="BLOCK_SIZE"/>2 elements long for regular blocks.
    /// The blocks are themselves organized in row major order.
    /// </para>
    /// <para>
    /// As an example, for a block size of 36x36, a 100x60 matrix would be stored in 6 blocks.
    /// Block 0 would be a Field[1296] array holding the upper left 36x36 square, block 1 would be
    /// a Field[1296] array holding the upper center 36x36 square, block 2 would be a Field[1008]
    /// array holding the upper right 36x28 rectangle, block 3 would be a Field[864] array holding
    /// the lower left 24x36 rectangle, block 4 would be a Field[864] array holding the lower
    /// center 24x36 rectangle and block 5 would be a Field[672] array holding the lower right
    /// 24x28 rectangle.
    /// </para>
    /// <para>
    /// The layout complexity overhead versus simple mapping of matrices to java
    /// arrays is negligible for small matrices (about 1%). The gain from cache efficiency leads
    /// to up to 3-fold improvements for matrices of moderate to large size.
    /// </para>
    ///
    /// <typeparam name="T">the type of the field elements</typeparam>
    public class BlockFieldMatrix<T> : AbstractFieldMatrix<T> where T : FieldElement<T>
    {
        ///
        /// Block size.
        ///
        public const int BLOCK_SIZE = 36;

        ///
        /// Blocks of matrix entries.
        ///
        private readonly T[][] blocks;

        ///
        /// Number of rows of the matrix.
        ///
        private readonly int rows;

        ///
        /// Number of columns of the matrix.
        ///
        private readonly int columns;

        ///
        /// Number of block rows of the matrix.
        ///
        private readonly int blockRows;

        ///
        /// Number of block columns of the matrix.
        ///
        private readonly int blockColumns;

        ///
        /// Create a new matrix with the supplied row and column dimensions.
        ///
        /// <param name="field">Field to which the elements belong.</param>
        /// <param name="rows">Number of rows in the new matrix.</param>
        /// <param name="columns">Number of columns in the new matrix.</param>
        /// <exception cref="NotStrictlyPositiveException"> if row or column dimension is not
        /// positive.</exception>
        public BlockFieldMatrix(Field<T> field, int rows, int columns)
            : base(field, rows, columns)
        {
            this.rows = rows;
            this.columns = columns;

            // number of blocks
            blockRows = (rows + BLOCK_SIZE - 1) / BLOCK_SIZE;
            blockColumns = (columns + BLOCK_SIZE - 1) / BLOCK_SIZE;

            // allocate storage blocks, taking care of smaller ones at right and bottom
            blocks = createBlocksLayout(field, rows, columns);
        }

        ///
        /// Create a new dense matrix copying entries from raw layout data.
        /// <para>The input array must already be in raw layout.</para>
        /// <para>Calling this constructor is equivalent to call:
        /// matrix = new BlockFieldMatrix(T)(getField(), rawData.Length, rawData[0].Length,
        ///                                   toBlocksLayout(rawData), false);
        /// </para>
        ///
        /// <param name="rawData">Data for the new matrix, in raw layout.</param>
        /// <exception cref="DimensionMismatchException"> if the <c>blockData</c> shape is
        /// inconsistent with block layout.</exception>
        /// <remarks>
        /// See <see cref="BlockFieldMatrix(int, int, FieldElement[][], boolean)"/>
        /// </remarks>
        public BlockFieldMatrix(T[][] rawData) : this(rawData.Length, rawData[0].Length, toBlocksLayout(rawData), false) { }

        ///
        /// Create a new dense matrix copying entries from block layout data.
        /// <para>The input array must already be in blocks layout.</para>
        ///
        /// <param name="rows">the number of rows in the new matrix</param>
        /// <param name="columns">the number of columns in the new matrix</param>
        /// <param name="blockData">data for new matrix</param>
        /// <param name="copyArray">if true, the input array will be copied, otherwise
        /// it will be referenced</param>
        /// <exception cref="DimensionMismatchException"> if the <c>blockData</c> shape is
        /// inconsistent with block layout.</exception>
        /// <exception cref="NotStrictlyPositiveException"> if row or column dimension is not
        /// positive.</exception>
        /// <remarks>
        /// See <see cref="createBlocksLayout(Field, int, int)"/><para/>
        /// See <see cref="toBlocksLayout(FieldElement[][])"/><para/>
        /// See <see cref="BlockFieldMatrix(FieldElement[][])"/>
        /// </remarks>
        public BlockFieldMatrix(int rows, int columns, T[][] blockData, Boolean copyArray)
            : base(extractField(blockData), rows, columns)
        {
            this.rows = rows;
            this.columns = columns;

            // number of blocks
            blockRows = (rows + BLOCK_SIZE - 1) / BLOCK_SIZE;
            blockColumns = (columns + BLOCK_SIZE - 1) / BLOCK_SIZE;

            if (copyArray)
            {
                // allocate storage blocks, taking care of smaller ones at right and bottom
                blocks = MathArrays.buildArray(getField(), blockRows * blockColumns, -1);
            }
            else
            {
                // reference existing array
                blocks = blockData;
            }

            int index = 0;
            for (int iBlock = 0; iBlock < blockRows; ++iBlock)
            {
                int iHeight = blockHeight(iBlock);
                for (int jBlock = 0; jBlock < blockColumns; ++jBlock, ++index)
                {
                    if (blockData[index].Length != iHeight * blockWidth(jBlock))
                    {
                        throw new DimensionMismatchException(blockData[index].Length,
                                                             iHeight * blockWidth(jBlock));
                    }
                    if (copyArray)
                    {
                        blocks[index] = (T[])blockData[index].Clone();
                    }
                }
            }
        }

        ///
        /// Convert a data array from raw layout to blocks layout.
        /// <para>
        /// Raw layout is the straightforward layout where element at row i and
        /// column j is in array element rawData[i][j]. Blocks layout
        /// is the layout used in <see cref="BlockFieldMatrix"/> instances, where the matrix
        /// is split in square blocks (except at right and bottom side where blocks may
        /// be rectangular to fit matrix size) and each block is stored in a flattened
        /// one-dimensional array.
        /// </para>
        /// <para>
        /// This method creates an array in blocks layout from an input array in raw layout.
        /// It can be used to provide the array argument of the
        /// <see cref="BlockFieldMatrix(int, int, FieldElement[][], boolean)"/>
        /// constructor.
        /// </para>
        ///
        /// <typeparam name="U">Type of the field elements.</typeparam>
        /// <param name="rawData">Data array in raw layout.</param>
        /// <returns>a new data array containing the same entries but in blocks layout</returns>
        /// <exception cref="DimensionMismatchException"> if <c>rawData</c> is not rectangular
        /// (not all rows have the same length).</exception>
        public static U[][] toBlocksLayout(U[][] rawData) where U : FieldElement
        {
            int rows = rawData.Length;
            int columns = rawData[0].Length;
            int blockRows = (rows + BLOCK_SIZE - 1) / BLOCK_SIZE;
            int blockColumns = (columns + BLOCK_SIZE - 1) / BLOCK_SIZE;

            // safety checks
            for (int i = 0; i < rawData.Length; ++i)
            {
                int length = rawData[i].Length;
                if (length != columns)
                {
                    throw new DimensionMismatchException(columns, length);
                }
            }

            // convert array
            Field field = extractField(rawData);
            U[][] blocks = MathArrays.buildArray(field, blockRows * blockColumns, -1);
            int blockIndex = 0;
            for (int iBlock = 0; iBlock < blockRows; ++iBlock)
            {
                int pStart = iBlock * BLOCK_SIZE;
                int pEnd = FastMath.min(pStart + BLOCK_SIZE, rows);
                int iHeight = pEnd - pStart;
                for (int jBlock = 0; jBlock < blockColumns; ++jBlock)
                {
                    int qStart = jBlock * BLOCK_SIZE;
                    int qEnd = FastMath.min(qStart + BLOCK_SIZE, columns);
                    int jWidth = qEnd - qStart;

                    // allocate new block
                    U[] block = MathArrays.buildArray(field, iHeight * jWidth);
                    blocks[blockIndex] = block;

                    // copy data
                    int index = 0;
                    for (int p = pStart; p < pEnd; ++p)
                    {
                        Array.Copy(rawData[p], qStart, block, index, jWidth);
                        index += jWidth;
                    }

                    ++blockIndex;
                }
            }

            return blocks;
        }

        ///
        /// Create a data array in blocks layout.
        /// <para>
        /// This method can be used to create the array argument of the
        /// <see cref="BlockFieldMatrix(int, int, FieldElement[][], boolean)"/>
        /// constructor.
        /// </para>
        ///
        /// <typeparam name="U">Type of the field elements.</typeparam>
        /// <param name="field">Field to which the elements belong.</param>
        /// <param name="rows">Number of rows in the new matrix.</param>
        /// <param name="columns">Number of columns in the new matrix.</param>
        /// <returns>a new data array in blocks layout.</returns>
        /// <remarks>
        /// See <see cref="toBlocksLayout(FieldElement[][])"/>
        /// </remarks>
        public static U[][] createBlocksLayout(Field field, int rows, int columns) where U : FieldElement
        {
            int blockRows = (rows + BLOCK_SIZE - 1) / BLOCK_SIZE;
            int blockColumns = (columns + BLOCK_SIZE - 1) / BLOCK_SIZE;

            U[][] blocks = MathArrays.buildArray(field, blockRows * blockColumns, -1);
            int blockIndex = 0;
            for (int iBlock = 0; iBlock < blockRows; ++iBlock)
            {
                int pStart = iBlock * BLOCK_SIZE;
                int pEnd = FastMath.min(pStart + BLOCK_SIZE, rows);
                int iHeight = pEnd - pStart;
                for (int jBlock = 0; jBlock < blockColumns; ++jBlock)
                {
                    int qStart = jBlock * BLOCK_SIZE;
                    int qEnd = FastMath.min(qStart + BLOCK_SIZE, columns);
                    int jWidth = qEnd - qStart;
                    blocks[blockIndex] = MathArrays.buildArray(field, iHeight * jWidth);
                    ++blockIndex;
                }
            }

            return blocks;
        }

        /// <inheritdoc/>
        public override FieldMatrix<T> createMatrix(int rowDimension, int columnDimension)
        {
            return new BlockFieldMatrix<T>(getField(), rowDimension, columnDimension);
        }

        /// <inheritdoc/>
        public override FieldMatrix<T> copy()
        {

            // create an empty matrix
            BlockFieldMatrix<T> copied = new BlockFieldMatrix<T>(getField(), rows, columns);

            // copy the blocks
            for (int i = 0; i < blocks.Length; ++i)
            {
                Array.Copy(blocks[i], 0, copied.blocks[i], 0, blocks[i].Length);
            }

            return copied;
        }

        /// <inheritdoc/>
        public new FieldMatrix<T> add(FieldMatrix<T> m)
        {
            try
            {
                return add((BlockFieldMatrix<T>)m);
            }
            catch (InvalidCastException)
            {

                // safety check
                checkAdditionCompatible(m);

                BlockFieldMatrix<T> outp = new BlockFieldMatrix<T>(getField(), rows, columns);

                // perform addition block-wise, to ensure good cache behavior
                int blockIndex = 0;
                for (int iBlock = 0; iBlock < outp.blockRows; ++iBlock)
                {
                    for (int jBlock = 0; jBlock < outp.blockColumns; ++jBlock)
                    {

                        // perform addition on the current block
                        T[] outBlock = outp.blocks[blockIndex];
                        T[] tBlock = blocks[blockIndex];
                        int pStart = iBlock * BLOCK_SIZE;
                        int pEnd = FastMath.min(pStart + BLOCK_SIZE, rows);
                        int qStart = jBlock * BLOCK_SIZE;
                        int qEnd = FastMath.min(qStart + BLOCK_SIZE, columns);
                        int k = 0;
                        for (int p = pStart; p < pEnd; ++p)
                        {
                            for (int q = qStart; q < qEnd; ++q)
                            {
                                outBlock[k] = tBlock[k].add(m.getEntry(p, q));
                                ++k;
                            }
                        }

                        // go to next block
                        ++blockIndex;
                    }
                }

                return outp;
            }
        }

        ///
        /// Compute the sum of <c>this</c> and <c>m</c>.
        ///
        /// <param name="m">matrix to be added</param>
        /// <returns><c>this + m</c></returns>
        /// <exception cref="MatrixDimensionMismatchException"> if <c>m</c> is not the same
        /// size as <c>this</c></exception>
        public BlockFieldMatrix<T> add(BlockFieldMatrix<T> m)
        {

            // safety check
            checkAdditionCompatible(m);

            BlockFieldMatrix<T> outp = new BlockFieldMatrix<T>(getField(), rows, columns);

            // perform addition block-wise, to ensure good cache behavior
            for (int blockIndex = 0; blockIndex < outp.blocks.Length; ++blockIndex)
            {
                T[] outBlock = outp.blocks[blockIndex];
                T[] tBlock = blocks[blockIndex];
                T[] mBlock = m.blocks[blockIndex];
                for (int k = 0; k < outBlock.Length; ++k)
                {
                    outBlock[k] = tBlock[k].add(mBlock[k]);
                }
            }

            return outp;
        }

        /// <inheritdoc/>
        public new FieldMatrix<T> subtract(FieldMatrix<T> m)
        {
            try
            {
                return subtract((BlockFieldMatrix<T>)m);
            }
            catch (InvalidCastException)
            {

                // safety check
                checkSubtractionCompatible(m);

                BlockFieldMatrix<T> outp = new BlockFieldMatrix<T>(getField(), rows, columns);

                // perform subtraction block-wise, to ensure good cache behavior
                int blockIndex = 0;
                for (int iBlock = 0; iBlock < outp.blockRows; ++iBlock)
                {
                    for (int jBlock = 0; jBlock < outp.blockColumns; ++jBlock)
                    {

                        // perform subtraction on the current block
                        T[] outBlock = outp.blocks[blockIndex];
                        T[] tBlock = blocks[blockIndex];
                        int pStart = iBlock * BLOCK_SIZE;
                        int pEnd = FastMath.min(pStart + BLOCK_SIZE, rows);
                        int qStart = jBlock * BLOCK_SIZE;
                        int qEnd = FastMath.min(qStart + BLOCK_SIZE, columns);
                        int k = 0;
                        for (int p = pStart; p < pEnd; ++p)
                        {
                            for (int q = qStart; q < qEnd; ++q)
                            {
                                outBlock[k] = tBlock[k].subtract(m.getEntry(p, q));
                                ++k;
                            }
                        }

                        // go to next block
                        ++blockIndex;
                    }
                }
                return outp;
            }
        }

        ///
        /// Compute <c>this - m</c>.
        ///
        /// <param name="m">matrix to be subtracted</param>
        /// <returns><c>this - m</c></returns>
        /// <exception cref="MatrixDimensionMismatchException"> if <c>m</c> is not the same
        /// size as <c>this</c></exception>
        public BlockFieldMatrix<T> subtract(BlockFieldMatrix<T> m)
        {
            // safety check
            checkSubtractionCompatible(m);

            BlockFieldMatrix<T> outp = new BlockFieldMatrix<T>(getField(), rows, columns);

            // perform subtraction block-wise, to ensure good cache behavior
            for (int blockIndex = 0; blockIndex < outp.blocks.Length; ++blockIndex)
            {
                T[] outBlock = outp.blocks[blockIndex];
                T[] tBlock = blocks[blockIndex];
                T[] mBlock = m.blocks[blockIndex];
                for (int k = 0; k < outBlock.Length; ++k)
                {
                    outBlock[k] = tBlock[k].subtract(mBlock[k]);
                }
            }
            return outp;
        }

        /// <inheritdoc/>
        public new FieldMatrix<T> scalarAdd(T d)
        {
            BlockFieldMatrix<T> outp = new BlockFieldMatrix<T>(getField(), rows, columns);

            // perform subtraction block-wise, to ensure good cache behavior
            for (int blockIndex = 0; blockIndex < outp.blocks.Length; ++blockIndex)
            {
                T[] outBlock = outp.blocks[blockIndex];
                T[] tBlock = blocks[blockIndex];
                for (int k = 0; k < outBlock.Length; ++k)
                {
                    outBlock[k] = tBlock[k].add(d);
                }
            }
            return outp;
        }

        /// <inheritdoc/>
        public new FieldMatrix<T> scalarMultiply(T d)
        {

            BlockFieldMatrix<T> outp = new BlockFieldMatrix<T>(getField(), rows, columns);

            // perform subtraction block-wise, to ensure good cache behavior
            for (int blockIndex = 0; blockIndex < outp.blocks.Length; ++blockIndex)
            {
                T[] outBlock = outp.blocks[blockIndex];
                T[] tBlock = blocks[blockIndex];
                for (int k = 0; k < outBlock.Length; ++k)
                {
                    outBlock[k] = tBlock[k].multiply(d);
                }
            }
            return outp;
        }

        /// <inheritdoc/>
        public new FieldMatrix<T> multiply(FieldMatrix<T> m)
        {
            try
            {
                return multiply((BlockFieldMatrix<T>)m);
            }
            catch (InvalidCastException)
            {

                // safety check
                checkMultiplicationCompatible(m);

                BlockFieldMatrix<T> outp = new BlockFieldMatrix<T>(getField(), rows, m.getColumnDimension());
                T zero = getField().getZero();

                // perform multiplication block-wise, to ensure good cache behavior
                int blockIndex = 0;
                for (int iBlock = 0; iBlock < outp.blockRows; ++iBlock)
                {

                    int pStart = iBlock * BLOCK_SIZE;
                    int pEnd = FastMath.min(pStart + BLOCK_SIZE, rows);

                    for (int jBlock = 0; jBlock < outp.blockColumns; ++jBlock)
                    {

                        int qStart = jBlock * BLOCK_SIZE;
                        int qEnd = FastMath.min(qStart + BLOCK_SIZE, m.getColumnDimension());

                        // select current block
                        T[] outBlock = outp.blocks[blockIndex];

                        // perform multiplication on current block
                        for (int kBlock = 0; kBlock < blockColumns; ++kBlock)
                        {
                            int kWidth = blockWidth(kBlock);
                            T[] tBlock = blocks[iBlock * blockColumns + kBlock];
                            int rStart = kBlock * BLOCK_SIZE;
                            int k = 0;
                            for (int p = pStart; p < pEnd; ++p)
                            {
                                int lStart = (p - pStart) * kWidth;
                                int lEnd = lStart + kWidth;
                                for (int q = qStart; q < qEnd; ++q)
                                {
                                    T sum = zero;
                                    int r = rStart;
                                    for (int l = lStart; l < lEnd; ++l)
                                    {
                                        sum = sum.add(tBlock[l].multiply(m.getEntry(r, q)));
                                        ++r;
                                    }
                                    outBlock[k] = outBlock[k].add(sum);
                                    ++k;
                                }
                            }
                        }

                        // go to next block
                        ++blockIndex;

                    }
                }
                return outp;
            }
        }

        ///
        /// Returns the result of postmultiplying <c>this</c> by <c>m</c>.
        ///
        /// <param name="m">matrix to postmultiply by</param>
        /// <returns><c>this * m</c></returns>
        /// <exception cref="DimensionMismatchException"> if the matrices are not compatible.
        /// </exception>
        public BlockFieldMatrix<T> multiply(BlockFieldMatrix<T> m)
        {
            // safety check
            checkMultiplicationCompatible(m);

            BlockFieldMatrix<T> outp = new BlockFieldMatrix<T>(getField(), rows, m.columns);
            T zero = getField().getZero();

            // perform multiplication block-wise, to ensure good cache behavior
            int blockIndex = 0;
            for (int iBlock = 0; iBlock < outp.blockRows; ++iBlock)
            {

                int pStart = iBlock * BLOCK_SIZE;
                int pEnd = FastMath.min(pStart + BLOCK_SIZE, rows);

                for (int jBlock = 0; jBlock < outp.blockColumns; ++jBlock)
                {
                    int jWidth = outp.blockWidth(jBlock);
                    int jWidth2 = jWidth + jWidth;
                    int jWidth3 = jWidth2 + jWidth;
                    int jWidth4 = jWidth3 + jWidth;

                    // select current block
                    T[] outBlock = outp.blocks[blockIndex];

                    // perform multiplication on current block
                    for (int kBlock = 0; kBlock < blockColumns; ++kBlock)
                    {
                        int kWidth = blockWidth(kBlock);
                        T[] tBlock = blocks[iBlock * blockColumns + kBlock];
                        T[] mBlock = m.blocks[kBlock * m.blockColumns + jBlock];
                        int k = 0;
                        for (int p = pStart; p < pEnd; ++p)
                        {
                            int lStart = (p - pStart) * kWidth;
                            int lEnd = lStart + kWidth;
                            for (int nStart = 0; nStart < jWidth; ++nStart)
                            {
                                T sum = zero;
                                int l = lStart;
                                int n = nStart;
                                while (l < lEnd - 3)
                                {
                                    sum = sum.
                                          add(tBlock[l].multiply(mBlock[n])).
                                          add(tBlock[l + 1].multiply(mBlock[n + jWidth])).
                                          add(tBlock[l + 2].multiply(mBlock[n + jWidth2])).
                                          add(tBlock[l + 3].multiply(mBlock[n + jWidth3]));
                                    l += 4;
                                    n += jWidth4;
                                }
                                while (l < lEnd)
                                {
                                    sum = sum.add(tBlock[l++].multiply(mBlock[n]));
                                    n += jWidth;
                                }
                                outBlock[k] = outBlock[k].add(sum);
                                ++k;
                            }
                        }
                    }

                    // go to next block
                    ++blockIndex;
                }
            }

            return outp;
        }

        /// <inheritdoc/>
        public new T[][] getData()
        {

            T[][] data = MathArrays.buildArray(getField(), getRowDimension(), getColumnDimension());
            int lastColumns = columns - (blockColumns - 1) * BLOCK_SIZE;

            for (int iBlock = 0; iBlock < blockRows; ++iBlock)
            {
                int pStart = iBlock * BLOCK_SIZE;
                int pEnd = FastMath.min(pStart + BLOCK_SIZE, rows);
                int regularPos = 0;
                int lastPos = 0;
                for (int p = pStart; p < pEnd; ++p)
                {
                    T[] dataP = data[p];
                    int blockIndex = iBlock * blockColumns;
                    int dataPos = 0;
                    for (int jBlock = 0; jBlock < blockColumns - 1; ++jBlock)
                    {
                        Array.Copy(blocks[blockIndex++], regularPos, dataP, dataPos, BLOCK_SIZE);
                        dataPos += BLOCK_SIZE;
                    }
                    Array.Copy(blocks[blockIndex], lastPos, dataP, dataPos, lastColumns);
                    regularPos += BLOCK_SIZE;
                    lastPos += lastColumns;
                }
            }

            return data;
        }

        /// <inheritdoc/>
        public new FieldMatrix<T> getSubMatrix(int startRow, int endRow, int startColumn, int endColumn)
        {
            // safety checks
            checkSubMatrixIndex(startRow, endRow, startColumn, endColumn);

            // create the output matrix
            BlockFieldMatrix<T> outp =
                new BlockFieldMatrix<T>(getField(), endRow - startRow + 1, endColumn - startColumn + 1);

            // compute blocks shifts
            int blockStartRow = startRow / BLOCK_SIZE;
            int rowsShift = startRow % BLOCK_SIZE;
            int blockStartColumn = startColumn / BLOCK_SIZE;
            int columnsShift = startColumn % BLOCK_SIZE;

            // perform extraction block-wise, to ensure good cache behavior
            int pBlock = blockStartRow;
            for (int iBlock = 0; iBlock < outp.blockRows; ++iBlock)
            {
                int iHeight = outp.blockHeight(iBlock);
                int qBlock = blockStartColumn;
                for (int jBlock = 0; jBlock < outp.blockColumns; ++jBlock)
                {
                    int jWidth = outp.blockWidth(jBlock);

                    // handle one block of the output matrix
                    int outIndex = iBlock * outp.blockColumns + jBlock;
                    T[] outBlock = outp.blocks[outIndex];
                    int index = pBlock * blockColumns + qBlock;
                    int width = blockWidth(qBlock);

                    int heightExcess = iHeight + rowsShift - BLOCK_SIZE;
                    int widthExcess = jWidth + columnsShift - BLOCK_SIZE;
                    if (heightExcess > 0)
                    {
                        // the submatrix block spans on two blocks rows from the original matrix
                        if (widthExcess > 0)
                        {
                            // the submatrix block spans on two blocks columns from the original matrix
                            int width2 = blockWidth(qBlock + 1);
                            copyBlockPart(blocks[index], width,
                                          rowsShift, BLOCK_SIZE,
                                          columnsShift, BLOCK_SIZE,
                                          outBlock, jWidth, 0, 0);
                            copyBlockPart(blocks[index + 1], width2,
                                          rowsShift, BLOCK_SIZE,
                                          0, widthExcess,
                                          outBlock, jWidth, 0, jWidth - widthExcess);
                            copyBlockPart(blocks[index + blockColumns], width,
                                          0, heightExcess,
                                          columnsShift, BLOCK_SIZE,
                                          outBlock, jWidth, iHeight - heightExcess, 0);
                            copyBlockPart(blocks[index + blockColumns + 1], width2,
                                          0, heightExcess,
                                          0, widthExcess,
                                          outBlock, jWidth, iHeight - heightExcess, jWidth - widthExcess);
                        }
                        else
                        {
                            // the submatrix block spans on one block column from the original matrix
                            copyBlockPart(blocks[index], width,
                                          rowsShift, BLOCK_SIZE,
                                          columnsShift, jWidth + columnsShift,
                                          outBlock, jWidth, 0, 0);
                            copyBlockPart(blocks[index + blockColumns], width,
                                          0, heightExcess,
                                          columnsShift, jWidth + columnsShift,
                                          outBlock, jWidth, iHeight - heightExcess, 0);
                        }
                    }
                    else
                    {
                        // the submatrix block spans on one block row from the original matrix
                        if (widthExcess > 0)
                        {
                            // the submatrix block spans on two blocks columns from the original matrix
                            int width2 = blockWidth(qBlock + 1);
                            copyBlockPart(blocks[index], width,
                                          rowsShift, iHeight + rowsShift,
                                          columnsShift, BLOCK_SIZE,
                                          outBlock, jWidth, 0, 0);
                            copyBlockPart(blocks[index + 1], width2,
                                          rowsShift, iHeight + rowsShift,
                                          0, widthExcess,
                                          outBlock, jWidth, 0, jWidth - widthExcess);
                        }
                        else
                        {
                            // the submatrix block spans on one block column from the original matrix
                            copyBlockPart(blocks[index], width,
                                          rowsShift, iHeight + rowsShift,
                                          columnsShift, jWidth + columnsShift,
                                          outBlock, jWidth, 0, 0);
                        }
                    }
                    ++qBlock;
                }
                ++pBlock;
            }

            return outp;
        }

        ///
        /// Copy a part of a block into another one
        /// <para>This method can be called only when the specified part fits in both
        /// blocks, no verification is done here.</para>
        ///
        /// <param name="srcBlock">source block</param>
        /// <param name="srcWidth">source block width (<see cref="BLOCK_SIZE"/> or smaller)</param>
        /// <param name="srcStartRow">start row in the source block</param>
        /// <param name="srcEndRow">end row (exclusive) in the source block</param>
        /// <param name="srcStartColumn">start column in the source block</param>
        /// <param name="srcEndColumn">end column (exclusive) in the source block</param>
        /// <param name="dstBlock">destination block</param>
        /// <param name="dstWidth">destination block width (<see cref="BLOCK_SIZE"/> or smaller)</param>
        /// <param name="dstStartRow">start row in the destination block</param>
        /// <param name="dstStartColumn">start column in the destination block</param>
        private void copyBlockPart(T[] srcBlock, int srcWidth, int srcStartRow, int srcEndRow, int srcStartColumn, int srcEndColumn, T[] dstBlock, int dstWidth, int dstStartRow, int dstStartColumn)
        {
            int length = srcEndColumn - srcStartColumn;
            int srcPos = srcStartRow * srcWidth + srcStartColumn;
            int dstPos = dstStartRow * dstWidth + dstStartColumn;
            for (int srcRow = srcStartRow; srcRow < srcEndRow; ++srcRow)
            {
                Array.Copy(srcBlock, srcPos, dstBlock, dstPos, length);
                srcPos += srcWidth;
                dstPos += dstWidth;
            }
        }

        /// <inheritdoc/>
        public new void setSubMatrix(T[][] subMatrix, int row, int column)
        {
            // safety checks
            MathUtils.checkNotNull(subMatrix);
            int refLength = subMatrix[0].Length;
            if (refLength == 0)
            {
                throw new NoDataException(new LocalizedFormats("AT_LEAST_ONE_COLUMN"));
            }
            int endRow = row + subMatrix.Length - 1;
            int endColumn = column + refLength - 1;
            checkSubMatrixIndex(row, endRow, column, endColumn);
            foreach (T[] subRow in subMatrix)
            {
                if (subRow.Length != refLength)
                {
                    throw new DimensionMismatchException(refLength, subRow.Length);
                }
            }

            // compute blocks bounds
            int blockStartRow = row / BLOCK_SIZE;
            int blockEndRow = (endRow + BLOCK_SIZE) / BLOCK_SIZE;
            int blockStartColumn = column / BLOCK_SIZE;
            int blockEndColumn = (endColumn + BLOCK_SIZE) / BLOCK_SIZE;

            // perform copy block-wise, to ensure good cache behavior
            for (int iBlock = blockStartRow; iBlock < blockEndRow; ++iBlock)
            {
                int iHeight = blockHeight(iBlock);
                int firstRow = iBlock * BLOCK_SIZE;
                int iStart = FastMath.max(row, firstRow);
                int iEnd = FastMath.min(endRow + 1, firstRow + iHeight);

                for (int jBlock = blockStartColumn; jBlock < blockEndColumn; ++jBlock)
                {
                    int jWidth = blockWidth(jBlock);
                    int firstColumn = jBlock * BLOCK_SIZE;
                    int jStart = FastMath.max(column, firstColumn);
                    int jEnd = FastMath.min(endColumn + 1, firstColumn + jWidth);
                    int jLength = jEnd - jStart;

                    // handle one block, row by row
                    T[] block = blocks[iBlock * blockColumns + jBlock];
                    for (int i = iStart; i < iEnd; ++i)
                    {
                        Array.Copy(subMatrix[i - row], jStart - column,
                                         block, (i - firstRow) * jWidth + (jStart - firstColumn),
                                         jLength);
                    }

                }
            }
        }

        /// <inheritdoc/>
        public new FieldMatrix<T> getRowMatrix(int row)
        {
            checkRowIndex(row);
            BlockFieldMatrix<T> outp = new BlockFieldMatrix<T>(getField(), 1, columns);

            // perform copy block-wise, to ensure good cache behavior
            int iBlock = row / BLOCK_SIZE;
            int iRow = row - iBlock * BLOCK_SIZE;
            int outBlockIndex = 0;
            int outIndex = 0;
            T[] outBlock = outp.blocks[outBlockIndex];
            for (int jBlock = 0; jBlock < blockColumns; ++jBlock)
            {
                int jWidth = blockWidth(jBlock);
                T[] block = blocks[iBlock * blockColumns + jBlock];
                int available = outBlock.Length - outIndex;
                if (jWidth > available)
                {
                    Array.Copy(block, iRow * jWidth, outBlock, outIndex, available);
                    outBlock = outp.blocks[++outBlockIndex];
                    Array.Copy(block, iRow * jWidth, outBlock, 0, jWidth - available);
                    outIndex = jWidth - available;
                }
                else
                {
                    Array.Copy(block, iRow * jWidth, outBlock, outIndex, jWidth);
                    outIndex += jWidth;
                }
            }

            return outp;
        }

        /// <inheritdoc/>
        public new void setRowMatrix(int row, FieldMatrix<T> matrix)
        {
            try
            {
                setRowMatrix(row, (BlockFieldMatrix<T>)matrix);
            }
            catch (InvalidCastException)
            {
                base.setRowMatrix(row, matrix);
            }
        }

        ///
        /// Sets the entries in row number <c>row</c>
        /// as a row matrix.  Row indices start at 0.
        ///
        /// <param name="row">the row to be set</param>
        /// <param name="matrix">row matrix (must have one row and the same number of columns
        /// as the instance)</param>
        /// <exception cref="MatrixDimensionMismatchException"> if the matrix dimensions do
        /// not match one instance row.</exception>
        /// <exception cref="OutOfRangeException"> if the specified row index is invalid.
        /// </exception>
        public void setRowMatrix(int row, BlockFieldMatrix<T> matrix)
        {
            checkRowIndex(row);
            int nCols = getColumnDimension();
            if ((matrix.getRowDimension() != 1) ||
                (matrix.getColumnDimension() != nCols))
            {
                throw new MatrixDimensionMismatchException(matrix.getRowDimension(),
                                                           matrix.getColumnDimension(),
                                                           1, nCols);
            }

            // perform copy block-wise, to ensure good cache behavior
            int iBlock = row / BLOCK_SIZE;
            int iRow = row - iBlock * BLOCK_SIZE;
            int mBlockIndex = 0;
            int mIndex = 0;
            T[] mBlock = matrix.blocks[mBlockIndex];
            for (int jBlock = 0; jBlock < blockColumns; ++jBlock)
            {
                int jWidth = blockWidth(jBlock);
                T[] block = blocks[iBlock * blockColumns + jBlock];
                int available = mBlock.Length - mIndex;
                if (jWidth > available)
                {
                    Array.Copy(mBlock, mIndex, block, iRow * jWidth, available);
                    mBlock = matrix.blocks[++mBlockIndex];
                    Array.Copy(mBlock, 0, block, iRow * jWidth, jWidth - available);
                    mIndex = jWidth - available;
                }
                else
                {
                    Array.Copy(mBlock, mIndex, block, iRow * jWidth, jWidth);
                    mIndex += jWidth;
                }
            }
        }

        /// <inheritdoc/>
        public new FieldMatrix<T> getColumnMatrix(int column)
        {
            checkColumnIndex(column);
            BlockFieldMatrix<T> outp = new BlockFieldMatrix<T>(getField(), rows, 1);

            // perform copy block-wise, to ensure good cache behavior
            int jBlock = column / BLOCK_SIZE;
            int jColumn = column - jBlock * BLOCK_SIZE;
            int jWidth = blockWidth(jBlock);
            int outBlockIndex = 0;
            int outIndex = 0;
            T[] outBlock = outp.blocks[outBlockIndex];
            for (int iBlock = 0; iBlock < blockRows; ++iBlock)
            {
                int iHeight = blockHeight(iBlock);
                T[] block = blocks[iBlock * blockColumns + jBlock];
                for (int i = 0; i < iHeight; ++i)
                {
                    if (outIndex >= outBlock.Length)
                    {
                        outBlock = outp.blocks[++outBlockIndex];
                        outIndex = 0;
                    }
                    outBlock[outIndex++] = block[i * jWidth + jColumn];
                }
            }

            return outp;
        }

        /// <inheritdoc/>
        public new void setColumnMatrix(int column, FieldMatrix<T> matrix)
        {
            try
            {
                setColumnMatrix(column, (BlockFieldMatrix<T>)matrix);
            }
            catch (InvalidCastException)
            {
                base.setColumnMatrix(column, matrix);
            }
        }

        ///
        /// Sets the entries in column number <c>column</c>
        /// as a column matrix.  Column indices start at 0.
        ///
        /// <param name="column">Column to be set.</param>
        /// <param name="matrix">Column matrix (must have one column and the same number of rows
        /// as the instance).</param>
        /// <exception cref="MatrixDimensionMismatchException"> if the matrix dimensions do
        /// not match one instance column.</exception>
        /// <exception cref="OutOfRangeException"> if the specified column index is invalid
        /// </exception>
        void setColumnMatrix(int column, BlockFieldMatrix<T> matrix)
        {
            checkColumnIndex(column);
            int nRows = getRowDimension();
            if ((matrix.getRowDimension() != nRows) ||
                (matrix.getColumnDimension() != 1))
            {
                throw new MatrixDimensionMismatchException(matrix.getRowDimension(),
                                                           matrix.getColumnDimension(),
                                                           nRows, 1);
            }

            // perform copy block-wise, to ensure good cache behavior
            int jBlock = column / BLOCK_SIZE;
            int jColumn = column - jBlock * BLOCK_SIZE;
            int jWidth = blockWidth(jBlock);
            int mBlockIndex = 0;
            int mIndex = 0;
            T[] mBlock = matrix.blocks[mBlockIndex];
            for (int iBlock = 0; iBlock < blockRows; ++iBlock)
            {
                int iHeight = blockHeight(iBlock);
                T[] block = blocks[iBlock * blockColumns + jBlock];
                for (int i = 0; i < iHeight; ++i)
                {
                    if (mIndex >= mBlock.Length)
                    {
                        mBlock = matrix.blocks[++mBlockIndex];
                        mIndex = 0;
                    }
                    block[i * jWidth + jColumn] = mBlock[mIndex++];
                }
            }
        }

        /// <inheritdoc/>
        public new FieldVector<T> getRowVector(int row)
        {
            checkRowIndex(row);
            T[] outData = MathArrays.buildArray(getField(), columns);

            // perform copy block-wise, to ensure good cache behavior
            int iBlock = row / BLOCK_SIZE;
            int iRow = row - iBlock * BLOCK_SIZE;
            int outIndex = 0;
            for (int jBlock = 0; jBlock < blockColumns; ++jBlock)
            {
                int jWidth = blockWidth(jBlock);
                T[] block = blocks[iBlock * blockColumns + jBlock];
                Array.Copy(block, iRow * jWidth, outData, outIndex, jWidth);
                outIndex += jWidth;
            }

            return new ArrayFieldVector<T>(getField(), outData, false);
        }

        /// <inheritdoc/>
        public new void setRowVector(int row, FieldVector<T> vector)
        {
            try
            {
                setRow(row, ((ArrayFieldVector<T>)vector).getDataRef());
            }
            catch (InvalidCastException)
            {
                base.setRowVector(row, vector);
            }
        }

        /// <inheritdoc/>
        public new FieldVector<T> getColumnVector(int column)
        {
            checkColumnIndex(column);
            T[] outData = MathArrays.buildArray(getField(), rows);

            // perform copy block-wise, to ensure good cache behavior
            int jBlock = column / BLOCK_SIZE;
            int jColumn = column - jBlock * BLOCK_SIZE;
            int jWidth = blockWidth(jBlock);
            int outIndex = 0;
            for (int iBlock = 0; iBlock < blockRows; ++iBlock)
            {
                int iHeight = blockHeight(iBlock);
                T[] block = blocks[iBlock * blockColumns + jBlock];
                for (int i = 0; i < iHeight; ++i)
                {
                    outData[outIndex++] = block[i * jWidth + jColumn];
                }
            }

            return new ArrayFieldVector<T>(getField(), outData, false);
        }

        /// <inheritdoc/>
        public new void setColumnVector(int column, FieldVector<T> vector)
        {
            try
            {
                setColumn(column, ((ArrayFieldVector<T>)vector).getDataRef());
            }
            catch (InvalidCastException)
            {
                base.setColumnVector(column, vector);
            }
        }

        /// <inheritdoc/>
        public new T[] getRow(int row)
        {
            checkRowIndex(row);
            T[] outp = MathArrays.buildArray(getField(), columns);

            // perform copy block-wise, to ensure good cache behavior
            int iBlock = row / BLOCK_SIZE;
            int iRow = row - iBlock * BLOCK_SIZE;
            int outIndex = 0;
            for (int jBlock = 0; jBlock < blockColumns; ++jBlock)
            {
                int jWidth = blockWidth(jBlock);
                T[] block = blocks[iBlock * blockColumns + jBlock];
                Array.Copy(block, iRow * jWidth, outp, outIndex, jWidth);
                outIndex += jWidth;
            }

            return outp;
        }

        /// <inheritdoc/>
        public new void setRow(int row, T[] array)
        {
            checkRowIndex(row);
            int nCols = getColumnDimension();
            if (array.Length != nCols)
            {
                throw new MatrixDimensionMismatchException(1, array.Length, 1, nCols);
            }

            // perform copy block-wise, to ensure good cache behavior
            int iBlock = row / BLOCK_SIZE;
            int iRow = row - iBlock * BLOCK_SIZE;
            int outIndex = 0;
            for (int jBlock = 0; jBlock < blockColumns; ++jBlock)
            {
                int jWidth = blockWidth(jBlock);
                T[] block = blocks[iBlock * blockColumns + jBlock];
                Array.Copy(array, outIndex, block, iRow * jWidth, jWidth);
                outIndex += jWidth;
            }
        }

        /// <inheritdoc/>
        public new T[] getColumn(int column)
        {
            checkColumnIndex(column);
            T[] outp = MathArrays.buildArray(getField(), rows);

            // perform copy block-wise, to ensure good cache behavior
            int jBlock = column / BLOCK_SIZE;
            int jColumn = column - jBlock * BLOCK_SIZE;
            int jWidth = blockWidth(jBlock);
            int outIndex = 0;
            for (int iBlock = 0; iBlock < blockRows; ++iBlock)
            {
                int iHeight = blockHeight(iBlock);
                T[] block = blocks[iBlock * blockColumns + jBlock];
                for (int i = 0; i < iHeight; ++i)
                {
                    outp[outIndex++] = block[i * jWidth + jColumn];
                }
            }

            return outp;
        }

        /// <inheritdoc/>
        public new void setColumn(int column, T[] array)
        {
            checkColumnIndex(column);
            int nRows = getRowDimension();
            if (array.Length != nRows)
            {
                throw new MatrixDimensionMismatchException(array.Length, 1, nRows, 1);
            }

            // perform copy block-wise, to ensure good cache behavior
            int jBlock = column / BLOCK_SIZE;
            int jColumn = column - jBlock * BLOCK_SIZE;
            int jWidth = blockWidth(jBlock);
            int outIndex = 0;
            for (int iBlock = 0; iBlock < blockRows; ++iBlock)
            {
                int iHeight = blockHeight(iBlock);
                T[] block = blocks[iBlock * blockColumns + jBlock];
                for (int i = 0; i < iHeight; ++i)
                {
                    block[i * jWidth + jColumn] = array[outIndex++];
                }
            }
        }

        /// <inheritdoc/>
        public override T getEntry(int row, int column)
        {
            checkRowIndex(row);
            checkColumnIndex(column);

            int iBlock = row / BLOCK_SIZE;
            int jBlock = column / BLOCK_SIZE;
            int k = (row - iBlock * BLOCK_SIZE) * blockWidth(jBlock) +
                (column - jBlock * BLOCK_SIZE);

            return blocks[iBlock * blockColumns + jBlock][k];
        }

        /// <inheritdoc/>
        public override void setEntry(int row, int column, T value)
        {
            checkRowIndex(row);
            checkColumnIndex(column);

            int iBlock = row / BLOCK_SIZE;
            int jBlock = column / BLOCK_SIZE;
            int k = (row - iBlock * BLOCK_SIZE) * blockWidth(jBlock) +
                (column - jBlock * BLOCK_SIZE);

            blocks[iBlock * blockColumns + jBlock][k] = value;
        }

        /// <inheritdoc/>
        public override void addToEntry(int row, int column, T increment)
        {
            checkRowIndex(row);
            checkColumnIndex(column);

            int iBlock = row / BLOCK_SIZE;
            int jBlock = column / BLOCK_SIZE;
            int k = (row - iBlock * BLOCK_SIZE) * blockWidth(jBlock) +
                (column - jBlock * BLOCK_SIZE);
            T[] blockIJ = blocks[iBlock * blockColumns + jBlock];

            blockIJ[k] = blockIJ[k].add(increment);
        }

        /// <inheritdoc/>
        public override void multiplyEntry(int row, int column, T factor)
        {
            checkRowIndex(row);
            checkColumnIndex(column);

            int iBlock = row / BLOCK_SIZE;
            int jBlock = column / BLOCK_SIZE;
            int k = (row - iBlock * BLOCK_SIZE) * blockWidth(jBlock) +
                (column - jBlock * BLOCK_SIZE);
            T[] blockIJ = blocks[iBlock * blockColumns + jBlock];

            blockIJ[k] = blockIJ[k].multiply(factor);
        }

        /// <inheritdoc/>
        public new FieldMatrix<T> transpose()
        {
            int nRows = getRowDimension();
            int nCols = getColumnDimension();
            BlockFieldMatrix<T> outp = new BlockFieldMatrix<T>(getField(), nCols, nRows);

            // perform transpose block-wise, to ensure good cache behavior
            int blockIndex = 0;
            for (int iBlock = 0; iBlock < blockColumns; ++iBlock)
            {
                for (int jBlock = 0; jBlock < blockRows; ++jBlock)
                {

                    // transpose current block
                    T[] outBlock = outp.blocks[blockIndex];
                    T[] tBlock = blocks[jBlock * blockColumns + iBlock];
                    int pStart = iBlock * BLOCK_SIZE;
                    int pEnd = FastMath.min(pStart + BLOCK_SIZE, columns);
                    int qStart = jBlock * BLOCK_SIZE;
                    int qEnd = FastMath.min(qStart + BLOCK_SIZE, rows);
                    int k = 0;
                    for (int p = pStart; p < pEnd; ++p)
                    {
                        int lInc = pEnd - pStart;
                        int l = p - pStart;
                        for (int q = qStart; q < qEnd; ++q)
                        {
                            outBlock[k] = tBlock[l];
                            ++k;
                            l += lInc;
                        }
                    }

                    // go to next block
                    ++blockIndex;

                }
            }
            return outp;
        }

        /// <inheritdoc/>
        public override int getRowDimension()
        {
            return rows;
        }

        /// <inheritdoc/>
        public override int getColumnDimension()
        {
            return columns;
        }

        /// <inheritdoc/>
        public new T[] operate(T[] v)
        {
            if (v.Length != columns)
            {
                throw new DimensionMismatchException(v.Length, columns);
            }
            T[] outp = MathArrays.buildArray(getField(), rows);
            T zero = getField().getZero();

            // perform multiplication block-wise, to ensure good cache behavior
            for (int iBlock = 0; iBlock < blockRows; ++iBlock)
            {
                int pStart = iBlock * BLOCK_SIZE;
                int pEnd = FastMath.min(pStart + BLOCK_SIZE, rows);
                for (int jBlock = 0; jBlock < blockColumns; ++jBlock)
                {
                    T[] block = blocks[iBlock * blockColumns + jBlock];
                    int qStart = jBlock * BLOCK_SIZE;
                    int qEnd = FastMath.min(qStart + BLOCK_SIZE, columns);
                    int k = 0;
                    for (int p = pStart; p < pEnd; ++p)
                    {
                        T sum = zero;
                        int q = qStart;
                        while (q < qEnd - 3)
                        {
                            sum = sum.
                                  add(block[k].multiply(v[q])).
                                  add(block[k + 1].multiply(v[q + 1])).
                                  add(block[k + 2].multiply(v[q + 2])).
                                  add(block[k + 3].multiply(v[q + 3]));
                            k += 4;
                            q += 4;
                        }
                        while (q < qEnd)
                        {
                            sum = sum.add(block[k++].multiply(v[q++]));
                        }
                        outp[p] = outp[p].add(sum);
                    }
                }
            }
            return outp;
        }

        /// <inheritdoc/>
        public new T[] preMultiply(T[] v)
        {

            if (v.Length != rows)
            {
                throw new DimensionMismatchException(v.Length, rows);
            }
            T[] outp = MathArrays.buildArray(getField(), columns);
            T zero = getField().getZero();

            // perform multiplication block-wise, to ensure good cache behavior
            for (int jBlock = 0; jBlock < blockColumns; ++jBlock)
            {
                int jWidth = blockWidth(jBlock);
                int jWidth2 = jWidth + jWidth;
                int jWidth3 = jWidth2 + jWidth;
                int jWidth4 = jWidth3 + jWidth;
                int qStart = jBlock * BLOCK_SIZE;
                int qEnd = FastMath.min(qStart + BLOCK_SIZE, columns);
                for (int iBlock = 0; iBlock < blockRows; ++iBlock)
                {
                    T[] block = blocks[iBlock * blockColumns + jBlock];
                    int pStart = iBlock * BLOCK_SIZE;
                    int pEnd = FastMath.min(pStart + BLOCK_SIZE, rows);
                    for (int q = qStart; q < qEnd; ++q)
                    {
                        int k = q - qStart;
                        T sum = zero;
                        int p = pStart;
                        while (p < pEnd - 3)
                        {
                            sum = sum.
                                  add(block[k].multiply(v[p])).
                                  add(block[k + jWidth].multiply(v[p + 1])).
                                  add(block[k + jWidth2].multiply(v[p + 2])).
                                  add(block[k + jWidth3].multiply(v[p + 3]));
                            k += jWidth4;
                            p += 4;
                        }
                        while (p < pEnd)
                        {
                            sum = sum.add(block[k].multiply(v[p++]));
                            k += jWidth;
                        }
                        outp[q] = outp[q].add(sum);
                    }
                }
            }
            return outp;
        }

        /// <inheritdoc/>
        public new T walkInRowOrder(FieldMatrixChangingVisitor<T> visitor)
        {
            visitor.start(rows, columns, 0, rows - 1, 0, columns - 1);
            for (int iBlock = 0; iBlock < blockRows; ++iBlock)
            {
                int pStart = iBlock * BLOCK_SIZE;
                int pEnd = FastMath.min(pStart + BLOCK_SIZE, rows);
                for (int p = pStart; p < pEnd; ++p)
                {
                    for (int jBlock = 0; jBlock < blockColumns; ++jBlock)
                    {
                        int jWidth = blockWidth(jBlock);
                        int qStart = jBlock * BLOCK_SIZE;
                        int qEnd = FastMath.min(qStart + BLOCK_SIZE, columns);
                        T[] block = blocks[iBlock * blockColumns + jBlock];
                        int k = (p - pStart) * jWidth;
                        for (int q = qStart; q < qEnd; ++q)
                        {
                            block[k] = visitor.visit(p, q, block[k]);
                            ++k;
                        }
                    }
                }
            }
            return visitor.end();
        }

        /// <inheritdoc/>
        public new T walkInRowOrder(FieldMatrixPreservingVisitor<T> visitor)
        {
            visitor.start(rows, columns, 0, rows - 1, 0, columns - 1);
            for (int iBlock = 0; iBlock < blockRows; ++iBlock)
            {
                int pStart = iBlock * BLOCK_SIZE;
                int pEnd = FastMath.min(pStart + BLOCK_SIZE, rows);
                for (int p = pStart; p < pEnd; ++p)
                {
                    for (int jBlock = 0; jBlock < blockColumns; ++jBlock)
                    {
                        int jWidth = blockWidth(jBlock);
                        int qStart = jBlock * BLOCK_SIZE;
                        int qEnd = FastMath.min(qStart + BLOCK_SIZE, columns);
                        T[] block = blocks[iBlock * blockColumns + jBlock];
                        int k = (p - pStart) * jWidth;
                        for (int q = qStart; q < qEnd; ++q)
                        {
                            visitor.visit(p, q, block[k]);
                            ++k;
                        }
                    }
                }
            }
            return visitor.end();
        }

        /// <inheritdoc/>
        public new T walkInRowOrder(FieldMatrixChangingVisitor<T> visitor, int startRow, int endRow,
                                int startColumn, int endColumn)
        {
            checkSubMatrixIndex(startRow, endRow, startColumn, endColumn);
            visitor.start(rows, columns, startRow, endRow, startColumn, endColumn);
            for (int iBlock = startRow / BLOCK_SIZE; iBlock < 1 + endRow / BLOCK_SIZE; ++iBlock)
            {
                int p0 = iBlock * BLOCK_SIZE;
                int pStart = FastMath.max(startRow, p0);
                int pEnd = FastMath.min((iBlock + 1) * BLOCK_SIZE, 1 + endRow);
                for (int p = pStart; p < pEnd; ++p)
                {
                    for (int jBlock = startColumn / BLOCK_SIZE; jBlock < 1 + endColumn / BLOCK_SIZE; ++jBlock)
                    {
                        int jWidth = blockWidth(jBlock);
                        int q0 = jBlock * BLOCK_SIZE;
                        int qStart = FastMath.max(startColumn, q0);
                        int qEnd = FastMath.min((jBlock + 1) * BLOCK_SIZE, 1 + endColumn);
                        T[] block = blocks[iBlock * blockColumns + jBlock];
                        int k = (p - p0) * jWidth + qStart - q0;
                        for (int q = qStart; q < qEnd; ++q)
                        {
                            block[k] = visitor.visit(p, q, block[k]);
                            ++k;
                        }
                    }
                }
            }
            return visitor.end();
        }

        /// <inheritdoc/>
        public new T walkInRowOrder(FieldMatrixPreservingVisitor<T> visitor, int startRow, int endRow, int startColumn, int endColumn)
        {
            checkSubMatrixIndex(startRow, endRow, startColumn, endColumn);
            visitor.start(rows, columns, startRow, endRow, startColumn, endColumn);
            for (int iBlock = startRow / BLOCK_SIZE; iBlock < 1 + endRow / BLOCK_SIZE; ++iBlock)
            {
                int p0 = iBlock * BLOCK_SIZE;
                int pStart = FastMath.max(startRow, p0);
                int pEnd = FastMath.min((iBlock + 1) * BLOCK_SIZE, 1 + endRow);
                for (int p = pStart; p < pEnd; ++p)
                {
                    for (int jBlock = startColumn / BLOCK_SIZE; jBlock < 1 + endColumn / BLOCK_SIZE; ++jBlock)
                    {
                        int jWidth = blockWidth(jBlock);
                        int q0 = jBlock * BLOCK_SIZE;
                        int qStart = FastMath.max(startColumn, q0);
                        int qEnd = FastMath.min((jBlock + 1) * BLOCK_SIZE, 1 + endColumn);
                        T[] block = blocks[iBlock * blockColumns + jBlock];
                        int k = (p - p0) * jWidth + qStart - q0;
                        for (int q = qStart; q < qEnd; ++q)
                        {
                            visitor.visit(p, q, block[k]);
                            ++k;
                        }
                    }
                }
            }
            return visitor.end();
        }

        /// <inheritdoc/>
        public new T walkInOptimizedOrder(FieldMatrixChangingVisitor<T> visitor)
        {
            visitor.start(rows, columns, 0, rows - 1, 0, columns - 1);
            int blockIndex = 0;
            for (int iBlock = 0; iBlock < blockRows; ++iBlock)
            {
                int pStart = iBlock * BLOCK_SIZE;
                int pEnd = FastMath.min(pStart + BLOCK_SIZE, rows);
                for (int jBlock = 0; jBlock < blockColumns; ++jBlock)
                {
                    int qStart = jBlock * BLOCK_SIZE;
                    int qEnd = FastMath.min(qStart + BLOCK_SIZE, columns);
                    T[] block = blocks[blockIndex];
                    int k = 0;
                    for (int p = pStart; p < pEnd; ++p)
                    {
                        for (int q = qStart; q < qEnd; ++q)
                        {
                            block[k] = visitor.visit(p, q, block[k]);
                            ++k;
                        }
                    }
                    ++blockIndex;
                }
            }
            return visitor.end();
        }

        /// <inheritdoc/>
        public new T walkInOptimizedOrder(FieldMatrixPreservingVisitor<T> visitor)
        {
            visitor.start(rows, columns, 0, rows - 1, 0, columns - 1);
            int blockIndex = 0;
            for (int iBlock = 0; iBlock < blockRows; ++iBlock)
            {
                int pStart = iBlock * BLOCK_SIZE;
                int pEnd = FastMath.min(pStart + BLOCK_SIZE, rows);
                for (int jBlock = 0; jBlock < blockColumns; ++jBlock)
                {
                    int qStart = jBlock * BLOCK_SIZE;
                    int qEnd = FastMath.min(qStart + BLOCK_SIZE, columns);
                    T[] block = blocks[blockIndex];
                    int k = 0;
                    for (int p = pStart; p < pEnd; ++p)
                    {
                        for (int q = qStart; q < qEnd; ++q)
                        {
                            visitor.visit(p, q, block[k]);
                            ++k;
                        }
                    }
                    ++blockIndex;
                }
            }
            return visitor.end();
        }

        /// <inheritdoc/>
        public new T walkInOptimizedOrder(FieldMatrixChangingVisitor<T> visitor, int startRow, int endRow, int startColumn, int endColumn)
        {
            checkSubMatrixIndex(startRow, endRow, startColumn, endColumn);
            visitor.start(rows, columns, startRow, endRow, startColumn, endColumn);
            for (int iBlock = startRow / BLOCK_SIZE; iBlock < 1 + endRow / BLOCK_SIZE; ++iBlock)
            {
                int p0 = iBlock * BLOCK_SIZE;
                int pStart = FastMath.max(startRow, p0);
                int pEnd = FastMath.min((iBlock + 1) * BLOCK_SIZE, 1 + endRow);
                for (int jBlock = startColumn / BLOCK_SIZE; jBlock < 1 + endColumn / BLOCK_SIZE; ++jBlock)
                {
                    int jWidth = blockWidth(jBlock);
                    int q0 = jBlock * BLOCK_SIZE;
                    int qStart = FastMath.max(startColumn, q0);
                    int qEnd = FastMath.min((jBlock + 1) * BLOCK_SIZE, 1 + endColumn);
                    T[] block = blocks[iBlock * blockColumns + jBlock];
                    for (int p = pStart; p < pEnd; ++p)
                    {
                        int k = (p - p0) * jWidth + qStart - q0;
                        for (int q = qStart; q < qEnd; ++q)
                        {
                            block[k] = visitor.visit(p, q, block[k]);
                            ++k;
                        }
                    }
                }
            }
            return visitor.end();
        }

        /// <inheritdoc/>
        public new T walkInOptimizedOrder(FieldMatrixPreservingVisitor<T> visitor, int startRow, int endRow, int startColumn, int endColumn)
        {
            checkSubMatrixIndex(startRow, endRow, startColumn, endColumn);
            visitor.start(rows, columns, startRow, endRow, startColumn, endColumn);
            for (int iBlock = startRow / BLOCK_SIZE; iBlock < 1 + endRow / BLOCK_SIZE; ++iBlock)
            {
                int p0 = iBlock * BLOCK_SIZE;
                int pStart = FastMath.max(startRow, p0);
                int pEnd = FastMath.min((iBlock + 1) * BLOCK_SIZE, 1 + endRow);
                for (int jBlock = startColumn / BLOCK_SIZE; jBlock < 1 + endColumn / BLOCK_SIZE; ++jBlock)
                {
                    int jWidth = blockWidth(jBlock);
                    int q0 = jBlock * BLOCK_SIZE;
                    int qStart = FastMath.max(startColumn, q0);
                    int qEnd = FastMath.min((jBlock + 1) * BLOCK_SIZE, 1 + endColumn);
                    T[] block = blocks[iBlock * blockColumns + jBlock];
                    for (int p = pStart; p < pEnd; ++p)
                    {
                        int k = (p - p0) * jWidth + qStart - q0;
                        for (int q = qStart; q < qEnd; ++q)
                        {
                            visitor.visit(p, q, block[k]);
                            ++k;
                        }
                    }
                }
            }
            return visitor.end();
        }

        ///
        /// Get the height of a block.
        ///
        /// <param name="blockRow">row index (in block sense) of the block</param>
        /// <returns>height (number of rows) of the block</returns>
        private int blockHeight(int blockRow)
        {
            return (blockRow == blockRows - 1) ? rows - blockRow * BLOCK_SIZE : BLOCK_SIZE;
        }

        ///
        /// Get the width of a block.
        ///
        /// <param name="blockColumn">column index (in block sense) of the block</param>
        /// <returns>width (number of columns) of the block</returns>
        private int blockWidth(int blockColumn)
        {
            return (blockColumn == blockColumns - 1) ? columns - blockColumn * BLOCK_SIZE : BLOCK_SIZE;
        }
    }
}


text:
void pre_auton()
{
  // Set bStopTasksBetweenModes to false if you want to keep user created tasks running between
  // Autonomous and Tele-Op modes. You will need to manage all user created tasks if set to false.
  bStopTasksBetweenModes = true;

	// All activities that occur before the competition starts
	// Example: clearing encoders, setting servo positions, ...
}

/////////////////////////////////////////////////////////////////////////////////////////
//
//                                 Autonomous Task
//
// This task is used to control your robot during the autonomous phase of a VEX Competition.
// You must modify the code to add your own robot specific commands here.
//
/////////////////////////////////////////////////////////////////////////////////////////

task autonomous()
{
  // .....................................................................................
  // Insert user code here.
  // .....................................................................................

	AutonomousCodePlaceholderForTesting();  // Remove this function call once you have "real" code.
}

/////////////////////////////////////////////////////////////////////////////////////////
//
//                                 User Control Task
//
// This task is used to control your robot during the user control phase of a VEX Competition.
// You must modify the code to add your own robot specific commands here.
//
/////////////////////////////////////////////////////////////////////////////////////////

task usercontrol()
{
#define C1LX vexRT[Ch4]
#define C1LY -vexRT[Ch3]
#define C1RX vexRT[Ch1]

while(1==1){
    clearLCDLine(0);
    clearLCDLine(1);
		displayLCDNumber(0, 0, SensorValue(arm), 5);
  	displayLCDNumber(1, 0, SensorValue(clawPot), 5);
		//holonomic drive code
		motor[FL] = -C1LY - C1LX - C1RX;
		motor[FR] =  C1LY - C1LX - C1RX;
		motor[BR] =  C1LY + C1LX - C1RX;
		motor[BL] = -C1LY + C1LX - C1RX;

		//Lift
		if(VexRT[Btn5U] && sensorValue(arm) < 2500){
			motor[RightLift1] = 127;
			motor[RightLift2] = 127;
			motor[LeftLift1] = 127;
			motor[LeftLift2] = 127;
		}
		//Lift reverse
		else if (VexRT[Btn5D]&& sensorValue(arm) > 0){
			motor[RightLift1] = -127;
			motor[RightLift2] = -127;
			motor[LeftLift1] = -127;
			motor[LeftLift2] = -127;
		}
		//Do nothing
		else{
			motor[RightLift1] = 0;
			motor[RightLift2] = 0;
			motor[LeftLift1] = 0;
			motor[LeftLift2] = 0;
		}

		//Opens claw
		if(VexRT[Btn6D] && sensorValue(clawPot) <= 2960){
			motor[claw] = -127;
    	motor[claw2] = -127;
		}
		//closes claw
		else if(VexRT[Btn6u] && sensorValue(clawPot) >= 50){
			motor[claw] = 127;
    	motor[claw2] = 127;
		}
		else if(VexRT[Btn8D]){
			motor[claw] = -127;
    	motor[claw2] = -127;
		}

		//Do nothing
		else{
			motor[claw] = 0;
			motor[claw2] = 0;
		}

}
}

redpajama_set_name: RedPajamaGithub


text:
@interface HLSParser : NSObject

@property (nonatomic, weak) id<HLSParserDelegate> delegate;
@property (nonatomic) NSString *urlString;
@property (nonatomic) BOOL isHLSFile;

- (instancetype)initWithURL:(NSString *)urlString;
- (void)startDownloadFile;
- (void)cancelDownloadFile;

@end


text:
class Plot: public QwtPlot
{
    Q_OBJECT

public:
    Plot(QWidget * = NULL);

public slots:
    void showContour(bool on);
    void showSpectrogram(bool on);
    void printPlot();

private:
    QwtPlotSpectrogram *d_spectrogram;
};


text:
<?php

use yii\helpers\Url;
use dektrium\user\models\User;

$I = new TestGuy($scenario);
$I->wantTo('ensure that confirmation works');

$I->amGoingTo('check that error is showed when token expired');
$user = $I->getFixture('user')->getModel('unconfirmed_with_expired_token');
$I->amOnPage(Url::toRoute(['/user/registration/confirm', 'id' => $user->id, 'token' => $user->confirmation_token]));
$I->see('Confirmation token is invalid');

$I->amGoingTo('check that user get confirmed');
$user = $I->getFixture('user')->getModel('unconfirmed');
$I->amOnPage(Url::toRoute(['/user/registration/confirm', 'id' => $user->id, 'token' => $user->confirmation_token]));
$I->see('Your account has been confirmed');
$I->seeRecord(User::className(), [
    'id' => $user->id,
    'confirmation_token' => null,
    'confirmation_sent_at' => null
]);


text:
package com.facebook.react;

import com.facebook.react.bridge.NativeModule;
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.uimanager.ViewManager;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.ListIterator;
import java.util.Map;
import java.util.Set;
import javax.annotation.Nullable;

/**
 * {@code CompositeReactPackage} allows to create a single package composed of views and modules
 * from several other packages.
 */
public class CompositeReactPackage extends ReactInstancePackage
    implements ViewManagerOnDemandReactPackage {

  private final List<ReactPackage> mChildReactPackages = new ArrayList<>();

  /**
   * The order in which packages are passed matters. It may happen that a NativeModule or
   * or a ViewManager exists in two or more ReactPackages. In that case the latter will win
   * i.e. the latter will overwrite the former. This re-occurrence is detected by
   * comparing a name of a module.
   */
  public CompositeReactPackage(ReactPackage arg1, ReactPackage arg2, ReactPackage... args) {
    mChildReactPackages.add(arg1);
    mChildReactPackages.add(arg2);

    Collections.addAll(mChildReactPackages, args);
  }

  /**
   * {@inheritDoc}
   */
  @Override
  public List<NativeModule> createNativeModules(ReactApplicationContext reactContext) {
    // This is for backward compatibility.
    final Map<String, NativeModule> moduleMap = new HashMap<>();
    for (ReactPackage reactPackage: mChildReactPackages) {
      for (NativeModule nativeModule: reactPackage.createNativeModules(reactContext)) {
        moduleMap.put(nativeModule.getName(), nativeModule);
      }
    }
    return new ArrayList<>(moduleMap.values());
  }

  /**
   * {@inheritDoc}
   */
  @Override
  public List<NativeModule> createNativeModules(
      ReactApplicationContext reactContext,
      ReactInstanceManager reactInstanceManager) {
    final Map<String, NativeModule> moduleMap = new HashMap<>();
    for (ReactPackage reactPackage: mChildReactPackages) {
      List<NativeModule> nativeModules;
      if (reactPackage instanceof ReactInstancePackage) {
        ReactInstancePackage reactInstancePackage = (ReactInstancePackage) reactPackage;
        nativeModules = reactInstancePackage.createNativeModules(
            reactContext,
            reactInstanceManager);
      } else {
        nativeModules = reactPackage.createNativeModules(reactContext);
      }
      for (NativeModule nativeModule: nativeModules) {
        moduleMap.put(nativeModule.getName(), nativeModule);
      }
    }
    return new ArrayList<>(moduleMap.values());
  }

  /**
   * {@inheritDoc}
   */
  @Override
  public List<ViewManager> createViewManagers(ReactApplicationContext reactContext) {
    final Map<String, ViewManager> viewManagerMap = new HashMap<>();
    for (ReactPackage reactPackage: mChildReactPackages) {
      for (ViewManager viewManager: reactPackage.createViewManagers(reactContext)) {
        viewManagerMap.put(viewManager.getName(), viewManager);
      }
    }
    return new ArrayList<>(viewManagerMap.values());
  }

  /** {@inheritDoc} */
  @Override
  public List<String> getViewManagerNames(
      ReactApplicationContext reactContext, boolean loadClasses) {
    Set<String> uniqueNames = new HashSet<>();
    for (ReactPackage reactPackage : mChildReactPackages) {
      if (reactPackage instanceof ViewManagerOnDemandReactPackage) {
        List<String> names =
            ((ViewManagerOnDemandReactPackage) reactPackage)
                .getViewManagerNames(reactContext, loadClasses);
        if (names != null) {
          uniqueNames.addAll(names);
        }
      }
    }
    return new ArrayList<>(uniqueNames);
  }

  /** {@inheritDoc} */
  @Override
  public @Nullable ViewManager createViewManager(
      ReactApplicationContext reactContext, String viewManagerName, boolean loadClasses) {
    ListIterator<ReactPackage> iterator = mChildReactPackages.listIterator(mChildReactPackages.size());
    while (iterator.hasPrevious()) {
      ReactPackage reactPackage = iterator.previous();
      if (reactPackage instanceof ViewManagerOnDemandReactPackage) {
        ViewManager viewManager =
            ((ViewManagerOnDemandReactPackage) reactPackage)
                .createViewManager(reactContext, viewManagerName, loadClasses);
        if (viewManager != null) {
          return viewManager;
        }
      }
    }
    return null;
  }
}


text:
package persist_lib

func Testservice1UnaryExample1Query(tx Runable, req Testservice1UnaryExample1QueryParams) *Result {
	row := tx.QueryRow(
		"SELECT id AS 'table_key', id, value, msg as inner_message, status as inner_enum FROM test_table WHERE id = $1 ",
		req.GetTableId(),
		req.GetStartTime(),
	)
	return newResultFromRow(row)
}
func Testservice1UnaryExample2Query(tx Runable, req Testservice1UnaryExample2QueryParams) *Result {
	row := tx.QueryRow(
		"SELECT id AS 'table_id', key, value, msg as inner_message, status as inner_enum FROM test_table WHERE id = $1 ",
		req.GetId(),
	)
	return newResultFromRow(row)
}
func Testservice1ServerStreamSelectQuery(tx Runable, req Testservice1ServerStreamSelectQueryParams) *Result {
	res, err := tx.Query(
		"SELECT id AS 'table_id', key, value, msg as inner_message, status as inner_enum FROM test_table WHERE id = $1 ",
		req.GetTableId(),
	)
	if err != nil {
		return newResultFromErr(err)
	}
	return newResultFromRows(res)
}
func Testservice1ClientStreamingExampleQuery(tx Runable, req Testservice1ClientStreamingExampleQueryParams) *Result {
	res, err := tx.Exec(
		"SELECT id AS 'table_id', key, value, msg as inner_message, status as inner_enum FROM test_table WHERE id = $1 ",
		req.GetTableId(),
	)
	if err != nil {
		return newResultFromErr(err)
	}
	return newResultFromSqlResult(res)
}

type Testservice1UnaryExample1QueryParams interface {
	GetTableId() int32
	GetStartTime() interface{}
}
type Testservice1UnaryExample2QueryParams interface {
	GetId() int32
}
type Testservice1ServerStreamSelectQueryParams interface {
	GetTableId() int32
}
type Testservice1ClientStreamingExampleQueryParams interface {
	GetTableId() int32
}


text:
from flask_sqlalchemy import SQLAlchemy
from flask_bcrypt import Bcrypt
from sqlalchemy.ext.hybrid import hybrid_property
from sqlalchemy.sql.expression import func
from itsdangerous import (TimedJSONWebSignatureSerializer as Serializer, BadSignature, SignatureExpired)

db = SQLAlchemy()
bcrypt = Bcrypt()

# This is the schema that stores information that is global to all models. As of this writing, that is just users.
GLOBAL_SCHEMA = 'shared'
# The idea here is that there would be a separate 'runs' schema for each model that stores all of the transient
# information about runs (including outputs). This schema is kept separate from the core model schema so that
# the model itself can easily be dumped and restored without dragging all the outputs along. Of course, if
# a Scenario is deleted in the main model during a restore this could cause referential integrity problems
# in the run schema.
RUN_SCHEMA = 'public_runs'

class DemandSector(db.Model):
    __tablename__ = 'DemandSectors'
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.Text)
    # more columns I'm ignoring for now...

class SupplyType(db.Model):
    __tablename__ = 'SupplyTypes'
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.Text)

class DemandSubsector(db.Model):
    __tablename__ = 'DemandSubsectors'
    id = db.Column(db.Integer, primary_key=True)
    sector_id = db.Column(db.ForeignKey(DemandSector.id))
    name = db.Column(db.Text)
    # more columns I'm ignoring for now...

    sector = db.relationship(DemandSector)

    def sector_name(self):
        return self.sector.name

class SupplyNode(db.Model):
    __tablename__ = 'SupplyNodes'
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.Text)
    supply_type_id = db.Column(db.ForeignKey(SupplyType.id))
    # more columns I'm ignoring for now...

    supply_type = db.relationship(SupplyType)

    def supply_type_name(self):
        return self.supply_type.name

class DemandCaseData(db.Model):
    __tablename__ = 'DemandStates'
    id = db.Column(db.Integer, primary_key=True)
    subsector_id = db.Column(db.ForeignKey(DemandSubsector.id))
    description = db.Column(db.Text)
    # more columns I'm ignoring for now...

    subsector = db.relationship(DemandSubsector, backref='demand_case_data')

class SupplyCaseData(db.Model):
    __tablename__ = 'SupplyStates'
    id = db.Column(db.Integer, primary_key=True)
    supply_node_id = db.Column(db.ForeignKey(SupplyNode.id))
    description = db.Column(db.Text)
    # more columns I'm ignoring for now...

    node = db.relationship(SupplyNode, backref='supply_case_data')

class DemandCase(db.Model):
    __tablename__ = 'DemandCases'
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.Text)

    data = db.relationship(DemandCaseData, secondary=lambda: demand_case_demand_case_data, backref='demand_cases')

class SupplyCase(db.Model):
    __tablename__ = 'SupplyCases'
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.Text)

    data = db.relationship(SupplyCaseData, secondary=lambda: supply_case_supply_case_data, backref='supply_cases')

# Join table for many-to-many relationship
demand_case_demand_case_data = db.Table(
    'DemandCasesData',
    db.Model.metadata,
    db.Column('demand_case_id', db.ForeignKey(DemandCase.id)),
    db.Column('demand_state_id', db.ForeignKey(DemandCaseData.id)),
    db.PrimaryKeyConstraint('demand_case_id', 'demand_state_id')
)

# Join table for many-to-many relationship
supply_case_supply_case_data = db.Table(
    'SupplyCasesData',
    db.Model.metadata,
    db.Column('supply_case_id', db.ForeignKey(SupplyCase.id)),
    db.Column('supply_state_id', db.ForeignKey(SupplyCaseData.id)),
    db.PrimaryKeyConstraint('supply_case_id', 'supply_state_id')
)

class Scenario(db.Model):
    __tablename__ = 'Scenarios'
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.Text)
    description = db.Column(db.Text)
    # note the extra table column name here since in the database the columns storing these ids don't end with '_id'
    demand_case_id = db.Column('demand_case', db.ForeignKey(DemandCase.id))
    supply_case_id = db.Column('supply_case', db.ForeignKey(SupplyCase.id))
    user_id = db.Column(db.ForeignKey(GLOBAL_SCHEMA + '.users.id'))

    # Note that the assumption of single_parent here will be true for any scenarios created via the API
    # (because the API creates a new DemandCase and a new SupplyCase for each new scenario) but it may not be true
    # for scenarios manually created in the database (multiple scenarios could share a demand case or supply case)
    # Therefore, trying to use the API (or sqlalchemy in general) to delete a scenario that was created manually
    # in the database could result in a foreign key constraint violation error rather than a successful deletion.
    demand_case = db.relationship(DemandCase, cascade="all, delete-orphan", single_parent=True)
    supply_case = db.relationship(SupplyCase, cascade="all, delete-orphan", single_parent=True)

    # Note that this relies on the runs backref being sorted with most recent first
    @property
    def latest_run(self):
        return self.runs[0] if self.runs else None

    @property
    def status(self):
        if self.latest_run is None:
            # This is a bit of a hack arising from the fact that we want the scenario to have a status even
            # when it has no runs, so we fabricate a fake one. I think it's acceptable but it has a bit of code
            # smell and could probably use revisiting.
            return ScenarioRunStatus(id=ScenarioRunStatus.NEVER_RUN_ID, name='Never run',
                                     description='This scenario has never been run', finished=False)
        else:
            return self.latest_run.status

    def outputs(self):
        if self.successfully_run():
            return self.latest_run.outputs
        else:
            return None

    def basic_outputs(self):
        o = self.outputs()
        return o.filter(Output.output_type_id.in_(OutputType.BASIC_OUTPUT_TYPE_IDS)) if o else None

    # This makes the assumption that a Scenario will have at most one active run at a time, and if it has an active
    # run it will be the most recent run. The API enforces this, but it is possible to manually muck it up in the
    # database.
    def is_running(self):
        return self.latest_run and not self.latest_run.status.finished

    def successfully_run(self):
        return self.latest_run and self.latest_run.status.successful

    def demand_package_group_ids(self):
        return [dcd.id for dcd in self.demand_case.data]

    def supply_package_group_ids(self):
        return [scd.id for scd in self.supply_case.data]

    # Updates the Scenario's Cases' associated DemandCaseData and SupplyCaseData ids to the arrays of integers
    # passed in. Note that this will discard any previously associated DemandCaseData and SupplyCaseData.
    def update_package_group_ids(self, new_demand_package_group_ids, new_supply_package_group_ids):
        self.demand_case.data = DemandCaseData.query.filter(DemandCaseData.id.in_(new_demand_package_group_ids)).all()
        self.supply_case.data = SupplyCaseData.query.filter(SupplyCaseData.id.in_(new_supply_package_group_ids)).all()

    def is_built_in(self):
        # built-in scenarios (which are readable by everybody) have a NULL/None user_id
        return self.user_id is None

    @classmethod
    def built_ins(cls):
        return cls.query.filter_by(user_id=None).all()

    # a helper method to automatically attach an empty DemandCase and SupplyCase to a new scenario
    @classmethod
    def new_with_cases(cls, **kwargs):
        scenario = cls(**kwargs)
        scenario.demand_case = DemandCase(name=scenario.name)
        scenario.supply_case = SupplyCase(name=scenario.name)
        return scenario

# Note: ideally, this and other "system" (universal) tables could be put in the 'shared' schema, but I don't want
# to undertake to move the rest of the system tables right now so I am leaving this in the model run schema
# for consistency.
class ScenarioRunStatus(db.Model):
    __tablename__ = 'scenario_run_statuses'
    __table_args__ = {'schema': RUN_SCHEMA}
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.Text, nullable=False, unique=True)
    description = db.Column(db.Text, nullable=False, unique=True)
    finished = db.Column(db.Boolean, nullable=False)

    NEVER_RUN_ID = 0
    QUEUED_ID = 1
    LAUNCHED_ID = 2
    RUNNING_ID = 3
    SUCCESS_ID = 4
    ERROR_ID = 5
    CANCELED_ID = 6
    LOST_ID = 7

    @property
    def successful(self):
        return self.id == self.SUCCESS_ID

    # This provides a consistent way to set up the contents of the table whether migrating an existing database
    # or setting up a test database. Just do `session.add_all(ScenarioRunStatus.contents())` then commit the session.
    @classmethod
    def contents(cls):
        return [
            cls(id=cls.QUEUED_ID, name='Queued', description='Scenario is awaiting its turn to run', finished=False),
            cls(id=cls.LAUNCHED_ID, name='Launched', description='Scenario run has been initiated', finished=False),
            cls(id=cls.RUNNING_ID, name='Running', description='Scenario is currently running', finished=False),
            cls(id=cls.SUCCESS_ID, name='Success', description='Run finished successfully', finished=True),
            cls(id=cls.ERROR_ID, name='Error', description='Run terminated due to an error', finished=True),
            cls(id=cls.CANCELED_ID, name='Canceled', description='Run was canceled by user', finished=True),
            cls(id=cls.LOST_ID, name='Lost', description='Run terminated for an unknown reason', finished=True)
        ]

class ScenarioRun(db.Model):
    __tablename__ = 'scenario_runs'
    __table_args__ = {'schema': RUN_SCHEMA}
    id = db.Column(db.Integer, primary_key=True)
    scenario_id = db.Column(db.ForeignKey(Scenario.id), nullable=False)
    ready_time = db.Column(db.DateTime(timezone=True), server_default=func.now())
    start_time = db.Column(db.DateTime(timezone=True))
    end_time = db.Column(db.DateTime(timezone=True))
    pathways_version = db.Column(db.Text())
    status_id = db.Column(db.ForeignKey(ScenarioRunStatus.id), server_default='1')
    pid = db.Column(db.Integer())

    scenario = db.relationship(Scenario, backref=db.backref('runs', order_by=ready_time.desc(),
                                                            cascade="all, delete-orphan"))
    status = db.relationship(ScenarioRunStatus)

# Note that this table is stored in a "global" schema separate from other model content, in anticipation of a future
# where the same set of users will have access to multiple models, each stored in their own schema
class User(db.Model):
    __tablename__ = 'users'
    __table_args__ = {'schema': GLOBAL_SCHEMA}

    id = db.Column(db.Integer, primary_key=True)
    email = db.Column(db.Text, nullable=False, unique=True)
    name = db.Column(db.Text, nullable=False, unique=True)
    password_hash = db.Column(db.Text, nullable=False)
    admin = db.Column(db.Boolean, server_default='false')

    scenarios = db.relationship(Scenario, backref='user')

    # A scenario is readable by a user if any of the following are true:
    # 1. The scenario is owned by the user
    # 2. The scenario is "built in" (owned by no user)
    # 3. The user is an admin (and can therefore read all scenarios)
    readable_scenarios = db.relationship(Scenario, primaryjoin=db.or_(id == Scenario.user_id,
                                                                      Scenario.user_id == None,
                                                                      admin == True))

    # Basic recipe for password hashing and checking is from http://exploreflask.readthedocs.io/en/latest/users.html
    @hybrid_property
    def password(self):
        return self.password_hash

    @password.setter
    def _set_password(self, plaintext):
        self.password_hash = bcrypt.generate_password_hash(plaintext)

    def is_correct_password(self, plaintext):
        return bcrypt.check_password_hash(self.password_hash, plaintext)

    def generate_auth_token(self, secret_key, expiration=86400):
        s = Serializer(secret_key, expires_in=expiration)
        return s.dumps({'id': self.id})

    @staticmethod
    def verify_auth_token(token, secret_key):
        s = Serializer(secret_key)
        try:
            data = s.loads(token)
        except SignatureExpired:
            return None  # valid token, but expired
        except BadSignature:
            return None  # invalid token
        user = User.query.get(data['id'])
        return user

    def owns_scenario(self, scenario):
        # the check for not None here may be a little paranoid, but since "built-in" scenarios will have a None
        # user.id, we want to make sure we haven't passed in something that will accidentally match by virtue of
        # incorrectly having an empty id field
        return (self.id is not None and self.id == scenario.user_id) or self.admin

    def can_read_scenario(self, scenario):
        return scenario.is_built_in() or self.owns_scenario(scenario)

    def is_guest(self):
        return False

# Guest mimics User's interface for determining whether access to a given scenario should be allowed, but is not
# actually a User, so can't do anything *too* dangerous. Polymorphism!
class Guest(object):
    def owns_scenario(self, *args):
        return False

    def can_read_scenario(self, scenario):
        return scenario.is_built_in()

    @property
    def readable_scenarios(self):
        return Scenario.built_ins()

    def is_guest(self):
        return True

class OutputType(db.Model):
    __tablename__ = 'output_types'
    __table_args__ = {'schema': RUN_SCHEMA}

    # These are the ids of the "basic" ouptut type ids; that is, those we want to show on the list of scenarios page.
    # See contents() below for which types these refer to.
    BASIC_OUTPUT_TYPE_IDS = [1, 3]

    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.Text, nullable=False, unique=True)

    # This provides a consistent way to set up the contents of the table whether migrating an existing database
    # or setting up a test database. Just do `session.add_all(OutputType.contents())` then commit the session.
    @classmethod
    def contents(cls):
        return [
                cls(id=1, name='Levelized cost'),
                cls(id=2, name='Energy demand by sector'),
                cls(id=3, name='Emissions by sector'),
                cls(id=4, name='Emissions per capita'),
                cls(id=5, name='Electricity supply by type'),
                cls(id=6, name='Residential energy by fuel type'),
                cls(id=7, name='Residential emissions by fuel type'),
                cls(id=8, name='Commercial energy by fuel type'),
                cls(id=9, name='Commercial emissions by fuel type'),
                cls(id=10, name='Transportation energy by fuel type'),
                cls(id=11, name='Transportation emissions by fuel type'),
                cls(id=12, name='Industrial energy by fuel type'),
                cls(id=13, name='Industrial emissions by fuel type')
        ]

class Output(db.Model):
    __tablename__ = 'outputs'
    __table_args__ = {'schema': RUN_SCHEMA}

    id = db.Column(db.Integer, primary_key=True)
    scenario_run_id = db.Column(db.ForeignKey(ScenarioRun.id))
    output_type_id = db.Column(db.ForeignKey(OutputType.id))
    unit = db.Column(db.Text())

    scenario_run = db.relationship(ScenarioRun, backref=db.backref('outputs', lazy='dynamic',
                                                                   cascade="all, delete-orphan"))
    output_type = db.relationship(OutputType)

    @property
    def output_type_name(self):
        return self.output_type.name

class OutputData(db.Model):
    __tablename__ = 'output_data'
    __table_args__ = {'schema': RUN_SCHEMA}

    id = db.Column(db.Integer, primary_key=True)
    parent_id = db.Column(db.ForeignKey(Output.id))
    series = db.Column(db.Text())
    year = db.Column(db.Integer())
    value = db.Column(db.Float())

    output = db.relationship(Output, backref=db.backref('data', order_by=[series, year], cascade="all, delete-orphan"))


text:
<?xml version="1.0" encoding="utf-8"?>
<!--

-->
<LinearLayout
        xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:orientation="horizontal"
        style="?attr/miniKeyboardPanelStyle"
        >
    <com.android.inputmethod.latin.MoreSuggestionsView
            xmlns:latin="http://schemas.android.com/apk/res/com.android.s16.inputmethod"
            android:id="@+id/more_suggestions_view"
            android:layout_alignParentBottom="true"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            latin:keyLabelSize="@dimen/suggestion_text_size"
            latin:keyHintLetterRatio="@fraction/more_suggestions_info_ratio"
            latin:keyHintLetterColor="@android:color/white"
            />
</LinearLayout>


text:
module.exports = {
  extends: 'exponent/react',
};