Skip to content

Commit

Permalink
move mex to private/, zmat.m can pre/post process, accept nd-array an…
Browse files Browse the repository at this point in the history
…d logical, can restore array size/type
  • Loading branch information
fangq committed Jul 11, 2019
1 parent 0412419 commit 177ed52
Show file tree
Hide file tree
Showing 5 changed files with 80 additions and 27 deletions.
16 changes: 9 additions & 7 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -21,15 +21,17 @@ Introduction

ZMat is a portable mex function to enable zlib/gzip/lzma/lzip based
data compression/decompression and base64 encoding/decoding support
in MATLAB and GNU Octave. It is fast and portable, can compress a
in MATLAB and GNU Octave. It is fast and portable, can process a
large array within a fraction of a second.

ZMat accepts 3 types of inputs: char-based strings, uint8 arrays
or vectors, or int8 arrays/vectors. Any other input format will
ZMat accepts 3 types of inputs: char-based strings, numerical arrays
or vectors, or logical arrays/vectors. Any other input format will
result in an error unless you typecast the input into int8/uint8
format. A multi-dimensional char/int8/uint8 array is accepeted
but will be processed as a 1D vector. One can reshape the output
after decoding using the 2nd output "info" from zmat.
format. A multi-dimensional numerical array is accepeted, and the
original input's type/dimension info is stored in the 2nd output
"info". If one calls zmat with both the encoded data (in byte vector)
and the "info" structure, zmat will attempts to restore the original
input's type and size after decoding.

ZMat uses zlib - an open-source and widely used library for data
compression. On Linux/Mac OSX, you need to have libz.so or libz.dylib
Expand Down Expand Up @@ -83,7 +85,7 @@ you need to edit is ~/.octaverc , where "~" is your home directory.
Using ZMat
================

ZMat provides a single mex function, zmat.mex* -- for both compressing/encoding
ZMat provides a single mex function, zipmat.mex* -- for both compressing/encoding
or decompresing/decoding data streams. The help info of the function is shown
below

Expand Down
5 changes: 2 additions & 3 deletions src/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

BACKEND ?=

ROOTDIR ?= ..
ROOTDIR ?= ../private
ZMATDIR ?= $(ROOTDIR)
MCXSRC :=$(ZMATDIR)/src

Expand Down Expand Up @@ -80,14 +80,13 @@ lib: ARFLAGS :=cr
lib: AROUTPUT :=

oct mex: CPPOPT+= $(DLLFLAG)
oct: CC=$(MEX)
oct: OUTPUT_DIR=..
oct: AR= CXXFLAGS='-O3' LFLAGS='$(-lz)' LDFLAGS='$(LFLAGS)' mkoctfile zmat.cpp easylzma/easylzma-0.0.8/lib/libeasylzma_s.a
oct: BINARY=zmat.mex
oct: ARFLAGS :=
oct: LINKOPT+=--mex $(INCLUDEDIRS)
oct: CXX=mkoctfile

#mex: CC=$(MEX)
mex: CXX=$(MEX)
mex: OUTPUTFLAG:=-output
mex: AR=$(MEX) zmat.cpp easylzma/easylzma-0.0.8/lib/libeasylzma_s.a $(INCLUDEDIRS)
Expand Down
4 changes: 2 additions & 2 deletions src/compilezmat.m
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
if(~exist('OCTAVE_VERSION','builtin'))
mex CFLAGS='$CFLAGS -O3 -g' -Ieasylzma/easylzma-0.0.8/include -c zmatlib.c
mex zmat.cpp zmatlib.o easylzma/easylzma-0.0.8/lib/libeasylzma_s.a -Ieasylzma/easylzma-0.0.8/include -outdir ../ CXXLIBS='$CXXLIBS -lz'
mex zmat.cpp zmatlib.o easylzma/easylzma-0.0.8/lib/libeasylzma_s.a -Ieasylzma/easylzma-0.0.8/include -output ../zipmat -outdir ../ CXXLIBS='$CXXLIBS -lz'
else
mex -Ieasylzma/easylzma-0.0.8/include -c zmatlib.c
mex zmat.cpp zmatlib.o easylzma/easylzma-0.0.8/lib/libeasylzma_s.a -Ieasylzma/easylzma-0.0.8/include -o ../zmat -lz
mex zmat.cpp zmatlib.o easylzma/easylzma-0.0.8/lib/libeasylzma_s.a -Ieasylzma/easylzma-0.0.8/include -o ../zipmat -lz
end

25 changes: 15 additions & 10 deletions src/zmat.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@

void zmat_usage();

const char *metadata[]={"type","size","status"};
const char *metadata[]={"type","size","byte","method","status"};

extern char *zmat_err[];

Expand Down Expand Up @@ -68,29 +68,27 @@ void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]){
}

