/*
* utils.h
* DIN Is Noise is copyright (c) 2006-2024 Jagannathan Sampath
* For more information, please visit http://dinisnoise.org/
*/

#ifndef _UTILS
#define _UTILS

#define SIGN(x) ((x) < 0 ? -1 : (x) > 0)

#include "log.h"
#include <cmath>

using namespace std;

template <typename T> T transfer (const T& v, const T& a, const T& b, const T& c, const T& d) {
  if (a != b) {
    T q = (v - a) / (b - a);
    T tv = c + q * (d - c);
    return tv;
  }
  return 0;
}

template <typename T> inline bool inrange (const T& min, const T& val, const T& max) {
  return ((val >= min) && (val <= max));
}

template<typename T> inline int clamp (const T& lo, T& val, const T& hi) {
  // ensures lo <= val <= hi
  if (val < lo) {
    val = lo; 
    return -1;
  } else if (val > hi) {
    val = hi; 
    return 1;
  } 
  return 0;
}

template<typename T> inline T& wrap (const T& lo, T& val, const T& hi) {
  // val stays between lo and hi but wraps
  if (val < lo) val = hi; else if (val > hi) val = lo;
  return val;
}

template<typename T> inline int bounce (T low, T& val, T high, T reb) {
	// val stays between lo and hi but rebounds
	if (val < low) {
		val += reb;
		return bounce (low, val, high, reb); // can still exceed high
	} else if (val > high) {
		val -= reb;
		return bounce (low, val, high, reb); // can still go below low
	}
	return 1;
}

template <typename T> int equals (T a, T b, T e = 0.0001f) {
	return (abs(a-b) <= e);
}

template <typename T> int sign (T t) {
  return ( (t > T(0)) - (t < T(0)) );
}

struct item_op {
	virtual int operator()(int) const = 0;
};

struct sel : item_op {
	int operator()(int) const { return 1;}
};

struct desel : item_op {
	int operator()(int) const { return 0;}
};

struct togg : item_op {
	int operator()(int i) const { return !i;}
};

void multiply (float* out, float* mul, int n); // multiply n muls with n outs; store in out
void multiply (float* out, int n, float d); // multiply n outs with d; store in out
void fill (float* buf, float s, float e, int n); // fill buf with values interpolated from s to e
void tween (float* buf1, float* buf2, int n, float amount); // interpolate buf2 -> buf1 by amount; store in buf1
void tween (float* buf1, float* buf2, int n, float* pamount); // interpolate buf2 -> buf1 by amount array; store in buf1

#endif
