// -*- C++ -*-

// ===== FUNCTIONS declared in auxil/inline.h: =====

inline void  swap(Type &x, Type &y);

inline void  swap0(Type &x, Type &y);
// swap() for y known to be zero

inline Type  min(const Type &x, const Type &y);

inline Type  max(const Type &x, const Type &y);

inline int   sign(const Type &x);

inline Type  abs(const Type &x);

inline void sort2(Type &x1, Type &x2);

inline int in_range_q(Type x, Type xmin, Type xmax);

inline void clip_range(Type &x, Type xmin, Type xmax);

// ===== FUNCTIONS declared in auxil/auxbit.h: =====

inline ulong rotate_left(ulong x, ulong s);

inline ulong rotate_right(ulong x, ulong s);

inline ulong graycode(ulong x);

inline ulong inverse_graycode(ulong x);
// inverse if graycode()

inline ulong parity(ulong x);

inline ulong bit_count(ulong x);
// return number of bits set

inline ulong bit_count_sparse(ulong x);
// return number of bits set
// the loop will execute once for each bit of x set

inline ulong highest_bit(ulong x);
// return index of highest bit set
// return ~0 if no bit is set

inline ulong lowest_bit(ulong x);
// return index of lowest bit set
// return ~0 if no bit is set

inline ulong ld(ulong x);
// returns k so that 2^k <= x < 2^(k+1)

inline ulong ldq(ulong x);
// return k if x=2**k
// else return ~0

inline unsigned long long ld(unsigned long long x);
// returns k so that 2^k <= x < 2^(k+1)

inline int is_pow_of_2(ulong x);
// return 1 if x == 0(!) or x == 2**k

inline int one_bit_q(ulong x);
// return 1 iff x \in {1,2,4,8,16,...}

inline ulong next_pow_of_2(ulong x);
// return x if x=2**k
// else return 2**ceil(log_2(x))

inline ulong next_exp_of_2(ulong x);
// return k if x=2**k
// else return k+1

inline ulong next_comb(ulong w);
// return smallest integer greater than u with the same number of bits set.
//
//  examples (binary notation):
//    1 -> 10 -> 100 -> 1000 -> 10000 -> 100000 -> 1000000 -> ...
//    11 -> 101 -> 110 -> 1001 -> 1010 -> 1100 -> 10001 -> ...
//    111 -> 1011 -> 1101 -> 1110 -> 10011 -> 10101 -> 10110 -> ...
//
//  special cases:
//    0 -> 0
//    if the number is too large then 0 is returned.
//
//  The bit pattern to change at the end of the word is:
//    0 1   0   ->    1 0   1
//       a   b           b+1 a-1
//
//  Example: (the bits marked by B remain fixed)
//    w       = BBBB01111100000000
//    z       = 000000000100000000   (the lowest set bit)
//    w+z     = BBBB10000000000000
//    (w+z)^w = 000011111100000000
//    next    = BBBB10000000001111
//
//  this was shamelessly stolen from Torsten Sillke's bitman.h
//  (the algorithm can be found in hakmem)

// ===== FUNCTIONS declared in auxil/auxdouble.h: =====

// ----- SRCFILE=auxil/auxdouble.cc: -----
double rnd01();
// random number in [0,1[

double white_noise();
// returns one sample of white noise (with mean=0, sigma=1)

double pythag(double a, double b);
// return sqrt(a*a+b*b)

double extr3_estimate(const double *f, double *xvalp/*=0*/);
// return extremum (y-value) of parabola through 
// the points (-1,a), (0,b), (+1,c)
// optional also get the x-value

double sinc(double x);
// return sin(pi*x)/(pi*x)

void sumdiff(double *x, double *y, ulong n);
// x[]=(x[]+y[]),  y[]=(x[]+y[])

void sumdiff_05(double *x, double *y, ulong n);
// x[]=(x[]+y[])*0.5,  y[]=(x[]+y[])*0.5

