#ifndef UTILS_H
#define UTILS_H

typedef __SIZE_TYPE__ size_t;
template<class T, size_t N>constexpr size_t array_size (T (&) [N]) { return N; }

template<class T, const int N> class TABLE {
  T data [N];
  public:
    /** @brief Konstruktor.
     *  @param f Ukazatel na constexpr funkci, která pak vytvoří tabulku.
     * */
    template<typename F> explicit constexpr TABLE (F f) noexcept {
      for (int n=0; n<N; n++) data [n] = f (n);
    }
    /** operator[] vrátí konstantní odkaz na prvek pole, protože se předpokládá,
     *  že instance této třídy bude jako taková též konstantní
     */
    const T & operator[] (const int index) const {
      return data [index];
    }
    /** @class iterator
     *  @brief range-based for () */
    class iterator {
      const T * ptr;
      public:
        iterator(const T * _ptr) : ptr (_ptr) {}
        iterator  operator++ ()                             { ++ptr;   return * this;    }
        bool      operator!= (const iterator & other) const { return   ptr != other.ptr; }
        const T & operator*  ()                       const { return * ptr;              }
    };
    iterator begin () const { return iterator (data    ); }
    iterator end   () const { return iterator (data + N); }
  protected:
};

static constexpr double X_PI = 3.14159265358979323846;
static constexpr double D_PI = 2.0 * X_PI;
/* cmath nejde použít, tak si to mírně zjednodušíme, ale musí to fungovat */
static constexpr double dabs (const double a) { return a < 0.0 ? -a : +a; }
static constexpr int i_round (const double a) { return a < 0.0 ? int (a - 0.5) : int (a + 0.5); }
/* tahle divná funkce počítá sinus, pokud even=true i kosinus, pokud even=false */
static constexpr double sincos (const double x, const bool even) {
  double result (0.0), element(1.0), divider(0.0);
  if (even) { element *= x; divider += 1.0; }
  constexpr double eps = 1.0e-9;      // maximální chyba výpočtu
  const double aa = - (x * x);
  for (;;) {
    result  += element;
    if (dabs  (element) < eps) break;
    divider += 1.0;
    double fact = divider;
    divider += 1.0;
    fact    *= divider;
    element *= aa / fact;
  }
  return result;
}

#endif // UTILS_H