[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
MATLAB like fread/fwrite available!
From: |
Superuser AIA |
Subject: |
MATLAB like fread/fwrite available! |
Date: |
Tue, 10 Jan 95 09:21:54 +0100 |
--------
Hello OCTAVE users,
For further use of our old MATLAB programs and datas we needed a procedure for
a raw file i/o like in the new MATLAB fread and fwrite. Therefore we
implemented these functions and added a mode 'b' to fopen. The help
informations for the added functions is implemented, too. Due to the use of
different ENDIAN models in our institute there is a new builtin-var called
'io_swap_bytes' which makes you able to swap the bytes while reading and
writing to files. Further floating-point conversions are not implemented yet.
We'll hope you can use these additions.
Some requested informations for bug reporting:
* octave, version 1.0
* machines: hppa1.1-hp-hpux9.01 / m68k-hp-hpux9.00 / i486-linux
The first diff in the file is a very small bug in the pager procedures, but
it caused trouble at the m68k-hp-hpux9.00 (leaving the page with a SIGSEV).
Fromon the second diff to the end you'll find the necessary differences for
the raw file i/o.
diff -c octave.old/src/pager.cc octave.new/src/pager.cc
*** octave.old/src/pager.cc Tue Jan 10 08:49:31 1995
--- octave.new/src/pager.cc Tue Jan 10 08:50:26 1995
***************
*** 109,117 ****
char *message = pager_buf->str ();
! if (message == (char *) NULL || *message == '\0')
{
delete [] message;
initialize_pager ();
return;
}
--- 109,121 ----
char *message = pager_buf->str ();
! if (message == (char *) NULL)
! goto initonly;
!
! if (*message == '\0')
{
delete [] message;
+ initonly:
initialize_pager ();
return;
}
diff -c octave.old/src/builtins.cc octave.new/src/builtins.cc
*** octave.old/src/builtins.cc Tue Jan 10 08:49:28 1995
--- octave.new/src/builtins.cc Tue Jan 10 08:49:51 1995
***************
*** 316,321 ****
--- 316,338 ----
{ "fgets",3, 2, builtin_fgets,
"[string, length] = fgets (\"filename\" or filenum, length): read a
string from a file", },
+ { "fread",4, 2, builtin_fread,
+ "[A, count] = fread (\"filename\" or filenum, size, 'precision'): binary
read from a file\n\n\
+ Valid values for 'precision' include:\n\n\
+ 'char', 'char*1'; 'schar', 'signed char', 'int8';\n\
+ 'uchar', 'unsigned char', 'uint8':\n\
+ Character, 8 bits\n\
+ 'short', 'int16'; 'ushort', 'unsigned short', 'uint16':\n\
+ Integer, 16 bits\n\
+ 'int'; 'uint', 'unsigned int':\n\
+ Integer, 16 or 32 bits\n\
+ 'long', 'int32'; 'ulong', 'unsigned long', 'uint32':\n\
+ Integer, 32 bits\n\
+ 'float32', 'real*4':\n\
+ Floating point value, 32 bits\n\
+ 'double', 'float64', 'real*8':\n\
+ Floating point value, 64 bits\n", },
+
{ "find", -1, 1, builtin_find,
"find (x): return vector of indices of nonzero elements", },
***************
*** 390,395 ****
--- 407,429 ----
{ "ftell", 2, 1, builtin_ftell,
"position = ftell (\"filename\" or filenum): returns the current file
position", },
+ { "fwrite",4, 1, builtin_fwrite,
+ "count = fwrite (\"filename\" or filenum, X, 'precision'): binary write
to a file\n\n\
+ Valid values for 'precision' include:\n\n\
+ 'char', 'char*1'; 'schar', 'signed char', 'int8';\n\
+ 'uchar', 'unsigned char', 'uint8':\n\
+ Character, 8 bits\n\
+ 'short', 'int16'; 'ushort', 'unsigned short', 'uint16':\n\
+ Integer, 16 bits\n\
+ 'int'; 'uint', 'unsigned int':\n\
+ Integer, 16 or 32 bits\n\
+ 'long', 'int32'; 'ulong', 'unsigned long', 'uint32':\n\
+ Integer, 32 bits\n\
+ 'float32', 'real*4':\n\
+ Floating point value, 32 bits\n\
+ 'double', 'float64', 'real*8':\n\
+ Floating point value, 64 bits\n", },
+
{ "getenv", 2, 1, builtin_getenv,
"getenv (\"string\"): get environment variable values", },
***************
*** 711,716 ****
--- 745,753 ----
{ "inf", "??", NULL,
"infinity", },
+ { "io_swap_bytes", "false", io_swap_bytes,
+ "swap bytes while low-level file i/o", },
+
{ "j", "??", NULL,
"sqrt (-1)", },
diff -c octave.old/src/file-io.cc octave.new/src/file-io.cc
*** octave.old/src/file-io.cc Tue Jan 10 08:49:28 1995
--- octave.new/src/file-io.cc Tue Jan 10 08:50:02 1995
***************
*** 38,44 ****
--- 38,46 ----
#include "statdefs.h"
#include "file-io.h"
#include "input.h"
+ #include "mappers.h"
#include "octave-hist.h"
+ #include "user-prefs.h"
#include "tree-const.h"
#include "error.h"
#include "utils.h"
***************
*** 342,349 ****
char m = mode[0];
if (m == 'r' || m == 'w' || m == 'a')
{
! m = mode[1];
! return (m == '\0' || (m == '+' && mode[2] == '\0'));
}
}
return 0;
--- 344,362 ----
char m = mode[0];
if (m == 'r' || m == 'w' || m == 'a')
{
! for(;;)
! {
! switch (*++mode)
! {
! case '+': case 'b':
! continue;
! case '\0':
! return 1;
! default:
! break;
! }
! break;
! }
}
}
return 0;
***************
*** 392,397 ****
--- 405,736 ----
retval[0] = tree_constant (string);
+ return retval;
+ }
+
+ struct elminfo{ unsigned realv:1; unsigned signedv:1; };
+
+ static size_t
+ decode_precision (const char *prec, struct elminfo *elminf)
+ { const struct { const char *name; unsigned realv:1; unsigned signedv:1;
+ size_t size; } *p,
+ ref [] =
+ { {"char", 0, 1, sizeof(char)},
+ {"char*1", 0, 1, sizeof(char)},
+ {"schar", 0, 1, sizeof(signed char)},
+ {"signed char", 0, 1, sizeof(signed char)},
+ {"uchar", 0, 0, sizeof(unsigned char)},
+ {"unsigned char", 0, 0, sizeof(unsigned char)},
+ {"short", 0, 1, sizeof(short)},
+ {"ushort", 0, 0, sizeof(unsigned short)},
+ {"unsigned short", 0, 0, sizeof(unsigned short)},
+ {"int", 0, 1, sizeof(int)},
+ {"uint", 0, 0, sizeof(unsigned)},
+ {"unsigned", 0, 0, sizeof(unsigned)},
+ {"long", 0, 1, sizeof(long)},
+ {"ulong", 0, 0, sizeof(unsigned long)},
+ {"unsigned long", 0, 0, sizeof(unsigned long)},
+ {"float", 1, 1, sizeof(float)},
+ {"float32", 1, 1, 4},
+ {"float*4", 1, 1, 4},
+ {"float64", 1, 1, 8},
+ {"double", 1, 1, sizeof(double)},
+ {"real*8", 1, 1, 8},
+ {"int8", 0, 1, 1},
+ {"int16", 0, 1, 2},
+ {"int32", 0, 1, 4},
+ {"uint8", 0, 0, 1},
+ {"uint16", 0, 0, 2},
+ {"uint32", 0, 0, 4},
+ {0, 0, 0, 0},
+ };
+ for (p=ref; p->name; p++)
+ if(!strcmp(p->name, prec))
+ {
+ elminf->realv = p->realv;
+ elminf->signedv = p->signedv;
+ return p->size;
+ }
+
+ error ("not a valid precision");
+ return 0;
+ }
+
+ /*srb*/
+ tree_constant *
+ fwrite_internal (const tree_constant *args, int nargin, int nargout) {
+ tree_constant *retval = NULL_TREE_CONST;
+
+ Pix p = file_io_get_file (args[1], "wb", "fwrite");
+
+ if (p == (Pix) NULL)
+ return retval;
+
+ size_t elmsize = 1;
+ elminfo elminf = {0, 0};
+ long sizer = 1, sizec = 1;
+ union {Matrix*matrix; char*string;} src;
+ enum {matrix,string,scalar} type;
+
+ if (args[2].is_matrix_type ()) {
+ sizer = (long) args[2].rows ();
+ sizec = (long) args[2].columns ();
+ type = matrix; src.matrix = &args[2].matrix_value ();
+ }
+ else if (args[2].is_string_type ()) {
+ sizer = (long) strlen(args[2].string_value ());
+ type = string; src.string = args[2].string_value ();
+ }
+ else if (args[2].is_scalar_type ()) {
+ type = scalar;
+ }
+ else
+ goto fwrite_usage;
+
+ if (args[3].is_string_type ())
+ elmsize = decode_precision (args[3].string_value (), &elminf);
+ else
+ {
+ fwrite_usage:
+ error ("fwrite: usage error");
+ return retval;
+ }
+
+ file_info file = file_list (p);
+
+ size_t count = 0, ir, ic;
+ union {char c[sizeof(double)*2];long l;double d;} buf;
+
+ #define WRITEbuf(type) \
+ if(elmsize==sizeof(type)) \
+ *(type*)(void*)&buf = (type)result
+
+ for (ic = 0; ic < sizec; ic++)
+ for (ir = 0; ir < sizer ; ir++)
+ {
+ double result;
+
+ switch (type)
+ {
+ case matrix:
+ result = src.matrix->xelem(ir,ic);
+ break;
+ case string:
+ result = src.string[ir];
+ break;
+ case scalar:
+ result = args[2].double_value ();
+ break;
+ }
+
+ if (elminf.realv)
+ {
+ WRITEbuf(float);
+ else WRITEbuf(double);
+ else goto unk_prec;
+ }
+ else if (elminf.signedv)
+ {
+ WRITEbuf(char);
+ else WRITEbuf(short);
+ else WRITEbuf(int);
+ else WRITEbuf(long);
+ else goto unk_prec;
+ }
+ else
+ {
+ WRITEbuf(unsigned char);
+ else WRITEbuf(unsigned short);
+ else WRITEbuf(unsigned int);
+ else WRITEbuf(unsigned long);
+ else
+ {
+ unk_prec: error ("fwrite: unknown precision");
+ return retval;
+ }
+ }
+
+ if (user_pref.io_swap_bytes)
+ {
+ unsigned char *bufb=NULL, *bufe=NULL;
+ unsigned bufbuf;
+
+ for (bufb=(unsigned char *)(void *)&buf, bufe=bufb+elmsize-1;
+ bufb<bufe;
+ bufb++, bufe--) {
+ bufbuf = *bufb;
+ *bufb = *bufe;
+ *bufe = bufbuf;
+ }
+ }
+
+ if (fwrite(&buf, elmsize, 1, file.fptr()) != 1)
+ goto eof;
+
+ count++;
+ }
+
+ eof:
+ retval = new tree_constant[2];
+ retval[0] = tree_constant ((double) count);
+
+ return retval;
+ }
+
+ tree_constant *
+ fread_internal (const tree_constant *args, int nargin, int nargout)
+ {
+ tree_constant *retval = NULL_TREE_CONST;
+
+ Pix p = file_io_get_file (args[1], "rb", "fread");
+
+ if (p == (Pix) NULL)
+ return retval;
+
+ size_t elmsize = 1;
+ elminfo elminf = {0, 0};
+ int variablesize = 1;
+ long sizer = 1, sizec = 1;
+ double d;
+
+ if (nargin >= 3) {
+ if (args[2].is_scalar_type ())
+ {
+ d = args[2].double_value ();
+ if (((variablesize = (xisinf(d) != 0)) && (d < 0)) ||
+ !variablesize &&
+ (sizer = (long) d) &&
+ (double) NINT (d) != (unsigned long) sizer)
+ {
+ error ("fread: size not a positive integer value");
+ return retval;
+ }
+ }
+ else if (args[2].is_matrix_type ())
+ {
+ sizer = (long) args[2].rows ();
+ sizec = (long) args[2].columns ();
+ variablesize = 0;
+
+ if (sizer * sizec != 2)
+ {
+ error ("fread: size not a two-valued vector");
+ return retval;
+ }
+
+ sizec = sizer == 1 ?
+ (long) args[2].matrix_value ().xelem(0,1) :
+ (long) args[2].matrix_value ().xelem(1,0) ;
+
+ sizer = (long) args[2].matrix_value ().xelem(0,0) ;
+
+ if ( sizer <= 0 || sizec <= 0 )
+ {
+ error ("fread: size not of positive integer values");
+ return retval;
+ }
+ }
+ else if (nargin == 3)
+ { if(args[2].is_string_type ())
+ goto fread_readprec;
+ goto fread_usage;
+ }
+ }
+
+ if (nargin == 4 && args[3].is_string_type ())
+ {
+ fread_readprec:
+ elmsize = decode_precision (args[nargin-1].string_value (), &elminf);
+ }
+ else if (nargin >= 4)
+ {
+ fread_usage:
+ error ("fread: usage error");
+ return retval;
+ }
+
+ file_info file = file_list (p);
+
+ Matrix tmp (sizer, sizec, 0.0);
+ size_t count = 0, ir, ic;
+ union {char c[sizeof(double)*2];long l;double d;} buf;
+ #define READ_BUF_SIZE 2048
+ #define READbuf(type) \
+ if(elmsize==sizeof(type)) \
+ result = *(type*)(void*)&buf
+
+ for (ic = 0; ic < sizec; ic++)
+ for (ir = 0; ir < sizer ; ir++)
+ {
+ double result;
+
+ if (fread(&buf, elmsize, 1, file.fptr()) != 1)
+ goto eof;
+
+ if (variablesize) {
+ if (count % READ_BUF_SIZE == 0)
+ tmp.resize(sizer+READ_BUF_SIZE-1,1);
+ sizer++;
+ }
+
+ if (user_pref.io_swap_bytes)
+ {
+ unsigned char *bufb=NULL, *bufe=NULL;
+ unsigned bufbuf;
+
+ for (bufb=(unsigned char *)(void *)&buf, bufe=bufb+elmsize-1;
+ bufb<bufe;
+ bufb++, bufe--) {
+ bufbuf = *bufb;
+ *bufb = *bufe;
+ *bufe = bufbuf;
+ }
+ }
+
+ if (elminf.realv)
+ {
+ READbuf(float);
+ else READbuf(double);
+ else goto unk_prec;
+ }
+ else if (elminf.signedv)
+ {
+ READbuf(char);
+ else READbuf(short);
+ else READbuf(int);
+ else READbuf(long);
+ else goto unk_prec;
+ }
+ else
+ {
+ READbuf(unsigned char);
+ else READbuf(unsigned short);
+ else READbuf(unsigned int);
+ else READbuf(unsigned long);
+ else
+ {
+ unk_prec: error ("fread: unknown precision");
+ return retval;
+ }
+ }
+ tmp.xelem(ir,ic) = result;
+ count++;
+ }
+
+ eof:
+ if (variablesize)
+ tmp.resize(--sizer,1);
+
+ if (nargout == 2)
+ {
+ retval = new tree_constant[3];
+ retval[1] = tree_constant ((double) count);
+ }
+ else
+ retval = new tree_constant[2];
+
+ retval[0] = tree_constant (tmp);
+
return retval;
}
diff -c octave.old/src/file-io.h octave.new/src/file-io.h
*** octave.old/src/file-io.h Tue Jan 10 08:49:28 1995
--- octave.new/src/file-io.h Tue Jan 10 08:50:02 1995
***************
*** 35,45 ****
--- 35,49 ----
extern tree_constant *fclose_internal (const tree_constant *args);
extern tree_constant *fflush_internal (const tree_constant *args);
extern tree_constant *fgets_internal (const tree_constant *args, int nargout);
+ extern tree_constant *fread_internal (const tree_constant *args, int nargin,
+ int nargout);
extern tree_constant *fopen_internal (const tree_constant *args);
extern tree_constant *freport_internal (void);
extern tree_constant *frewind_internal (const tree_constant *args);
extern tree_constant *fseek_internal (const tree_constant *args, int nargin);
extern tree_constant *ftell_internal (const tree_constant *args);
+ extern tree_constant *fwrite_internal (const tree_constant *args, int nargin,
+ int nargout);
extern void initialize_file_io (void);
diff -c octave.old/src/g-builtins.cc octave.new/src/g-builtins.cc
*** octave.old/src/g-builtins.cc Tue Jan 10 08:49:30 1995
--- octave.new/src/g-builtins.cc Tue Jan 10 08:50:14 1995
***************
*** 643,648 ****
--- 643,664 ----
}
/*
+ * binary read from a file
+ */
+ tree_constant *
+ builtin_fread (const tree_constant *args, int nargin, int nargout)
+ {
+ tree_constant *retval = NULL_TREE_CONST;
+
+ if (nargin < 2 || nargin > 4 || nargout > 2)
+ print_usage ("fread");
+ else
+ retval = fread_internal (args, nargin, nargout);
+
+ return retval;
+ }
+
+ /*
* Find nonzero elements. This should probably only work if
* do_fortran_indexing is true...
*/
***************
*** 856,861 ****
--- 872,893 ----
else
retval = ftell_internal (args);
+ return retval;
+ }
+
+ /*
+ * binary write to a file
+ */
+ tree_constant *
+ builtin_fwrite (const tree_constant *args, int nargin, int nargout)
+ {
+ tree_constant *retval = NULL_TREE_CONST;
+
+ if (nargin != 4 || nargout > 1)
+ print_usage ("fwrite");
+ else
+ retval = fwrite_internal (args, nargin, nargout);
+
return retval;
}
diff -c octave.old/src/g-builtins.h octave.new/src/g-builtins.h
*** octave.old/src/g-builtins.h Tue Jan 10 08:49:30 1995
--- octave.new/src/g-builtins.h Tue Jan 10 08:50:14 1995
***************
*** 62,67 ****
--- 62,68 ----
extern tree_constant *builtin_fflush (const tree_constant *, int, int);
extern tree_constant *builtin_fft (const tree_constant *, int, int);
extern tree_constant *builtin_fgets (const tree_constant *, int, int);
+ extern tree_constant *builtin_fread (const tree_constant *, int, int);
extern tree_constant *builtin_find (const tree_constant *, int, int);
extern tree_constant *builtin_flops (const tree_constant *, int, int);
extern tree_constant *builtin_fopen (const tree_constant *, int, int);
***************
*** 75,80 ****
--- 76,82 ----
extern tree_constant *builtin_fsqp (const tree_constant *, int, int);
extern tree_constant *builtin_fsqp_options (const tree_constant *, int, int);
extern tree_constant *builtin_ftell (const tree_constant *, int, int);
+ extern tree_constant *builtin_fwrite (const tree_constant *, int, int);
extern tree_constant *builtin_getenv (const tree_constant *, int, int);
extern tree_constant *builtin_givens (const tree_constant *, int, int);
extern tree_constant *builtin_hess (const tree_constant *, int, int);
diff -c octave.old/src/t-builtins.cc octave.new/src/t-builtins.cc
*** octave.old/src/t-builtins.cc Tue Jan 10 08:49:32 1995
--- octave.new/src/t-builtins.cc Tue Jan 10 08:50:33 1995
***************
*** 798,808 ****
return retval;
}
! static istream stream;
! static ifstream file;
if (strcmp (*argv, "-") == 0)
{
! stream = cin;
}
else
{
--- 798,808 ----
return retval;
}
! istream *stream;
! ifstream file;
if (strcmp (*argv, "-") == 0)
{
! stream = &cin;
}
else
{
***************
*** 813,819 ****
error ("load: couldn't open input file `%s'", *argv);
return retval;
}
! stream = file;
}
int count = 0;
--- 813,819 ----
error ("load: couldn't open input file `%s'", *argv);
return retval;
}
! stream = &file;
}
int count = 0;
***************
*** 822,828 ****
{
// Read name for this entry or break on EOF.
delete [] nm;
! nm = extract_keyword (stream, "name");
if (nm == (char *) NULL)
{
if (count == 0)
--- 822,828 ----
{
// Read name for this entry or break on EOF.
delete [] nm;
! nm = extract_keyword (*stream, "name");
if (nm == (char *) NULL)
{
if (count == 0)
***************
*** 844,850 ****
continue;
}
! load_variable (nm, force, stream);
if (error_state)
{
--- 844,850 ----
continue;
}
! load_variable (nm, force, *stream);
if (error_state)
{
***************
*** 853,861 ****
}
}
- if (file);
- file.close ();
-
return retval;
}
--- 853,858 ----
***************
*** 960,972 ****
argc--;
argv++;
! static ostream stream;
! static ofstream file;
if (strcmp (*argv, "-") == 0)
{
// XXX FIXME XXX -- should things intended for the screen end up in a
// tree_constant (string)?
! stream = cout;
}
else if (argc == 1 && glob_pattern_p (*argv)) // Guard against things
{ // like `save a*',
--- 957,969 ----
argc--;
argv++;
! ostream *stream;
! ofstream file;
if (strcmp (*argv, "-") == 0)
{
// XXX FIXME XXX -- should things intended for the screen end up in a
// tree_constant (string)?
! stream = &cout;
}
else if (argc == 1 && glob_pattern_p (*argv)) // Guard against things
{ // like `save a*',
***************
*** 982,988 ****
error ("save: couldn't open output file `%s'", *argv);
return retval;
}
! stream = file;
}
--- 979,985 ----
error ("save: couldn't open output file `%s'", *argv);
return retval;
}
! stream = &file;
}
***************
*** 996,1002 ****
SYMTAB_ALL_SCOPES);
for (int i = 0; i < count; i++)
! curr_sym_tab->save (stream, vars[i],
is_globally_visible (vars[i]), prec);
delete [] vars;
--- 993,999 ----
SYMTAB_ALL_SCOPES);
for (int i = 0; i < count; i++)
! curr_sym_tab->save (*stream, vars[i],
is_globally_visible (vars[i]), prec);
delete [] vars;
***************
*** 1016,1022 ****
for (i = 0; i < count; i++)
{
if (fnmatch (*argv, lvars[i], __FNM_FLAGS) == 0
! && curr_sym_tab->save (stream, lvars[i],
is_globally_visible (lvars[i]),
prec) != 0)
saved_or_error++;
--- 1013,1019 ----
for (i = 0; i < count; i++)
{
if (fnmatch (*argv, lvars[i], __FNM_FLAGS) == 0
! && curr_sym_tab->save (*stream, lvars[i],
is_globally_visible (lvars[i]),
prec) != 0)
saved_or_error++;
***************
*** 1028,1034 ****
for (i = 0; i < count; i++)
{
if (fnmatch (*argv, bvars[i], __FNM_FLAGS) == 0
! && global_sym_tab->save (stream, bvars[i], 0, prec) != 0)
saved_or_error++;
}
--- 1025,1031 ----
for (i = 0; i < count; i++)
{
if (fnmatch (*argv, bvars[i], __FNM_FLAGS) == 0
! && global_sym_tab->save (*stream, bvars[i], 0, prec) != 0)
saved_or_error++;
}
***************
*** 1040,1048 ****
}
}
- if (file);
- file.close ();
-
return retval;
}
--- 1037,1042 ----
diff -c octave.old/src/user-prefs.cc octave.new/src/user-prefs.cc
*** octave.old/src/user-prefs.cc Tue Jan 10 08:49:32 1995
--- octave.new/src/user-prefs.cc Tue Jan 10 08:50:44 1995
***************
*** 110,115 ****
--- 110,125 ----
}
/*
+ * Should we swap the bytes while low-level file i/o in order
+ * to get around the machine dependency?
+ */
+ int
+ io_swap_bytes (void)
+ {
+ user_pref.io_swap_bytes = check_str_pref ("io_swap_bytes");
+ }
+
+ /*
* Should we allow silent conversion of complex to real when a real
* type is what we\'re really looking for?
*/
diff -c octave.old/src/user-prefs.h octave.new/src/user-prefs.h
*** octave.old/src/user-prefs.h Tue Jan 10 08:49:32 1995
--- octave.new/src/user-prefs.h Tue Jan 10 08:50:44 1995
***************
*** 28,33 ****
--- 28,34 ----
{
int do_fortran_indexing;
int empty_list_elements_ok;
+ int io_swap_bytes;
int implicit_str_to_num_ok;
int ok_to_lose_imaginary_part;
int prefer_column_vectors;
***************
*** 63,68 ****
--- 64,70 ----
extern int do_fortran_indexing (void);
extern int empty_list_elements_ok (void);
+ extern int io_swap_bytes (void);
extern int implicit_str_to_num_ok (void);
extern int ok_to_lose_imaginary_part (void);
extern int prefer_column_vectors (void);
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- MATLAB like fread/fwrite available!,
Superuser AIA <=