double norm(const double *f, ulong n);
// return sqrt(\sum_k{f[k]*f[k]})

void normalize(double *f, ulong n, double v/*=1.0*/);
// scale f[] to norm v

double scalar_product(const double *f, const double *g, ulong n);
// return \sum_k{f[k]*g[k]}

double mean(const double *f, ulong n);
// return (\sum_k{f[k]})/n

double subtract_mean(double *f, ulong n, double *dst=0);
// subtract from f[] its mean value

double sigma(const double *f, ulong n, double *mp/*=0*/);
// return standard deviation
// = sqrt(\sum_k{sqr(f[k]-mean(f[]))}/n)

void mean_sigma(const double *f, ulong n, double *mp, double *sp);
// set *mp to mean, sp *to standard deviation of f[]

void smooth(double *f, ulong n, ulong m/*=1*/);
//  apply (1/4,1/2,1/4) - filter

double rms_diff(const double *f, const double *g, ulong n);
// return sqrt(\sum_k{sqr(f[k]-g[k])})/n

double rms_diff(const Complex *f, const Complex *g, ulong n);
// return sqrt(\sum_k{sqr(abs(f[k]-g[k]))})/n

ulong * histogram(const double *f, ulong n, ulong nbox, ulong *hh/*=0*/);
// put histogram of f[] (with nbox boxes) into hh[]

void welch_win(double *f, ulong n);
// multiply f[] with a welch window

void ri_multiply(const double *fr, const double *fi,
            double *gr, double *gi, ulong n);
// complex multiply array g[] by f[]:
//  Complex(gr[],gi[]) *= Complex(fr[],fi[])

// ===== FUNCTIONS declared in auxil/copy.h: =====

swap(Type *f, Type *g, ulong n);
// swap arrays

copy_mem(const Type *src, Type *dst, ulong n);
// copy array using memcpy()

copy(const Type1 *src, Type2 *dst, ulong n);
// copy array

copy(const Type1 *src, ulong ns,;
     Type2 *dst, ulong nd)
// copy as much as makes sense, fill rest with zeroes
// from src[] (length ns) to dst[] (length nd):

skip_copy(const Type1 *src, Type2 *dst, ulong n, ulong d);
// copy n elements from src[] at positions
// [0],[d],[2d],[3d],...,[(n-1)*d]
// to dst[0, 1, ... ,n-1]

skip_copy_back(const Type1 *src, Type2 *dst, ulong n, ulong d);
// copy n elements from src[0, 1, ... ,n-1]
// to dst[] at positions
// [0],[d],[2d],[3d],...,[(n-1)*d]

null(Type *f, ulong n);
// set array to zero:

fill(Type *dst, ulong n, Type v);
// fill array with value v

fill_seq(Type *dst, ulong n, Type start=0, Type step=1);
// fill array with values
// start, start+step, start+2*step, ...

// ===== FUNCTIONS declared in auxil/minmax.h: =====

min(const Type *f, ulong n);
// returns minimum of array

min_idx(const Type *f, ulong n);
// returns index of minimum of array

max(const Type *f, ulong n);
// returns maximum of array


max_idx(const Type *f, ulong n);
// returns index of maximum of array

min_max(const Type *f, ulong n, Type *mi, Type *ma);
// sets *mi to minimum of array
// and  *ma to maximum of array

min_max_idx(const Type *f, ulong n, ulong *ii, ulong *ia);
// sets *ii to index of minimum of array
// and  *ia to index of maximum of array

update_min_max(const Type *f, ulong n, Type *mi, Type *ma);
// sets *mi to minimum of array_min and *mi
// and  *ma to maximum of array_max and *ma

next_min5_idx(const Type *f, ulong n, ulong start=0);
// returns index of first element (index >= start+2)
// which is minimal wrt. its 2 left and 2 right neighbours
// if no such element is found, n is returned

next_max5_idx(const Type *f, ulong n, ulong start=0);
// returns index of first element (index >= start+2)
// which is maximal wrt. its 2 left and 2 right neighbours
// if no such element is found, n is returned

