nd4j-backends/nd4j-api-parent/nd4j-api/src/main/java/org/nd4j/linalg/factory/BaseNDArrayFactory.java
@Override
    public INDArray concat(int dimension, INDArray... toConcat) {
        if (toConcat.length == 1)
            return toConcat[0];
        int sumAlongDim = 0;
        boolean allC = toConcat[0].ordering() == 'c';

        long[] outputShape = ArrayUtil.copy(toConcat[0].shape());
        outputShape[dimension] = sumAlongDim;

        for (int i = 0; i < toConcat.length; i++) {
            sumAlongDim += toConcat[i].size(dimension);
            allC = allC && toConcat[i].ordering() == 'c';
            for (int j = 0; j < toConcat[i].rank(); j++) {
                if (j != dimension && toConcat[i].size(j) != outputShape[j] && !toConcat[i].isVector()) {
                    throw new IllegalArgumentException(
                                    "Illegal concatenation at array " + i + " and shape element " + j);
                }
            }
        }



        long[] sortedStrides = Nd4j.getStrides(outputShape);

        INDArray ret = Nd4j.create(outputShape, sortedStrides);
        allC &= (ret.ordering() == 'c');

        if (toConcat[0].isScalar()) {
            INDArray retLinear = ret.linearView();
            for (int i = 0; i < retLinear.length(); i++)
                retLinear.putScalar(i, toConcat[i].getDouble(0));
            return ret;
        }



        if (dimension == 0 && allC) {
            int currBuffer = 0;
            int currBufferOffset = 0;
            for (int i = 0; i < ret.length(); i++) {
                ret.data().put(i, toConcat[currBuffer].data()
                                .getDouble(toConcat[currBuffer].offset() + currBufferOffset++));
                if (currBufferOffset >= toConcat[currBuffer].length()) {
                    currBuffer++;
                    currBufferOffset = 0;
                }
            }

            return ret;
        }

        int arrOffset = 0;

        // FIXME: int cast

        INDArray[] retAlongDimensionArrays = new INDArray[(int) ret.tensorssAlongDimension(dimension)];
        for (int i = 0; i < retAlongDimensionArrays.length; i++)
            retAlongDimensionArrays[i] = ret.tensorAlongDimension(i, dimension);

        for (INDArray arr : toConcat) {
            long arrTensorLength = -1;

            if (arr.tensorssAlongDimension(dimension) != ret.tensorssAlongDimension(dimension))
                throw new IllegalStateException("Illegal concatenate. Tensors along dimension must be same length.");


            for (int i = 0; i < arr.tensorssAlongDimension(dimension); i++) {
                INDArray retLinear = retAlongDimensionArrays[i];
                INDArray arrTensor = arr.tensorAlongDimension(i, dimension);

                arrTensorLength = arrTensor.length();
                for (int j = 0; j < arrTensor.length(); j++) {
                    int idx = j + arrOffset;
                    retLinear.putScalar(idx, arrTensor.getDouble(j));
                }
            }

            //bump the sliding window
            arrOffset += arrTensorLength;

        }

        return ret;

    }
@Override
    public INDArray concat(int dimension, INDArray... toConcat) {
        if (toConcat.length == 1)
            return toConcat[0];
        int sumAlongDim = 0;
        boolean allC = toConcat[0].ordering() == 'c';

        long[] outputShape = ArrayUtil.copy(toConcat[0].shape());
        outputShape[dimension] = sumAlongDim;

        for (int i = 0; i < toConcat.length; i++) {
            sumAlongDim += toConcat[i].size(dimension);
            allC = allC && toConcat[i].ordering() == 'c';
            for (int j = 0; j < toConcat[i].rank(); j++) {
                if (j != dimension && toConcat[i].size(j) != outputShape[j] && !toConcat[i].isVector()) {
                    throw new IllegalArgumentException(
                                    "Illegal concatenation at array " + i + " and shape element " + j);
                }
            }
        }



        long[] sortedStrides = Nd4j.getStrides(outputShape);

        INDArray ret = Nd4j.create(outputShape, sortedStrides);
        allC &= (ret.ordering() == 'c');

        if (toConcat[0].isScalar()) {
            INDArray retLinear = ret.linearView();
            for (int i = 0; i < retLinear.length(); i++)
                retLinear.putScalar(i, toConcat[i].getDouble(0));
            return ret;
        }



        if (dimension == 0 && allC) {
            int currBuffer = 0;
            int currBufferOffset = 0;
            for (int i = 0; i < ret.length(); i++) {
                ret.data().put(i, toConcat[currBuffer].data()
                                .getDouble(toConcat[currBuffer].offset() + currBufferOffset++));
                if (currBufferOffset >= toConcat[currBuffer].length()) {
                    currBuffer++;
                    currBufferOffset = 0;
                }
            }

            return ret;
        }

        int arrOffset = 0;

        // FIXME: int cast

        INDArray[] retAlongDimensionArrays = new INDArray[(int) ret.tensorssAlongDimension(dimension)];
        for (int i = 0; i < retAlongDimensionArrays.length; i++)
            retAlongDimensionArrays[i] = ret.tensorAlongDimension(i, dimension);

        for (INDArray arr : toConcat) {
            long arrTensorLength = -1;

            if (arr.tensorssAlongDimension(dimension) != ret.tensorssAlongDimension(dimension))
                throw new IllegalStateException("Illegal concatenate. Tensors along dimension must be same length.");


            for (int i = 0; i < arr.tensorssAlongDimension(dimension); i++) {
                INDArray retLinear = retAlongDimensionArrays[i];
                INDArray arrTensor = arr.tensorAlongDimension(i, dimension);

                arrTensorLength = arrTensor.length();
                for (int j = 0; j < arrTensor.length(); j++) {
                    int idx = j + arrOffset;
                    retLinear.putScalar(idx, arrTensor.getDouble(j));
                }
            }

            //bump the sliding window
            arrOffset += arrTensorLength;

        }

        return ret;

    }
