1 /* Copyright (C) FFLAS-FFPACK 2017 2 * written by Clement Pernet (clement.pernet@univ-grenoble-alpes.fr) 3 * ========LICENCE======== 4 * This file is part of the library FFLAS-FFPACK. 5 * 6 * FFLAS-FFPACK is free software: you can redistribute it and/or modify 7 * it under the terms of the GNU Lesser General Public 8 * License as published by the Free Software Foundation; either 9 * version 2.1 of the License, or (at your option) any later version. 10 * 11 * This library 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 GNU 14 * Lesser General Public License for more details. 15 * 16 * You should have received a copy of the GNU Lesser General Public 17 * License along with this library; if not, write to the Free Software 18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 19 * ========LICENCE======== 20 */ 21 22 #ifndef __FFLAS_IO_H 23 #define __FFLAS_IO_H 24 25 #include <cstring> 26 #include <stdio.h> 27 #include <stdlib.h> 28 #include <fstream> 29 30 namespace FFLAS{ 31 32 enum FFLAS_FORMAT { 33 FflasAuto = 0, // Automated detection of the format 34 FflasDense = 1, // Dense format (Array) 35 FflasSMS = 2, // Sparse Matrix format (Matrix Market) 36 FflasBinary = 3, // Binary format 37 FflasMath = 4, // Standard math. notation 38 FflasMaple = 5, // Maple input 39 FflasSageMath = 6 // SageMath input 40 }; 41 42 template<class Field> 43 std::ostream& WriteMatrix (std::ostream& c, const Field& F, size_t m, size_t n, 44 typename Field::ConstElement_ptr A, size_t lda, 45 FFLAS_FORMAT format = FflasMath, 46 bool column_major=false); 47 } 48 49 #include "fflas-ffpack/fflas/fflas.h" 50 #include "fflas_memory.h" 51 52 // Reading and writing matrices over field 53 54 namespace FFLAS{ 55 preamble(std::ifstream & ifs,FFLAS_FORMAT & format)56 inline void preamble(std::ifstream&ifs, FFLAS_FORMAT& format){ 57 char st[9] = {0}; 58 ifs.read(st, 8); 59 if (!strcmp(st,"FFBinFmt")){ 60 format = FflasBinary; 61 }else{ 62 // No detection of non-binary formats for the moment 63 format = FflasSMS; 64 } 65 ifs.seekg(0, std::ios::beg); 66 return; 67 } 68 69 /** 70 * @brief ReadMatrix: read a matrix from an input stream 71 * @param ifs: input stream 72 * @param F: base field 73 * @param [out] m: row dimension 74 * @param [out] n: column dimension 75 * @param [out] A: output matrix 76 * @param format: input format (FflasAuto, FflasDense, FflasSMS, FflasBinary) 77 */ 78 template<class Field> 79 typename Field::Element_ptr 80 ReadMatrix (std::ifstream& ifs, Field& F, size_t& m, size_t& n, 81 typename Field::Element_ptr& A, FFLAS_FORMAT format = FflasAuto){ 82 83 FFLAS_FORMAT form = format; 84 85 if (form == FflasAuto){ 86 // Preamble analysis. Update form to the discovered format. 87 preamble(ifs, form); 88 } 89 90 switch (form){ 91 case FflasDense:{ 92 ifs >> m; 93 ifs >> n; 94 A = fflas_new(F, m,n); 95 for (size_t i=0; i<m*n; i++){ 96 F.read (ifs, A[i]); 97 } 98 break; 99 } 100 case FflasSMS:{ 101 // Ignore comments (starting with %) 102 while (ifs.peek() == '%') { 103 ifs.ignore(std::numeric_limits<std::streamsize>::max(), '\n'); 104 } 105 106 ifs >> m >> n; 107 size_t i,j; 108 std::string tmp; 109 typename Field::Element val; 110 ifs >> tmp; 111 A = fflas_new(F, m,n); 112 fzero(F,m,n,A,n); 113 do{ 114 ifs >> i >> j; 115 if (i>m || j>n){ 116 std::cerr<<"Matrix file does not respect the SMS format"<<std::endl; 117 return NULL; 118 } 119 F.read (ifs, val); 120 if (i>0 && i>0) F.assign (A [(i-1)*n+j-1], val); 121 } while (!(i==0 && j==0 && F.isZero(val))); 122 break; 123 } 124 case FflasBinary:{ 125 char st[9]; 126 ifs.getline(st, 9); 127 if (strcmp (st,"FFBinFmt")){ 128 std::cerr<<"Not a FFLAS-FFPACK binary matrix format: preamble = "<<st<<std::endl; 129 return NULL; 130 } 131 size_t mm, nn; 132 ifs.read(reinterpret_cast<char *>(&mm), sizeof(size_t)); 133 ifs.read(reinterpret_cast<char *>(&nn), sizeof(size_t)); 134 m=mm,n=nn; 135 A = fflas_new(F, m,n); 136 ifs.read (reinterpret_cast<char *>(A), sizeof(typename Field::Element)*m*n); 137 ifs.close(); 138 break; 139 } 140 default: 141 std::cerr<<"Unable to detect the file format"<<std::endl; 142 } 143 return A; 144 } 145 146 /** 147 * @brief ReadMatrix: read a matrix from a file 148 * @param matrix_file: filename 149 * @param F: base field 150 * @param [out] m: row dimension 151 * @param [out] n: column dimension 152 * @param [out] A: output matrix 153 * @param format: input format (FflasAuto, FflasDense, FflasSMS, FflasBinary) 154 */ 155 template<class Field> 156 inline typename Field::Element_ptr 157 ReadMatrix (const std::string& matrix_file, Field & F, size_t & m, size_t& n, 158 typename Field::Element_ptr& A, FFLAS_FORMAT format = FflasAuto){ 159 160 std::ios_base::openmode mode = std::ios::in; 161 if (format == FflasBinary) 162 mode |= std::ifstream::binary; 163 164 std::ifstream ifs (matrix_file, mode); 165 if (ifs.is_open()){ 166 ReadMatrix (ifs, F, m, n, A, format); 167 ifs.close(); 168 } else 169 std::cerr<<"Error: unable to open file "<<matrix_file<<std::endl; 170 171 return A; 172 } 173 174 /** 175 * @brief WriteMatrix: write a matrix to an output stream 176 * @param c: output stream 177 * @param F: base field 178 * @param m: row dimension 179 * @param n: column dimension 180 * @param A: matrix 181 * @param format: input format (FflasAuto, FflasDense, FflasSMS, FflasBinary) 182 * @param column_major: whether the matrix is stored in column or row major (row by default) 183 */ 184 template<class Field> WriteMatrix(std::ostream & c,const Field & F,size_t m,size_t n,typename Field::ConstElement_ptr A,size_t lda,FFLAS_FORMAT format,bool column_major)185 inline std::ostream& WriteMatrix (std::ostream& c, const Field& F, size_t m, size_t n, 186 typename Field::ConstElement_ptr A, size_t lda, 187 FFLAS_FORMAT format, bool column_major) { 188 switch (format){ 189 case FflasSageMath: 190 c << "Matrix ("; 191 if (F.characteristic() == 0) 192 c << "ZZ, "; 193 else 194 c << "GF("<<F.cardinality()<<"), "; 195 c << m <<", " << n << ", [" ; 196 for (size_t i = 0; i<m; ++i){ 197 c << '['; 198 for (size_t j=0; j<n;++j){ 199 if (column_major) F.write (c, A[j*lda+i]); 200 else F.write (c, A[i*lda+j]); 201 if (j < n-1) c << ", "; 202 } 203 c << ']'; 204 if (i < m-1) c << ", "; 205 } 206 c << "])\n"; 207 break; 208 case FflasMaple: 209 c << "Matrix ("; 210 c << m <<", " << n << ", [" ; 211 for (size_t i = 0; i<m; ++i){ 212 c << '['; 213 for (size_t j=0; j<n;++j){ 214 if (column_major) F.write (c, A[j*lda+i]); 215 else F.write (c, A[i*lda+j]); 216 if (j < n-1) c << ", "; 217 } 218 c << ']'; 219 if (i < m-1) c << ", "; 220 } 221 c << "]);\n"; 222 break; 223 case FflasDense: 224 c<<m<<" "<<n<<std::endl; 225 for (size_t i = 0; i<m; ++i){ 226 for (size_t j=0; j<n;++j){ 227 if (column_major) F.write (c, A[j*lda+i]); 228 else F.write (c, A[i*lda+j]); 229 c << ' '; 230 } 231 } 232 c<<std::endl; 233 break; 234 case FflasSMS: 235 c<<m<<' '<<n<<' '<<F.cardinality()<<std::endl; 236 for (size_t i = 0; i<m; ++i){ 237 for (size_t j=0; j<n;++j){ 238 typename Field::ConstElement_ptr x; 239 if (column_major) x= A + j*lda+i; 240 else x = A + i*lda +j; 241 if (!F.isZero(*x)){ 242 c << (i+1) << ' ' << (j+1) << ' '; 243 F.write (c, *x); 244 c << std::endl; 245 } 246 } 247 } 248 c << "0 0 0"<<std::endl; 249 break; 250 case FflasBinary:{ 251 char st[9]="FFBinFmt"; 252 c.write (st, 8); 253 c<<std::endl; 254 c.write ( reinterpret_cast<char*> (&m), sizeof (size_t)); 255 c.write ( reinterpret_cast<char*> (&n), sizeof (size_t)); 256 c.write ( reinterpret_cast<const char*> (A), sizeof(typename Field::Element)*m*n); 257 break; 258 } 259 default:{ // format == FflasMath 260 size_t char_width = ceil(FFLAS::bitsize (F,m,n,A,lda)*0.301029995663982); 261 Givaro::Integer p; 262 F.characteristic(p); 263 if (p==0 || F.minElement()<0) char_width++; // minus sign 264 c.fill(' '); 265 for (size_t i = 0; i<m; ++i){ 266 for (size_t j=0; j<n;++j){ 267 c.width(char_width); 268 if (column_major) F.write (c, A[j*lda+i]); 269 else F.write (c, A[i*lda+j]); 270 if (j < n-1) c << ' '; 271 } 272 c<<std::endl; 273 } 274 } 275 } 276 return c ; 277 } 278 279 /** 280 * @brief WriteMatrix: write a matrix to a file 281 * @param matrix_file: file name 282 * @param F: base field 283 * @param m: row dimension 284 * @param n: column dimension 285 * @param A: matrix 286 * @param format: input format (FflasAuto, FflasDense, FflasSMS, FflasBinary) 287 * @param column_major: whether the matrix is stored in column or row major (row by default) 288 */ 289 template<class Field> 290 void WriteMatrix (std::string& matrix_file, const Field& F, int m, int n, 291 typename Field::ConstElement_ptr A, size_t lda, 292 FFLAS_FORMAT format = FflasDense, 293 bool column_major=false) { 294 295 std::ios_base::openmode mode = std::ios::out; 296 if (format == FflasBinary) 297 mode |= std::ios::binary; 298 299 std::ofstream ofs (matrix_file, mode); 300 if (ofs.is_open()){ 301 WriteMatrix (ofs, F, m, n, A, lda, format, column_major); 302 ofs.close(); 303 } else 304 std::cerr<<"Error: unable to open file "<<matrix_file<<std::endl; 305 } 306 307 /** 308 * @brief WritePermutation: write a permutation matrix to an output stream 309 * @param c: output stream 310 * @param P: permutation 311 * @param N: size of the permutation 312 */ WritePermutation(std::ostream & c,const size_t * P,size_t N)313 inline std::ostream& WritePermutation (std::ostream& c, const size_t* P, size_t N){ 314 c<<"[ "; 315 for (size_t i=0; i<N; ++i){ 316 if (i) 317 c<<", "; 318 c<<P[i]; 319 } 320 c<<"]"<<std::endl; 321 return c; 322 } 323 324 } //namespace FFLAS 325 326 #endif //__FFLAS_IO_H 327 /* -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ 328 // vim:sts=4:sw=4:ts=4:et:sr:cino=>s,f0,{0,g0,(0,\:0,t0,+0,=s 329