<commit_before>/* -*- mode: C++; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
// vim:sts=4:sw=4:ts=4:noet:sr:cino=>s,f0,{0,g0,(0,\:0,t0,+0,=s
/* Copyright (C) FFLAS-FFPACK 2017
 * written by <NAME> (<EMAIL>)
 * ========LICENCE========
 * This file is part of the library FFLAS-FFPACK.
 *
 * FFLAS-FFPACK is free software: you can redistribute it and/or modify
 * it under the terms of the  GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 * ========LICENCE========
 */

#ifndef __FFLAS_IO_H
#define __FFLAS_IO_H

#include <cstring>
#include <stdio.h>
#include <stdlib.h>
#include <fstream>
//#include "fflas-ffpack/fflas/fflas.h"
#include "fflas_memory.h"

// Reading and writing matrices over field

namespace FFLAS{

    enum FFLAS_FORMAT {
        FflasAuto     = 0, // Automated detection of the format
        FflasDense    = 1, // Dense format (Array)
        FflasSMS      = 2, // Sparse Matrix format (Matrix Market)
        FflasBinary   = 3, // Binary format
        FflasMath     = 4, // Standard math. notation
        FflasMaple    = 5, // Maple input
        FflasSageMath = 6  // SageMath input
    };
    

    inline void preamble(std::ifstream&ifs, FFLAS_FORMAT& format){
		char st[8];
		ifs.getline(st, 9);
		if (!strcmp(st,"FFBinFmt")){
			format = FflasBinary;

		}else{
				// No detection of non-binary formats for the moment
			format = FflasSMS;
		}
		ifs.seekg(0);
		return;
			// Detect Dense and SMS formats
    }

		/**
		 * @brief ReadMatrix: read a matrix from an input stream
		 * @param ifs: input stream
		 * @param F: base field
		 * @param [out] m: row dimension
		 * @param [out] n: column dimension
		 * @param [out] A: output matrix
		 * @param format: input format (FflasAuto, FflasDense, FflasSMS, FflasBinary)
		 */
    template<class Field>
    typename Field::Element_ptr
    ReadMatrix (std::ifstream& ifs, Field& F, size_t& m, size_t& n,
                typename Field::Element_ptr& A, FFLAS_FORMAT format = FflasAuto){

		FFLAS_FORMAT form = format;

		if (form == FflasAuto){
				// Preamble analysis. Update form to the discovered format.
			preamble(ifs, form);
		}

        switch (form){
            case FflasDense:{
                ifs >> m;
                ifs >> n;
                A = fflas_new(F, m,n);
                for (size_t i=0; i<m*n; i++){
                    F.read (ifs, A[i]);
                }
                break;
			}
            case FflasSMS:{
                ifs >> m;
                ifs >> n;
                size_t i,j;
				std::string tmp;
				typename Field::Element val;
				ifs >> tmp;
                A = fflas_new(F, m,n);
                do{
                    ifs >> i >> j;
					if (i>m || j>n){
						std::cerr<<"Matrix file does not respect the SMS format"<<std::endl;
						return NULL;
					}
                    F.read (ifs, val);
					if (i>0 && i>0) F.assign (A [(i-1)*n+j-1], val);
                } while (!(i==0 && j==0 && F.isZero(val)));
                break;
			}
            case FflasBinary:{
				char st[9];
				ifs.getline(st, 9);
				if (strcmp (st,"FFBinFmt")){
					std::cerr<<"Not a FFLAS-FFPACK binary matrix format: preamble = "<<st<<std::endl;
					return NULL;
				}
				size_t mm, nn;
				ifs.read(reinterpret_cast<char *>(&mm), sizeof(size_t));
				ifs.read(reinterpret_cast<char *>(&nn), sizeof(size_t));
				m=mm,n=nn;
				A = fflas_new(F, m,n);
				ifs.read (reinterpret_cast<char *>(A), sizeof(typename Field::Element)*m*n);
				ifs.close();
                break;
			}
            default:
                std::cerr<<"Unable to detect the file format"<<std::endl;
        }
        return A;
    }

