Qucs-core
0.0.19
|
00001 /* 00002 * matlab_producer.cpp - the Matlab data file producer 00003 * 00004 * Copyright (C) 2009 Stefan Jahn <stefan@lkcc.org> 00005 * 00006 * This is free software; you can redistribute it and/or modify 00007 * it under the terms of the GNU General Public License as published by 00008 * the Free Software Foundation; either version 2, or (at your option) 00009 * any later version. 00010 * 00011 * This software is distributed in the hope that it will be useful, 00012 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00014 * GNU General Public License for more details. 00015 * 00016 * You should have received a copy of the GNU General Public License 00017 * along with this package; see the file COPYING. If not, write to 00018 * the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor, 00019 * Boston, MA 02110-1301, USA. 00020 * 00021 * $Id$ 00022 * 00023 */ 00024 00025 #if HAVE_CONFIG_H 00026 # include <config.h> 00027 #endif 00028 00029 #include <stdio.h> 00030 #include <stdlib.h> 00031 #include <time.h> 00032 #include <ctype.h> 00033 #include <string.h> 00034 00035 #include "matlab_producer.h" 00036 #include "matrix.h" 00037 #include "matvec.h" 00038 #include "constants.h" 00039 00040 #include <cstdint> 00041 00042 using namespace qucs; 00043 00044 /* Global variables. */ 00045 FILE * matlab_out = NULL; // output file stream 00046 int matlab_symbols = 1; // convert data names to have valid Matlab identifier 00047 int nr_bigendian = 0; // endianness 00048 00049 // Test endianness. 00050 // http://www.geeksforgeeks.org/little-and-big-endian-mystery/ 00051 static void initendian (void) { 00052 unsigned int i = 1; 00053 char *c = (char*)&i; 00054 nr_bigendian = (*c == 1) ? 0 : 1; 00055 } 00056 00057 // Writes a Matlab v4 header. 00058 static void matlab_header (int32_t rows, int32_t cols, const char * name) { 00059 00060 // MOPT 00061 char mopt[4]; 00062 mopt[0] = nr_bigendian ? 1 : 0; // endianness 00063 mopt[1] = 0; // always zero 00064 switch (sizeof (nr_double_t) * 8) { 00065 case 32: mopt[2] = 1; break; 00066 case 64: mopt[2] = 0; break; 00067 } 00068 mopt[3] = 0; // numeric full matrix 00069 fwrite (mopt, sizeof (mopt), 1, matlab_out); 00070 00071 // dimension 00072 fwrite (&rows, sizeof (int32_t), 1, matlab_out); 00073 fwrite (&cols, sizeof (int32_t), 1, matlab_out); 00074 00075 // imaginary flag 00076 int32_t imag = 1; 00077 fwrite (&imag, sizeof (int32_t), 1, matlab_out); 00078 00079 // data name length 00080 int32_t len = strlen (name) + 1; 00081 fwrite (&len, sizeof (int32_t), 1, matlab_out); 00082 00083 char * p = strdup(name); 00084 // data name 00085 if (matlab_symbols) { 00086 // convert to valid Matlab identifiers 00087 for (unsigned int i = 0; i < strlen (name); i++, p++) { 00088 if (!isalnum (*p) && *p != '_') 00089 *p = '_'; 00090 } 00091 } 00092 fwrite (p, 1, len, matlab_out); 00093 free(p); 00094 } 00095 00096 // Writes a Matlab v4 vector. 00097 static void matlab_vector (::vector * v) { 00098 int n; 00099 00100 // real part 00101 for (n = 0; n < v->getSize (); n++) { 00102 nr_double_t r = real (v->get (n)); 00103 fwrite (&r, sizeof (nr_double_t), 1, matlab_out); 00104 } 00105 // imaginary part 00106 for (n = 0; n < v->getSize (); n++) { 00107 nr_double_t i = imag (v->get (n)); 00108 fwrite (&i, sizeof (nr_double_t), 1, matlab_out); 00109 } 00110 } 00111 00112 // Writes a Matlab v4 matrix. 00113 static void matlab_matrix (matrix * m) { 00114 int r, c; 00115 00116 // real part 00117 for (c = 0; c < m->getCols (); c++) { 00118 for (r = 0; r < m->getRows (); r++) { 00119 nr_double_t re = real (m->get (r, c)); 00120 fwrite (&re, sizeof (nr_double_t), 1, matlab_out); 00121 } 00122 } 00123 // imaginary part 00124 for (c = 0; c < m->getCols (); c++) { 00125 for (r = 0; r < m->getRows (); r++) { 00126 nr_double_t im = imag (m->get (r, c)); 00127 fwrite (&im, sizeof (nr_double_t), 1, matlab_out); 00128 } 00129 } 00130 } 00131 00132 // Saves a dataset vector into a Matlab file. 00133 static void matlab_save (::vector * v) { 00134 int r, c; 00135 char * n, * sn; 00136 const char * vn = v->getName (); 00137 matvec * mv = NULL; 00138 matrix m; 00139 00140 // is vector matrix entry 00141 if ((n = matvec::isMatrixVector (vn, r, c)) != NULL) { 00142 // valid matrix vector and simple matrix 00143 if ((mv = matvec::getMatrixVector (v, n)) != NULL && mv->getSize () == 1) { 00144 // only save at first matrix entry [1,1] 00145 if (r == 0 && c == 0) { 00146 // save matrix 00147 matlab_header (mv->getRows (), mv->getCols (), n); 00148 m = mv->get (0); 00149 matlab_matrix (&m); 00150 } 00151 } 00152 else { 00153 // save vector 00154 sn = (char *) malloc (strlen (n) + 8); 00155 if (matlab_symbols) { 00156 // convert indices to valid Matlab identifiers 00157 sprintf (sn, "%s_%d_%d", n, r + 1, c + 1); 00158 } else { 00159 sprintf (sn, "%s", vn); 00160 } 00161 matlab_header (v->getSize (), 1, sn); 00162 matlab_vector (v); 00163 free (sn); 00164 } 00165 free (n); 00166 delete mv; 00167 } 00168 else { 00169 // save vector 00170 matlab_header (v->getSize (), 1, vn); 00171 matlab_vector (v); 00172 } 00173 } 00174 00175 /* This is the overall Matlab producer. */ 00176 void matlab_producer (void) { 00177 00178 dataset * data = qucs_data; 00179 qucs::vector * v; 00180 00181 // initialize endianness 00182 initendian (); 00183 00184 // independent vectors and matrices 00185 for (v = data->getDependencies (); v != NULL; v = (::vector *) v->getNext ()) { 00186 matlab_save (v); 00187 } 00188 00189 // dependent vectors and matrices 00190 for (v = data->getVariables (); v != NULL; v = (::vector *) v->getNext ()) { 00191 matlab_save (v); 00192 } 00193 }