try{
if(mxIsChar(prhs[0]) || mxIsUint8(prhs[0]) || mxIsInt8(prhs[0])){
if(mxIsChar(prhs[0]) || (mxIsNumeric(prhs[0]) && ~mxIsComplex(prhs[0])) || mxIsLogical(prhs[0])){
int ret;
mwSize inputsize=mxGetNumberOfElements(prhs[0]);
mwSize inputsize=mxGetNumberOfElements(prhs[0])*mxGetElementSize(prhs[0]);
mwSize buflen[2]={0};
unsigned char *outputbuf=NULL;
size_t outputsize=0;
unsigned char * inputstr=(mxIsChar(prhs[0])? (unsigned char *)mxArrayToString(prhs[0]) : (unsigned char *)mxGetData(prhs[0]));

int errcode=zmat_run(inputsize, inputstr, &outputsize, &outputbuf, zipid, &ret, iscompress);
if(errcode<0)
mexErrMsgTxt(zmat_err[-errcode]);

if(outputbuf){
buflen[0]=1;
buflen[1]=outputsize;
plhs[0] = mxCreateNumericArray(2,buflen,mxUINT8_CLASS,mxREAL);
plhs[0] = mxCreateNumericArray(2,buflen,mxUINT8_CLASS,mxREAL);
memcpy((unsigned char*)mxGetPr(plhs[0]),outputbuf,buflen[1]);
free(outputbuf);
}
if(nlhs>1){
mwSize inputdim[2]={1,0}, *dims=(mwSize *)mxGetDimensions(prhs[0]);
unsigned int *inputsize=NULL;
plhs[1]=mxCreateStructMatrix(1,1,3,metadata);
plhs[1]=mxCreateStructMatrix(1,1,5,metadata);
mxArray *val = mxCreateString(mxGetClassName(prhs[0]));
mxSetFieldByNumber(plhs[1],0,0, val);

Expand All @@ -103,11 +101,18 @@ void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]){
mxSetFieldByNumber(plhs[1],0,1, val);

val = mxCreateDoubleMatrix(1,1,mxREAL);
*mxGetPr(val) = ret;
*mxGetPr(val) = mxGetElementSize(prhs[0]);
mxSetFieldByNumber(plhs[1],0,2, val);

val = mxCreateString(zipmethods[zipid]);
mxSetFieldByNumber(plhs[1],0,3, val);

val = mxCreateDoubleMatrix(1,1,mxREAL);
*mxGetPr(val) = ret;
mxSetFieldByNumber(plhs[1],0,4, val);
}
}else{
mexErrMsgTxt("the input must be in char or int8/uint8 format");
mexErrMsgTxt("the input must be a char, non-complex numerical or logical array");
}
}catch(const char *err){
mexPrintf("Error: %s\n",err);
Expand All @@ -124,5 +129,5 @@ void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]){
*/

void zmat_usage(){
printf("Usage:\n [output,info]=zmat(input,iscompress,method);\n\nPlease run 'help zmat' for more details.\n");
printf("Usage:\n\t[output,info]=zmat(input,iscompress,method);\n\nPlease run 'help zmat' for more details.\n");
}
57 changes: 52 additions & 5 deletions zmat.m
Original file line number Diff line number Diff line change
@@ -1,18 +1,23 @@
function [output, info]=zmat(input, iscompress, method)
function varargout=zmat(varargin)
%
% output=zmat(input)
% or
% [output, info]=zmat(input, iscompress, method)
% output=zmat(input, info)
%
% A portable data compression/decompression toolbox for MATLAB/GNU Octave
%
% author: Qianqian Fang <q.fang at neu.edu>
% date for initial version: 04/30/2019
% initial version created on 04/30/2019
%
% input:
% input: a string, int8 or uint8 array
% input: a char, non-complex numeric or logical vector or array
% iscompress: (optional) if iscompress is 1, zmat compresses/encodes the input,
% if 0, it decompresses/decodes the input. Default value is 1.
% if one defines iscompress as the info struct (2nd output of
% zmat) during encoding, zmat will perform a
% decoding/decompression operation and recover the original
% input using the info stored in the info structure.
% method: (optional) compression method, currently, zmat supports the below methods
% 'zlib': zlib/zip based data compression (default)
% 'gzip': gzip formatted data compression
Expand All @@ -25,15 +30,57 @@
% info: (optional) a struct storing additional info regarding the input data, may have
% 'type': the class of the input array
% 'size': the dimensions of the input array
% 'byte': the number of bytes per element in the input array
% 'status': the zlib function return value, including potential error codes (<0)
%
% example:
%
% [ss, info]=zmat(uint8(eye(5)))
% [ss, info]=zmat(eye(5))
% orig=zmat(ss,0)
% orig=reshape(orig, info.size)
% orig=zmat(ss,info)
% ss=char(zmat('zmat test',1,'base64'))
% orig=char(zmat(ss,0,'base64'))
%
% -- this function is part of the ZMAT toolbox (http://github.com/fangq/zmat)
%

if(exist('zipmat')~=3 && exist('zipmat')~=2)
error('zipmat mex file is not found. you must download the mex file or recompile');
end

if(nargin==0)
fprintf(1,'Usage:\n\t[output,info]=zmat(input,iscompress,method);\nPlease run "help zmat" for more details.\n');
return;
end

input=varargin{1};
iscompress=1;
zipmethod='zlib';

if(~(ischar(input) || islogical(input) || (isnumeric(input) && isreal(input))))
error('input must be a char, non-complex numeric or logical vector or N-D array');
end

if(ischar(input))
input=uint8(input);
end

if(nargin>1)
iscompress=varargin{2};
if(isstruct(varargin{2}))
inputinfo=varargin{2};
iscompress=0;
zipmethod=inputinfo.method;
end
end

if(nargin>2)
zipmethod=varargin{3};
end

[varargout{1:nargout}]=zipmat(input,iscompress,zipmethod);

if(exist('inputinfo','var') && isfield(inputinfo,'type'))
varargout{1}=typecast(varargout{1},inputinfo.type);
varargout{1}=reshape(varargout{1},inputinfo.size);
end

0 comments on commit 177ed52

Please sign in to comment.