using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ParallelForDemo
{
    class Program
    {
        private static double obliczenia(double argument)
        {
            for (int i = 0; i < 10; ++i) argument = Math.Asin(Math.Sin(argument));
            return argument;
        }

        static void Main(string[] args)
        {
            //przygotowania 
            int rozmiar = 10000;
            Random r = new Random();
            double[] tablica = new double[rozmiar];
            for(int i=0;i<tablica.Length;++i) tablica[i] = r.NextDouble();

            //obliczenia sekwencyjne
            int iloscPowtorzen = 100;
            double[] wyniki = new double[tablica.Length];
            int start = System.Environment.TickCount;
            for(int powtorzenia = 0; powtorzenia<iloscPowtorzen;++powtorzenia)
                for(int i=0;i<tablica.Length; ++i)
                    wyniki[i] = obliczenia(tablica[i]);
            int stop = System.Environment.TickCount;
            Console.WriteLine("Obliczenia sekwencyjne trwały " + (stop - start).ToString() + " ms.");

            //obliczenia równoległe
            start = System.Environment.TickCount;
            for(int powtorzenia = 0; powtorzenia < iloscPowtorzen; ++powtorzenia)
                Parallel.For(0, tablica.Length, i=>{ wyniki[i] = obliczenia(tablica[i]); });
            stop = System.Environment.TickCount;
            Console.WriteLine("Obliczenia równoległe trwały " + (stop - start).ToString() + " ms.");

            /*
            //prezentacja wyników 
            string s = "Wyniki:\n";
            for(int i=0;i<tablica.Length;++i)
                s += i + ". " + tablica[i] + " ?= " + wyniki[i] + "\n";
            Console.WriteLine(s);
            */

            przerywaniePetli();
        }

        private static void przerywaniePetli()
        {
            Random r = new Random();
            long suma  = 0;
            long licznik = 0;
            string s = "";

            //iteracje zostaną wykonane tylko dla liczb parzystych
            //pętla zostanie przerwana wcześniej, jeżeli wylosowana liczba jest większa od 90
            Parallel.For(
                0, 
                10000, 
                (int i, ParallelLoopState stanPetli) =>
                    {
                        int liczba = r.Next(7); //losowanie liczby oczek na kostce
                        if(liczba == 0)
                        {
                            s += "0 (Stop);";
                            stanPetli.Stop();
                        }
                        if(stanPetli.IsStopped) return;
                        if(liczba % 2 == 0)
                        {
                                   s += liczba.ToString() + "; ";
                                   obliczenia(liczba);
                                   suma += liczba;
                                   licznik += 1;
                        }
                        else
                        {
                            s += liczba.ToString() + "; ";
                        }
                    });

            Console.WriteLine(
                "Wylosowane liczby: " + s + "\n" +
                "Liczba pasujących liczb: " + licznik + "\n" +
                "Suma: " + suma + "\n" +
                "Średnia: " + (suma / (double)licznik).ToString());
        }
    }
}
