/** * JWave - Java implementation of wavelet transform algorithms * * Copyright 2010-2012 Christian Scheiblich * * Licensed 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. * * This file BlockIndex.java is part of JWave. * * @author Christian Scheiblich * date 12.06.2011 23:45:37 * contact graetz@mailfish.de */ package math.transform.jwave.blocks; import java.util.ArrayList; import math.transform.jwave.blocks.exc.BlockError; import math.transform.jwave.blocks.exc.BlockException; import math.transform.jwave.blocks.exc.BlockFailure; /** * A block that stores given data sparse to reduce memory costs. * * @date 12.06.2011 23:45:37 * @author Christian Scheiblich */ public class BlockIndex extends Block { /** * Array for storing the row indices of values. */ ArrayList< Integer > _arrI; /** * Array for storing the column indices of values. */ ArrayList< Integer > _arrJ; /** * Array for storing values. */ ArrayList< Double > _arrVal; /** * Constructor taking position and dimension. * * @date 12.06.2011 23:45:37 * @author Christian Scheiblich * @see math.transform.jwave.blocks.Block#Block(int, int, int, int) */ public BlockIndex( int offSetRow, int offSetCol, int noOfRows, int noOfCols ) throws BlockException { super( offSetRow, offSetCol, noOfRows, noOfCols ); } /** * Returns either 0 if there is no value stored for the pair (i,j) or the * value stored for the pair (i,j). * * @date 12.06.2011 23:45:37 * @author Christian Scheiblich * @see math.transform.jwave.blocks.Block#get(int, int) */ @Override public double get( int i, int j ) throws BlockException { if( !isMemAllocated( ) ) throw new BlockFailure( "BlockIndex#get -- memory is not allocted" ); boolean isOccupied = false; try { isOccupied = isOccupied( i, j ); } catch( BlockException blockException ) { String exceptionMsg = blockException.getMessage( ); throw new BlockFailure( "BlockIndex#get -- " + exceptionMsg ); } double val = 0.; if( isOccupied ) { int pos = getOccupiedInternalArrayIndices( i, j ); val = _arrVal.get( pos ); } return val; } /** * Returns a complete matrix filled by zeros and the entries stored at pairs * (i,j). * * @date 12.06.2011 23:45:37 * @author Christian Scheiblich * @see math.transform.jwave.blocks.Block#get() */ @Override public double[ ][ ] get( ) throws BlockException { double[ ][ ] matrix = new double[ _noOfRows ][ _noOfCols ]; int noOf = _arrVal.size( ); for( int p = 0; p < noOf; p++ ) matrix[ _arrI.get( p ) ][ _arrJ.get( p ) ] = _arrVal.get( p ); return matrix; } /** * Add an entry to the array lists by extending those. * * @date 12.06.2011 23:45:37 * @author Christian Scheiblich * @see math.transform.jwave.blocks.Block#set(int, int, double) */ @Override public void set( int i, int j, double val ) throws BlockException { if( !isMemAllocated( ) ) throw new BlockFailure( "BlockIndex#set -- memory is not allocted" ); boolean isOccupied = false; try { isOccupied = isOccupied( i, j ); } catch( BlockException blockException ) { String exceptionMsg = blockException.getMessage( ); throw new BlockFailure( "BlockIndex#set -- " + exceptionMsg ); } if( !isOccupied ) { _arrI.add( i ); _arrJ.add( j ); _arrVal.add( val ); } else { int pos = getOccupiedInternalArrayIndices( i, j ); _arrI.set( pos, i ); _arrJ.set( pos, j ); _arrVal.set( pos, val ); } // if } /** * Allocated memory for the index block as extendible array lists. * * @date 12.06.2011 23:45:37 * @author Christian Scheiblich * @see math.transform.jwave.blocks.Block#allocateMemory() */ @Override public void allocateMemory( ) throws BlockException { _arrI = new ArrayList< Integer >( ); _arrJ = new ArrayList< Integer >( ); _arrVal = new ArrayList< Double >( ); _isMemAllocated = true; } /** * Erase the allocated memory by setting null pointers. * * @date 12.06.2011 23:45:37 * @author Christian Scheiblich * @see math.transform.jwave.blocks.Block#eraseMemory() */ @Override public void eraseMemory( ) throws BlockException { _arrI = null; _arrJ = null; _arrVal = null; _isMemAllocated = false; } /** * Checks if a given pair is already stored in the Block. * * @date 13.06.2011 14:44:54 * @author Christian Scheiblich * @param i * local index for rows * @param j * local index for columns * @return false if pair (i,j) is not stored yet other wise if pair (i,j) is * stored true * @throws BlockException * if indices are negative or out of bound or no memory is * allocated. */ private boolean isOccupied( int i, int j ) throws BlockException { if( !isMemAllocated( ) ) throw new BlockFailure( "BlockIndex#isOccupied -- memory is not allocted" ); try { checkIndices( i, j ); // check for correct indices } catch( BlockException blockException ) { String exceptionMsg = blockException.getMessage( ); throw new BlockFailure( "BlockIndex#isOccupied -- " + exceptionMsg ); } boolean isOccupied = false; int noOfIndicesI = _arrI.size( ); int noOfIndicesJ = _arrJ.size( ); if( noOfIndicesI != noOfIndicesJ ) throw new BlockError( "BlockIndex#isOccupied -- something wicked happend to internal sizes" ); for( int p = 0; p < noOfIndicesI; p++ ) if( i == _arrI.get( p ) && j == _arrJ.get( p ) ) isOccupied = true; return isOccupied; } /** * Searches and returns the internal index for both array lists for a * requested pair of indices. * * @date 13.06.2011 15:31:47 * @author Christian Scheiblich * @param i * local index for rows * @param j * local index for columns * @return an integer displaying the internal index of both array lists * @throws BlockException * if given pair (i,j) is negative or out of bound or non memory is * allocated. */ private int getOccupiedInternalArrayIndices( int i, int j ) throws BlockException { if( !isMemAllocated( ) ) throw new BlockFailure( "BlockIndex#getOccupiedInternalArrayIndices -- memory is not allocted" ); try { checkIndices( i, j ); // check for correct indices } catch( BlockException blockException ) { String exceptionMsg = blockException.getMessage( ); throw new BlockFailure( "BlockIndex#getOccupiedIndexRow -- " + exceptionMsg ); } int p = 0; boolean isFound = false; while( !isFound && p < _arrI.size( ) ) { if( i == _arrI.get( p ) ) { if( j == _arrJ.get( p ) ) isFound = true; } // if p++; } // whiles if( isFound ) { if( p > 0 ) p--; } else p = -1; return p; } } // class