#include "mylib.h"
#include <iostream>
#include <cassert>
#include <vector>
using namespace std;
int main()
{

    //b)
    DenseMatrix const M(5,3); // Dense matrix, also initialized
    vector<double> const u{{1,2,3}};
    vector<double> f1 = M.Mult(u);
    vector<double> const v{{-1,2,-3,4,-5}};
    vector<double> f2 = M.MultT(v);

    for(unsigned int i = 0; i < f1.size(); i++)
    {
        cout << f1.at(i) << " ";
    }
    cout << endl;
    for(unsigned int i = 0; i < f2.size(); i++)
    {
        cout << f2.at(i) << " ";
    }
    cout << endl;


    //c)
    int n=5000;
    DenseMatrix const A(n,n);
    vector<double> w = {};
    for(int i = -n/2; i < n/2; i++)
    {
        w.push_back(i);
    } 


    int const NLOOPS=100;

    double t1 = clock(); // start timer
    vector<double> f3 = A.Mult(w);
    for (int k=1; k<NLOOPS; ++k)
    {
        f3 = A.Mult(w);
    }
    t1 = (clock()-t1)/CLOCKS_PER_SEC/NLOOPS;
    cout << "Time for Mult per it: " << t1 << endl;

    double t2 = clock(); // start timer
    vector<double> f4 = A.MultT(w);
    for (int k=1; k<NLOOPS; ++k)
    {
        f4 = A.MultT(w);
    }
    t2 = (clock()-t2)/CLOCKS_PER_SEC/NLOOPS;
    cout << "Time for MultT per it: " << t2 << endl; 
    //slower because consecutive calls to data vector of Matrix are more apart (+m) due to column wise access (non contiguous memory)

    double maxDiff = 0.0;
    for (size_t i = 0; i < f3.size(); ++i) {
        double diff = abs(f3[i] - f4[i]);
        if (diff > maxDiff) {
            maxDiff = diff;
        }
    }
    cout << "difference f3 and f4: " << maxDiff << endl;


    //d)
    cout << "-----------------DYADIC------------------" <<endl;
    vector<double> x = {};
    for(int k=0; k < n; k++)
    {
        x.push_back(f(k, n));
    }
    Dyadic const D(x,x);

    double t3 = clock(); // start timer
    vector<double> f5 = D.Mult(w);
    for (int k=1; k<NLOOPS; ++k)
    {
        f5 = D.Mult(w);
    }
    t3 = (clock()-t3)/CLOCKS_PER_SEC/NLOOPS;
    cout << "Time for Mult per it: " << t3 << endl;

    double t4 = clock(); // start timer
    vector<double> f6 = D.MultT(w);
    for (int k=1; k<NLOOPS; ++k)
    {
        f6 = D.MultT(w);
    }
    t4 = (clock()-t4)/CLOCKS_PER_SEC/NLOOPS;
    cout << "Time for MultT per it: " << t4 << endl; 
    //slower because consecutive calls to data vector of Matrix are more apart (+m) due to column wise access (non contiguous memory)

    double maxDiff2 = 0.0;
    for (size_t i = 0; i < f5.size(); ++i) {
        double diff = abs(f5[i] - f6[i]);
        if (diff > maxDiff2) {
            maxDiff2 = diff;
        }
    }
    cout << "difference f5 and f6: " << maxDiff2 << endl;


    
    return 0;
}
