My Project  0.0.16
QUCS Mapping
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
matlab_producer.cpp
Go to the documentation of this file.
1 /*
2  * matlab_producer.cpp - the Matlab data file producer
3  *
4  * Copyright (C) 2009 Stefan Jahn <stefan@lkcc.org>
5  *
6  * This is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2, or (at your option)
9  * any later version.
10  *
11  * This software is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this package; see the file COPYING. If not, write to
18  * the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
19  * Boston, MA 02110-1301, USA.
20  *
21  * $Id: matlab_producer.cpp 1825 2011-03-11 20:42:14Z ela $
22  *
23  */
24 
25 #if HAVE_CONFIG_H
26 # include <config.h>
27 #endif
28 
29 #include <stdio.h>
30 #include <stdlib.h>
31 #include <time.h>
32 #include <ctype.h>
33 #include <string.h>
34 
35 #include "matlab_producer.h"
36 #include "matrix.h"
37 #include "matvec.h"
38 #include "constants.h"
39 
40 /* Global variables. */
41 FILE * matlab_out = NULL; // output file stream
42 int matlab_symbols = 1; // convert data names to have valid Matlab identifier
43 int nr_bigendian = 0; // endianness
44 
45 // Test endianness.
46 static void initendian (void) {
47  unsigned char EndianTest[2] = { 1, 0 };
48  nr_int16_t x = * (nr_int16_t *) EndianTest;
49  nr_bigendian = (x == 1) ? 0 : 1;
50 }
51 
52 // Writes a Matlab v4 header.
53 static void matlab_header (nr_int32_t rows, nr_int32_t cols, char * name) {
54 
55  // MOPT
56  char mopt[4];
57  mopt[0] = nr_bigendian ? 1 : 0; // endianness
58  mopt[1] = 0; // always zero
59  switch (sizeof (nr_double_t) * 8) {
60  case 32: mopt[2] = 1; break;
61  case 64: mopt[2] = 0; break;
62  }
63  mopt[3] = 0; // numeric full matrix
64  fwrite (mopt, sizeof (mopt), 1, matlab_out);
65 
66  // dimension
67  fwrite (&rows, sizeof (nr_int32_t), 1, matlab_out);
68  fwrite (&cols, sizeof (nr_int32_t), 1, matlab_out);
69 
70  // imaginary flag
71  nr_int32_t imag = 1;
72  fwrite (&imag, sizeof (nr_int32_t), 1, matlab_out);
73 
74  // data name length
75  nr_int32_t len = strlen (name) + 1;
76  fwrite (&len, sizeof (nr_int32_t), 1, matlab_out);
77 
78  // data name
79  if (matlab_symbols) {
80  char * p = name;
81  // convert to valid Matlab identifiers
82  for (unsigned int i = 0; i < strlen (name); i++, p++) {
83  if (!isalnum (*p) && *p != '_')
84  *p = '_';
85  }
86  }
87  fwrite (name, 1, len, matlab_out);
88 }
89 
90 // Writes a Matlab v4 vector.
91 static void matlab_vector (vector * v) {
92  int n;
93 
94  // real part
95  for (n = 0; n < v->getSize (); n++) {
96  nr_double_t r = real (v->get (n));
97  fwrite (&r, sizeof (nr_double_t), 1, matlab_out);
98  }
99  // imaginary part
100  for (n = 0; n < v->getSize (); n++) {
101  nr_double_t i = imag (v->get (n));
102  fwrite (&i, sizeof (nr_double_t), 1, matlab_out);
103  }
104 }
105 
106 // Writes a Matlab v4 matrix.
107 static void matlab_matrix (matrix * m) {
108  int r, c;
109 
110  // real part
111  for (c = 0; c < m->getCols (); c++) {
112  for (r = 0; r < m->getRows (); r++) {
113  nr_double_t re = real (m->get (r, c));
114  fwrite (&re, sizeof (nr_double_t), 1, matlab_out);
115  }
116  }
117  // imaginary part
118  for (c = 0; c < m->getCols (); c++) {
119  for (r = 0; r < m->getRows (); r++) {
120  nr_double_t im = imag (m->get (r, c));
121  fwrite (&im, sizeof (nr_double_t), 1, matlab_out);
122  }
123  }
124 }
125 
126 // Saves a dataset vector into a Matlab file.
127 static void matlab_save (vector * v) {
128  int r, c;
129  char * n, * sn;
130  char * vn = v->getName ();
131  matvec * mv = NULL;
132  matrix m;
133 
134  // is vector matrix entry
135  if ((n = matvec::isMatrixVector (vn, r, c)) != NULL) {
136  // valid matrix vector and simple matrix
137  if ((mv = matvec::getMatrixVector (v, n)) != NULL && mv->getSize () == 1) {
138  // only save at first matrix entry [1,1]
139  if (r == 0 && c == 0) {
140  // save matrix
141  matlab_header (mv->getRows (), mv->getCols (), n);
142  m = mv->get (0);
143  matlab_matrix (&m);
144  }
145  }
146  else {
147  // save vector
148  sn = (char *) malloc (strlen (n) + 8);
149  if (matlab_symbols) {
150  // convert indices to valid Matlab identifiers
151  sprintf (sn, "%s_%d_%d", n, r + 1, c + 1);
152  } else {
153  sprintf (sn, "%s", vn);
154  }
155  matlab_header (v->getSize (), 1, sn);
156  matlab_vector (v);
157  free (sn);
158  }
159  free (n);
160  if (mv) delete mv;
161  }
162  else {
163  // save vector
164  matlab_header (v->getSize (), 1, vn);
165  matlab_vector (v);
166  }
167 }
168 
169 /* This is the overall Matlab producer. */
170 void matlab_producer (void) {
171 
172  dataset * data = qucs_data;
173  vector * v;
174 
175  // initialize endianness
176  initendian ();
177 
178  // independent vectors and matrices
179  for (v = data->getDependencies (); v != NULL; v = (vector *) v->getNext ()) {
180  matlab_save (v);
181  }
182 
183  // dependent vectors and matrices
184  for (v = data->getVariables (); v != NULL; v = (vector *) v->getNext ()) {
185  matlab_save (v);
186  }
187 }