Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <cstdint>
- #include <type_traits>
- #include <type_traits>
- template<typename T>
- struct uiChecks {
- static constexpr bool isUnsigned = std::is_unsigned<T>::value || std::is_same<T, __uint128_t>::value;
- static constexpr bool isIntegral = std::is_integral<T>::value || std::is_same<T, __uint128_t>::value;
- static constexpr bool isBig = std::endian::native == std::endian::big;
- };
- template <typename T>
- void uiRequired() {
- static_assert(uiChecks<T>::isUnsigned, "Type must be unsigned integer type");
- static_assert(uiChecks<T>::isIntegral, "Type must be an integer");
- }
- //select uint type that is double of T width
- template <typename T>
- struct twiceWide {
- using type = typename std::conditional<(sizeof(T) == 1), uint16_t,
- typename std::conditional<(sizeof(T) == 2), uint32_t,
- typename std::conditional<(sizeof(T) == 4), uint64_t,
- typename std::conditional<(sizeof(T) == 8), __uint128_t,
- void>::type>::type>::type>::type;
- };
- //Fast sine approximation.
- template <typename T>
- T ukaelSine(T num) {
- uiRequired<T>(); //check uint compatibility
- using T2 = typename twiceWide<T>::type; //requires twice T bit width for squaring
- bool secondHalf = (num >> ((sizeof(T)<<3) - 1)); //sizeof(T)*8-1. values that're more than 0.5*UINT_MAX
- num <<= 1; //get 2 periods of saw wave
- T2 buf = (static_cast<T2>(num)<<1) - ((T)~0); //store to twiceWide to prevent overflow
- num = static_cast<T>((buf * buf) >> ((sizeof(T)<<3) + 1)); //square and revert back to T scale
- num = secondHalf ? num : ~num; //invert 2nd half
- return num;
- }
- //Crunchy Sine
- template <typename T>
- T ukaelCSine(T num) {
- uiRequired<T>();
- bool secondHalf = (num >> ((sizeof(T)<<3) - 1));
- bool evenQuarter = (num >> ((sizeof(T)<<3) - 2))==0 || (num >> ((sizeof(T)<<3) - 2))==2;
- num = evenQuarter ? ~num : num; //invert even quarters
- num <<= 2; //2 period saw
- num >>= sizeof(T)<<2; //square root. Crunchy precision
- num*=num; //square
- num >>= 1; //divide by 2
- num = secondHalf ? num : ~num; //invert 2nd half
- return num;
- }
- //triangle
- template <typename T>
- T ukaelTriangle(T num) {
- uiRequired<T>();
- num+=((T)~0)>>2; //add UINT_MAX/4
- bool secondHalf = (num >> ((sizeof(T)<<3) - 1));
- num <<= 1; //*2
- num = secondHalf ? ~num : num; //invert 2nd half
- return num;
- }
- //Saw
- template <typename T>
- T ukaelSaw(T num){
- num+=((T)~0)>>1; //add UINT_MAX/2
- return num;
- }
- //Square
- template <typename T>
- T ukaelSquare(T num){
- uiRequired<T>();
- return ( num>>((sizeof(T)<<3)-1) ) ? T(0) : ~0; //hi if 0 to 0.5, low if 0.5 to 1.0
- }
- //Pulse square 2 arguments
- template <typename T>
- T ukaelPulse(T num, T dutyCycle) {
- uiRequired<T>();
- return (num >= dutyCycle) ? T(0) : ~0 ; //same as square but dutyCycle sets treshold
- }
- //pseudo random noise generator, 2 optionally different types
- template <typename T>
- T ukaelNoise(T num) {
- uiRequired<T>();
- constexpr size_t sz = sizeof(T)*2;
- num^=num<<((num&sz)+2);
- num*=3083;
- num^=num>>((num&sz)+2);
- return num;
- }
Advertisement
Comments
-
Comment was deleted
-
- https://pastebin.com/DckxKHju
Add Comment
Please, Sign In to add comment
Advertisement