You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
249 lines
6.8 KiB
249 lines
6.8 KiB
/***************************************************************************
|
|
ksmatrixmat.cpp
|
|
-------------------
|
|
begin : 01-January-2000
|
|
copyright : (C) 2000 by Kamil Dobkowski
|
|
email : kamildobk@poczta.onet.pl
|
|
***************************************************************************/
|
|
|
|
/***************************************************************************
|
|
* *
|
|
* This program is free software; you can redistribute it and/or modify *
|
|
* it under the terms of the GNU General Public License as published by *
|
|
* the Free Software Foundation; either version 2 of the License, or *
|
|
* (at your option) any later version. *
|
|
* *
|
|
***************************************************************************/
|
|
|
|
|
|
#include"ksmatrixmat.h"
|
|
#include<memory>
|
|
|
|
//-------------------------------------------------------------------------//
|
|
|
|
KSMatrixMAT::KSMatrixMAT()
|
|
{
|
|
}
|
|
|
|
|
|
//-------------------------------------------------------------------------//
|
|
|
|
KSMatrixMAT::~KSMatrixMAT()
|
|
{
|
|
}
|
|
|
|
//-------------------------------------------------------------------------//
|
|
|
|
bool KSMatrixMAT::check( QDataStream &is )
|
|
// Filename isn't interesing but should be "*.mat"
|
|
// Check the first header in a stream
|
|
{
|
|
KSMatrix *h = read_header(is);
|
|
if ( !h ) return false;
|
|
delete h;
|
|
return true;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------//
|
|
|
|
KSHeadersList *KSMatrixMAT::headers( QDataStream& is )
|
|
{
|
|
KSHeadersList *result = new KSHeadersList();
|
|
|
|
while ( !is.atEnd() ) {
|
|
int data_size;
|
|
// read header
|
|
KSMatrix *hdr = read_header( is, NULL, NULL, &data_size );
|
|
// end of header list
|
|
if ( !hdr ) break;
|
|
// add it to the list
|
|
result->push_back( hdr );
|
|
// skip next header.size bytes
|
|
is.device()->at( is.device()->at()+data_size );
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
//-------------------------------------------------------------------------//
|
|
|
|
KSMatrix *KSMatrixMAT::load( QDataStream& is, const QString& matrixname )
|
|
{
|
|
auto_ptr<KSMatrix> m;
|
|
bool swap;
|
|
int esize;
|
|
int dsize;
|
|
|
|
while ( !is.atEnd() ) {
|
|
// read header
|
|
auto_ptr<KSMatrix> h(read_header( is, &swap, &esize, &dsize ));
|
|
// Check whether we found matrix, we have been looking for.
|
|
if ( h->name() == matrixname ) { m = h; break; }
|
|
// skip bytes to the next header
|
|
is.device()->at( is.device()->at()+dsize );
|
|
// this is not the header we are looking for, delete it
|
|
}
|
|
|
|
if ( is.atEnd() ) return NULL;
|
|
|
|
int enumb = m->cols()*m->rows();
|
|
int estep = enumb / 20 + 1;
|
|
int ecurr = 0;
|
|
|
|
// alloc data, that will be managed by this object
|
|
// remember that header has data set to NULL while rows and cols are sot to non-zero
|
|
int rows = m->rows();
|
|
int cols = m->cols();
|
|
m->resize( 0, 0 );
|
|
m->resize( rows, cols );
|
|
|
|
for( int i=0; i<m->cols(); i++ )
|
|
for( int j=0; j<m->rows(); j++ ) {
|
|
// calculate a pointer to memory
|
|
void *ptr = (char*)m->ptr() + j*m->lo() + i*m->po(); // + part*esize;
|
|
// read esize bytes in binary format, directly to memory
|
|
if ( is.readRawBytes((char*)ptr,esize).device()->status() != IO_Ok ) return NULL;
|
|
// if endian ordering is different - swap bytes
|
|
if ( swap ) swap_bytes( ptr, esize );
|
|
}
|
|
return m.release();
|
|
}
|
|
|
|
//-------------------------------------------------------------------------//
|
|
|
|
KSMatrix *KSMatrixMAT::read_header( QDataStream& is, bool *swap_ptr, int *esize_ptr, int *data_size_ptr )
|
|
{
|
|
Header header;
|
|
Flags flags;
|
|
|
|
bool swap = false;
|
|
|
|
is.readRawBytes((char*)&header.type, 4);
|
|
is.readRawBytes((char*)&header.mrows, 4);
|
|
is.readRawBytes((char*)&header.ncols, 4);
|
|
is.readRawBytes((char*)&header.imagf, 4);
|
|
is.readRawBytes((char*)&header.namlen, 4);
|
|
|
|
if ( is.device()->status() != IO_Ok ) return NULL;
|
|
|
|
// If 'type' is nonzero and the byte order is swapped, 'type' will be
|
|
// bigger than we expect, so we swap bytes.
|
|
//
|
|
// If 'type' is zero, it means the file was written on a little endian
|
|
// machine, and we only need to swap if we are running on a big endian
|
|
// machine.
|
|
//
|
|
int type = header.type;
|
|
|
|
#if defined WORDS_BIGENDIAN
|
|
if ( type == 0 ) swap = true;
|
|
#endif
|
|
|
|
if ( type < 0 || type > 9999 ) swap = true;
|
|
|
|
if ( swap ) {
|
|
swap_bytes( &header.type, 4 );
|
|
swap_bytes( &header.mrows, 4 );
|
|
swap_bytes( &header.ncols, 4 );
|
|
swap_bytes( &header.imagf, 4 );
|
|
swap_bytes( &header.namlen, 4 );
|
|
}
|
|
|
|
if ( header.type < 0 ||
|
|
header.type > 4052 ||
|
|
header.imagf > 1 ||
|
|
header.imagf < 0 ) return NULL;
|
|
|
|
type = header.type;
|
|
|
|
flags.T = TypeT(type % 10); type /= 10;
|
|
flags.P = TypeP(type % 10); type /= 10;
|
|
flags.O = TypeO(type % 10); type /= 10;
|
|
flags.M = TypeM(type % 10);
|
|
|
|
if ( flags.M == VAX_D_FLOAT ||
|
|
flags.M == VAX_G_FLOAT ||
|
|
flags.M == CRAY ||
|
|
flags.T == TEXT ||
|
|
flags.T == SPARSE) return NULL;
|
|
|
|
// Create output matrix
|
|
|
|
EType etype;
|
|
switch( flags.P ) {
|
|
case E_DOUBLE: etype = EDouble; break;
|
|
case E_FLOAT: etype = EFloat; break;
|
|
case E_INTEGER: etype = ELong; break;
|
|
case E_SHORT: etype = EShort; break;
|
|
case E_USHORT: etype = EUShort; break;
|
|
case E_UCHAR: etype = EUChar; break;
|
|
default: return NULL;
|
|
}
|
|
|
|
auto_ptr<KSMatrix> result( KSMatrix::create(etype) );
|
|
QCString name( header.namlen );
|
|
is.readRawBytes( name.data(), header.namlen );
|
|
result->setName( name );
|
|
|
|
int esize = result->elementSize();
|
|
int elementOffset = esize * (header.imagf?2:1);
|
|
int lineOffset = elementOffset * header.ncols;
|
|
int dataSize = lineOffset * header.mrows;
|
|
result->setRawData( NULL, header.mrows, header.ncols, false );
|
|
|
|
if ( esize_ptr ) *esize_ptr = esize;
|
|
if ( swap_ptr ) *swap_ptr = swap;
|
|
if ( data_size_ptr ) *data_size_ptr = dataSize;
|
|
return result.release();
|
|
}
|
|
|
|
//-------------------------------------------------------------------------//
|
|
|
|
void KSMatrixMAT::swap_bytes( void *adr, unsigned int len )
|
|
// But, but What is it ?!
|
|
// Swap 'len' bytes at the pointer 'adr'
|
|
{
|
|
unsigned int i; char *ptr;
|
|
for( ptr=static_cast<char *>(adr), i=0; i < len>>1; i++ ) {
|
|
char temp = ptr[i]; ptr[i] = ptr[len-i-1]; ptr[len-i-1] = temp;
|
|
}
|
|
}
|
|
|
|
//-------------------------------------------------------------------------//
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|