#include "mylib.h"
#include <cmath>
#include <iostream>
using namespace std;

double f(unsigned int k, unsigned int nm) {
    
    return 1.0 / (1.0 + exp(-(10.0*k/(nm-1)-5)));
}

DenseMatrix::DenseMatrix(unsigned int n, unsigned int m): n_(n), m_(m), data_(n*m)
{
    unsigned int nm = max(n,m);
    for(unsigned int rowIt = 0; rowIt < n_; rowIt++)
    {
        for(unsigned int colIt=0; colIt <m_; colIt++)
        {
            data_.at(rowIt*m+colIt) = (f(rowIt,nm)*f(colIt,nm));
        }
    }
}

vector<double> DenseMatrix::Mult(const vector<double> &u) const{
    if(u.size() !=  m_)
    {
        cout << "Dimension mismatch: expected " << m_ << " but got " << u.size() << "!" << endl;
        return {};
    }
    vector<double> f1 = {};
    double sum;
    for(unsigned int rowIt = 0; rowIt < n_; rowIt++)
    {
        sum = 0;
        for(unsigned int colIt=0; colIt <m_; colIt++)
        {
            sum += data_.at(rowIt*m_+colIt) * u.at(colIt);
        }
        f1.push_back(sum);
    }
    return f1;
}

vector<double> DenseMatrix::MultT(const vector<double> &v) const{
    if(v.size() !=  n_)
    {
       cout << "Dimension mismatch: expected " << n_ << " but got " << v.size() << "!" << endl;
        return {};
    }
    vector<double> f2 = {};
    double sum;
    for(unsigned int colIt = 0; colIt < m_; colIt++)
    {
        sum = 0;
        for(unsigned int rowIt=0; rowIt <n_; rowIt++)
        {
            sum += data_.at(rowIt*m_+colIt) * v.at(rowIt);
        }
        f2.push_back(sum);
    }
    return f2;
}


//-----------------------------------------------------------------------------------------------
Dyadic::Dyadic(vector<double>& u, vector<double>& v):u_(u), v_(v){

}

vector<double> Dyadic::Mult(const vector<double> &w) const{
    unsigned int m = v_.size();
    if(w.size() !=  m)
    {
        cout << "Dimension mismatch!" << endl;
        return {};
    }
    vector<double> f1 = {};
    double skalar = 0;
    for(unsigned int vIt = 0; vIt < m; vIt++)
    {
        skalar += v_.at(vIt)*w.at(vIt);
    }
    for(unsigned int uIt=0; uIt < u_.size(); uIt++)
    {
        f1.push_back(u_.at(uIt)*skalar);
    }

    return f1;
}

vector<double> Dyadic::MultT(const vector<double> &w) const{
    unsigned int n = u_.size();
    if(w.size() !=  n)
    {
        cout << "Dimension mismatch!" << endl;
        return {};
    }
    vector<double> f1 = {};
    double skalar = 0;
    for(unsigned int uIt = 0; uIt < n; uIt++)
    {
        skalar += u_.at(uIt)*w.at(uIt);
    }
    for(unsigned int vIt=0; vIt < v_.size(); vIt++)
    {
        f1.push_back(v_.at(vIt)*skalar);
    }

    return f1;
}