		/**
		 * @brief ReadMatrix: read a matrix from a file
		 * @param matrix_file: filename
		 * @param F: base field
		 * @param [out] m: row dimension
		 * @param [out] n: column dimension
		 * @param [out] A: output matrix
		 * @param format: input format (FflasAuto, FflasDense, FflasSMS, FflasBinary)
		 */
    template<class Field>
    inline typename Field::Element_ptr
    ReadMatrix (const std::string& matrix_file, Field & F, size_t & m, size_t& n,
                typename Field::Element_ptr& A, FFLAS_FORMAT format = FflasAuto){

        std::ios_base::openmode mode = std::ios::in;
        if (format == FflasBinary)
            mode |= std::ifstream::binary;

        std::ifstream ifs (matrix_file, mode);
		if (ifs.is_open()){
			ReadMatrix (ifs, F, m, n, A, format);
			ifs.close();
		} else
			std::cerr<<"Error: unable to open file "<<matrix_file<<std::endl;

        return A;
    }

		/**
		 * @brief WriteMatrix: write a matrix to an output stream
		 * @param c: output stream
		 * @param F: base field
		 * @param m: row dimension
		 * @param n: column dimension
		 * @param A: matrix
		 * @param format: input format (FflasAuto, FflasDense, FflasSMS, FflasBinary)
		 * @param column_major: whether the matrix is stored in column or row major (row by default)
		 */
    template<class Field>
    std::ostream& WriteMatrix (std::ostream& c, const Field& F, size_t m, size_t n,
                               typename Field::ConstElement_ptr A, size_t lda,
                               FFLAS_FORMAT format = FflasMath,
                               bool column_major=false) {
		switch (format){
			case FflasSageMath:
				c << "Matrix (";
                if (F.characteristic() == 0)
                    c << "ZZ, ";
                else
					c << "GF("<<F.cardinality()<<"), ";
				c << m <<", " << n << ", [" ;
				for (size_t i = 0; i<m; ++i){
					c << '[';
					for (size_t j=0; j<n;++j){
						if (column_major) F.write (c, A[j*lda+i]);
						else F.write (c, A[i*lda+j]);
						if (j < n-1) c << ", ";
					}
					c << ']';
					if (i < m-1) c << ", ";
				}
				c << "]);\n";
				break;
			case FflasMaple:
				c << "Matrix (";<commit_msg>Removed semicolon for SageMath output<commit_after>/* -*- mode: C++; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
// vim:sts=4:sw=4:ts=4:noet:sr:cino=>s,f0,{0,g0,(0,\:0,t0,+0,=s
/* Copyright (C) FFLAS-FFPACK 2017
 * written by <NAME> (<EMAIL>)
 * ========LICENCE========
 * This file is part of the library FFLAS-FFPACK.
 *
 * FFLAS-FFPACK is free software: you can redistribute it and/or modify
 * it under the terms of the  GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 * ========LICENCE========
 */

#ifndef __FFLAS_IO_H
#define __FFLAS_IO_H

#include <cstring>
#include <stdio.h>
#include <stdlib.h>
#include <fstream>
//#include "fflas-ffpack/fflas/fflas.h"
#include "fflas_memory.h"

// Reading and writing matrices over field

namespace FFLAS{

    enum FFLAS_FORMAT {
        FflasAuto     = 0, // Automated detection of the format
        FflasDense    = 1, // Dense format (Array)
        FflasSMS      = 2, // Sparse Matrix format (Matrix Market)
        FflasBinary   = 3, // Binary format
        FflasMath     = 4, // Standard math. notation
        FflasMaple    = 5, // Maple input
        FflasSageMath = 6  // SageMath input
    };
    

    inline void preamble(std::ifstream&ifs, FFLAS_FORMAT& format){
		char st[8];
		ifs.getline(st, 9);
		if (!strcmp(st,"FFBinFmt")){
			format = FflasBinary;

		}else{
				// No detection of non-binary formats for the moment
			format = FflasSMS;
		}
		ifs.seekg(0);
		return;
			// Detect Dense and SMS formats
    }

		/**
		 * @brief ReadMatrix: read a matrix from an input stream
		 * @param ifs: input stream
		 * @param F: base field
		 * @param [out] m: row dimension
		 * @param [out] n: column dimension
		 * @param [out] A: output matrix
		 * @param format: input format (FflasAuto, FflasDense, FflasSMS, FflasBinary)
		 */
    template<class Field>
    typename Field::Element_ptr
    ReadMatrix (std::ifstream& ifs, Field& F, size_t& m, size_t& n,
                typename Field::Element_ptr& A, FFLAS_FORMAT format = FflasAuto){

		FFLAS_FORMAT form = format;

		if (form == FflasAuto){
				// Preamble analysis. Update form to the discovered format.
			preamble(ifs, form);
		}

        switch (form){
            case FflasDense:{
                ifs >> m;
                ifs >> n;
                A = fflas_new(F, m,n);
                for (size_t i=0; i<m*n; i++){
                    F.read (ifs, A[i]);
                }
                break;
			}
            case FflasSMS:{
                ifs >> m;
                ifs >> n;
                size_t i,j;
				std::string tmp;
				typename Field::Element val;
				ifs >> tmp;
                A = fflas_new(F, m,n);
                do{
                    ifs >> i >> j;
					if (i>m || j>n){
						std::cerr<<"Matrix file does not respect the SMS format"<<std::endl;
						return NULL;
					}
                    F.read (ifs, val);
					if (i>0 && i>0) F.assign (A [(i-1)*n+j-1], val);
                } while (!(i==0 && j==0 && F.isZero(val)));
                break;
			}
            case FflasBinary:{
				char st[9];
				ifs.getline(st, 9);
				if (strcmp (st,"FFBinFmt")){
					std::cerr<<"Not a FFLAS-FFPACK binary matrix format: preamble = "<<st<<std::endl;
					return NULL;
				}
				size_t mm, nn;
				ifs.read(reinterpret_cast<char *>(&mm), sizeof(size_t));
				ifs.read(reinterpret_cast<char *>(&nn), sizeof(size_t));
				m=mm,n=nn;
				A = fflas_new(F, m,n);
				ifs.read (reinterpret_cast<char *>(A), sizeof(typename Field::Element)*m*n);
				ifs.close();
                break;
			}
            default:
                std::cerr<<"Unable to detect the file format"<<std::endl;
        }
        return A;
    }

		/**
		 * @brief ReadMatrix: read a matrix from a file
		 * @param matrix_file: filename
		 * @param F: base field
		 * @param [out] m: row dimension
		 * @param [out] n: column dimension
		 * @param [out] A: output matrix
		 * @param format: input format (FflasAuto, FflasDense, FflasSMS, FflasBinary)
		 */
    template<class Field>
    inline typename Field::Element_ptr
    ReadMatrix (const std::string& matrix_file, Field & F, size_t & m, size_t& n,
                typename Field::Element_ptr& A, FFLAS_FORMAT format = FflasAuto){

        std::ios_base::openmode mode = std::ios::in;
        if (format == FflasBinary)
            mode |= std::ifstream::binary;

        std::ifstream ifs (matrix_file, mode);
		if (ifs.is_open()){
			ReadMatrix (ifs, F, m, n, A, format);
			ifs.close();
		} else
			std::cerr<<"Error: unable to open file "<<matrix_file<<std::endl;

        return A;
    }

		/**
		 * @brief WriteMatrix: write a matrix to an output stream
		 * @param c: output stream
		 * @param F: base field
		 * @param m: row dimension
		 * @param n: column dimension
		 * @param A: matrix
		 * @param format: input format (FflasAuto, FflasDense, FflasSMS, FflasBinary)
		 * @param column_major: whether the matrix is stored in column or row major (row by default)
		 */
    template<class Field>
    std::ostream& WriteMatrix (std::ostream& c, const Field& F, size_t m, size_t n,
                               typename Field::ConstElement_ptr A, size_t lda,
                               FFLAS_FORMAT format = FflasMath,
                               bool column_major=false) {
		switch (format){
			case FflasSageMath:
				c << "Matrix (";
                if (F.characteristic() == 0)
                    c << "ZZ, ";
                else
					c << "GF("<<F.cardinality()<<"), ";
				c << m <<", " << n << ", [" ;
				for (size_t i = 0; i<m; ++i){
					c << '[';
					for (size_t j=0; j<n;++j){
						if (column_major) F.write (c, A[j*lda+i]);
						else F.write (c, A[i*lda+j]);
						if (j < n-1) c << ", ";
					}
					c << ']';
					if (i < m-1) c << ", ";
				}
				c << "])\n";
				break;
			case FflasMaple:
				c << "Matrix (";
{'fraction_non_alphanumeric': 0.13938070353326573, 'fraction_numerical': 0.008267685827938537, 'mean_word_length': 2.2436124462433593, 'pattern_counts': {'":': 0, '<': 137, '<?xml version=': 0, '>': 65, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '899799', 'n_tokens_mistral': 4846, 'n_tokens_neox': 4219, 'n_words': 1296}