pl-nk v0.4.5
Plonk|Plink|Plank are a set of cross-platform C/C++ frameworks for audio software development
plonk_InlineMiscOps.h
00001 /*
00002  -------------------------------------------------------------------------------
00003  This file is part of the Plink, Plonk, Plank libraries
00004   by Martin Robinson
00005  
00006  http://code.google.com/p/pl-nk/
00007  
00008  Copyright University of the West of England, Bristol 2011-14
00009  All rights reserved.
00010  
00011  Redistribution and use in source and binary forms, with or without
00012  modification, are permitted provided that the following conditions are met:
00013  
00014  * Redistributions of source code must retain the above copyright
00015    notice, this list of conditions and the following disclaimer.
00016  * Redistributions in binary form must reproduce the above copyright
00017    notice, this list of conditions and the following disclaimer in the
00018    documentation and/or other materials provided with the distribution.
00019  * Neither the name of University of the West of England, Bristol nor 
00020    the names of its contributors may be used to endorse or promote products
00021    derived from this software without specific prior written permission.
00022  
00023  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
00024  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
00025  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 
00026  DISCLAIMED. IN NO EVENT SHALL UNIVERSITY OF THE WEST OF ENGLAND, BRISTOL BE 
00027  LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 
00028  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE 
00029  GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
00030  HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
00031  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 
00032  OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
00033  
00034  This software makes use of third party libraries. For more information see:
00035  doc/license.txt included in the distribution.
00036  -------------------------------------------------------------------------------
00037  */
00038 
00039 #ifndef PLONK_INLINEMISCOPS_H
00040 #define PLONK_INLINEMISCOPS_H
00041 
00042 #include "plonk_Constants.h"
00043 #include "plonk_InlineUnaryOps.h"
00044 
00045 //------------------------------------------------------------------------------
00046 
00054 template<class Type> inline Type clip (Type const& value, Type const& lower, Type const& upper) throw() { return min (max (lower, value), upper); }
00055 
00056 inline int wrap (int value, int lower, int upper) throw()
00057 {
00058         int range;
00059     
00060         if (value >= upper) 
00061         {
00062                 range = upper - lower;
00063                 value -= range;
00064         
00065                 if (value < upper) 
00066             return value;
00067         } 
00068         else if (value < lower) 
00069         {
00070                 range = upper - lower;
00071                 value += range;
00072         
00073                 if (value >= lower) 
00074             return value;
00075         } 
00076         else
00077     {
00078         return value;
00079         }
00080     
00081         if (upper == lower) 
00082         return lower;
00083         else
00084         return value % range + lower;
00085 }
00086 
00087 template<class Type>
00088 inline Type wrap (Type const& v, Type const& lower, Type const& upper) throw()
00089 {
00090         Type range;
00091     Type value = v;
00092     
00093         if (value >= upper) 
00094         {
00095                 range = upper - lower;
00096                 value -= range;
00097         
00098                 if (value < upper) 
00099             return value;
00100         } 
00101         else if (value < lower) 
00102         {
00103                 range = upper - lower;
00104                 value += range;
00105         
00106                 if (value >= lower) 
00107             return value;
00108         } 
00109         else
00110     {
00111         return value;
00112         }
00113     
00114         if (upper == lower) 
00115         return lower;
00116     else
00117         return value - range * floor ((value - lower) / range); 
00118 }
00119 
00120 
00121 
00122 template<class Type>
00123 inline Type linlin (Type const& input, 
00124                     Type const& inLow, Type const& inHigh,
00125                     Type const& outLow, Type const& outHigh) throw()
00126 {
00127         const Type inRange = inHigh - inLow;
00128         const Type outRange = outHigh - outLow;
00129         return (input - inLow) * outRange / inRange + outLow;
00130 }
00131 
00132 template<class Type>
00133 inline Type linlin2 (Type const& input, 
00134                      Type const& inLow, Type const& inRange,
00135                      Type const& outLow, Type const& outRange) throw()
00136 {
00137         return (input - inLow) * outRange / inRange + outLow;
00138 }
00139 
00140 template<class Type>
00141 inline Type linsin (Type const& input, 
00142                     Type const& inLow, Type const& inHigh,
00143                     Type const& outLow, Type const& outHigh) throw()
00144 {
00145         const Type inRange = inHigh - inLow;
00146         const Type outRange = outHigh - outLow;
00147     
00148         const Type inPhase = (input - inLow) * Math<Type>::getPi() / inRange + Math<Type>::getPi();
00149         const Type cosInPhase = cos (inPhase) * Math<Type>::get0_5() + Math<Type>::get0_5();
00150         
00151         return cosInPhase * outRange + outLow;  
00152 }
00153 
00154 template<class Type>
00155 inline Type linsin2 (Type const& input, 
00156                      Type const& inLow, Type const& inRange,
00157                      Type const& outLow, Type const& outRange) throw()
00158 {       
00159         const Type inPhase = (input - inLow) * Math<Type>::getPi() / inRange + Math<Type>::getPi();
00160         const Type cosInPhase = cos (inPhase) * Math<Type>::get0_5() + Math<Type>::get0_5();
00161         return cosInPhase * outRange + outLow;  
00162 }
00163 
00164 template<class Type>
00165 inline Type linexp (Type const& input, 
00166                     Type const& inLow, Type const& inHigh,
00167                     Type const& outLow, Type const& outHigh) throw()
00168 {
00169         const Type outRatio = outHigh / outLow;
00170         const Type reciprocalInRange = Math<Type>::get1() / (inHigh - inLow);
00171         const Type inLowOverInRange = reciprocalInRange * inLow;
00172         return outLow * pow (outRatio, input * reciprocalInRange - inLowOverInRange);   
00173 }
00174 
00175 template<class Type>
00176 inline Type linexp2 (Type const& input, 
00177                      Type const& reciprocalInRange, Type const& inLowOverInRange,
00178                      Type const& outLow, Type const& outRatio) throw()
00179 {
00180         return outLow * pow (outRatio, input * reciprocalInRange - inLowOverInRange);   
00181 }
00182 
00183 template<class Type>
00184 inline Type linwelch (Type const& input, 
00185                       Type const& inLow, Type const& inHigh,
00186                       Type const& outLow, Type const& outHigh) throw()
00187 {
00188         const Type inRange = inHigh - inLow;
00189         const Type outRange = outHigh - outLow;
00190         const Type inPos = (input - inLow) / inRange;
00191     
00192         if (outLow < outHigh)
00193                 return outLow + outRange * sin (Math<Type>::getPi_2() * inPos);
00194         else
00195                 return outHigh - outRange * sin (Math<Type>::getPi_2() - Math<Type>::getPi_2() * inPos);
00196 }
00197 
00198 //template<class Type>
00199 //inline Type explin (Type const& input, 
00200 //                    Type const& inLow, Type const& inHigh, 
00201 //                    Type const& outLow, Type const& outHigh)
00202 //{
00203 //    if (input <= inLow) 
00204 //        return outLow;
00205 //    
00206 //    if (input >= inHigh) 
00207 //        return outHigh;
00208 //    
00209 //    return log (input / inLow) / log (inHigh / inLow) * (outHigh - outLow) + outLow;
00210 //}
00211 
00212 template<class Type>
00213 inline Type explin (Type const& input, 
00214                     Type const& inLow, Type const& inHigh, 
00215                     Type const& outLow, Type const& outHigh)
00216 {    
00217     const Type clipped = clip (input, inLow, inHigh);
00218     return log (clipped / inLow) / log (inHigh / inLow) * (outHigh - outLow) + outLow;
00219 }
00220 
00221 //------------------------------------------------------------------------------
00222 
00223 template<class ValueType, class IndexType, signed Extension, signed Offset> class InterpBase;
00224 template<class ValueType, class IndexType> class InterpNone;
00225 template<class ValueType, class IndexType> class InterpLinear;
00226 template<class ValueType, class IndexType> class InterpLagrange3;
00227 
00228 class Interp
00229 {
00230 public:
00231     enum TypeCode
00232     {
00233         None,
00234         Linear,
00235         Lagrange3,
00236         NumTypes
00237     };
00238 };
00239 
00240 template<class ValueType, class IndexType, Interp::TypeCode TypeCode>
00241 class InterpSelect
00242 {
00243 };
00244 
00245 template<class ValueType, class IndexType>
00246 class InterpSelect<ValueType, IndexType, Interp::None>
00247 {
00248 public:
00249     typedef InterpNone<ValueType,IndexType> InterpType;
00250 };
00251 
00252 template<class ValueType, class IndexType>
00253 class InterpSelect<ValueType, IndexType, Interp::Linear>
00254 {
00255 public:
00256     typedef InterpLinear<ValueType,IndexType> InterpType;
00257 };
00258 
00259 template<class ValueType, class IndexType>
00260 class InterpSelect<ValueType, IndexType, Interp::Lagrange3>
00261 {
00262 public:
00263     typedef InterpLagrange3<ValueType,IndexType> InterpType;
00264 };
00265 
00266 
00267 template<class ValueType, class IndexType, signed Extension, signed Offset>
00268 class InterpBase : public Interp
00269 {
00270 public:
00271     struct ExtensionBuffer
00272     {
00273         ValueType buffer[Extension];
00274     };
00275 
00276     static inline int getExtension() throw() { return Extension; }
00277     static inline int getOffset() throw() { return Offset; }
00278     static inline const IndexType& getExtensionAsIndex() throw() { static const IndexType v (Extension); return v; }
00279     static inline const IndexType& getOffsetAsIndex() throw() { static const IndexType v (Offset); return v; }    
00280 };
00281 
00282 template<class ValueType, class IndexType>
00283 class InterpNone : public InterpBase<ValueType,IndexType,0,0>
00284 {
00285 public:    
00286     static inline ValueType lookup (const ValueType* table, IndexType const& index) throw()
00287     {
00288         return table[int (index)];
00289     }
00290 };
00291 
00292 template<class ValueType, class IndexType>
00293 class InterpLinear : public InterpBase<ValueType,IndexType,1,0>
00294 {
00295 public:    
00296     static inline ValueType interp (ValueType const& value0, ValueType const& value1, IndexType const& frac) throw()
00297     {
00298         return value0 + ValueType ((value1 - value0) * frac);
00299     }
00300     
00301     static inline ValueType lookup (const ValueType* table, IndexType const& index) throw()
00302     {
00303         const int index0 = int (index);
00304         const int index1 = index0 + 1;
00305         const IndexType frac = index - IndexType (index0);
00306         return interp (table[index0], table[index1], frac);
00307     }
00308 };
00309 
00310 template<class ValueType>
00311 class InterpLinear<ValueType,int> : public InterpBase<ValueType,int,1,0>
00312 {
00313 public:
00314     typedef int IndexType;
00315     
00316     static inline ValueType interp (ValueType const& value0, ValueType const& value1, IndexType const& frac) throw()
00317     {
00318         (void)value1;
00319         (void)frac;
00320         return value0;
00321     }
00322     
00323     static inline ValueType lookup (const ValueType* table, IndexType const& index) throw()
00324     {
00325         return table[index];
00326     }
00327 };
00328 
00329 template<class ValueType, class IndexType>
00330 class InterpLagrange3 : public InterpBase<ValueType,IndexType,4,1>
00331 {
00332 public:
00333     static inline ValueType interp (ValueType const& value_1,
00334                                     ValueType const& value0,
00335                                     ValueType const& value1,
00336                                     ValueType const& value2,
00337                                     IndexType const& frac) throw()
00338     {        
00339         const ValueType half = Math<ValueType>::get0_5();
00340         const ValueType third = Math<ValueType>::get1_3();
00341         const ValueType sixth = Math<ValueType>::get1_6();
00342         const ValueType c0 = value0;
00343         const ValueType c1 = value1 - third * value_1 - half * value0 - sixth * value2;
00344         const ValueType c2 = half * (value_1 + value1) - value0;
00345         const ValueType c3 = sixth * (value2 - value_1) + half * (value0 - value1);
00346         return ((c3 * frac + c2) * frac + c1) * frac + c0;
00347     }
00348     
00349     static inline ValueType lookup (const ValueType* table, IndexType const& index) throw()
00350     {
00351         const int index0 = int (index);
00352         const int index1 = index0 + 1;
00353         const int index_1 = index0 - 1;
00354         const int index2 = index1 + 1;
00355         const IndexType frac = index - IndexType (index0);
00356         return interp (table[index_1], table[index0], table[index1], table[index2], frac);
00357     }
00358 };
00359 
00360 template<class ValueType>
00361 class InterpLagrange3<ValueType,int> : public InterpBase<ValueType,int,4,1>
00362 {
00363 public:
00364     typedef int IndexType;
00365 
00366     static inline ValueType interp (ValueType const& value_1,
00367                                     ValueType const& value0,
00368                                     ValueType const& value1,
00369                                     ValueType const& value2,
00370                                     IndexType const& frac) throw()
00371     {
00372         (void)value_1;
00373         (void)value1;
00374         (void)value2;
00375         (void)frac;
00376         return value0;
00377     }
00378     
00379     static inline ValueType lookup (const ValueType* table, IndexType const& index) throw()
00380     {
00381         return table[index];
00382     }
00383 };
00384 
00385 
00386 template<class Type, signed NumBits>
00387 class BitsBase
00388 {
00389 public:
00390 };
00391 
00392 
00393 #define PLONK_BITSBASE_DECLARE(TypeCode,TypeSize)\
00394     template<class Type>\
00395     class BitsBase<Type,TypeSize>\
00396     {\
00397     public:\
00398         typedef PlankU##TypeCode InternalType;\
00399         \
00400         static inline Type countOnes             (Type const& value) throw() { return (Type)pl_CountOnesU##TypeCode ((InternalType)value);          }\
00401         static inline Type countLeadingZeros     (Type const& value) throw() { return (Type)pl_CountLeadingZerosU##TypeCode ((InternalType)value);  }\
00402         static inline Type countTrailingZeroes   (Type const& value) throw() { return (Type)pl_CountTrailingZerosU##TypeCode ((InternalType)value); }\
00403         static inline Type countLeadingOnes      (Type const& value) throw() { return (Type)pl_CountLeadingOnesU##TypeCode ((InternalType)value);   }\
00404         static inline Type countTrailingOnes     (Type const& value) throw() { return (Type)pl_CountTrailingOnesU##TypeCode ((InternalType)value);  }\
00405         static inline Type numBitsRequired       (Type const& value) throw() { return (Type)pl_NumBitsRequiredU##TypeCode ((InternalType)value);    }\
00406         static inline Type nextPowerOf2          (Type const& value) throw() { return (Type)pl_NextPowerOf2U##TypeCode ((InternalType)value);       }\
00407         static inline bool isPowerOf2            (Type const& value) throw() { return (Type)pl_IsPowerOf2U##TypeCode ((InternalType)value);         }\
00408     }
00409 
00410 PLONK_BITSBASE_DECLARE(C,1);
00411 PLONK_BITSBASE_DECLARE(S,2);
00412 PLONK_BITSBASE_DECLARE(I,4);
00413 PLONK_BITSBASE_DECLARE(LL,8);
00414 
00415 
00417 class Bits
00418 {
00419 public:
00420     template<class Type> static inline Type countOnes             (Type const& value) throw() { return BitsBase<Type,sizeof(Type)>::countOnes (value);              }
00421     template<class Type> static inline Type countLeadingZeros     (Type const& value) throw() { return BitsBase<Type,sizeof(Type)>::countLeadingZeros (value);      }
00422     template<class Type> static inline Type countTrailingZeroes   (Type const& value) throw() { return BitsBase<Type,sizeof(Type)>::countTrailingZeroes (value);    }
00423     template<class Type> static inline Type countLeadingOnes      (Type const& value) throw() { return BitsBase<Type,sizeof(Type)>::countLeadingOnes (value);       }
00424     template<class Type> static inline Type countTrailingOnes     (Type const& value) throw() { return BitsBase<Type,sizeof(Type)>::countTrailingOnes (value);      }
00425     template<class Type> static inline Type numBitsRequired       (Type const& value) throw() { return BitsBase<Type,sizeof(Type)>::numBitsRequired (value);        }
00426     template<class Type> static inline Type nextPowerOf2          (Type const& value) throw() { return BitsBase<Type,sizeof(Type)>::nextPowerOf2 (value);           }
00427     template<class Type> static inline bool isPowerOf2            (Type const& value) throw() { return BitsBase<Type,sizeof(Type)>::isPowerOf2 (value);             }
00428 };
00429 
00430 
00432 class NumericalConverter
00433 {
00434 public:
00435     template<class InType, class OutType>
00436     static inline void roundCopy (const InType inValue, OutType& outValue) throw()     { outValue = OutType (inValue); }        
00437     
00438     static inline void roundCopy (const double inValue, char& outValue) throw()        { outValue = char (inValue + 0.5); }
00439         static inline void roundCopy (const double inValue, short& outValue) throw()       { outValue = short (inValue + 0.5); }
00440         static inline void roundCopy (const double inValue, int& outValue) throw()         { outValue = int (inValue + 0.5); }
00441         static inline void roundCopy (const double inValue, Int24& outValue) throw()       { outValue = Int24 (inValue + 0.5); }
00442     static inline void roundCopy (const double inValue, LongLong& outValue) throw()    { outValue = LongLong (inValue + 0.5); }    
00443     
00444     static inline void roundCopy (const float inValue, char& outValue) throw()         { outValue = char (inValue + 0.5f); }
00445         static inline void roundCopy (const float inValue, short& outValue) throw()        { outValue = short (inValue + 0.5f); }
00446         static inline void roundCopy (const float inValue, int& outValue) throw()          { outValue = int (inValue + 0.5f); }
00447     static inline void roundCopy (const float inValue, Int24& outValue) throw()        { outValue = Int24 (inValue + 0.5f); }
00448     static inline void roundCopy (const float inValue, LongLong& outValue) throw()     { outValue = LongLong (inValue + 0.5f); }
00449 };
00450 
00451 
00452 
00454 
00455 #endif // PLONK_INLINEMISCOPS_H
 All Classes Functions Typedefs Enumerations Enumerator Properties