1 // Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
2 // Copyright (C) 2002-2004 - INRIA - Vincent COUVERT
3 // Copyright (C) ???? - INRIA - Serge STEER
5 // This file must be used under the terms of the CeCILL.
6 // This source file is licensed as described in the file COPYING, which
7 // you should have received as part of this distribution. The terms
8 // are also available at
9 // http://www.cecill.info/licences/Licence_CeCILL_V2-en.txt
11 function WritemiMatrix(fd,value,ArrayName)
12 // Save variables in a Matlab binary file
13 // This function has been developped following the 'MAT-File Format' description:
14 // www.mathworks.com/access/helpdesk/help/pdf_doc/matlab/matfile_format.pdf
17 ArrayFlagSize=8; // 8 bytes
19 // Position is saved to come back here after writing
20 SavePosBefore=mtell(fd);
25 // Position is saved to compute number of written bytes
26 NumberOfBytes=mtell(fd);
28 // Save space for ARRAY FLAGS
29 WriteEmptyArrayFlags(fd);
31 // Compute array dimensions
32 if type(value)==10 then
33 WriteDimensionArray(fd,size(mstr2sci(value)));
35 WriteDimensionArray(fd,size(value));
38 // Write variable name
39 WriteArrayName(fd,ArrayName);
43 if type(value)==1 then // DOUBLE value
44 value=matrix(value,1,-1);
45 Flags(1)=bool2s(~isreal(value));
48 WriteSimpleElement(fd,real(value),miDOUBLE);
50 WriteSimpleElement(fd,imag(value),miDOUBLE);
52 elseif type(value)==10 then // CHARACTER STRING value
53 if size(value,"*")==1 then
54 value=matrix(ascii(mstr2sci(value)),1,-1);
58 WriteSimpleElement(fd,value,miUINT16);
60 warning(gettext("Scilab string matrix saved as Matlab Cell."));
62 value=matrix(value,1,-1);
67 value=mlist(["ce","dims","entries"],int32(sz),entries)
68 mseek(SavePosBefore,fd);
69 WritemiMatrix(fd,value,ArrayName);
72 elseif type(value)==8 then // INTEGER value
73 value=matrix(value,1,-1);
79 WriteSimpleElement(fd,value,miINT8);
82 WriteSimpleElement(fd,value,miUINT8);
85 WriteSimpleElement(fd,value,miINT16);
88 WriteSimpleElement(fd,value,miUINT16);
91 WriteSimpleElement(fd,value,miINT32);
94 WriteSimpleElement(fd,value,miUINT32);
96 error(msprintf(gettext("Unknown integer type: %s."),typeof(value)));
98 elseif type(value)==17 then // MLIST used ofr CELLS and STRUCTS
104 for k=1:lstsize(value.entries)
105 WritemiMatrix(fd,value(k).entries,"");
109 Fnams=getfield(1,value);
112 WriteSimpleElement(fd,FieldNameLength,miINT32);
114 NumberOfFields=size(Fnams,2);
116 for k=1:NumberOfFields
117 FieldNames=[FieldNames ascii(Fnams(k)) zeros(1,FieldNameLength-length(Fnams(k)))];
120 WriteSimpleElement(fd,FieldNames,miINT8);
121 if prod(size(value))==1 then
122 for k=1:NumberOfFields
123 WritemiMatrix(fd,value(Fnams(k)),"");
126 for i=1:prod(size(value))
127 for k=1:NumberOfFields
128 WritemiMatrix(fd,value(i)(Fnams(k)),"");
133 error(msprintf(gettext("%s mlist type not yet implemented."),typeof(value)));
135 elseif or(type(value)==[5,7]) then // SPARSE matrices
136 if type(value)==5 then // Scilab sparse is converted to Matlab sparse
137 value=mtlb_sparse(value);
140 [ij,v,mn]=spget(value);
143 NnzMax=length(RowIndex);
145 WriteSimpleElement(fd,RowIndex,miINT32);
148 for k=1:size(col,"*")-1
149 if col(k)<>col(k+1) then
150 ColumnIndex=[ColumnIndex;col(k+1)]
155 for k=1:size(ColumnIndex,"*")
156 ptr=[ptr;size(find(col==ColumnIndex(k)),"*")]
158 ColumnIndex=cumsum(ptr);
160 WriteSimpleElement(fd,ColumnIndex,miINT32);
162 Flags(1)=bool2s(~isreal(v));
163 WriteSimpleElement(fd,real(v),miDOUBLE);
165 WriteSimpleElement(fd,imag(v),miDOUBLE);
168 error(msprintf(gettext("%s not yet implemented."),typeof(value)));
171 SavePosAfter=mtell(fd);
173 NumberOfBytes=SavePosAfter-NumberOfBytes
176 WriteTag(fd,miMatrix,NumberOfBytes);
178 mseek(SavePosBefore+TagSize+TagSize+ArrayFlagSize,fd);
180 // Update array flags
181 WriteArrayFlags(fd,Flags,Class,NnzMax);
183 mseek(SavePosAfter,fd);
186 function fd=open_matfile_wb(fil)
188 // Opens a file in 'w+b' mode
191 fd=mopen(fil,"w+b",0)
194 function swap=write_matfile_header(fd)
196 // Write the mat file header informations
199 head=gettext("MATLAB 5.0 MAT-file, Generated by Scilab");
200 head=head+part(" ",1:(124-length(head)));
201 mput(ascii(head),'uc',fd);
204 mput(version,'uc',fd);
206 endian_indicator=ascii(["M" "I"]);
207 mput(endian_indicator,'uc',fd);
209 // Character are read just after to get endian
210 // Because mput swap automatically bytes
211 // if endian not given when writing
212 mseek(mtell(fd)-2,fd);
213 IM_MI=mget(2,'uc',fd);
214 if and(IM_MI==[73,77]) then // little endian file
216 elseif and(IM_MI==[77,73]) then // big endian file
219 error(gettext("Error while writing MI."));
221 // Following call to mseek is needed under Windows
222 // to set file pointer after reading
226 function WriteEmptyTag(fd)
228 // Reserve space for a tag
236 function WriteEmptyArrayFlags(fd)
238 // Reserve space for an array flag
241 for k=1:ArrayFlagSize+TagSize
246 function WriteArrayFlags(fd,Flags,Class,NnzMax)
248 // Write an array flag
251 WriteTag(fd,miUINT32,ArrayFlagSize);
253 mseek(mtell(fd)-ArrayFlagSize,fd);
255 Flags=[0 Flags(3:-1:1)];
258 B(3)=bits2byte(Flags);
262 mput(NnzMax,md_i,fd);
265 function WriteDimensionArray(fd,dims)
267 // Write dimensions of an array
270 WriteSimpleElement(fd,dims,miINT32);
273 function WriteArrayName(fd,ArrayName)
275 // Write name of an array
278 WriteSimpleElement(fd,ascii(ArrayName),miINT8);
281 function WriteTag(fd,DataType,NumberOfBytes,Compressed)
291 Compressed=NumberOfBytes<=4;
294 mseek(SavePos-NumberOfBytes-TagSize/2,fd);
295 mput(NumberOfBytes,md_s,fd);
296 mput(DataType,md_s,fd);
298 mseek(SavePos-NumberOfBytes-TagSize,fd);
299 mput(DataType,md_i,fd);
300 mput(NumberOfBytes,md_i,fd);
306 function WriteSimpleElement(fd,value,DataType)
308 // Write an element in file
311 // If data is of double type
312 // and made of integer values
313 // then it is writen in an INT* format to save space
314 if DataType==miDOUBLE & and(double(int(value))==value) then
315 if min(value)>=0 & max(value)<=255 then // min and max value for int8
317 elseif min(value)>=-128 & max(value)<=127 then // min and max value for int8
319 //miINT8 replaced by miINT16 due to an error somewhere (matlab or
320 //scilab?) the generated file gives incorrect result in Matlab!
322 // scilab var=-40;savematfile('foosci.mat','var','-mat','-v6');
323 // matlab load foosci.mat;var
326 elseif min(value)>=0 & max(value)<=65535 then // min and max value for int16
328 elseif min(value)>=-32768 & max(value)<=32767 then // min and max value for int16
330 elseif min(value)>=0 & max(value)<=4294967295 then // min and max value for int32
332 elseif min(value)>=-2147483648 & max(value)<=2147483647 then // min and max value for int32
337 NumberOfValues=length(value);
343 NumberOfBytes=NumberOfValues*8;
346 NumberOfBytes=NumberOfValues;
349 NumberOfBytes=NumberOfValues;
352 NumberOfBytes=NumberOfValues*2;
355 NumberOfBytes=NumberOfValues*2;
358 NumberOfBytes=NumberOfValues*4;
361 NumberOfBytes=NumberOfValues*4;
364 error(msprintf(gettext("Error while writing MI."),string(DataType)));
367 Compressed=NumberOfBytes<=4;
369 mseek(mtell(fd)-TagSize/2,fd);
374 WriteTag(fd,DataType,NumberOfBytes);
376 WritePaddingBytes(fd);
380 function WritePaddingBytes(fd)
382 // Write padding bytes to have a number of bytes multiple of 8
385 np=modulo(8-modulo(mtell(fd),8),8);
391 function i=bits2byte(b)
393 // Converts 4-bits value to a byte value