
//
// To jest przykładowy kod z podrozdziału 24.5.2 „Macierze jednowymiarowe” książki
// "Programowanie. Teoria i praktyka z wykorzystaniem C++" Bjarne'a Stroustrupa.
//

#include "Matrix.h"

using namespace Numeric_lib;

//------------------------------------------------------------------------------

double f(double a) { return a*a; }

//------------------------------------------------------------------------------

double f2(double a, double b) { return a*b; }

//------------------------------------------------------------------------------

double scale(double d, double s) { return d*s; }

//------------------------------------------------------------------------------

void scale_in_place(double& d, double s) { d *= s; }

//------------------------------------------------------------------------------

int main()
{
    Matrix<int,1> a1(8);          // a1 jest jednowymiarową macierzą liczb typu int.
    Matrix<int>   a(8);           // Oznacza Matrix<int,1> a(8);.

    a.size();                     // Liczba elementów w macierzy.
    a.dim1();                     // Liczba elementów w pierwszym wymiarze.

    int  i = 4;
    int  n = 7;
    int* p = a.data();            // Wydobywa dane jako wskaźnik na tablicę.

    a(i);                         // i-ty element (styl języka Fortran), ale sprawdzany jest zakres.
    a[i];                         // i-ty element (styl języka C), ze sprawdzaniem zakresu.
    //a(1,2);                     // Błąd: a jest macierzą jednowymiarową.

    a.slice(i);                   // Elementy od elementu a[i] do końca.
    a.slice(i,n);                  // n elementów od a[i] do a[i+n–1].

    a.slice(4,4) = a.slice(0,4);  // Przypisuje pierwszą połowę a do jej drugiej połowy.
    a.slice(4) = a.slice(0,4);    // Przypisuje pierwszą połowę a do jej drugiej połowy.

    Matrix<int> a2 = a;           // inicjowanie kopiujące
    a = a2;                       // przypisanie kopiujące
    a *= 7;                       // Skalowanie: a[i]*=7 dla każdego i (także +=, –=, /=, itp.).
    a = 7;                        // a[i]=7 dla każdego i

    a.apply(f);                   // a[i]=f(a[i]) dla każdego elementu a[i]
    a.apply(f2,7);                // a[i]=f(a[i],7) dla każdego elementu a[i]

    Matrix<int> b = apply(abs,a); // Tworzy nową macierz, w której b(i)==abs(a(i)).

    b = a*7;                      // b[i] = a[i]*7 dla każdego i
    a *= 7;                       // a[i] =a[i]*7 dla każdego i
    Matrix<double> x(10);
    Matrix<double> y = apply(f,x);// y[i] =f(x[i]) dla każdego i
    x.apply(f);                   // x[i] =f(x[i]) dla każdego i

    b = apply(f2,a,7);            // b[i]=f(a[i],x) dla każdego i
    b = apply(scale,a,7);         // b[i] = a[i]*7 dla każdego i
    x.apply(scale_in_place,7);    // a[i] *= 7 dla każdego i

    Matrix<int> a3  = scale_and_add(a,8,a2); // Dodawanie i mnożenie w jednej operacji.
    int r = dot_product(a3,a);               // iloczyn skalarny

}

//------------------------------------------------------------------------------

void some_function(double* p, int n)
{
    double val[] = { 1.2, 2.3, 3.4, 4.5 };
    Matrix<double> data(p,n);
    Matrix<double> constants(val);
    // ...
}

//------------------------------------------------------------------------------