max_sumbox_idx(const Type *f, ulong n, ulong boxlen);
// finds box of length boxlen
// for which sum of the elements is maximal
// returns index of first element of that box

min_sumbox_idx(const Type *f, ulong n, ulong boxlen);
// finds box of length boxlen
// for which sum of the elements is minimal
// returns index of first element of that box

// ===== FUNCTIONS declared in auxil/scale.h: =====

linear_scale(Type *f, ulong n,;
             Type mi, Type ma,     // old min, max
             Type nmi, Type nma)   // new min, max
// linear scale so that
//   new_min==nmi,  ne_max==nma
// supply (or pretend) old min and max

linear_scale(Type *f, ulong n,;
             Type nmi, Type nma)   // new min, max
// linear scale so that
//   new_min==nmi,  ne_max==nma

log_scale(Type *f, ulong n, double xi, double xa, Type nma);

// ===== FUNCTIONS declared in auxil/scan.h: =====

first_eq_idx(const Type *f, ulong n, Type v);
// return index of first element == v
// returns n if all !=v

first_ne_idx(const Type *f, ulong n, Type v);
// return index of first element != v
// returns n if all ==v

first_ge_idx(const Type *f, ulong n, Type v);
// returns index of first element >=v
// returns n if no such element is found

first_le_idx(const Type *f, ulong n, Type v);
// returns index of first element <=v
// returns n if no such element is found

last_eq_idx(const Type *f, ulong n, Type v);
// return index of last element == v
// returns n if all !=v

last_ne_idx(const Type *f, ulong n, Type v);
// return index of last element != v
// returns n if all ==v

last_ge_idx(const Type *f, ulong n, Type v);
// return index of last element >= v
// returns n if all <v

last_le_idx(const Type *f, ulong n, Type v);
// return index of last element <= v
// returns n if all >v

eq_count(const Type *f, ulong n, Type v);
// returns number of elements that are ==v

ne_count(const Type *f, ulong n, Type v);
// returns number of elements that are !=v

ge_count(const Type *f, ulong n, Type v);
// returns number of elements that are >=v

le_count(const Type *f, ulong n, Type v);
// returns number of elements that are <=v

// ===== FUNCTIONS declared in auxil/scanbox.h: =====

first_ge_sumbox_idx(const Type *f, ulong n, Type v, ulong boxlen);
// finds first box of length boxlen
// for which sum of the elements is >=v
// returns index of first element of that box
// returns n if no such box is found

last_ge_sumbox_idx(const Type *f, ulong n, Type v, ulong boxlen);
// finds last box of length boxlen
// for which sum of the elements is >=v
// returns index of first element of that box
// returns n if no such box is found
// add boxlen-1 to the result to get end of the box

first_le_sumbox_idx(const Type *f, ulong n, Type v, ulong boxlen);
// finds first box of length boxlen
// for which sum of the elements is <=v
// returns index of first element of that box
// returns n if no such box is found

last_le_sumbox_idx(const Type *f, ulong n, Type v, ulong boxlen);
// finds last box of length boxlen
// for which sum of the elements is <=v
// returns index of first element of that box
// returns n if no such box is found
// add boxlen-1 to the result to get end of the box

// ===== FUNCTIONS declared in auxil/shift.h: =====

shift_left(Type *f, ulong n, ulong s);
// shift towards element #0

shift_right(Type *f, ulong n, ulong s);
// shift away from element #0

shift(Type *f, ulong n, long s);

// ===== FUNCTIONS declared in auxil/misc.h: =====

get_sum(const Type *f, ulong n);
// return sum of array f[]

diff(Type *f, ulong n, ulong j=1);
// first difference (applied j times) of f[]

negate(Type *f, ulong n);
// negate f[]

multiply(Type *f, ulong n, Type s);
// multiply f[] by s

apply_func(Type *f, ulong n, Type (*func)(Type));
// apply function func to each element of f[]

