From: drowe67 Date: Tue, 17 Apr 2012 04:50:22 +0000 (+0000) Subject: first 2 unit tests pass for fdmdv C port X-Git-Url: http://git.whiteaudio.com/gitweb/?a=commitdiff_plain;h=b393e0d3f125792d699cb2f69acdfaf2026d30f9;p=freetel-svn-tracking.git first 2 unit tests pass for fdmdv C port git-svn-id: https://svn.code.sf.net/p/freetel/code@370 01035d8c-6547-0410-b346-abe4f91aad63 --- diff --git a/codec2-dev/octave/tfdmdv.m b/codec2-dev/octave/tfdmdv.m new file mode 100644 index 00000000..3e7e7975 --- /dev/null +++ b/codec2-dev/octave/tfdmdv.m @@ -0,0 +1,58 @@ +% tfdmdv.m +% +% Octave script that evaluates the output of tfdmdv.c Unit Test program for FDMDV modem. +% +% Copyright David Rowe 2012 +% This program is distributed under the terms of the GNU General Public License +% Version 2 +% + +fdmdv; % load modem code + +% Generate reference vectors using Octave implementation of FDMDV modem + +passes = fails = 0; +frames = 10; +prev_tx_symbols = ones(Nc+1,1); +tx_bits_log = []; +tx_symbols_log = []; + +for f=1:frames + + tx_bits = get_test_bits(Nc*Nb); + tx_bits_log = [tx_bits_log tx_bits]; + tx_symbols = bits_to_qpsk(prev_tx_symbols, tx_bits, 'dqpsk'); + prev_tx_symbols = tx_symbols; + tx_symbols_log = [tx_symbols_log tx_symbols]; + +end + +% Compare to the output from the C version + +load ../unittest/tfdmdv_out.txt + +figure(1) +subplot(211) +plot(tx_bits_log - tx_bits_tfdmdv); +title('tx bits') +subplot(212) +plot(tx_symbols_log - tx_symbols_tfdmdv); +title('tx symbols') + +if sum(tx_bits_log - tx_bits_tfdmdv) == 0 + printf("fdmdv_get_test_bits..: OK\n"); + passes++; +else; + printf("fdmdv_get_test_bits..: FAIL\n"); + fails++; +end + +if sum(tx_symbols_log - tx_symbols_tfdmdv) == 0 + printf("bits_to_dqpsk_symbols: OK\n"); + passes++; +else; + printf("bits_to_dqpsk_symbols: FAIL\n"); + fails++; +end + +printf("\npasses: %d fails: %d\n", passes, fails); diff --git a/codec2-dev/src/fdmdv.c b/codec2-dev/src/fdmdv.c index 7ece1ffd..a4d7a2ee 100644 --- a/codec2-dev/src/fdmdv.c +++ b/codec2-dev/src/fdmdv.c @@ -26,48 +26,21 @@ along with this program; if not, see . */ -/*---------------------------------------------------------------------------*\ - - DEFINES - -\*---------------------------------------------------------------------------*/ - -#define FS 8000 /* sample rate in Hz */ -#define T (1/Fs) /* sample period in seconds */ -#define RS 50 /* symbol rate in Hz */ -#define NC 14 /* number of carriers */ -#define NB 2 /* Bits/symbol for QPSK modulation */ -#define RB (Nc*Rs*Nb) /* bit rate */ -#define M Fs/Rs /* oversampling factor */ -#define NSYM 4 /* number of symbols to filter over */ -#define FSEP 75 /* Separation between carriers (Hz) */ -#define FCENTRE 1200 /* Centre frequency, Nc/2 carriers below this, Nc/2 carriers above (Hz) */ -#define NT 5 /* number of symbols we estimate timing over */ -#define P 4 /* oversample factor used for initial rx symbol filtering */ -#define NFILTER (NSYM*M) /* size of tx/rx filters at sampel rate M */ -#define NFILTERTIMING (M+Nfilter+M) /* filter memory used for resampling after timing estimation */ - -#define NTEST_BITS (Nc*Nb*4) /* length of test bit sequence */ - -/*---------------------------------------------------------------------------*\ - - STRUCT for States - -\*---------------------------------------------------------------------------*/ - -struct FDMDV { - int current_test_bit; -}; - /*---------------------------------------------------------------------------*\ INCLUDES \*---------------------------------------------------------------------------*/ +#include +#include +#include +#include + +#include "fdmdv_internal.h" #include "fdmdv.h" #include "rn.h" -#include "testbits.h" +#include "test_bits.h" /*---------------------------------------------------------------------------*\ @@ -111,7 +84,7 @@ static COMP cdot(COMP a[], COMP b[], int n) int i; for(i=0; icurrent_test_bit = 0; + f->tx_pilot_bit = 0; + for(c=0; cprev_tx_symbols[c].real = 1.0; + f->prev_tx_symbols[c].imag = 0.0; + } + return f; } /*---------------------------------------------------------------------------*\ @@ -165,6 +148,30 @@ void codec2_destroy(struct FDMDV *fdmdv) free(fdmdv); } +/*---------------------------------------------------------------------------*\ + + FUNCTION....: fdmdv_get_test_bits() + AUTHOR......: David Rowe + DATE CREATED: 16/4/2012 + + Generate a frame of bits from a repeating sequence of random data. OK so + it's not very random if it repeats but it makes syncing at the demod easier + for test purposes. + +\*---------------------------------------------------------------------------*/ + +void fdmdv_get_test_bits(struct FDMDV *f, int tx_bits[]) +{ + int i; + + for(i=0; icurrent_test_bit]; + f->current_test_bit++; + if (f->current_test_bit > (NTEST_BITS-1)) + f->current_test_bit = 0; + } + } + /*---------------------------------------------------------------------------*\ FUNCTION....: bits_to_dqpsk_symbols() @@ -180,7 +187,6 @@ void bits_to_dqpsk_symbols(COMP tx_symbols[], COMP prev_tx_symbols[], int tx_bit { int c, msb, lsb; COMP j = {0.0,1.0}; - COMP minusj = {0.0,-1.0}; /* map tx_bits to to Nc DQPSK symbols */ @@ -201,9 +207,9 @@ void bits_to_dqpsk_symbols(COMP tx_symbols[], COMP prev_tx_symbols[], int tx_bit two spectral lines at +/- Rs/2 */ if (*pilot_bit) - tx_symbols[Nc] = cneg(prev_tx_symbols[Nc]); + tx_symbols[NC] = cneg(prev_tx_symbols[NC]); else - tx_symbols[Nc] = prev_tx_symbols[Nc]; + tx_symbols[NC] = prev_tx_symbols[NC]; if (*pilot_bit) *pilot_bit = 0; diff --git a/codec2-dev/src/fdmdv.h b/codec2-dev/src/fdmdv.h index 671636ff..647b87bf 100644 --- a/codec2-dev/src/fdmdv.h +++ b/codec2-dev/src/fdmdv.h @@ -33,18 +33,31 @@ extern "C" { #endif +#define FDMDV_BITS_PER_FRAME 28 +#define FDMDV_SAMPLES_PER_FRAME 160 + struct FDMDV; +struct FDMDV_STATS { + float snr; /* estimated SNR of rx signal in dB */ + COMP *rx_symbols; /* NC+1 latest received symbols, for scatter plot */ + int fest_track; /* == 0, freq est in acquire mode, == 1 in track mode */ + float foff; /* estimated freq offset in Hz */ + float timing; /* timing offset 0..1 as fraction of symbol period */ + float clock_offset; /* Estimated tx/rx sample clock offset in ppm */ +}; + + struct FDMDV *fdmdv_create(void); void fdmdv_destroy(struct FDMDV *fdmdv_state); -void fdmdv_mod(struct FDMDV *fdmdv_state, int tx_bits[], COMP tx_fdm[]); -void fdmdv_demod(struct FDMDV *fdmdv_state, int tx_bits[], float rx_fdm[], int *nin); +void fdmdv_mod(struct FDMDV *fdmdv_state, COMP tx_fdm[], int tx_bits[]); +void fdmdv_demod(struct FDMDV *fdmdv_state, int rx_bits[], int *sync, float rx_fdm[], int *nin); void fdmdv_get_test_bits(struct FDMDV *fdmdv_state, int tx_bits[]); void fdmdv_put_test_bits(struct FDMDV *fdmdv_state, int rx_bits[]); -float fdmdv_get_snr(struct FDMDV *fdmdv_state); +float fdmdv_get_demod_stats(struct FDMDV *fdmdv_state, struct FDMDV_STATS *fdmdv_stats); void fdmdv_get_waterfall_line(struct FDMDV *fdmdv_state, float magnitudes[], int *magnitude_points); #endif diff --git a/codec2-dev/src/fdmdv_internal.h b/codec2-dev/src/fdmdv_internal.h index f70d683a..a995a42a 100644 --- a/codec2-dev/src/fdmdv_internal.h +++ b/codec2-dev/src/fdmdv_internal.h @@ -31,6 +31,47 @@ #include "comp.h" +/*---------------------------------------------------------------------------*\ + + DEFINES + +\*---------------------------------------------------------------------------*/ + +#define FS 8000 /* sample rate in Hz */ +#define T (1.0/FS) /* sample period in seconds */ +#define RS 50 /* symbol rate in Hz */ +#define NC 14 /* number of carriers */ +#define NB 2 /* Bits/symbol for QPSK modulation */ +#define RB (NC*RS*NB) /* bit rate */ +#define M (FS/RS) /* oversampling factor */ +#define NSYM 4 /* number of symbols to filter over */ +#define FSEP 75 /* Separation between carriers (Hz) */ +#define FCENTRE 1200 /* Centre frequency, Nc/2 carriers below this, Nc/2 carriers above (Hz) */ +#define NT 5 /* number of symbols we estimate timing over */ +#define P 4 /* oversample factor used for initial rx symbol filtering */ +#define NFILTER (NSYM*M) /* size of tx/rx filters at sampel rate M */ +#define NFILTERTIMING (M+Nfilter+M) /* filter memory used for resampling after timing estimation */ + +#define NTEST_BITS (NC*NB*4) /* length of test bit sequence */ + +/*---------------------------------------------------------------------------*\ + + STRUCT for States + +\*---------------------------------------------------------------------------*/ + +struct FDMDV { + int current_test_bit; + int tx_pilot_bit; + COMP prev_tx_symbols[NC+1]; +}; + +/*---------------------------------------------------------------------------*\ + + FUNCTION PROTOTYPES + +\*---------------------------------------------------------------------------*/ + void bits_to_dqpsk_symbols(COMP tx_symbols[], COMP prev_tx_symbols[], int tx_bits[], int *pilot_bit); #endif diff --git a/codec2-dev/unittest/Makefile.am b/codec2-dev/unittest/Makefile.am index 41b12834..60a4aa5a 100644 --- a/codec2-dev/unittest/Makefile.am +++ b/codec2-dev/unittest/Makefile.am @@ -3,7 +3,7 @@ AUTOMAKE_OPTS = gnu NAME = libcodec2 AM_CPPFLAGS = $(AM_CFLAGS) -noinst_PROGRAMS = genres genlsp extract vqtrain vqtrainjnd tnlp tinterp tquant tcodec2 vq_train_jvm scalarlsptest +noinst_PROGRAMS = genres genlsp extract vqtrain vqtrainjnd tnlp tinterp tquant tcodec2 vq_train_jvm scalarlsptest tfdmdv genres_SOURCES = genres.c ../src/lpc.c genres_LDADD = $(lib_LTLIBRARIES) @@ -52,3 +52,7 @@ scalarlsptest_SOURCES = scalarlsptest.c ../src/quantise.c ../src/lpc.c ../src/ls scalarlsptest_LDADD = $(lib_LTLIBRARIES) scalarlsptest_LDFLAGS = $(LIBS) +tfdmdv_SOURCES = tfdmdv.c ../src/fdmdv.c +tfdmdv_LDADD = $(lib_LTLIBRARIES) +tfdmdv_LDFLAGS = $(LIBS) + diff --git a/codec2-dev/unittest/Makefile.in b/codec2-dev/unittest/Makefile.in index 94f4a037..801a6e3f 100644 --- a/codec2-dev/unittest/Makefile.in +++ b/codec2-dev/unittest/Makefile.in @@ -39,7 +39,7 @@ host_triplet = @host@ noinst_PROGRAMS = genres$(EXEEXT) genlsp$(EXEEXT) extract$(EXEEXT) \ vqtrain$(EXEEXT) vqtrainjnd$(EXEEXT) tnlp$(EXEEXT) \ tinterp$(EXEEXT) tquant$(EXEEXT) tcodec2$(EXEEXT) \ - vq_train_jvm$(EXEEXT) scalarlsptest$(EXEEXT) + vq_train_jvm$(EXEEXT) scalarlsptest$(EXEEXT) tfdmdv$(EXEEXT) subdir = unittest DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 @@ -74,6 +74,9 @@ am_tcodec2_OBJECTS = tcodec2.$(OBJEXT) quantise.$(OBJEXT) \ interp.$(OBJEXT) pack.$(OBJEXT) $(am__objects_1) tcodec2_OBJECTS = $(am_tcodec2_OBJECTS) tcodec2_DEPENDENCIES = +am_tfdmdv_OBJECTS = tfdmdv.$(OBJEXT) fdmdv.$(OBJEXT) +tfdmdv_OBJECTS = $(am_tfdmdv_OBJECTS) +tfdmdv_DEPENDENCIES = am_tinterp_OBJECTS = tinterp.$(OBJEXT) sine.$(OBJEXT) fft.$(OBJEXT) \ kiss_fft.$(OBJEXT) interp.$(OBJEXT) lpc.$(OBJEXT) \ lsp.$(OBJEXT) quantise.$(OBJEXT) $(am__objects_1) \ @@ -110,13 +113,15 @@ CCLD = $(CC) LINK = $(LIBTOOL) --tag=CC --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(AM_LDFLAGS) $(LDFLAGS) -o $@ SOURCES = $(extract_SOURCES) $(genlsp_SOURCES) $(genres_SOURCES) \ - $(scalarlsptest_SOURCES) $(tcodec2_SOURCES) $(tinterp_SOURCES) \ - $(tnlp_SOURCES) $(tquant_SOURCES) $(vq_train_jvm_SOURCES) \ - $(vqtrain_SOURCES) $(vqtrainjnd_SOURCES) + $(scalarlsptest_SOURCES) $(tcodec2_SOURCES) $(tfdmdv_SOURCES) \ + $(tinterp_SOURCES) $(tnlp_SOURCES) $(tquant_SOURCES) \ + $(vq_train_jvm_SOURCES) $(vqtrain_SOURCES) \ + $(vqtrainjnd_SOURCES) DIST_SOURCES = $(extract_SOURCES) $(genlsp_SOURCES) $(genres_SOURCES) \ - $(scalarlsptest_SOURCES) $(tcodec2_SOURCES) $(tinterp_SOURCES) \ - $(tnlp_SOURCES) $(tquant_SOURCES) $(vq_train_jvm_SOURCES) \ - $(vqtrain_SOURCES) $(vqtrainjnd_SOURCES) + $(scalarlsptest_SOURCES) $(tcodec2_SOURCES) $(tfdmdv_SOURCES) \ + $(tinterp_SOURCES) $(tnlp_SOURCES) $(tquant_SOURCES) \ + $(vq_train_jvm_SOURCES) $(vqtrain_SOURCES) \ + $(vqtrainjnd_SOURCES) ETAGS = etags CTAGS = ctags DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) @@ -264,6 +269,9 @@ tcodec2_LDFLAGS = $(LIBS) scalarlsptest_SOURCES = scalarlsptest.c ../src/quantise.c ../src/lpc.c ../src/lsp.c ../src/dump.c ../src/fft.c ../src/kiss_fft.c $(CODEBOOKS) scalarlsptest_LDADD = $(lib_LTLIBRARIES) scalarlsptest_LDFLAGS = $(LIBS) +tfdmdv_SOURCES = tfdmdv.c ../src/fdmdv.c +tfdmdv_LDADD = $(lib_LTLIBRARIES) +tfdmdv_LDFLAGS = $(LIBS) all: all-am .SUFFIXES: @@ -319,6 +327,9 @@ scalarlsptest$(EXEEXT): $(scalarlsptest_OBJECTS) $(scalarlsptest_DEPENDENCIES) tcodec2$(EXEEXT): $(tcodec2_OBJECTS) $(tcodec2_DEPENDENCIES) @rm -f tcodec2$(EXEEXT) $(LINK) $(tcodec2_LDFLAGS) $(tcodec2_OBJECTS) $(tcodec2_LDADD) $(LIBS) +tfdmdv$(EXEEXT): $(tfdmdv_OBJECTS) $(tfdmdv_DEPENDENCIES) + @rm -f tfdmdv$(EXEEXT) + $(LINK) $(tfdmdv_LDFLAGS) $(tfdmdv_OBJECTS) $(tfdmdv_LDADD) $(LIBS) tinterp$(EXEEXT): $(tinterp_OBJECTS) $(tinterp_DEPENDENCIES) @rm -f tinterp$(EXEEXT) $(LINK) $(tinterp_LDFLAGS) $(tinterp_OBJECTS) $(tinterp_LDADD) $(LIBS) @@ -354,6 +365,7 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/codec2.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dump.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/extract.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fdmdv.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fft.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/genlsp.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/genres.Po@am__quote@ @@ -369,6 +381,7 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/scalarlsptest.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sine.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tcodec2.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tfdmdv.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tinterp.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tnlp.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tquant.Po@am__quote@ @@ -677,6 +690,20 @@ pack.obj: ../src/pack.c @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o pack.obj `if test -f '../src/pack.c'; then $(CYGPATH_W) '../src/pack.c'; else $(CYGPATH_W) '$(srcdir)/../src/pack.c'; fi` +fdmdv.o: ../src/fdmdv.c +@am__fastdepCC_TRUE@ if $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT fdmdv.o -MD -MP -MF "$(DEPDIR)/fdmdv.Tpo" -c -o fdmdv.o `test -f '../src/fdmdv.c' || echo '$(srcdir)/'`../src/fdmdv.c; \ +@am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/fdmdv.Tpo" "$(DEPDIR)/fdmdv.Po"; else rm -f "$(DEPDIR)/fdmdv.Tpo"; exit 1; fi +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='../src/fdmdv.c' object='fdmdv.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o fdmdv.o `test -f '../src/fdmdv.c' || echo '$(srcdir)/'`../src/fdmdv.c + +fdmdv.obj: ../src/fdmdv.c +@am__fastdepCC_TRUE@ if $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT fdmdv.obj -MD -MP -MF "$(DEPDIR)/fdmdv.Tpo" -c -o fdmdv.obj `if test -f '../src/fdmdv.c'; then $(CYGPATH_W) '../src/fdmdv.c'; else $(CYGPATH_W) '$(srcdir)/../src/fdmdv.c'; fi`; \ +@am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/fdmdv.Tpo" "$(DEPDIR)/fdmdv.Po"; else rm -f "$(DEPDIR)/fdmdv.Tpo"; exit 1; fi +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='../src/fdmdv.c' object='fdmdv.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o fdmdv.obj `if test -f '../src/fdmdv.c'; then $(CYGPATH_W) '../src/fdmdv.c'; else $(CYGPATH_W) '$(srcdir)/../src/fdmdv.c'; fi` + mostlyclean-libtool: -rm -f *.lo diff --git a/codec2-dev/unittest/tfdmdv.c b/codec2-dev/unittest/tfdmdv.c index 374f5d17..06b2c05b 100644 --- a/codec2-dev/unittest/tfdmdv.c +++ b/codec2-dev/unittest/tfdmdv.c @@ -29,15 +29,76 @@ along with this program; if not, see . */ +#include #include #include +#include +#include "fdmdv_internal.h" #include "fdmdv.h" +#define FRAMES 10 + +void octave_save_int(FILE *f, char name[], int data[], int len); +void octave_save_complex(FILE *f, char name[], COMP data[], int len); + int main(int argc, char *argv[]) { - - /* save to text file for comparison to Octave version */ + struct FDMDV *fdmdv; + int tx_bits[FDMDV_BITS_PER_FRAME*FRAMES]; + COMP tx_symbols[(NC+1)*FRAMES]; + FILE *fout; + int f,i; + + fdmdv = fdmdv_create(); + + for(f=0; fprev_tx_symbols, + &tx_bits[FDMDV_BITS_PER_FRAME*f], &fdmdv->tx_pilot_bit); + memcpy(fdmdv->prev_tx_symbols, &tx_symbols[(NC+1)*f], (NC+1)*sizeof(COMP)); + } + + codec2_destroy(fdmdv); + + /* dump to Octave file for evaluation by Octave script */ + + fout = fopen("tfdmdv_out.txt","wt"); + assert(fout != NULL); + fprintf(fout, "# Created by tfdmdv.c\n"); + octave_save_int(fout, "tx_bits_tfdmdv", tx_bits, FDMDV_BITS_PER_FRAME*FRAMES); + octave_save_complex(fout, "tx_symbols_tfdmdv", tx_symbols, (NC+1)*FRAMES); + fclose(fout); return 0; } + +void octave_save_int(FILE *f, char name[], int data[], int len) +{ + int i; + + fprintf(f, "# name: %s\n", name); + fprintf(f, "# type: matrix\n"); + fprintf(f, "# rows: %d\n", 1); + fprintf(f, "# columns: %d\n", len); + + for(i=0; i