@ Override public INDArray concat ( int dimension , INDArray ... toConcat ) { if ( toConcat . length == 1 ) return toConcat [ 0 ] ; int sumAlongDim = 0 ; boolean allC = toConcat [ 0 ] . ordering ( ) == ' ' ; long [ ] outputShape = ArrayUtil . copy ( toConcat [ 0 ] . shape ( ) ) ; outputShape [ dimension ] = sumAlongDim ; for ( int i = 0 ; i < toConcat . length ; i ++ ) { sumAlongDim += toConcat [ i ] . size ( dimension ) ; allC = allC && toConcat [ i ] . ordering ( ) == ' ' ; for ( int j = 0 ; j < toConcat [ i ] . rank ( ) ; j ++ ) { if ( j != dimension && toConcat [ i ] . size ( j ) != outputShape [ j ] && ! toConcat [ i ] . isVector ( ) ) { throw new IllegalArgumentException ( "Illegal concatenation at array " + i + " and shape element " + j ) ; } } } long [ ] sortedStrides = Nd4j . getStrides ( outputShape ) ; INDArray ret = Nd4j . create ( outputShape , sortedStrides ) ; allC &= ( ret . ordering ( ) == ' ' ) ; if ( toConcat [ 0 ] . isScalar ( ) ) { INDArray retLinear = ret . linearView ( ) ; for ( int i = 0 ; i < retLinear . length ( ) ; i ++ ) retLinear . putScalar ( i , toConcat [ i ] . getDouble ( 0 ) ) ; return ret ; } if ( dimension == 0 && allC ) { int currBuffer = 0 ; int currBufferOffset = 0 ; for ( int i = 0 ; i < ret . length ( ) ; i ++ ) { ret . data ( ) . put ( i , toConcat [ currBuffer ] . data ( ) . getDouble ( toConcat [ currBuffer ] . offset ( ) + currBufferOffset ++ ) ) ; if ( currBufferOffset >= toConcat [ currBuffer ] . length ( ) ) { currBuffer ++ ; currBufferOffset = 0 ; } } return ret ; } int arrOffset = 0 ; // FIXME: int cast INDArray [ ] retAlongDimensionArrays = new INDArray [ ( int ) ret . tensorssAlongDimension ( dimension ) ] ; for ( int i = 0 ; i < retAlongDimensionArrays . length ; i ++ ) retAlongDimensionArrays [ i ] = ret . tensorAlongDimension ( i , dimension ) ; for ( INDArray arr : toConcat ) { long arrTensorLength = - 1 ; if ( arr . tensorssAlongDimension ( dimension ) != ret . tensorssAlongDimension ( dimension ) ) throw new IllegalStateException ( "Illegal concatenate. Tensors along dimension must be same length." ) ; for ( int i = 0 ; i < arr . tensorssAlongDimension ( dimension ) ; i ++ ) { INDArray retLinear = retAlongDimensionArrays [ i ] ; INDArray arrTensor = arr . tensorAlongDimension ( i , dimension ) ; arrTensorLength = arrTensor . length ( ) ; for ( int j = 0 ; j < arrTensor . length ( ) ; j ++ ) { int idx = j + arrOffset ; retLinear . putScalar ( idx , arrTensor . getDouble ( j ) ) ; } } //bump the sliding window arrOffset += arrTensorLength ; } return ret ; }
concatenate ndarrays along a dimension

@param dimension the dimension to concatenate along
@param toConcat  the ndarrays to concatenate
@return the concatenate ndarrays
concatenate ndarrays along a dimension