Example usage for java.nio DoubleBuffer position

List of usage examples for java.nio DoubleBuffer position

Introduction

In this page you can find the example usage for java.nio DoubleBuffer position.

Prototype

public final Buffer position(int newPosition) 

Source Link

Document

Sets the position of this buffer.

Usage

From source file:org.mitre.math.linear.BufferRealMatrix.java

/**
 * Returns the result of postmultiplying this by m.
 *
 * @param m    matrix to postmultiply by
 * @return     this * m// w  w w  .j av  a 2s . c o  m
 * @throws     IllegalArgumentException
 *             if columnDimension(this) != rowDimension(m)
 */
public BufferRealMatrix multiply(final BufferRealMatrix b) throws IllegalArgumentException {

    // safety check
    MatrixUtils.checkMultiplicationCompatible(this, b);

    try {
        final BufferRealMatrix c = new BufferRealMatrix(rows, b.columns, null);
        // allocate one row for our matrix
        final ByteBuffer abb = ByteBuffer.allocate(BLOCK_SIZE * DOUBLE_BYTE_SIZE);
        // for some funny reason we can't get an array, even if we wrap it before! So, allocate it here and use latter
        //  final double[] ar = new double[BLOCK_SIZE]; This isn't faster

        // perform multiplication block-wise, to ensure good cache behavior
        int blockIndex = 0;
        for (int iBlock = 0; iBlock < c.blockRows; ++iBlock) {
            final int pStart = iBlock * BLOCK_SIZE;
            final int pEnd = Math.min(pStart + BLOCK_SIZE, rows);
            //System.err.printf("pStart=%d\tpEnd=%d\tblockRows=%d\tblockColumns=%d\n", pStart, pEnd, c.blockRows, c.blockColumns);
            for (int jBlock = 0; jBlock < c.blockColumns; ++jBlock) {
                final int jWidth = BLOCK_SIZE; // square block no matter what
                final int jWidth2 = jWidth + jWidth;
                final int jWidth3 = jWidth2 + jWidth;
                final int jWidth4 = jWidth3 + jWidth;

                // select current product block
                DoubleBuffer cdb = c.dataFileChannel
                        .map(FileChannel.MapMode.READ_WRITE, c.getBlockOffset(blockIndex), BLOCK_BYTE_SIZE)
                        .asDoubleBuffer();
                cdb.clear();

                // perform multiplication on current block
                for (int kBlock = 0; kBlock < blockColumns; ++kBlock) {
                    //final int kWidth = blockWidth(kBlock);
                    final int kWidth = BLOCK_SIZE;

                    LOG.debug(String.format("Getting a block %d and b block %d", iBlock * blockColumns + kBlock,
                            kBlock * b.blockColumns + jBlock));

                    // walk down the blocks columns
                    DoubleBuffer bdb = b.dataFileChannel
                            .map(FileChannel.MapMode.READ_WRITE,
                                    b.getBlockOffset(kBlock * b.blockColumns + jBlock), BLOCK_BYTE_SIZE)
                            .asDoubleBuffer();
                    bdb.clear();

                    LOG.debug("Processing blocks");
                    for (int p = pStart, k = 0; p < pEnd; ++p) {
                        // a's width (# cols) is the same as b's height (# rows) and c's width
                        final int lStart = (p - pStart) * kWidth; // Square padded with zeros    
                        final int lEnd = blockWidth(kBlock); // Can stop at the last column in a's block
                        //System.err.printf("k=%d\tp=%d\tlstart=%d\tlend=%d\t\n", k, p, lStart, lEnd);
                        // For each row in a, multiple the columns in b
                        // Can stop at the last column in the c's block which should be the last column in b

                        // walk across A's blocks rows grabbing a row at a time
                        abb.clear();
                        this.dataFileChannel.position(this.getBlockOffset(iBlock * blockColumns + kBlock)
                                + (lStart * DOUBLE_BYTE_SIZE));
                        final int r = this.dataFileChannel.read(abb); // relative get into local bytebuffer
                        //System.err.printf("Got %d bytes (%d doubles) for %d block width\n", r, r / DOUBLE_BYTE_SIZE, kWidth);
                        if (r == -1) {
                            LOG.fatal("Unable to read in data");
                        }
                        abb.clear();
                        final DoubleBuffer adb = abb.asDoubleBuffer();
                        adb.clear();
                        // tried getting access to local copy (array) but it wasn't faster access

                        for (int nStart = 0; nStart < c.blockWidth(jBlock); ++nStart) {
                            double sum = 0;
                            int l = 0; // first column in this row
                            int n = nStart;
                            // do four at a time (why four?)
                            adb.position(l);

                            while (l < lEnd - 3) {
                                sum += adb.get() * bdb.get(n) + adb.get() * bdb.get(n + jWidth)
                                        + adb.get() * bdb.get(n + jWidth2) + adb.get() * bdb.get(n + jWidth3);
                                l += 4;
                                n += jWidth4;
                            }
                            while (l < lEnd) {
                                sum += adb.get() * bdb.get(n);
                                n += jWidth;
                                l++;
                            }
                            sum += cdb.get(k);
                            cdb.put(k++, sum);
                            //System.err.printf("k=%d\tn=%d\n", k, n);
                        }
                        // correct k for difference in blockWidth since we are always square
                        k = (p + 1) * BLOCK_SIZE;
                        //System.err.printf("end of p-loop (%d), k=%d\n", p, k);
                    }
                }
                this.dataFileChannel.force(false);
                System.err.printf("Finished block %d\n", blockIndex);
                // go to next block
                ++blockIndex;
            }
        }
        return c;
    } catch (IOException ex) {
        throw new IllegalArgumentException(ex.getMessage());
    }
}