1055 lines
58 KiB
C++
1055 lines
58 KiB
C++
/**
|
|
* @file kMath.cpp
|
|
*
|
|
* @internal
|
|
* Copyright (C) 2005-2021 by LMI Technologies Inc.
|
|
* Licensed under the MIT License.
|
|
* Redistributed files must retain the above copyright notice.
|
|
*/
|
|
#include <kApi/Data/kMath.h>
|
|
#include <math.h>
|
|
|
|
kBeginStaticClassEx(k, kMath)
|
|
kEndStaticClassEx()
|
|
|
|
kFx(kStatus) xkMath_InitStatic()
|
|
{
|
|
return kOK;
|
|
}
|
|
|
|
kFx(kStatus) xkMath_ReleaseStatic()
|
|
{
|
|
return kOK;
|
|
}
|
|
|
|
template<typename T>
|
|
struct kIsEq
|
|
{
|
|
bool operator()(const T& v1, const T& v2) const { return v1 == v2; }
|
|
};
|
|
|
|
template<typename T>
|
|
struct kIsNeq
|
|
{
|
|
bool operator()(const T& v1, const T& v2) const { return v1 != v2; }
|
|
};
|
|
|
|
template<typename T>
|
|
struct kIsLt
|
|
{
|
|
bool operator()(const T& v1, const T& v2) const { return v1 < v2; }
|
|
};
|
|
|
|
template<typename T>
|
|
struct kIsLte
|
|
{
|
|
bool operator()(const T& v1, const T& v2) const { return v1 <= v2; }
|
|
};
|
|
|
|
template<typename T>
|
|
struct kIsGt
|
|
{
|
|
bool operator()(const T& v1, const T& v2) const { return v1 > v2; }
|
|
};
|
|
|
|
template<typename T>
|
|
struct kIsGte
|
|
{
|
|
bool operator()(const T& v1, const T& v2) const { return v1 >= v2; }
|
|
};
|
|
|
|
template<typename T>
|
|
struct kAdd
|
|
{
|
|
T operator()(const T& v1, const T& v2) const { return v1 + v2; }
|
|
};
|
|
|
|
template<typename T>
|
|
struct kSubtract
|
|
{
|
|
T operator()(const T& v1, const T& v2) const { return v1 - v2; }
|
|
};
|
|
|
|
template<typename T>
|
|
struct kMultiply
|
|
{
|
|
T operator()(const T& v1, const T& v2) const { return v1 * v2; }
|
|
};
|
|
|
|
template<typename T>
|
|
struct kDivide
|
|
{
|
|
T operator()(const T& v1, const T& v2) const { return v1 / v2; }
|
|
};
|
|
|
|
template<typename T, typename P>
|
|
kStatus kMathFindFirst(const T* v, kSize count, const P& pred, const T& value, kSize* index)
|
|
{
|
|
auto it = v;
|
|
auto end = it + count;
|
|
|
|
if ((!v && (count > 0)) || !index)
|
|
{
|
|
return kERROR_PARAMETER;
|
|
}
|
|
|
|
*index = count;
|
|
|
|
if (count > 0)
|
|
{
|
|
while (it != end)
|
|
{
|
|
if (pred(*it, value))
|
|
{
|
|
*index = (kSize) (it - v);
|
|
break;
|
|
}
|
|
it++;
|
|
}
|
|
}
|
|
|
|
return kOK;
|
|
}
|
|
|
|
template<typename T, typename P>
|
|
kStatus kMathFindLast(const T* v, kSize count, const P& pred, const T& value, kSize* index)
|
|
{
|
|
const T* it = v + count - 1;
|
|
const T* end = it - count;
|
|
|
|
if ((!v && (count > 0)) || !index)
|
|
{
|
|
return kERROR_PARAMETER;
|
|
}
|
|
|
|
*index = count;
|
|
|
|
if (count > 0)
|
|
{
|
|
while (it != end)
|
|
{
|
|
if (pred(*it, value))
|
|
{
|
|
*index = (kSize) (it - v);
|
|
break;
|
|
}
|
|
it--;
|
|
}
|
|
}
|
|
|
|
return kOK;
|
|
}
|
|
|
|
template<typename T>
|
|
kStatus kMathFindMin(const T* v, kSize count, kSize* index)
|
|
{
|
|
const T* it = v;
|
|
const T* end = it + count;
|
|
const T* minIt = it;
|
|
|
|
if (!it || (count == 0) || !index)
|
|
{
|
|
return kERROR_PARAMETER;
|
|
}
|
|
|
|
while (it != end)
|
|
{
|
|
if (*it < *minIt)
|
|
{
|
|
minIt = it;
|
|
}
|
|
it++;
|
|
}
|
|
|
|
*index = (kSize) (minIt - v);
|
|
return kOK;
|
|
}
|
|
|
|
template<typename T>
|
|
kStatus kMathFindMax(const T* v, kSize count, kSize* index)
|
|
{
|
|
const T* it = v;
|
|
const T* end = it + count;
|
|
const T* maxIt = it;
|
|
|
|
if (!it || (count == 0) || !index)
|
|
{
|
|
return kERROR_PARAMETER;
|
|
}
|
|
|
|
while (it != end)
|
|
{
|
|
if (*it > *maxIt)
|
|
{
|
|
maxIt = it;
|
|
}
|
|
it++;
|
|
}
|
|
|
|
*index = (kSize) (maxIt - v);
|
|
return kOK;
|
|
}
|
|
|
|
template<typename T, typename V>
|
|
kStatus kMathSum(const T* v, kSize count, V* sum)
|
|
{
|
|
const T* it = v;
|
|
const T* itEnd = it + count;
|
|
V accum = 0;
|
|
|
|
if ((!v && (count > 0)) || !sum)
|
|
{
|
|
return kERROR_PARAMETER;
|
|
}
|
|
|
|
while (it != itEnd)
|
|
{
|
|
accum += (V) (*it++);
|
|
}
|
|
|
|
*sum = accum;
|
|
|
|
return kOK;
|
|
}
|
|
|
|
template<typename T>
|
|
kStatus kMathAverage(const T* v, kSize count, k64f* average)
|
|
{
|
|
const T* it = v;
|
|
const T* itEnd = it + count;
|
|
k64f sum = 0;
|
|
|
|
if (!v || (count < 1) || !average)
|
|
{
|
|
return kERROR_PARAMETER;
|
|
}
|
|
|
|
while (it != itEnd)
|
|
{
|
|
sum += (k64f) (*it++);
|
|
}
|
|
|
|
*average = sum / count;
|
|
|
|
return kOK;
|
|
}
|
|
|
|
template<typename T>
|
|
kStatus kMathStdev(const T* v, kSize count, k64f* stdev)
|
|
{
|
|
const T* it = v;
|
|
const T* itEnd = it + count;
|
|
k64f sum = 0;
|
|
k64f sumSq = 0;
|
|
k64f num, den, quotient;
|
|
|
|
if (!v || (count < 2) || !stdev)
|
|
{
|
|
return kERROR_PARAMETER;
|
|
}
|
|
|
|
while (it != itEnd)
|
|
{
|
|
sumSq += ((k64f) *it) * ((k64f) *it);
|
|
sum += *it++;
|
|
}
|
|
|
|
num = count*sumSq - sum*sum;
|
|
den = count*(count - 1.0);
|
|
quotient = num/den;
|
|
|
|
if (quotient <= 0) *stdev = 0;
|
|
else *stdev = sqrt(quotient);
|
|
|
|
return kOK;
|
|
}
|
|
|
|
template<typename T>
|
|
kStatus kMathMin(const T* v, kSize count, T* minValue)
|
|
{
|
|
kStatus status;
|
|
kSize index;
|
|
|
|
if (!minValue)
|
|
{
|
|
return kERROR_PARAMETER;
|
|
}
|
|
|
|
status = kMathFindMin(v, count, &index);
|
|
if (!kSuccess(status))
|
|
{
|
|
return status;
|
|
}
|
|
|
|
*minValue = v[index];
|
|
return kOK;
|
|
}
|
|
|
|
template<typename T>
|
|
kStatus kMathMax(const T* v, kSize count, T* maxValue)
|
|
{
|
|
kStatus status;
|
|
kSize index;
|
|
|
|
if (!maxValue)
|
|
{
|
|
return kERROR_PARAMETER;
|
|
}
|
|
|
|
status = kMathFindMax(v, count, &index);
|
|
if (!kSuccess(status))
|
|
{
|
|
return status;
|
|
}
|
|
|
|
*maxValue = v[index];
|
|
|
|
return kOK;
|
|
}
|
|
|
|
template<typename T>
|
|
kStatus kMathCentroid(const T* v, kSize count, k64f* centroid)
|
|
{
|
|
const T* it = v;
|
|
const T* itEnd = it + count;
|
|
k64f sum = 0;
|
|
k64f wSum = 0;
|
|
|
|
if (!v || (count < 1) || !centroid)
|
|
{
|
|
return kERROR_PARAMETER;
|
|
}
|
|
|
|
while (it != itEnd)
|
|
{
|
|
sum += *it++;
|
|
wSum += sum;
|
|
}
|
|
|
|
*centroid = (sum != 0) ? (count - wSum/sum) : (count/2.0);
|
|
|
|
return kOK;
|
|
}
|
|
|
|
template<typename T>
|
|
kStatus kMathSet(T* v, kSize count, const T& value)
|
|
{
|
|
T* it = v;
|
|
T* itEnd = it + count;
|
|
|
|
if (!v && (count > 0))
|
|
{
|
|
return kERROR_PARAMETER;
|
|
}
|
|
|
|
while (it != itEnd)
|
|
{
|
|
*it++ = value;
|
|
}
|
|
|
|
return kOK;
|
|
}
|
|
|
|
template<typename T>
|
|
kStatus kMathStep(T* v, kSize count, const T& startValue, const T& increment)
|
|
{
|
|
T* it = v;
|
|
T* itEnd = it + count;
|
|
T value = startValue;
|
|
|
|
if (kIsNull(v) && (count > 0))
|
|
{
|
|
return kERROR_PARAMETER;
|
|
}
|
|
|
|
while (it != itEnd)
|
|
{
|
|
*it++ = value;
|
|
value += increment;
|
|
}
|
|
|
|
return kOK;
|
|
}
|
|
|
|
template<typename T>
|
|
kStatus kMathSpan(T* v, kSize count, const T& startValue, const T& endValue)
|
|
{
|
|
kSize i = 0;
|
|
|
|
if (kIsNull(v) && (count > 0))
|
|
{
|
|
return kERROR_PARAMETER;
|
|
}
|
|
else if (count == 0)
|
|
{
|
|
return kOK;
|
|
}
|
|
else if (count == 1)
|
|
{
|
|
v[0] = endValue;
|
|
}
|
|
else
|
|
{
|
|
for (i = 0; i < count; ++i)
|
|
{
|
|
v[i] = (T) (startValue + (k64f)i*(endValue - startValue)/(count-1.0));
|
|
}
|
|
}
|
|
|
|
return kOK;
|
|
}
|
|
|
|
template<typename T>
|
|
kStatus kMathAbs(const T* vIn, T* vOut, kSize count)
|
|
{
|
|
const T* itIn = vIn;
|
|
const T* itInEnd = itIn + count;
|
|
T* itOut = vOut;
|
|
|
|
if ((!vIn || !vOut) && (count > 0))
|
|
{
|
|
return kERROR_PARAMETER;
|
|
}
|
|
|
|
while (itIn != itInEnd)
|
|
{
|
|
*itOut++ = (*itIn >= 0) ? (*itIn) : -(*itIn);
|
|
itIn++;
|
|
}
|
|
|
|
return kOK;
|
|
}
|
|
|
|
template<typename T, typename Op>
|
|
kStatus kMathApply(const T* vIn, T* vOut, kSize count, const Op& op, const T& value)
|
|
{
|
|
const T* itIn = vIn;
|
|
const T* itInEnd = itIn + count;
|
|
T* itOut = vOut;
|
|
|
|
if ((!vIn || !vOut) && (count > 0))
|
|
{
|
|
return kERROR_PARAMETER;
|
|
}
|
|
|
|
while (itIn != itInEnd)
|
|
{
|
|
*itOut++ = op(*itIn++, value);
|
|
}
|
|
|
|
return kOK;
|
|
}
|
|
|
|
template<typename T, typename Op>
|
|
kStatus kMathApply(const T* vIn1, const T* vIn2, T* vOut, kSize count, const Op& op)
|
|
{
|
|
const T* itIn1 = vIn1;
|
|
const T* itIn1End = itIn1 + count;
|
|
const T* itIn2 = vIn2;
|
|
T* itOut = vOut;
|
|
|
|
if ((!vIn1 || !vIn2 || !vOut) && (count > 0))
|
|
{
|
|
return kERROR_PARAMETER;
|
|
}
|
|
|
|
while (itIn1 != itIn1End)
|
|
{
|
|
*itOut++ = op(*itIn1++, *itIn2++);
|
|
}
|
|
|
|
return kOK;
|
|
}
|
|
|
|
template<typename T>
|
|
kStatus kMathClampC(const T* vIn, T* vOut, kSize count, T minValue, T maxValue)
|
|
{
|
|
const T* itIn = vIn;
|
|
const T* itInEnd = itIn + count;
|
|
T* itOut = vOut;
|
|
|
|
if ((!vIn || !vOut) && (count > 0))
|
|
{
|
|
return kERROR_PARAMETER;
|
|
}
|
|
|
|
while (itIn != itInEnd)
|
|
{
|
|
if (*itIn < minValue) *itOut = minValue;
|
|
else if (*itIn > maxValue) *itOut = maxValue;
|
|
else *itOut = *itIn;
|
|
itIn++;
|
|
itOut++;
|
|
}
|
|
|
|
return kOK;
|
|
}
|
|
|
|
template<typename T, typename P>
|
|
kStatus kMathReplaceC(const T* vIn, T* vOut, kSize count, const P& pred, T value, T replacement)
|
|
{
|
|
const T* itIn = vIn;
|
|
const T* itInEnd = itIn + count;
|
|
T* itOut = vOut;
|
|
|
|
if ((!vIn || !vOut) && (count > 0))
|
|
{
|
|
return kERROR_PARAMETER;
|
|
}
|
|
|
|
while (itIn != itInEnd)
|
|
{
|
|
if (pred(*itIn, value)) *itOut = replacement;
|
|
else *itOut = *itIn;
|
|
itIn++;
|
|
itOut++;
|
|
}
|
|
|
|
return kOK;
|
|
}
|
|
|
|
template<typename T, typename P>
|
|
kStatus kMathCompareC(const T* vIn, kBool* vOut, kSize count, const P& pred, T value)
|
|
{
|
|
const T* itIn = vIn;
|
|
const T* itInEnd = itIn + count;
|
|
kBool* itOut = vOut;
|
|
|
|
if ((!vIn || !vOut) && (count > 0))
|
|
{
|
|
return kERROR_PARAMETER;
|
|
}
|
|
|
|
while (itIn != itInEnd)
|
|
{
|
|
*itOut++ = pred(*itIn++, value);
|
|
}
|
|
|
|
return kOK;
|
|
}
|
|
|
|
template<typename T>
|
|
kStatus kMathMovingAvg(const T* vIn, T* vOut, kSize count, kSize window)
|
|
{
|
|
const T* itIn = vIn;
|
|
const T* itInEnd = itIn + count;
|
|
T* itOut = vOut;
|
|
const T *windowBegin, *windowEnd, *windowReader, *windowBeginEnd;
|
|
T sum, average;
|
|
|
|
if (!vIn || !vOut || (window < 1) || (count < window))
|
|
{
|
|
return kERROR_PARAMETER;
|
|
}
|
|
|
|
sum = 0;
|
|
windowBegin = itIn;
|
|
windowEnd = itIn + window;
|
|
windowReader = windowBegin;
|
|
while (windowReader != windowEnd)
|
|
{
|
|
sum += *windowReader++;
|
|
}
|
|
|
|
windowBeginEnd = itInEnd - window;
|
|
while (windowBegin != windowBeginEnd)
|
|
{
|
|
average = sum/(T)window;
|
|
sum -= *windowBegin++;
|
|
sum += *windowEnd++;
|
|
*itOut++ = average;
|
|
}
|
|
|
|
*itOut = sum/(T)window;
|
|
|
|
return kOK;
|
|
}
|
|
|
|
template<typename T>
|
|
kStatus kMath_Gcd(T a, T b, T& out)
|
|
{
|
|
T mod;
|
|
|
|
/* Iterative version of */
|
|
/* f(a, b) {return b == 0 ? a : f(b, a % b);} */
|
|
while (kTRUE)
|
|
{
|
|
if (b == 0)
|
|
{
|
|
break;
|
|
}
|
|
|
|
mod = a % b;
|
|
a = b;
|
|
b = mod;
|
|
}
|
|
|
|
out = kMath_Abs_(a);
|
|
|
|
return kOK;
|
|
}
|
|
|
|
template<typename T>
|
|
kStatus kMath_Lcm(const T& a, const T& b, T& out)
|
|
{
|
|
T gcd;
|
|
|
|
/* a = b = 0 gives 0 for GCD; handle this as a special case. */
|
|
if (a == 0 && b == 0)
|
|
{
|
|
out = 0;
|
|
|
|
return kOK;
|
|
}
|
|
|
|
kCheck(kMath_Gcd(a, b, gcd));
|
|
|
|
out = kMath_Abs_((a * b) / gcd);
|
|
|
|
return kOK;
|
|
}
|
|
|
|
/* Exports */
|
|
|
|
kFx(kStatus) kMath_FindFirst32s(const k32s* v, kSize count, kComparison comparison, k32s value, kSize* index)
|
|
{
|
|
switch(comparison)
|
|
{
|
|
case kCOMPARISON_EQ: return kMathFindFirst(v, count, kIsEq <k32s>(), value, index);
|
|
case kCOMPARISON_NEQ: return kMathFindFirst(v, count, kIsNeq<k32s>(), value, index);
|
|
case kCOMPARISON_LT: return kMathFindFirst(v, count, kIsLt <k32s>(), value, index);
|
|
case kCOMPARISON_LTE: return kMathFindFirst(v, count, kIsLte<k32s>(), value, index);
|
|
case kCOMPARISON_GT: return kMathFindFirst(v, count, kIsGt <k32s>(), value, index);
|
|
case kCOMPARISON_GTE: return kMathFindFirst(v, count, kIsGte<k32s>(), value, index);
|
|
default: return kERROR_PARAMETER;
|
|
}
|
|
}
|
|
|
|
kFx(kStatus) kMath_FindFirst64f(const k64f* v, kSize count, kComparison comparison, k64f value, kSize* index)
|
|
{
|
|
switch(comparison)
|
|
{
|
|
case kCOMPARISON_EQ: return kMathFindFirst(v, count, kIsEq <k64f>(), value, index);
|
|
case kCOMPARISON_NEQ: return kMathFindFirst(v, count, kIsNeq<k64f>(), value, index);
|
|
case kCOMPARISON_LT: return kMathFindFirst(v, count, kIsLt <k64f>(), value, index);
|
|
case kCOMPARISON_LTE: return kMathFindFirst(v, count, kIsLte<k64f>(), value, index);
|
|
case kCOMPARISON_GT: return kMathFindFirst(v, count, kIsGt <k64f>(), value, index);
|
|
case kCOMPARISON_GTE: return kMathFindFirst(v, count, kIsGte<k64f>(), value, index);
|
|
default: return kERROR_PARAMETER;
|
|
}
|
|
}
|
|
|
|
kFx(kStatus) kMath_FindLast32s(const k32s* v, kSize count, kComparison comparison, k32s value, kSize* index)
|
|
{
|
|
switch(comparison)
|
|
{
|
|
case kCOMPARISON_EQ: return kMathFindLast(v, count, kIsEq <k32s>(), value, index);
|
|
case kCOMPARISON_NEQ: return kMathFindLast(v, count, kIsNeq<k32s>(), value, index);
|
|
case kCOMPARISON_LT: return kMathFindLast(v, count, kIsLt <k32s>(), value, index);
|
|
case kCOMPARISON_LTE: return kMathFindLast(v, count, kIsLte<k32s>(), value, index);
|
|
case kCOMPARISON_GT: return kMathFindLast(v, count, kIsGt <k32s>(), value, index);
|
|
case kCOMPARISON_GTE: return kMathFindLast(v, count, kIsGte<k32s>(), value, index);
|
|
default: return kERROR_PARAMETER;
|
|
}
|
|
}
|
|
|
|
kFx(kStatus) kMath_FindLast64f(const k64f* v, kSize count, kComparison comparison, k64f value, kSize* index)
|
|
{
|
|
switch(comparison)
|
|
{
|
|
case kCOMPARISON_EQ: return kMathFindLast(v, count, kIsEq <k64f>(), value, index);
|
|
case kCOMPARISON_NEQ: return kMathFindLast(v, count, kIsNeq<k64f>(), value, index);
|
|
case kCOMPARISON_LT: return kMathFindLast(v, count, kIsLt <k64f>(), value, index);
|
|
case kCOMPARISON_LTE: return kMathFindLast(v, count, kIsLte<k64f>(), value, index);
|
|
case kCOMPARISON_GT: return kMathFindLast(v, count, kIsGt <k64f>(), value, index);
|
|
case kCOMPARISON_GTE: return kMathFindLast(v, count, kIsGte<k64f>(), value, index);
|
|
default: return kERROR_PARAMETER;
|
|
}
|
|
}
|
|
|
|
kFx(kStatus) kMath_FindMin8u(const k8u* v, kSize count, kSize* index)
|
|
{
|
|
return kMathFindMin(v, count, index);
|
|
}
|
|
|
|
kFx(kStatus) kMath_FindMin32u(const k32u* v, kSize count, kSize* index)
|
|
{
|
|
return kMathFindMin(v, count, index);
|
|
}
|
|
|
|
kFx(kStatus) kMath_FindMin32s(const k32s* v, kSize count, kSize* index)
|
|
{
|
|
return kMathFindMin(v, count, index);
|
|
}
|
|
|
|
kFx(kStatus) kMath_FindMin64u(const k64u* v, kSize count, kSize* index)
|
|
{
|
|
return kMathFindMin(v, count, index);
|
|
}
|
|
|
|
kFx(kStatus) kMath_FindMin64f(const k64f* v, kSize count, kSize* index)
|
|
{
|
|
return kMathFindMin(v, count, index);
|
|
}
|
|
|
|
kFx(kStatus) kMath_FindMax8u(const k8u* v, kSize count, kSize* index)
|
|
{
|
|
return kMathFindMax(v, count, index);
|
|
}
|
|
|
|
kFx(kStatus) kMath_FindMax32u(const k32u* v, kSize count, kSize* index)
|
|
{
|
|
return kMathFindMax(v, count, index);
|
|
}
|
|
|
|
kFx(kStatus) kMath_FindMax32s(const k32s* v, kSize count, kSize* index)
|
|
{
|
|
return kMathFindMax(v, count, index);
|
|
}
|
|
|
|
kFx(kStatus) kMath_FindMax64u(const k64u* v, kSize count, kSize* index)
|
|
{
|
|
return kMathFindMax(v, count, index);
|
|
}
|
|
|
|
kFx(kStatus) kMath_FindMax64f(const k64f* v, kSize count, kSize* index)
|
|
{
|
|
return kMathFindMax(v, count, index);
|
|
}
|
|
|
|
kFx(kStatus) kMath_Sum32s(const k32s* v, kSize count, k64s* sum)
|
|
{
|
|
return kMathSum(v, count, sum);
|
|
}
|
|
|
|
kFx(kStatus) kMath_Sum64u(const k64u* v, kSize count, k64u* sum)
|
|
{
|
|
return kMathSum(v, count, sum);
|
|
}
|
|
|
|
kFx(kStatus) kMath_Sum64f(const k64f* v, kSize count, k64f* sum)
|
|
{
|
|
return kMathSum(v, count, sum);
|
|
}
|
|
|
|
kFx(kStatus) kMath_Average8u(const k8u* v, kSize count, k64f* average)
|
|
{
|
|
return kMathAverage(v, count, average);
|
|
}
|
|
|
|
kFx(kStatus) kMath_Average32s(const k32s* v, kSize count, k64f* average)
|
|
{
|
|
return kMathAverage(v, count, average);
|
|
}
|
|
|
|
kFx(kStatus) kMath_Average64f(const k64f* v, kSize count, k64f* average)
|
|
{
|
|
return kMathAverage(v, count, average);
|
|
}
|
|
|
|
kFx(kStatus) kMath_Stdev8u(const k8u* v, kSize count, k64f* stdev)
|
|
{
|
|
return kMathStdev(v, count, stdev);
|
|
}
|
|
|
|
kFx(kStatus) kMath_Stdev32s(const k32s* v, kSize count, k64f* stdev)
|
|
{
|
|
return kMathStdev(v, count, stdev);
|
|
}
|
|
|
|
kFx(kStatus) kMath_Stdev64f(const k64f* v, kSize count, k64f* stdev)
|
|
{
|
|
return kMathStdev(v, count, stdev);
|
|
}
|
|
|
|
kFx(kStatus) kMath_Min8u(const k8u* v, kSize count, k8u* minValue)
|
|
{
|
|
return kMathMin(v, count, minValue);
|
|
}
|
|
|
|
kFx(kStatus) kMath_Min32s(const k32s* v, kSize count, k32s* minValue)
|
|
{
|
|
return kMathMin(v, count, minValue);
|
|
}
|
|
|
|
kFx(kStatus) kMath_Min32u(const k32u* v, kSize count, k32u* minValue)
|
|
{
|
|
return kMathMin(v, count, minValue);
|
|
}
|
|
|
|
kFx(kStatus) kMath_Min64u(const k64u* v, kSize count, k64u* minValue)
|
|
{
|
|
return kMathMin(v, count, minValue);
|
|
}
|
|
|
|
kFx(kStatus) kMath_Min64f(const k64f* v, kSize count, k64f* minValue)
|
|
{
|
|
return kMathMin(v, count, minValue);
|
|
}
|
|
|
|
kFx(kStatus) kMath_Max8u(const k8u* v, kSize count, k8u* maxValue)
|
|
{
|
|
return kMathMax(v, count, maxValue);
|
|
}
|
|
|
|
kFx(kStatus) kMath_Max32u(const k32u* v, kSize count, k32u* maxValue)
|
|
{
|
|
return kMathMax(v, count, maxValue);
|
|
}
|
|
|
|
kFx(kStatus) kMath_Max32s(const k32s* v, kSize count, k32s* maxValue)
|
|
{
|
|
return kMathMax(v, count, maxValue);
|
|
}
|
|
|
|
kFx(kStatus) kMath_Max64u(const k64u* v, kSize count, k64u* maxValue)
|
|
{
|
|
return kMathMax(v, count, maxValue);
|
|
}
|
|
|
|
kFx(kStatus) kMath_Max64f(const k64f* v, kSize count, k64f* maxValue)
|
|
{
|
|
return kMathMax(v, count, maxValue);
|
|
}
|
|
|
|
|
|
kFx(kStatus) kMath_Centroid32s(const k32s* v, kSize count, k64f* centroid)
|
|
{
|
|
return kMathCentroid(v, count, centroid);
|
|
}
|
|
|
|
kFx(kStatus) kMath_Centroid64f(const k64f* v, kSize count, k64f* centroid)
|
|
{
|
|
return kMathCentroid(v, count, centroid);
|
|
}
|
|
|
|
kFx(kStatus) kMath_Set32s(k32s* v, kSize count, k32s value)
|
|
{
|
|
return kMathSet(v, count, value);
|
|
}
|
|
|
|
kFx(kStatus) kMath_Set64f(k64f* v, kSize count, k64f value)
|
|
{
|
|
return kMathSet(v, count, value);
|
|
}
|
|
|
|
kFx(kStatus) kMath_Step32s(k32s* v, kSize count, k32s startValue, k32s increment)
|
|
{
|
|
return kMathStep(v, count, startValue, increment);
|
|
}
|
|
|
|
kFx(kStatus) kMath_Step64f(k64f* v, kSize count, k64f startValue, k64f increment)
|
|
{
|
|
return kMathStep(v, count, startValue, increment);
|
|
}
|
|
|
|
kFx(kStatus) kMath_Span32s(k32s* v, kSize count, k32s startValue, k32s endValue)
|
|
{
|
|
return kMathSpan(v, count, startValue, endValue);
|
|
}
|
|
|
|
kFx(kStatus) kMath_Span64f(k64f* v, kSize count, k64f startValue, k64f endValue)
|
|
{
|
|
return kMathSpan(v, count, startValue, endValue);
|
|
}
|
|
|
|
kFx(kStatus) kMath_Abs32s(const k32s* vIn, k32s* vOut, kSize count)
|
|
{
|
|
return kMathAbs(vIn, vOut, count);
|
|
}
|
|
|
|
kFx(kStatus) kMath_Abs64f(const k64f* vIn, k64f* vOut, kSize count)
|
|
{
|
|
return kMathAbs(vIn, vOut, count);
|
|
}
|
|
|
|
kFx(kStatus) kMath_AddC32s(const k32s* vIn, k32s* vOut, kSize count, k32s value)
|
|
{
|
|
return kMathApply(vIn, vOut, count, kAdd<k32s>(), value);
|
|
}
|
|
|
|
kFx(kStatus) kMath_AddC64f(const k64f* vIn, k64f* vOut, kSize count, k64f value)
|
|
{
|
|
return kMathApply(vIn, vOut, count, kAdd<k64f>(), value);
|
|
}
|
|
|
|
kFx(kStatus) kMath_SubC32s(const k32s* vIn, k32s* vOut, kSize count, k32s value)
|
|
{
|
|
return kMathApply(vIn, vOut, count, kSubtract<k32s>(), value);
|
|
}
|
|
|
|
kFx(kStatus) kMath_SubC64f(const k64f* vIn, k64f* vOut, kSize count, k64f value)
|
|
{
|
|
return kMathApply(vIn, vOut, count, kSubtract<k64f>(), value);
|
|
}
|
|
|
|
kFx(kStatus) kMath_MulC32s(const k32s* vIn, k32s* vOut, kSize count, k32s value)
|
|
{
|
|
return kMathApply(vIn, vOut, count, kMultiply<k32s>(), value);
|
|
}
|
|
|
|
kFx(kStatus) kMath_MulC64f(const k64f* vIn, k64f* vOut, kSize count, k64f value)
|
|
{
|
|
return kMathApply(vIn, vOut, count, kMultiply<k64f>(), value);
|
|
}
|
|
|
|
kFx(kStatus) kMath_DivC32s(const k32s* vIn, k32s* vOut, kSize count, k32s value)
|
|
{
|
|
return kMathApply(vIn, vOut, count, kDivide<k32s>(), value);
|
|
}
|
|
|
|
kFx(kStatus) kMath_DivC64f(const k64f* vIn, k64f* vOut, kSize count, k64f value)
|
|
{
|
|
return kMathApply(vIn, vOut, count, kDivide<k64f>(), value);
|
|
}
|
|
|
|
kFx(kStatus) kMath_ClampC32s(const k32s* vIn, k32s* vOut, kSize count, k32s minValue, k32s maxValue)
|
|
{
|
|
return kMathClampC(vIn, vOut, count, minValue, maxValue);
|
|
}
|
|
|
|
kFx(kStatus) kMath_ClampC64f(const k64f* vIn, k64f* vOut, kSize count, k64f minValue, k64f maxValue)
|
|
{
|
|
return kMathClampC(vIn, vOut, count, minValue, maxValue);
|
|
}
|
|
|
|
kFx(kStatus) kMath_ReplaceC32s(const k32s* vIn, k32s* vOut, kSize count, kComparison comparison, k32s value, k32s replacement)
|
|
{
|
|
switch(comparison)
|
|
{
|
|
case kCOMPARISON_EQ: return kMathReplaceC(vIn, vOut, count, kIsEq <k32s>(), value, replacement);
|
|
case kCOMPARISON_NEQ: return kMathReplaceC(vIn, vOut, count, kIsNeq<k32s>(), value, replacement);
|
|
case kCOMPARISON_LT: return kMathReplaceC(vIn, vOut, count, kIsLt <k32s>(), value, replacement);
|
|
case kCOMPARISON_LTE: return kMathReplaceC(vIn, vOut, count, kIsLte<k32s>(), value, replacement);
|
|
case kCOMPARISON_GT: return kMathReplaceC(vIn, vOut, count, kIsGt <k32s>(), value, replacement);
|
|
case kCOMPARISON_GTE: return kMathReplaceC(vIn, vOut, count, kIsGte<k32s>(), value, replacement);
|
|
default: return kERROR_PARAMETER;
|
|
}
|
|
}
|
|
|
|
kFx(kStatus) kMath_ReplaceC64f(const k64f* vIn, k64f* vOut, kSize count, kComparison comparison, k64f value, k64f replacement)
|
|
{
|
|
switch(comparison)
|
|
{
|
|
case kCOMPARISON_EQ: return kMathReplaceC(vIn, vOut, count, kIsEq <k64f>(), value, replacement);
|
|
case kCOMPARISON_NEQ: return kMathReplaceC(vIn, vOut, count, kIsNeq<k64f>(), value, replacement);
|
|
case kCOMPARISON_LT: return kMathReplaceC(vIn, vOut, count, kIsLt <k64f>(), value, replacement);
|
|
case kCOMPARISON_LTE: return kMathReplaceC(vIn, vOut, count, kIsLte<k64f>(), value, replacement);
|
|
case kCOMPARISON_GT: return kMathReplaceC(vIn, vOut, count, kIsGt <k64f>(), value, replacement);
|
|
case kCOMPARISON_GTE: return kMathReplaceC(vIn, vOut, count, kIsGte<k64f>(), value, replacement);
|
|
default: return kERROR_PARAMETER;
|
|
}
|
|
}
|
|
|
|
kFx(kStatus) kMath_CompareC32s(const k32s* vIn, kBool* vOut, kSize count, kComparison comparison, k32s value)
|
|
{
|
|
switch(comparison)
|
|
{
|
|
case kCOMPARISON_EQ: return kMathCompareC(vIn, vOut, count, kIsEq <k32s>(), value);
|
|
case kCOMPARISON_NEQ: return kMathCompareC(vIn, vOut, count, kIsNeq<k32s>(), value);
|
|
case kCOMPARISON_LT: return kMathCompareC(vIn, vOut, count, kIsLt <k32s>(), value);
|
|
case kCOMPARISON_LTE: return kMathCompareC(vIn, vOut, count, kIsLte<k32s>(), value);
|
|
case kCOMPARISON_GT: return kMathCompareC(vIn, vOut, count, kIsGt <k32s>(), value);
|
|
case kCOMPARISON_GTE: return kMathCompareC(vIn, vOut, count, kIsGte<k32s>(), value);
|
|
default: return kERROR_PARAMETER;
|
|
}
|
|
}
|
|
|
|
kFx(kStatus) kMath_CompareC64f(const k64f* vIn, kBool* vOut, kSize count, kComparison comparison, k64f value)
|
|
{
|
|
switch(comparison)
|
|
{
|
|
case kCOMPARISON_EQ: return kMathCompareC(vIn, vOut, count, kIsEq <k64f>(), value);
|
|
case kCOMPARISON_NEQ: return kMathCompareC(vIn, vOut, count, kIsNeq<k64f>(), value);
|
|
case kCOMPARISON_LT: return kMathCompareC(vIn, vOut, count, kIsLt <k64f>(), value);
|
|
case kCOMPARISON_LTE: return kMathCompareC(vIn, vOut, count, kIsLte<k64f>(), value);
|
|
case kCOMPARISON_GT: return kMathCompareC(vIn, vOut, count, kIsGt <k64f>(), value);
|
|
case kCOMPARISON_GTE: return kMathCompareC(vIn, vOut, count, kIsGte<k64f>(), value);
|
|
default: return kERROR_PARAMETER;
|
|
}
|
|
}
|
|
|
|
kFx(kStatus) kMath_Add32s(const k32s* vIn1, const k32s* vIn2, k32s* vOut, kSize count)
|
|
{
|
|
return kMathApply(vIn1, vIn2, vOut, count, kAdd<k32s>());
|
|
}
|
|
|
|
kFx(kStatus) kMath_Add64f(const k64f* vIn1, const k64f* vIn2, k64f* vOut, kSize count)
|
|
{
|
|
return kMathApply(vIn1, vIn2, vOut, count, kAdd<k64f>());
|
|
}
|
|
|
|
kFx(kStatus) kMath_Sub32s(const k32s* vIn1, const k32s* vIn2, k32s* vOut, kSize count)
|
|
{
|
|
return kMathApply(vIn1, vIn2, vOut, count, kSubtract<k32s>());
|
|
}
|
|
|
|
kFx(kStatus) kMath_Sub64f(const k64f* vIn1, const k64f* vIn2, k64f* vOut, kSize count)
|
|
{
|
|
return kMathApply(vIn1, vIn2, vOut, count, kSubtract<k64f>());
|
|
}
|
|
|
|
kFx(kStatus) kMath_Mul32s(const k32s* vIn1, const k32s* vIn2, k32s* vOut, kSize count)
|
|
{
|
|
return kMathApply(vIn1, vIn2, vOut, count, kMultiply<k32s>());
|
|
}
|
|
|
|
kFx(kStatus) kMath_Mul64f(const k64f* vIn1, const k64f* vIn2, k64f* vOut, kSize count)
|
|
{
|
|
return kMathApply(vIn1, vIn2, vOut, count, kMultiply<k64f>());
|
|
}
|
|
|
|
kFx(kStatus) kMath_Div32s(const k32s* vIn1, const k32s* vIn2, k32s* vOut, kSize count)
|
|
{
|
|
return kMathApply(vIn1, vIn2, vOut, count, kDivide<k32s>());
|
|
}
|
|
|
|
kFx(kStatus) kMath_Div64f(const k64f* vIn1, const k64f* vIn2, k64f* vOut, kSize count)
|
|
{
|
|
return kMathApply(vIn1, vIn2, vOut, count, kDivide<k64f>());
|
|
}
|
|
|
|
kFx(kStatus) kMath_MovingAvg32s(const k32s* vIn, k32s* vOut, kSize count, kSize window)
|
|
{
|
|
return kMathMovingAvg(vIn, vOut, count, window);
|
|
}
|
|
|
|
kFx(kStatus) kMath_MovingAvg64f(const k64f* vIn, k64f* vOut, kSize count, kSize window)
|
|
{
|
|
return kMathMovingAvg(vIn, vOut, count, window);
|
|
}
|
|
|
|
kFx(kStatus) kMath_Gcd32s(k32s a, k32s b, k32s* result)
|
|
{
|
|
return kMath_Gcd(a, b, *result);
|
|
}
|
|
|
|
kFx(kStatus) kMath_Lcm32s(k32s a, k32s b, k32s* result)
|
|
{
|
|
return kMath_Lcm(a, b, *result);
|
|
}
|
|
|
|
/* Adapted from: http://stackoverflow.com/questions/3272424/compute-fast-log-base-2-ceiling */
|
|
kFx(k32u) kMath_Log2Ceil32u(k32u a)
|
|
{
|
|
static const k32u t[5] = { 0xFFFF0000u, 0x0000FF00u, 0x000000F0u, 0x0000000Cu, 0x00000002u };
|
|
k32u y = ((a & (a-1u)) == 0u) ? 0u : 1u;
|
|
k32u j = 16;
|
|
k32u i, k;
|
|
|
|
for (i = 0; i < kCountOf(t); ++i)
|
|
{
|
|
k = ((a & t[i]) == 0) ? 0 : j;
|
|
y += k;
|
|
a >>= k;
|
|
j >>= 1;
|
|
}
|
|
|
|
return y;
|
|
}
|
|
|
|
kFx(k64f) kMath_Round64f(k64f a)
|
|
{
|
|
return (a >= 0.0) ? floor(a + 0.5) : ceil(a - 0.5);
|
|
}
|