3038 lines
103 KiB
C++
3038 lines
103 KiB
C++
// Copyright Epic Games, Inc. All Rights Reserved.
|
|
|
|
#include "LearningFrameAttribute.h"
|
|
|
|
#if UE_LEARNING_ISPC
|
|
#include "Learning.ispc.generated.h"
|
|
#endif
|
|
|
|
namespace UE::Learning
|
|
{
|
|
namespace FrameAttribute::Private
|
|
{
|
|
static inline bool FindMinimum(
|
|
int32& OutChannelIdx,
|
|
int32& OutFrameIdx,
|
|
float& OutMinimumValue,
|
|
const TLearningArrayView<2, const float> Values)
|
|
{
|
|
OutChannelIdx = INDEX_NONE;
|
|
OutFrameIdx = INDEX_NONE;
|
|
OutMinimumValue = UE_MAX_FLT;
|
|
|
|
const int32 ChannelNum = Values.Num<0>();
|
|
const int32 FrameNum = Values.Num<1>();
|
|
|
|
for (int32 ChannelIdx = 0; ChannelIdx < ChannelNum; ChannelIdx++)
|
|
{
|
|
for (int32 FrameIdx = 0; FrameIdx < FrameNum; FrameIdx++)
|
|
{
|
|
if (Values[ChannelIdx][FrameIdx] < OutMinimumValue)
|
|
{
|
|
OutChannelIdx = ChannelIdx;
|
|
OutFrameIdx = FrameIdx;
|
|
OutMinimumValue = Values[ChannelIdx][FrameIdx];
|
|
}
|
|
}
|
|
}
|
|
|
|
return OutChannelIdx != INDEX_NONE;
|
|
}
|
|
|
|
static inline bool FindMaximum(
|
|
int32& OutChannelIdx,
|
|
int32& OutFrameIdx,
|
|
float& OutMaximumValue,
|
|
const TLearningArrayView<2, const float> Values)
|
|
{
|
|
OutChannelIdx = INDEX_NONE;
|
|
OutFrameIdx = INDEX_NONE;
|
|
OutMaximumValue = -UE_MAX_FLT;
|
|
|
|
const int32 ChannelNum = Values.Num<0>();
|
|
const int32 FrameNum = Values.Num<1>();
|
|
|
|
for (int32 ChannelIdx = 0; ChannelIdx < ChannelNum; ChannelIdx++)
|
|
{
|
|
for (int32 FrameIdx = 0; FrameIdx < FrameNum; FrameIdx++)
|
|
{
|
|
if (Values[ChannelIdx][FrameIdx] > OutMaximumValue)
|
|
{
|
|
OutChannelIdx = ChannelIdx;
|
|
OutFrameIdx = FrameIdx;
|
|
OutMaximumValue = Values[ChannelIdx][FrameIdx];
|
|
}
|
|
}
|
|
}
|
|
|
|
return OutChannelIdx != INDEX_NONE;
|
|
}
|
|
|
|
static inline void Add(TLearningArrayView<1, float> Out, const TLearningArrayView<1, const float> Lhs, const TLearningArrayView<1, const float> Rhs)
|
|
{
|
|
check(Out.Num() == Lhs.Num());
|
|
check(Out.Num() == Rhs.Num());
|
|
const int32 ValueNum = Out.Num();
|
|
for (int32 ValueIdx = 0; ValueIdx < ValueNum; ValueIdx++)
|
|
{
|
|
Out[ValueIdx] = Lhs[ValueIdx] + Rhs[ValueIdx];
|
|
}
|
|
}
|
|
|
|
static inline void Sub(TLearningArrayView<1, float> Out, const TLearningArrayView<1, const float> Lhs, const TLearningArrayView<1, const float> Rhs)
|
|
{
|
|
check(Out.Num() == Lhs.Num());
|
|
check(Out.Num() == Rhs.Num());
|
|
const int32 ValueNum = Out.Num();
|
|
for (int32 ValueIdx = 0; ValueIdx < ValueNum; ValueIdx++)
|
|
{
|
|
Out[ValueIdx] = Lhs[ValueIdx] - Rhs[ValueIdx];
|
|
}
|
|
}
|
|
|
|
static inline void Mul(TLearningArrayView<1, float> Out, const TLearningArrayView<1, const float> Lhs, const TLearningArrayView<1, const float> Rhs)
|
|
{
|
|
check(Out.Num() == Lhs.Num());
|
|
check(Out.Num() == Rhs.Num());
|
|
const int32 ValueNum = Out.Num();
|
|
for (int32 ValueIdx = 0; ValueIdx < ValueNum; ValueIdx++)
|
|
{
|
|
Out[ValueIdx] = Lhs[ValueIdx] * Rhs[ValueIdx];
|
|
}
|
|
}
|
|
|
|
static inline void Div(TLearningArrayView<1, float> Out, const TLearningArrayView<1, const float> Lhs, const TLearningArrayView<1, const float> Rhs)
|
|
{
|
|
check(Out.Num() == Lhs.Num());
|
|
check(Out.Num() == Rhs.Num());
|
|
const int32 ValueNum = Out.Num();
|
|
for (int32 ValueIdx = 0; ValueIdx < ValueNum; ValueIdx++)
|
|
{
|
|
Out[ValueIdx] = Lhs[ValueIdx] / Rhs[ValueIdx];
|
|
}
|
|
}
|
|
|
|
static inline void Dot(TLearningArrayView<1, float> InOut, const TLearningArrayView<1, const float> Lhs, const TLearningArrayView<1, const float> Rhs)
|
|
{
|
|
check(InOut.Num() == Lhs.Num());
|
|
check(InOut.Num() == Rhs.Num());
|
|
const int32 ValueNum = InOut.Num();
|
|
for (int32 ValueIdx = 0; ValueIdx < ValueNum; ValueIdx++)
|
|
{
|
|
InOut[ValueIdx] += Lhs[ValueIdx] * Rhs[ValueIdx];
|
|
}
|
|
}
|
|
|
|
static inline void Neg(TLearningArrayView<1, float> Out, const TLearningArrayView<1, const float> In)
|
|
{
|
|
check(Out.Num() == In.Num());
|
|
const int32 ValueNum = Out.Num();
|
|
for (int32 ValueIdx = 0; ValueIdx < ValueNum; ValueIdx++)
|
|
{
|
|
Out[ValueIdx] = -In[ValueIdx];
|
|
}
|
|
}
|
|
|
|
static inline void Inv(TLearningArrayView<1, float> Out, const TLearningArrayView<1, const float> In)
|
|
{
|
|
check(Out.Num() == In.Num());
|
|
const int32 ValueNum = Out.Num();
|
|
for (int32 ValueIdx = 0; ValueIdx < ValueNum; ValueIdx++)
|
|
{
|
|
Out[ValueIdx] = 1.0f / In[ValueIdx];
|
|
}
|
|
}
|
|
|
|
static inline void Abs(TLearningArrayView<1, float> Out, const TLearningArrayView<1, const float> In)
|
|
{
|
|
check(Out.Num() == In.Num());
|
|
const int32 ValueNum = Out.Num();
|
|
for (int32 ValueIdx = 0; ValueIdx < ValueNum; ValueIdx++)
|
|
{
|
|
Out[ValueIdx] = FMath::Abs(In[ValueIdx]);
|
|
}
|
|
}
|
|
|
|
static inline void Log(TLearningArrayView<1, float> Out, const TLearningArrayView<1, const float> In)
|
|
{
|
|
check(Out.Num() == In.Num());
|
|
const int32 ValueNum = Out.Num();
|
|
for (int32 ValueIdx = 0; ValueIdx < ValueNum; ValueIdx++)
|
|
{
|
|
Out[ValueIdx] = FMath::Loge(In[ValueIdx]);
|
|
}
|
|
}
|
|
|
|
static inline void Exp(TLearningArrayView<1, float> Out, const TLearningArrayView<1, const float> In)
|
|
{
|
|
check(Out.Num() == In.Num());
|
|
const int32 ValueNum = Out.Num();
|
|
for (int32 ValueIdx = 0; ValueIdx < ValueNum; ValueIdx++)
|
|
{
|
|
Out[ValueIdx] = FMath::Exp(In[ValueIdx]);
|
|
}
|
|
}
|
|
|
|
static inline void Sqrt(TLearningArrayView<1, float> Out, const TLearningArrayView<1, const float> In)
|
|
{
|
|
check(Out.Num() == In.Num());
|
|
const int32 ValueNum = Out.Num();
|
|
for (int32 ValueIdx = 0; ValueIdx < ValueNum; ValueIdx++)
|
|
{
|
|
Out[ValueIdx] = FMath::Sqrt(In[ValueIdx]);
|
|
}
|
|
}
|
|
|
|
static inline void LengthSquared(TLearningArrayView<1, float> InOut, const TLearningArrayView<1, const float> In)
|
|
{
|
|
check(InOut.Num() == In.Num());
|
|
const int32 ValueNum = InOut.Num();
|
|
for (int32 ValueIdx = 0; ValueIdx < ValueNum; ValueIdx++)
|
|
{
|
|
InOut[ValueIdx] += In[ValueIdx] * In[ValueIdx];
|
|
}
|
|
}
|
|
|
|
static inline void SqrtInplace(TLearningArrayView<1, float> InOut)
|
|
{
|
|
const int32 ValueNum = InOut.Num();
|
|
for (int32 ValueIdx = 0; ValueIdx < ValueNum; ValueIdx++)
|
|
{
|
|
InOut[ValueIdx] = FMath::Sqrt(InOut[ValueIdx]);
|
|
}
|
|
}
|
|
|
|
static inline void Normalize(TLearningArrayView<2, float> Out, const TLearningArrayView<2, const float> In)
|
|
{
|
|
check(Out.Num<0>() == In.Num<0>());
|
|
check(Out.Num<1>() == In.Num<1>());
|
|
|
|
const int32 ChannelNum = In.Num<0>();
|
|
const int32 FrameNum = In.Num<1>();
|
|
for (int32 FrameIdx = 0; FrameIdx < FrameNum; FrameIdx++)
|
|
{
|
|
float LengthSquared = 0.0f;
|
|
for (int32 ChannelIdx = 0; ChannelIdx < ChannelNum; ChannelIdx++)
|
|
{
|
|
LengthSquared += In[ChannelIdx][FrameIdx] * In[ChannelIdx][FrameIdx];
|
|
}
|
|
|
|
const float Length = FMath::Sqrt(LengthSquared);
|
|
|
|
for (int32 ChannelIdx = 0; ChannelIdx < ChannelNum; ChannelIdx++)
|
|
{
|
|
Out[ChannelIdx][FrameIdx] = In[ChannelIdx][FrameIdx] / Length;
|
|
}
|
|
}
|
|
}
|
|
|
|
static inline void AddConstant(TLearningArrayView<1, float> Out, const TLearningArrayView<1, const float> Lhs, const float Rhs)
|
|
{
|
|
check(Out.Num() == Lhs.Num());
|
|
const int32 ValueNum = Out.Num();
|
|
for (int32 ValueIdx = 0; ValueIdx < ValueNum; ValueIdx++)
|
|
{
|
|
Out[ValueIdx] = Lhs[ValueIdx] + Rhs;
|
|
}
|
|
}
|
|
|
|
static inline void SubConstant(TLearningArrayView<1, float> Out, const TLearningArrayView<1, const float> Lhs, const float Rhs)
|
|
{
|
|
check(Out.Num() == Lhs.Num());
|
|
const int32 ValueNum = Out.Num();
|
|
for (int32 ValueIdx = 0; ValueIdx < ValueNum; ValueIdx++)
|
|
{
|
|
Out[ValueIdx] = Lhs[ValueIdx] - Rhs;
|
|
}
|
|
}
|
|
|
|
static inline void MulConstant(TLearningArrayView<1, float> Out, const TLearningArrayView<1, const float> Lhs, const float Rhs)
|
|
{
|
|
check(Out.Num() == Lhs.Num());
|
|
const int32 ValueNum = Out.Num();
|
|
for (int32 ValueIdx = 0; ValueIdx < ValueNum; ValueIdx++)
|
|
{
|
|
Out[ValueIdx] = Lhs[ValueIdx] * Rhs;
|
|
}
|
|
}
|
|
|
|
static inline void DivConstant(TLearningArrayView<1, float> Out, const TLearningArrayView<1, const float> Lhs, const float Rhs)
|
|
{
|
|
check(Out.Num() == Lhs.Num());
|
|
const int32 ValueNum = Out.Num();
|
|
for (int32 ValueIdx = 0; ValueIdx < ValueNum; ValueIdx++)
|
|
{
|
|
Out[ValueIdx] = Lhs[ValueIdx] / Rhs;
|
|
}
|
|
}
|
|
|
|
static inline void ConstantAdd(TLearningArrayView<1, float> Out, const float Lhs, const TLearningArrayView<1, const float> Rhs)
|
|
{
|
|
check(Out.Num() == Rhs.Num());
|
|
const int32 ValueNum = Out.Num();
|
|
for (int32 ValueIdx = 0; ValueIdx < ValueNum; ValueIdx++)
|
|
{
|
|
Out[ValueIdx] = Lhs + Rhs[ValueIdx];
|
|
}
|
|
}
|
|
|
|
static inline void ConstantSub(TLearningArrayView<1, float> Out, const float Lhs, const TLearningArrayView<1, const float> Rhs)
|
|
{
|
|
check(Out.Num() == Rhs.Num());
|
|
const int32 ValueNum = Out.Num();
|
|
for (int32 ValueIdx = 0; ValueIdx < ValueNum; ValueIdx++)
|
|
{
|
|
Out[ValueIdx] = Lhs - Rhs[ValueIdx];
|
|
}
|
|
}
|
|
|
|
static inline void ConstantMul(TLearningArrayView<1, float> Out, const float Lhs, const TLearningArrayView<1, const float> Rhs)
|
|
{
|
|
check(Out.Num() == Rhs.Num());
|
|
const int32 ValueNum = Out.Num();
|
|
for (int32 ValueIdx = 0; ValueIdx < ValueNum; ValueIdx++)
|
|
{
|
|
Out[ValueIdx] = Lhs * Rhs[ValueIdx];
|
|
}
|
|
}
|
|
|
|
static inline void ConstantDiv(TLearningArrayView<1, float> Out, const float Lhs, const TLearningArrayView<1, const float> Rhs)
|
|
{
|
|
check(Out.Num() == Rhs.Num());
|
|
const int32 ValueNum = Out.Num();
|
|
for (int32 ValueIdx = 0; ValueIdx < ValueNum; ValueIdx++)
|
|
{
|
|
Out[ValueIdx] = Lhs / Rhs[ValueIdx];
|
|
}
|
|
}
|
|
|
|
static inline void LogicalAnd(TLearningArrayView<1, float> Out, const TLearningArrayView<1, const float> Lhs, const TLearningArrayView<1, const float> Rhs)
|
|
{
|
|
check(Out.Num() == Lhs.Num());
|
|
check(Out.Num() == Rhs.Num());
|
|
const int32 ValueNum = Out.Num();
|
|
for (int32 ValueIdx = 0; ValueIdx < ValueNum; ValueIdx++)
|
|
{
|
|
Out[ValueIdx] = Lhs[ValueIdx] && Rhs[ValueIdx];
|
|
}
|
|
}
|
|
|
|
static inline void LogicalOr(TLearningArrayView<1, float> Out, const TLearningArrayView<1, const float> Lhs, const TLearningArrayView<1, const float> Rhs)
|
|
{
|
|
check(Out.Num() == Lhs.Num());
|
|
check(Out.Num() == Rhs.Num());
|
|
const int32 ValueNum = Out.Num();
|
|
for (int32 ValueIdx = 0; ValueIdx < ValueNum; ValueIdx++)
|
|
{
|
|
Out[ValueIdx] = Lhs[ValueIdx] || Rhs[ValueIdx];
|
|
}
|
|
}
|
|
|
|
static inline void LogicalNot(TLearningArrayView<1, float> Out, const TLearningArrayView<1, const float> In)
|
|
{
|
|
check(Out.Num() == In.Num());
|
|
const int32 ValueNum = Out.Num();
|
|
for (int32 ValueIdx = 0; ValueIdx < ValueNum; ValueIdx++)
|
|
{
|
|
Out[ValueIdx] = !In[ValueIdx];
|
|
}
|
|
}
|
|
|
|
static inline void Gt(TLearningArrayView<1, float> Out, const TLearningArrayView<1, const float> Lhs, const TLearningArrayView<1, const float> Rhs)
|
|
{
|
|
check(Out.Num() == Lhs.Num());
|
|
check(Out.Num() == Rhs.Num());
|
|
const int32 ValueNum = Out.Num();
|
|
for (int32 ValueIdx = 0; ValueIdx < ValueNum; ValueIdx++)
|
|
{
|
|
Out[ValueIdx] = Lhs[ValueIdx] > Rhs[ValueIdx];
|
|
}
|
|
}
|
|
|
|
static inline void Ge(TLearningArrayView<1, float> Out, const TLearningArrayView<1, const float> Lhs, const TLearningArrayView<1, const float> Rhs)
|
|
{
|
|
check(Out.Num() == Lhs.Num());
|
|
check(Out.Num() == Rhs.Num());
|
|
const int32 ValueNum = Out.Num();
|
|
for (int32 ValueIdx = 0; ValueIdx < ValueNum; ValueIdx++)
|
|
{
|
|
Out[ValueIdx] = Lhs[ValueIdx] >= Rhs[ValueIdx];
|
|
}
|
|
}
|
|
|
|
static inline void Lt(TLearningArrayView<1, float> Out, const TLearningArrayView<1, const float> Lhs, const TLearningArrayView<1, const float> Rhs)
|
|
{
|
|
check(Out.Num() == Lhs.Num());
|
|
check(Out.Num() == Rhs.Num());
|
|
const int32 ValueNum = Out.Num();
|
|
for (int32 ValueIdx = 0; ValueIdx < ValueNum; ValueIdx++)
|
|
{
|
|
Out[ValueIdx] = Lhs[ValueIdx] < Rhs[ValueIdx];
|
|
}
|
|
}
|
|
|
|
static inline void Le(TLearningArrayView<1, float> Out, const TLearningArrayView<1, const float> Lhs, const TLearningArrayView<1, const float> Rhs)
|
|
{
|
|
check(Out.Num() == Lhs.Num());
|
|
check(Out.Num() == Rhs.Num());
|
|
const int32 ValueNum = Out.Num();
|
|
for (int32 ValueIdx = 0; ValueIdx < ValueNum; ValueIdx++)
|
|
{
|
|
Out[ValueIdx] = Lhs[ValueIdx] <= Rhs[ValueIdx];
|
|
}
|
|
}
|
|
|
|
static inline void Eq(TLearningArrayView<1, float> Out, const TLearningArrayView<1, const float> Lhs, const TLearningArrayView<1, const float> Rhs)
|
|
{
|
|
check(Out.Num() == Lhs.Num());
|
|
check(Out.Num() == Rhs.Num());
|
|
const int32 ValueNum = Out.Num();
|
|
for (int32 ValueIdx = 0; ValueIdx < ValueNum; ValueIdx++)
|
|
{
|
|
Out[ValueIdx] = Lhs[ValueIdx] == Rhs[ValueIdx];
|
|
}
|
|
}
|
|
|
|
static inline void Neq(TLearningArrayView<1, float> Out, const TLearningArrayView<1, const float> Lhs, const TLearningArrayView<1, const float> Rhs)
|
|
{
|
|
check(Out.Num() == Lhs.Num());
|
|
check(Out.Num() == Rhs.Num());
|
|
const int32 ValueNum = Out.Num();
|
|
for (int32 ValueIdx = 0; ValueIdx < ValueNum; ValueIdx++)
|
|
{
|
|
Out[ValueIdx] = Lhs[ValueIdx] != Rhs[ValueIdx];
|
|
}
|
|
}
|
|
|
|
static inline void GtConstant(TLearningArrayView<1, float> Out, const TLearningArrayView<1, const float> Lhs, const float Rhs)
|
|
{
|
|
check(Out.Num() == Lhs.Num());
|
|
const int32 ValueNum = Out.Num();
|
|
for (int32 ValueIdx = 0; ValueIdx < ValueNum; ValueIdx++)
|
|
{
|
|
Out[ValueIdx] = Lhs[ValueIdx] > Rhs;
|
|
}
|
|
}
|
|
|
|
static inline void GeConstant(TLearningArrayView<1, float> Out, const TLearningArrayView<1, const float> Lhs, const float Rhs)
|
|
{
|
|
check(Out.Num() == Lhs.Num());
|
|
const int32 ValueNum = Out.Num();
|
|
for (int32 ValueIdx = 0; ValueIdx < ValueNum; ValueIdx++)
|
|
{
|
|
Out[ValueIdx] = Lhs[ValueIdx] >= Rhs;
|
|
}
|
|
}
|
|
|
|
static inline void LtConstant(TLearningArrayView<1, float> Out, const TLearningArrayView<1, const float> Lhs, const float Rhs)
|
|
{
|
|
check(Out.Num() == Lhs.Num());
|
|
const int32 ValueNum = Out.Num();
|
|
for (int32 ValueIdx = 0; ValueIdx < ValueNum; ValueIdx++)
|
|
{
|
|
Out[ValueIdx] = Lhs[ValueIdx] < Rhs;
|
|
}
|
|
}
|
|
|
|
static inline void LeConstant(TLearningArrayView<1, float> Out, const TLearningArrayView<1, const float> Lhs, const float Rhs)
|
|
{
|
|
check(Out.Num() == Lhs.Num());
|
|
const int32 ValueNum = Out.Num();
|
|
for (int32 ValueIdx = 0; ValueIdx < ValueNum; ValueIdx++)
|
|
{
|
|
Out[ValueIdx] = Lhs[ValueIdx] <= Rhs;
|
|
}
|
|
}
|
|
|
|
static inline void EqConstant(TLearningArrayView<1, float> Out, const TLearningArrayView<1, const float> Lhs, const float Rhs)
|
|
{
|
|
check(Out.Num() == Lhs.Num());
|
|
const int32 ValueNum = Out.Num();
|
|
for (int32 ValueIdx = 0; ValueIdx < ValueNum; ValueIdx++)
|
|
{
|
|
Out[ValueIdx] = Lhs[ValueIdx] == Rhs;
|
|
}
|
|
}
|
|
|
|
static inline void NeqConstant(TLearningArrayView<1, float> Out, const TLearningArrayView<1, const float> Lhs, const float Rhs)
|
|
{
|
|
check(Out.Num() == Lhs.Num());
|
|
const int32 ValueNum = Out.Num();
|
|
for (int32 ValueIdx = 0; ValueIdx < ValueNum; ValueIdx++)
|
|
{
|
|
Out[ValueIdx] = Lhs[ValueIdx] != Rhs;
|
|
}
|
|
}
|
|
|
|
static inline void ConstantGt(TLearningArrayView<1, float> Out, const float Lhs, const TLearningArrayView<1, const float> Rhs)
|
|
{
|
|
check(Out.Num() == Rhs.Num());
|
|
const int32 ValueNum = Out.Num();
|
|
for (int32 ValueIdx = 0; ValueIdx < ValueNum; ValueIdx++)
|
|
{
|
|
Out[ValueIdx] = Lhs > Rhs[ValueIdx];
|
|
}
|
|
}
|
|
|
|
static inline void ConstantGe(TLearningArrayView<1, float> Out, const float Lhs, const TLearningArrayView<1, const float> Rhs)
|
|
{
|
|
check(Out.Num() == Rhs.Num());
|
|
const int32 ValueNum = Out.Num();
|
|
for (int32 ValueIdx = 0; ValueIdx < ValueNum; ValueIdx++)
|
|
{
|
|
Out[ValueIdx] = Lhs >= Rhs[ValueIdx];
|
|
}
|
|
}
|
|
|
|
static inline void ConstantLt(TLearningArrayView<1, float> Out, const float Lhs, const TLearningArrayView<1, const float> Rhs)
|
|
{
|
|
check(Out.Num() == Rhs.Num());
|
|
const int32 ValueNum = Out.Num();
|
|
for (int32 ValueIdx = 0; ValueIdx < ValueNum; ValueIdx++)
|
|
{
|
|
Out[ValueIdx] = Lhs < Rhs[ValueIdx];
|
|
}
|
|
}
|
|
|
|
static inline void ConstantLe(TLearningArrayView<1, float> Out, const float Lhs, const TLearningArrayView<1, const float> Rhs)
|
|
{
|
|
check(Out.Num() == Rhs.Num());
|
|
const int32 ValueNum = Out.Num();
|
|
for (int32 ValueIdx = 0; ValueIdx < ValueNum; ValueIdx++)
|
|
{
|
|
Out[ValueIdx] = Lhs < Rhs[ValueIdx];
|
|
}
|
|
}
|
|
|
|
static inline void ConstantEq(TLearningArrayView<1, float> Out, const float Lhs, const TLearningArrayView<1, const float> Rhs)
|
|
{
|
|
check(Out.Num() == Rhs.Num());
|
|
const int32 ValueNum = Out.Num();
|
|
for (int32 ValueIdx = 0; ValueIdx < ValueNum; ValueIdx++)
|
|
{
|
|
Out[ValueIdx] = Lhs == Rhs[ValueIdx];
|
|
}
|
|
}
|
|
|
|
static inline void ConstantNeq(TLearningArrayView<1, float> Out, const float Lhs, const TLearningArrayView<1, const float> Rhs)
|
|
{
|
|
check(Out.Num() == Rhs.Num());
|
|
const int32 ValueNum = Out.Num();
|
|
for (int32 ValueIdx = 0; ValueIdx < ValueNum; ValueIdx++)
|
|
{
|
|
Out[ValueIdx] = Lhs != Rhs[ValueIdx];
|
|
}
|
|
}
|
|
|
|
static inline void FilterGaussian(TLearningArrayView<1, float> Out, const TLearningArrayView<1, const float> In, const float StdInFrames)
|
|
{
|
|
check(Out.Num() == In.Num());
|
|
check(StdInFrames >= 0.0f);
|
|
|
|
#if UE_LEARNING_ISPC
|
|
|
|
ispc::LearningFilterGaussian(Out.GetData(), In.GetData(), In.Num(), StdInFrames);
|
|
|
|
#else
|
|
const int32 StdRange = FMath::RoundToInt(StdInFrames * 3.0f);
|
|
|
|
const int32 ValueNum = Out.Num();
|
|
for (int32 ValueIdx = 0; ValueIdx < ValueNum; ValueIdx++)
|
|
{
|
|
float Total = 0.0f;
|
|
Out[ValueIdx] = 0.0f;
|
|
|
|
const int32 RangeMin = FMath::Max(ValueIdx - StdRange, 0);
|
|
const int32 RangeMax = FMath::Min(ValueIdx + StdRange, ValueNum - 1);
|
|
|
|
for (int32 Offset = -StdRange; Offset <= +StdRange; Offset++)
|
|
{
|
|
if (ValueIdx + Offset >= 0 && ValueIdx + Offset < ValueNum)
|
|
{
|
|
const float Weight = FMath::InvExpApprox(FMath::Square(Offset / StdInFrames));
|
|
Out[ValueIdx] += Weight * In[ValueIdx + Offset];
|
|
Total += Weight;
|
|
}
|
|
}
|
|
|
|
Out[ValueIdx] = Out[ValueIdx] / Total;
|
|
}
|
|
#endif
|
|
}
|
|
|
|
static inline void FilterMajorityVote(TLearningArrayView<1, float> Out, const TLearningArrayView<1, const float> In, const int32 FilterWidthInFrames)
|
|
{
|
|
check(Out.Num() == In.Num());
|
|
check(FilterWidthInFrames >= 0.0f);
|
|
|
|
#if UE_LEARNING_ISPC
|
|
|
|
ispc::LearningFilterMajorityVote(Out.GetData(), In.GetData(), In.Num(), FilterWidthInFrames);
|
|
|
|
#else
|
|
const int32 ValueNum = Out.Num();
|
|
for (int32 ValueIdx = 0; ValueIdx < ValueNum; ValueIdx++)
|
|
{
|
|
int32 Total = 0;
|
|
|
|
const int32 RangeMin = FMath::Max(ValueIdx - FilterWidthInFrames, 0);
|
|
const int32 RangeMax = FMath::Min(ValueIdx + FilterWidthInFrames, ValueNum - 1);
|
|
|
|
for (int32 Offset = -FilterWidthInFrames; Offset <= +FilterWidthInFrames; Offset++)
|
|
{
|
|
if (ValueIdx + Offset >= 0 && ValueIdx + Offset < ValueNum)
|
|
{
|
|
Total += In[ValueIdx + Offset] ? 1 : -1;
|
|
}
|
|
}
|
|
|
|
Out[ValueIdx] = Total > 0;
|
|
}
|
|
#endif
|
|
}
|
|
|
|
static inline void MeanStd(float& OutMean, float& OutStd, const TLearningArrayView<1, const float> In)
|
|
{
|
|
const int32 Num = In.Num();
|
|
|
|
OutMean = 0.0f;
|
|
OutStd = 0.0f;
|
|
for (int32 Idx = 0; Idx < Num; Idx++)
|
|
{
|
|
OutStd += (((float)Idx / Num) / (Idx + 1)) * FMath::Square(In[Idx] - OutMean);
|
|
OutMean += (In[Idx] - OutMean) / (Idx + 1);
|
|
}
|
|
OutStd = FMath::Sqrt(OutStd);
|
|
}
|
|
|
|
static inline void LogMeanStd(float& OutMean, float& OutLogStd, const TLearningArrayView<1, const float> In)
|
|
{
|
|
const int32 Num = In.Num();
|
|
|
|
OutMean = 0.0f;
|
|
OutLogStd = 0.0f;
|
|
for (int32 Idx = 0; Idx < Num; Idx++)
|
|
{
|
|
const float Value = FMath::Loge(FMath::Max(In[Idx], UE_SMALL_NUMBER));
|
|
OutLogStd += (((float)Idx / Num) / (Idx + 1)) * FMath::Square(Value - OutMean);
|
|
OutMean += (Value - OutMean) / (Idx + 1);
|
|
}
|
|
OutMean = FMath::Exp(OutMean);
|
|
OutLogStd = FMath::Sqrt(OutLogStd);
|
|
}
|
|
|
|
static inline void QuatInv(TLearningArrayView<2, float> Out, const TLearningArrayView<2, const float> In)
|
|
{
|
|
check(Out.Num<0>() == 4);
|
|
check(In.Num<0>() == 4);
|
|
check(Out.Num<1>() == In.Num<1>());
|
|
|
|
const int32 ValueNum = Out.Num<1>();
|
|
for (int32 ValueIdx = 0; ValueIdx < ValueNum; ValueIdx++)
|
|
{
|
|
const FQuat4f InValue = FQuat4f(In[0][ValueIdx], In[1][ValueIdx], In[2][ValueIdx], In[3][ValueIdx]);
|
|
const FQuat4f OutValue = InValue.Inverse();
|
|
Out[0][ValueIdx] = OutValue.X;
|
|
Out[1][ValueIdx] = OutValue.Y;
|
|
Out[2][ValueIdx] = OutValue.Z;
|
|
Out[3][ValueIdx] = OutValue.W;
|
|
}
|
|
}
|
|
|
|
static inline void QuatAbs(TLearningArrayView<2, float> Out, const TLearningArrayView<2, const float> In)
|
|
{
|
|
check(Out.Num<0>() == 4);
|
|
check(In.Num<0>() == 4);
|
|
check(Out.Num<1>() == In.Num<1>());
|
|
|
|
const int32 ValueNum = Out.Num<1>();
|
|
for (int32 ValueIdx = 0; ValueIdx < ValueNum; ValueIdx++)
|
|
{
|
|
const FQuat4f InValue = FQuat4f(In[0][ValueIdx], In[1][ValueIdx], In[2][ValueIdx], In[3][ValueIdx]);
|
|
const FQuat4f OutValue = InValue.GetShortestArcWith(FQuat4f::Identity);
|
|
Out[0][ValueIdx] = OutValue.X;
|
|
Out[1][ValueIdx] = OutValue.Y;
|
|
Out[2][ValueIdx] = OutValue.Z;
|
|
Out[3][ValueIdx] = OutValue.W;
|
|
}
|
|
}
|
|
|
|
static inline void QuatToRotationVector(TLearningArrayView<2, float> Out, const TLearningArrayView<2, const float> In)
|
|
{
|
|
check(Out.Num<0>() == 3);
|
|
check(In.Num<0>() == 4);
|
|
check(Out.Num<1>() == In.Num<1>());
|
|
|
|
const int32 ValueNum = Out.Num<1>();
|
|
for (int32 ValueIdx = 0; ValueIdx < ValueNum; ValueIdx++)
|
|
{
|
|
const FQuat4f InValue = FQuat4f(In[0][ValueIdx], In[1][ValueIdx], In[2][ValueIdx], In[3][ValueIdx]);
|
|
const FVector3f OutValue = InValue.ToRotationVector();
|
|
Out[0][ValueIdx] = OutValue.X;
|
|
Out[1][ValueIdx] = OutValue.Y;
|
|
Out[2][ValueIdx] = OutValue.Z;
|
|
}
|
|
}
|
|
|
|
static inline void QuatFromRotationVector(TLearningArrayView<2, float> Out, const TLearningArrayView<2, const float> In)
|
|
{
|
|
check(Out.Num<0>() == 4);
|
|
check(In.Num<0>() == 3);
|
|
check(Out.Num<1>() == In.Num<1>());
|
|
|
|
const int32 ValueNum = Out.Num<1>();
|
|
for (int32 ValueIdx = 0; ValueIdx < ValueNum; ValueIdx++)
|
|
{
|
|
const FVector3f InValue = FVector3f(In[0][ValueIdx], In[1][ValueIdx], In[2][ValueIdx]);
|
|
const FQuat4f OutValue = FQuat4f::MakeFromRotationVector(InValue);
|
|
Out[0][ValueIdx] = OutValue.X;
|
|
Out[1][ValueIdx] = OutValue.Y;
|
|
Out[2][ValueIdx] = OutValue.Z;
|
|
Out[3][ValueIdx] = OutValue.W;
|
|
}
|
|
}
|
|
|
|
static inline void QuatMul(
|
|
TLearningArrayView<1, float> OutX,
|
|
TLearningArrayView<1, float> OutY,
|
|
TLearningArrayView<1, float> OutZ,
|
|
TLearningArrayView<1, float> OutW,
|
|
const TLearningArrayView<1, const float> LhsX,
|
|
const TLearningArrayView<1, const float> LhsY,
|
|
const TLearningArrayView<1, const float> LhsZ,
|
|
const TLearningArrayView<1, const float> LhsW,
|
|
const TLearningArrayView<1, const float> RhsX,
|
|
const TLearningArrayView<1, const float> RhsY,
|
|
const TLearningArrayView<1, const float> RhsZ,
|
|
const TLearningArrayView<1, const float> RhsW)
|
|
{
|
|
const int32 ValueNum = OutX.Num();
|
|
for (int32 ValueIdx = 0; ValueIdx < ValueNum; ValueIdx++)
|
|
{
|
|
const FQuat4f Lhs = FQuat4f(LhsX[ValueIdx], LhsY[ValueIdx], LhsZ[ValueIdx], LhsW[ValueIdx]);
|
|
const FQuat4f Rhs = FQuat4f(RhsX[ValueIdx], RhsY[ValueIdx], RhsZ[ValueIdx], RhsW[ValueIdx]);
|
|
const FQuat4f Out = Lhs * Rhs;
|
|
OutX[ValueIdx] = Out.X;
|
|
OutY[ValueIdx] = Out.Y;
|
|
OutZ[ValueIdx] = Out.Z;
|
|
OutW[ValueIdx] = Out.W;
|
|
}
|
|
}
|
|
|
|
static inline void QuatMulInv(
|
|
TLearningArrayView<1, float> OutX,
|
|
TLearningArrayView<1, float> OutY,
|
|
TLearningArrayView<1, float> OutZ,
|
|
TLearningArrayView<1, float> OutW,
|
|
const TLearningArrayView<1, const float> LhsX,
|
|
const TLearningArrayView<1, const float> LhsY,
|
|
const TLearningArrayView<1, const float> LhsZ,
|
|
const TLearningArrayView<1, const float> LhsW,
|
|
const TLearningArrayView<1, const float> RhsX,
|
|
const TLearningArrayView<1, const float> RhsY,
|
|
const TLearningArrayView<1, const float> RhsZ,
|
|
const TLearningArrayView<1, const float> RhsW)
|
|
{
|
|
const int32 ValueNum = OutX.Num();
|
|
for (int32 ValueIdx = 0; ValueIdx < ValueNum; ValueIdx++)
|
|
{
|
|
const FQuat4f Lhs = FQuat4f(LhsX[ValueIdx], LhsY[ValueIdx], LhsZ[ValueIdx], LhsW[ValueIdx]);
|
|
const FQuat4f Rhs = FQuat4f(RhsX[ValueIdx], RhsY[ValueIdx], RhsZ[ValueIdx], RhsW[ValueIdx]);
|
|
const FQuat4f Out = Lhs * Rhs.Inverse();
|
|
OutX[ValueIdx] = Out.X;
|
|
OutY[ValueIdx] = Out.Y;
|
|
OutZ[ValueIdx] = Out.Z;
|
|
OutW[ValueIdx] = Out.W;
|
|
}
|
|
}
|
|
|
|
static inline void QuatInvMul(
|
|
TLearningArrayView<1, float> OutX,
|
|
TLearningArrayView<1, float> OutY,
|
|
TLearningArrayView<1, float> OutZ,
|
|
TLearningArrayView<1, float> OutW,
|
|
const TLearningArrayView<1, const float> LhsX,
|
|
const TLearningArrayView<1, const float> LhsY,
|
|
const TLearningArrayView<1, const float> LhsZ,
|
|
const TLearningArrayView<1, const float> LhsW,
|
|
const TLearningArrayView<1, const float> RhsX,
|
|
const TLearningArrayView<1, const float> RhsY,
|
|
const TLearningArrayView<1, const float> RhsZ,
|
|
const TLearningArrayView<1, const float> RhsW)
|
|
{
|
|
const int32 ValueNum = OutX.Num();
|
|
for (int32 ValueIdx = 0; ValueIdx < ValueNum; ValueIdx++)
|
|
{
|
|
const FQuat4f Lhs = FQuat4f(LhsX[ValueIdx], LhsY[ValueIdx], LhsZ[ValueIdx], LhsW[ValueIdx]);
|
|
const FQuat4f Rhs = FQuat4f(RhsX[ValueIdx], RhsY[ValueIdx], RhsZ[ValueIdx], RhsW[ValueIdx]);
|
|
const FQuat4f Out = Lhs.Inverse() * Rhs;
|
|
OutX[ValueIdx] = Out.X;
|
|
OutY[ValueIdx] = Out.Y;
|
|
OutZ[ValueIdx] = Out.Z;
|
|
OutW[ValueIdx] = Out.W;
|
|
}
|
|
}
|
|
|
|
static inline void QuatRotate(
|
|
TLearningArrayView<1, float> OutX,
|
|
TLearningArrayView<1, float> OutY,
|
|
TLearningArrayView<1, float> OutZ,
|
|
const TLearningArrayView<1, const float> LhsX,
|
|
const TLearningArrayView<1, const float> LhsY,
|
|
const TLearningArrayView<1, const float> LhsZ,
|
|
const TLearningArrayView<1, const float> LhsW,
|
|
const TLearningArrayView<1, const float> RhsX,
|
|
const TLearningArrayView<1, const float> RhsY,
|
|
const TLearningArrayView<1, const float> RhsZ)
|
|
{
|
|
const int32 ValueNum = OutX.Num();
|
|
for (int32 ValueIdx = 0; ValueIdx < ValueNum; ValueIdx++)
|
|
{
|
|
const FQuat4f Lhs = FQuat4f(LhsX[ValueIdx], LhsY[ValueIdx], LhsZ[ValueIdx], LhsW[ValueIdx]);
|
|
const FVector3f Rhs = FVector3f(RhsX[ValueIdx], RhsY[ValueIdx], RhsZ[ValueIdx]);
|
|
const FVector3f Out = Lhs.RotateVector(Rhs);
|
|
OutX[ValueIdx] = Out.X;
|
|
OutY[ValueIdx] = Out.Y;
|
|
OutZ[ValueIdx] = Out.Z;
|
|
}
|
|
}
|
|
|
|
static inline void QuatUnrotate(
|
|
TLearningArrayView<1, float> OutX,
|
|
TLearningArrayView<1, float> OutY,
|
|
TLearningArrayView<1, float> OutZ,
|
|
const TLearningArrayView<1, const float> LhsX,
|
|
const TLearningArrayView<1, const float> LhsY,
|
|
const TLearningArrayView<1, const float> LhsZ,
|
|
const TLearningArrayView<1, const float> LhsW,
|
|
const TLearningArrayView<1, const float> RhsX,
|
|
const TLearningArrayView<1, const float> RhsY,
|
|
const TLearningArrayView<1, const float> RhsZ)
|
|
{
|
|
const int32 ValueNum = OutX.Num();
|
|
for (int32 ValueIdx = 0; ValueIdx < ValueNum; ValueIdx++)
|
|
{
|
|
const FQuat4f Lhs = FQuat4f(LhsX[ValueIdx], LhsY[ValueIdx], LhsZ[ValueIdx], LhsW[ValueIdx]);
|
|
const FVector3f Rhs = FVector3f(RhsX[ValueIdx], RhsY[ValueIdx], RhsZ[ValueIdx]);
|
|
const FVector3f Out = Lhs.UnrotateVector(Rhs);
|
|
OutX[ValueIdx] = Out.X;
|
|
OutY[ValueIdx] = Out.Y;
|
|
OutZ[ValueIdx] = Out.Z;
|
|
}
|
|
}
|
|
|
|
static inline void QuatBetween(
|
|
TLearningArrayView<1, float> OutX,
|
|
TLearningArrayView<1, float> OutY,
|
|
TLearningArrayView<1, float> OutZ,
|
|
TLearningArrayView<1, float> OutW,
|
|
const TLearningArrayView<1, const float> LhsX,
|
|
const TLearningArrayView<1, const float> LhsY,
|
|
const TLearningArrayView<1, const float> LhsZ,
|
|
const TLearningArrayView<1, const float> RhsX,
|
|
const TLearningArrayView<1, const float> RhsY,
|
|
const TLearningArrayView<1, const float> RhsZ)
|
|
{
|
|
const int32 ValueNum = OutX.Num();
|
|
for (int32 ValueIdx = 0; ValueIdx < ValueNum; ValueIdx++)
|
|
{
|
|
const FVector3f Lhs = FVector3f(LhsX[ValueIdx], LhsY[ValueIdx], LhsZ[ValueIdx]);
|
|
const FVector3f Rhs = FVector3f(RhsX[ValueIdx], RhsY[ValueIdx], RhsZ[ValueIdx]);
|
|
const FQuat4f Out = FQuat4f::FindBetween(Lhs, Rhs);
|
|
OutX[ValueIdx] = Out.X;
|
|
OutY[ValueIdx] = Out.Y;
|
|
OutZ[ValueIdx] = Out.Z;
|
|
OutW[ValueIdx] = Out.W;
|
|
}
|
|
}
|
|
|
|
static inline void QuatMulConstant(TLearningArrayView<2, float> Out, const TLearningArrayView<2, const float> Lhs, const FQuat4f Rhs)
|
|
{
|
|
check(Out.Num<0>() == 4);
|
|
check(Lhs.Num<0>() == 4);
|
|
check(Out.Num<1>() == Lhs.Num<1>());
|
|
|
|
const int32 ValueNum = Out.Num<1>();
|
|
for (int32 ValueIdx = 0; ValueIdx < ValueNum; ValueIdx++)
|
|
{
|
|
const FQuat4f LhsValue = FQuat4f(Lhs[0][ValueIdx], Lhs[1][ValueIdx], Lhs[2][ValueIdx], Lhs[3][ValueIdx]);
|
|
const FQuat4f OutValue = LhsValue * Rhs;
|
|
Out[0][ValueIdx] = OutValue.X;
|
|
Out[1][ValueIdx] = OutValue.Y;
|
|
Out[2][ValueIdx] = OutValue.Z;
|
|
Out[3][ValueIdx] = OutValue.W;
|
|
}
|
|
}
|
|
|
|
static inline void QuatInvMulConstant(TLearningArrayView<2, float> Out, const TLearningArrayView<2, const float> Lhs, const FQuat4f Rhs)
|
|
{
|
|
check(Out.Num<0>() == 4);
|
|
check(Lhs.Num<0>() == 4);
|
|
check(Out.Num<1>() == Lhs.Num<1>());
|
|
|
|
const int32 ValueNum = Out.Num<1>();
|
|
for (int32 ValueIdx = 0; ValueIdx < ValueNum; ValueIdx++)
|
|
{
|
|
const FQuat4f LhsValue = FQuat4f(Lhs[0][ValueIdx], Lhs[1][ValueIdx], Lhs[2][ValueIdx], Lhs[3][ValueIdx]);
|
|
const FQuat4f OutValue = LhsValue.Inverse() * Rhs;
|
|
Out[0][ValueIdx] = OutValue.X;
|
|
Out[1][ValueIdx] = OutValue.Y;
|
|
Out[2][ValueIdx] = OutValue.Z;
|
|
Out[3][ValueIdx] = OutValue.W;
|
|
}
|
|
}
|
|
|
|
static inline void QuatMulInvConstant(TLearningArrayView<2, float> Out, const TLearningArrayView<2, const float> Lhs, const FQuat4f Rhs)
|
|
{
|
|
check(Out.Num<0>() == 4);
|
|
check(Lhs.Num<0>() == 4);
|
|
check(Out.Num<1>() == Lhs.Num<1>());
|
|
|
|
const int32 ValueNum = Out.Num<1>();
|
|
for (int32 ValueIdx = 0; ValueIdx < ValueNum; ValueIdx++)
|
|
{
|
|
const FQuat4f LhsValue = FQuat4f(Lhs[0][ValueIdx], Lhs[1][ValueIdx], Lhs[2][ValueIdx], Lhs[3][ValueIdx]);
|
|
const FQuat4f OutValue = LhsValue * Rhs.Inverse();
|
|
Out[0][ValueIdx] = OutValue.X;
|
|
Out[1][ValueIdx] = OutValue.Y;
|
|
Out[2][ValueIdx] = OutValue.Z;
|
|
Out[3][ValueIdx] = OutValue.W;
|
|
}
|
|
}
|
|
|
|
static inline void QuatRotateConstant(TLearningArrayView<2, float> Out, const TLearningArrayView<2, const float> Lhs, const FVector3f Rhs)
|
|
{
|
|
check(Out.Num<0>() == 3);
|
|
check(Lhs.Num<0>() == 4);
|
|
check(Out.Num<1>() == Lhs.Num<1>());
|
|
|
|
const int32 ValueNum = Out.Num<1>();
|
|
for (int32 ValueIdx = 0; ValueIdx < ValueNum; ValueIdx++)
|
|
{
|
|
const FQuat4f LhsValue = FQuat4f(Lhs[0][ValueIdx], Lhs[1][ValueIdx], Lhs[2][ValueIdx], Lhs[3][ValueIdx]);
|
|
const FVector3f OutValue = LhsValue.RotateVector(Rhs);
|
|
Out[0][ValueIdx] = OutValue.X;
|
|
Out[1][ValueIdx] = OutValue.Y;
|
|
Out[2][ValueIdx] = OutValue.Z;
|
|
}
|
|
}
|
|
|
|
static inline void QuatUnrotateConstant(TLearningArrayView<2, float> Out, const TLearningArrayView<2, const float> Lhs, const FVector3f Rhs)
|
|
{
|
|
check(Out.Num<0>() == 3);
|
|
check(Lhs.Num<0>() == 4);
|
|
check(Out.Num<1>() == Lhs.Num<1>());
|
|
|
|
const int32 ValueNum = Out.Num<1>();
|
|
for (int32 ValueIdx = 0; ValueIdx < ValueNum; ValueIdx++)
|
|
{
|
|
const FQuat4f LhsValue = FQuat4f(Lhs[0][ValueIdx], Lhs[1][ValueIdx], Lhs[2][ValueIdx], Lhs[3][ValueIdx]);
|
|
const FVector3f OutValue = LhsValue.RotateVector(Rhs);
|
|
Out[0][ValueIdx] = OutValue.X;
|
|
Out[1][ValueIdx] = OutValue.Y;
|
|
Out[2][ValueIdx] = OutValue.Z;
|
|
}
|
|
}
|
|
|
|
static inline void QuatBetweenConstant(TLearningArrayView<2, float> Out, const TLearningArrayView<2, const float> Lhs, const FVector3f Rhs)
|
|
{
|
|
check(Out.Num<0>() == 4);
|
|
check(Lhs.Num<0>() == 3);
|
|
check(Out.Num<1>() == Lhs.Num<1>());
|
|
|
|
const int32 ValueNum = Out.Num<1>();
|
|
for (int32 ValueIdx = 0; ValueIdx < ValueNum; ValueIdx++)
|
|
{
|
|
const FVector3f LhsValue = FVector3f(Lhs[0][ValueIdx], Lhs[1][ValueIdx], Lhs[2][ValueIdx]);
|
|
const FQuat4f OutValue = FQuat4f::FindBetween(LhsValue, Rhs);
|
|
Out[0][ValueIdx] = OutValue.X;
|
|
Out[1][ValueIdx] = OutValue.Y;
|
|
Out[2][ValueIdx] = OutValue.Z;
|
|
Out[3][ValueIdx] = OutValue.W;
|
|
}
|
|
}
|
|
|
|
static inline void QuatConstantMul(TLearningArrayView<2, float> Out, const FQuat4f Lhs, const TLearningArrayView<2, const float> Rhs)
|
|
{
|
|
check(Out.Num<0>() == 4);
|
|
check(Rhs.Num<0>() == 4);
|
|
check(Out.Num<1>() == Rhs.Num<1>());
|
|
|
|
const int32 ValueNum = Out.Num<1>();
|
|
for (int32 ValueIdx = 0; ValueIdx < ValueNum; ValueIdx++)
|
|
{
|
|
const FQuat4f RhsValue = FQuat4f(Rhs[0][ValueIdx], Rhs[1][ValueIdx], Rhs[2][ValueIdx], Rhs[3][ValueIdx]);
|
|
const FQuat4f OutValue = Lhs * RhsValue;
|
|
Out[0][ValueIdx] = OutValue.X;
|
|
Out[1][ValueIdx] = OutValue.Y;
|
|
Out[2][ValueIdx] = OutValue.Z;
|
|
Out[3][ValueIdx] = OutValue.W;
|
|
}
|
|
}
|
|
|
|
static inline void QuatConstantInvMul(TLearningArrayView<2, float> Out, const FQuat4f Lhs, const TLearningArrayView<2, const float> Rhs)
|
|
{
|
|
check(Out.Num<0>() == 4);
|
|
check(Rhs.Num<0>() == 4);
|
|
check(Out.Num<1>() == Rhs.Num<1>());
|
|
|
|
const int32 ValueNum = Out.Num<1>();
|
|
for (int32 ValueIdx = 0; ValueIdx < ValueNum; ValueIdx++)
|
|
{
|
|
const FQuat4f RhsValue = FQuat4f(Rhs[0][ValueIdx], Rhs[1][ValueIdx], Rhs[2][ValueIdx], Rhs[3][ValueIdx]);
|
|
const FQuat4f OutValue = Lhs.Inverse() * RhsValue;
|
|
Out[0][ValueIdx] = OutValue.X;
|
|
Out[1][ValueIdx] = OutValue.Y;
|
|
Out[2][ValueIdx] = OutValue.Z;
|
|
Out[3][ValueIdx] = OutValue.W;
|
|
}
|
|
}
|
|
|
|
static inline void QuatConstantMulInv(TLearningArrayView<2, float> Out, const FQuat4f Lhs, const TLearningArrayView<2, const float> Rhs)
|
|
{
|
|
check(Out.Num<0>() == 4);
|
|
check(Rhs.Num<0>() == 4);
|
|
check(Out.Num<1>() == Rhs.Num<1>());
|
|
|
|
const int32 ValueNum = Out.Num<1>();
|
|
for (int32 ValueIdx = 0; ValueIdx < ValueNum; ValueIdx++)
|
|
{
|
|
const FQuat4f RhsValue = FQuat4f(Rhs[0][ValueIdx], Rhs[1][ValueIdx], Rhs[2][ValueIdx], Rhs[3][ValueIdx]);
|
|
const FQuat4f OutValue = Lhs * RhsValue.Inverse();
|
|
Out[0][ValueIdx] = OutValue.X;
|
|
Out[1][ValueIdx] = OutValue.Y;
|
|
Out[2][ValueIdx] = OutValue.Z;
|
|
Out[3][ValueIdx] = OutValue.W;
|
|
}
|
|
}
|
|
|
|
static inline void QuatConstantRotate(TLearningArrayView<2, float> Out, const FQuat4f Lhs, const TLearningArrayView<2, const float> Rhs)
|
|
{
|
|
check(Out.Num<0>() == 3);
|
|
check(Rhs.Num<0>() == 3);
|
|
check(Out.Num<1>() == Rhs.Num<1>());
|
|
|
|
const int32 ValueNum = Out.Num<1>();
|
|
for (int32 ValueIdx = 0; ValueIdx < ValueNum; ValueIdx++)
|
|
{
|
|
const FVector3f RhsValue = FVector3f(Rhs[0][ValueIdx], Rhs[1][ValueIdx], Rhs[2][ValueIdx]);
|
|
const FVector3f OutValue = Lhs.RotateVector(RhsValue);
|
|
Out[0][ValueIdx] = OutValue.X;
|
|
Out[1][ValueIdx] = OutValue.Y;
|
|
Out[2][ValueIdx] = OutValue.Z;
|
|
}
|
|
}
|
|
|
|
static inline void QuatConstantUnrotate(TLearningArrayView<2, float> Out, const FQuat4f Lhs, const TLearningArrayView<2, const float> Rhs)
|
|
{
|
|
check(Out.Num<0>() == 3);
|
|
check(Rhs.Num<0>() == 3);
|
|
check(Out.Num<1>() == Rhs.Num<1>());
|
|
|
|
const int32 ValueNum = Out.Num<1>();
|
|
for (int32 ValueIdx = 0; ValueIdx < ValueNum; ValueIdx++)
|
|
{
|
|
const FVector3f RhsValue = FVector3f(Rhs[0][ValueIdx], Rhs[1][ValueIdx], Rhs[2][ValueIdx]);
|
|
const FVector3f OutValue = Lhs.UnrotateVector(RhsValue);
|
|
Out[0][ValueIdx] = OutValue.X;
|
|
Out[1][ValueIdx] = OutValue.Y;
|
|
Out[2][ValueIdx] = OutValue.Z;
|
|
}
|
|
}
|
|
|
|
static inline void QuatConstantBetween(TLearningArrayView<2, float> Out, const FVector3f Lhs, const TLearningArrayView<2, const float> Rhs)
|
|
{
|
|
check(Out.Num<0>() == 4);
|
|
check(Rhs.Num<0>() == 3);
|
|
check(Out.Num<1>() == Rhs.Num<1>());
|
|
|
|
const int32 ValueNum = Out.Num<1>();
|
|
for (int32 ValueIdx = 0; ValueIdx < ValueNum; ValueIdx++)
|
|
{
|
|
const FVector3f RhsValue = FVector3f(Rhs[0][ValueIdx], Rhs[1][ValueIdx], Rhs[2][ValueIdx]);
|
|
const FQuat4f OutValue = FQuat4f::FindBetween(Lhs, RhsValue);
|
|
Out[0][ValueIdx] = OutValue.X;
|
|
Out[1][ValueIdx] = OutValue.Y;
|
|
Out[2][ValueIdx] = OutValue.Z;
|
|
Out[3][ValueIdx] = OutValue.W;
|
|
}
|
|
}
|
|
|
|
// We need these custom Vector4 functions because the defaults for the FVector4f class will treat it like a Vector3
|
|
|
|
static inline float Vector4Length(const FVector4f X)
|
|
{
|
|
return FMath::Sqrt(X.X * X.X + X.Y * X.Y + X.Z * X.Z + X.W * X.W);
|
|
}
|
|
|
|
static inline FVector4f Vector4Normalize(const FVector4f X)
|
|
{
|
|
return X / Vector4Length(X);
|
|
}
|
|
|
|
static inline FVector4f DominantEigenVector(
|
|
const FMatrix44f& A,
|
|
const FVector4f V0,
|
|
const int32 Iterations,
|
|
const float Epsilon)
|
|
{
|
|
// Initial Guess at Eigen Vector & Value
|
|
FVector4f V = V0;
|
|
float EV = (A.TransformFVector4(V) / V).X;
|
|
|
|
for (int32 Iteration = 0; Iteration < Iterations; Iteration++)
|
|
{
|
|
// Power Iteration
|
|
const FVector4f Av = A.TransformFVector4(V);
|
|
|
|
// Next Guess at Eigen Vector & Value
|
|
const FVector4f VNew = Vector4Normalize(Av);
|
|
const float EVNew = (A.TransformFVector4(VNew) / VNew).X;
|
|
|
|
// Break if converged
|
|
if (FMath::Abs(EV - EVNew) < Epsilon)
|
|
{
|
|
break;
|
|
}
|
|
|
|
// Update best guess
|
|
V = VNew;
|
|
EV = EVNew;
|
|
}
|
|
|
|
return V;
|
|
}
|
|
|
|
static inline void QuatMeanStd(FQuat4f& OutMean, FVector3f& OutStd, const TLearningArrayView<2, const float> In)
|
|
{
|
|
check(In.Num<0>() == 4);
|
|
|
|
const int32 Num = In.Num<1>();
|
|
|
|
FMatrix44f Accum;
|
|
FPlatformMemory::Memzero(&Accum, sizeof(FMatrix44f));
|
|
|
|
for (int64 Idx = 0; Idx < Num; Idx++)
|
|
{
|
|
const FQuat4f Q = FQuat4f(In[0][Idx], In[1][Idx], In[2][Idx], In[3][Idx]);
|
|
|
|
Accum.M[0][0] += ((Q.X * Q.X) - Accum.M[0][0]) / (Idx + 1);
|
|
Accum.M[0][1] += ((Q.X * Q.Y) - Accum.M[0][1]) / (Idx + 1);
|
|
Accum.M[0][2] += ((Q.X * Q.Z) - Accum.M[0][2]) / (Idx + 1);
|
|
Accum.M[0][3] += ((Q.X * Q.W) - Accum.M[0][3]) / (Idx + 1);
|
|
|
|
Accum.M[1][0] += ((Q.Y * Q.X) - Accum.M[1][0]) / (Idx + 1);
|
|
Accum.M[1][1] += ((Q.Y * Q.Y) - Accum.M[1][1]) / (Idx + 1);
|
|
Accum.M[1][2] += ((Q.Y * Q.Z) - Accum.M[1][2]) / (Idx + 1);
|
|
Accum.M[1][3] += ((Q.Y * Q.W) - Accum.M[1][3]) / (Idx + 1);
|
|
|
|
Accum.M[2][0] += ((Q.Z * Q.X) - Accum.M[2][0]) / (Idx + 1);
|
|
Accum.M[2][1] += ((Q.Z * Q.Y) - Accum.M[2][1]) / (Idx + 1);
|
|
Accum.M[2][2] += ((Q.Z * Q.Z) - Accum.M[2][2]) / (Idx + 1);
|
|
Accum.M[2][3] += ((Q.Z * Q.W) - Accum.M[2][3]) / (Idx + 1);
|
|
|
|
Accum.M[3][0] += ((Q.W * Q.X) - Accum.M[3][0]) / (Idx + 1);
|
|
Accum.M[3][1] += ((Q.W * Q.Y) - Accum.M[3][1]) / (Idx + 1);
|
|
Accum.M[3][2] += ((Q.W * Q.Z) - Accum.M[3][2]) / (Idx + 1);
|
|
Accum.M[3][3] += ((Q.W * Q.W) - Accum.M[3][3]) / (Idx + 1);
|
|
}
|
|
|
|
const FVector4f AverageQuat = DominantEigenVector(Accum, FVector4f(0.0f, 0.0f, 0.0f, 1.0f), 128, 0.0f);
|
|
OutMean = FQuat4f(AverageQuat.X, AverageQuat.Y, AverageQuat.Z, AverageQuat.W);
|
|
check(OutMean.IsNormalized());
|
|
|
|
OutStd = FVector3f::ZeroVector;
|
|
for (int64 Idx = 0; Idx < Num; Idx++)
|
|
{
|
|
const FQuat4f Q = FQuat4f(In[0][Idx], In[1][Idx], In[2][Idx], In[3][Idx]);
|
|
const FQuat4f Diff = (Q * OutMean.Inverse()).GetShortestArcWith(FQuat4f::Identity);
|
|
OutStd += FMath::Square(Diff.ToRotationVector()) / Num;
|
|
}
|
|
OutStd.X = FMath::Sqrt(OutStd.X);
|
|
OutStd.Y = FMath::Sqrt(OutStd.Y);
|
|
OutStd.Z = FMath::Sqrt(OutStd.Z);
|
|
}
|
|
|
|
}
|
|
|
|
void FFrameAttribute::Check() const
|
|
{
|
|
FrameRangeSet.Check();
|
|
check(AttributeData.Num<1>() == FrameRangeSet.GetTotalFrameNum());
|
|
}
|
|
|
|
void FFrameAttribute::Empty() { FrameRangeSet.Empty(); AttributeData.Empty(); }
|
|
bool FFrameAttribute::IsEmpty() const { return FrameRangeSet.IsEmpty(); }
|
|
|
|
const FFrameRangeSet& FFrameAttribute::GetFrameRangeSet() const { return FrameRangeSet; }
|
|
int32 FFrameAttribute::GetTotalFrameNum() const { return AttributeData.Num<1>(); }
|
|
int32 FFrameAttribute::GetTotalRangeNum() const { return FrameRangeSet.GetTotalRangeNum(); }
|
|
int32 FFrameAttribute::GetChannelNum() const { return AttributeData.Num<0>(); }
|
|
|
|
TLearningArrayView<2, const float> FFrameAttribute::GetAttributeData() const { return AttributeData; }
|
|
|
|
TLearningArrayView<1, const float> FFrameAttribute::GetChannelAttributeData(const int32 ChannelIdx) const { return AttributeData[ChannelIdx]; }
|
|
|
|
const float& FFrameAttribute::GetChannelAttributeDataAtFrame(const int32 ChannelIdx, const int32 RangeFrameIdx) const { return AttributeData[ChannelIdx][RangeFrameIdx]; }
|
|
|
|
TLearningArrayView<1, const float> FFrameAttribute::GetChannelEntryRangeAttributeData(const int32 ChannelIdx, const int32 EntryIdx, const int32 RangeIdx) const
|
|
{
|
|
return AttributeData[ChannelIdx].Slice(FrameRangeSet.GetEntryRangeOffset(EntryIdx, RangeIdx), FrameRangeSet.GetEntryRangeLength(EntryIdx, RangeIdx));
|
|
}
|
|
|
|
TLearningArrayView<1, const float> FFrameAttribute::GetChannelRangeAttributeData(const int32 ChannelIdx, const int32 RangeOffset, const int32 RangeLength) const
|
|
{
|
|
return AttributeData[ChannelIdx].Slice(RangeOffset, RangeLength);
|
|
}
|
|
|
|
TLearningArrayView<2, float> FFrameAttribute::GetAttributeData() { return AttributeData; }
|
|
|
|
TLearningArrayView<1, float> FFrameAttribute::GetChannelAttributeData(const int32 ChannelIdx) { return AttributeData[ChannelIdx]; }
|
|
|
|
float& FFrameAttribute::GetChannelAttributeDataAtFrame(const int32 ChannelIdx, const int32 RangeFrameIdx) { return AttributeData[ChannelIdx][RangeFrameIdx]; }
|
|
|
|
TLearningArrayView<1, float> FFrameAttribute::GetChannelEntryRangeAttributeData(const int32 ChannelIdx, const int32 EntryIdx, const int32 RangeIdx)
|
|
{
|
|
return AttributeData[ChannelIdx].Slice(FrameRangeSet.GetEntryRangeOffset(EntryIdx, RangeIdx), FrameRangeSet.GetEntryRangeLength(EntryIdx, RangeIdx));
|
|
}
|
|
|
|
TLearningArrayView<1, float> FFrameAttribute::GetChannelRangeAttributeData(const int32 ChannelIdx, const int32 RangeOffset, const int32 RangeLength)
|
|
{
|
|
return AttributeData[ChannelIdx].Slice(RangeOffset, RangeLength);
|
|
}
|
|
|
|
namespace FrameAttribute
|
|
{
|
|
void Intersection(FFrameAttribute& OutFrameAttribute, const FFrameAttribute& FrameAttribute, const FFrameRangeSet& FrameRangeSet)
|
|
{
|
|
if (FrameRangeSet::Equal(FrameAttribute.FrameRangeSet, FrameRangeSet))
|
|
{
|
|
OutFrameAttribute = FrameAttribute;
|
|
return;
|
|
}
|
|
|
|
// Perform Intersection and get offsets
|
|
TLearningArray<1, int32> LhsOffsets;
|
|
TLearningArray<1, int32> RhsOffsets;
|
|
LhsOffsets.SetNumUninitialized({ FrameAttribute.FrameRangeSet.GetTotalRangeNum() + FrameRangeSet.GetTotalRangeNum() });
|
|
RhsOffsets.SetNumUninitialized({ FrameAttribute.FrameRangeSet.GetTotalRangeNum() + FrameRangeSet.GetTotalRangeNum() });
|
|
|
|
const int32 OutTotalRangeNum = UE::Learning::FrameRangeSet::IntersectionWithOffsets(
|
|
OutFrameAttribute.FrameRangeSet,
|
|
LhsOffsets,
|
|
RhsOffsets,
|
|
FrameAttribute.FrameRangeSet,
|
|
FrameRangeSet);
|
|
|
|
// Resize back to correct size
|
|
LhsOffsets.SetNumUninitialized({ OutTotalRangeNum });
|
|
RhsOffsets.SetNumUninitialized({ OutTotalRangeNum });
|
|
|
|
const int32 ChannelNum = FrameAttribute.GetChannelNum();
|
|
const int32 TotalFrameNum = OutFrameAttribute.FrameRangeSet.GetTotalFrameNum();
|
|
|
|
OutFrameAttribute.AttributeData.SetNumUninitialized({ ChannelNum, TotalFrameNum });
|
|
|
|
for (int32 ChannelIdx = 0; ChannelIdx < ChannelNum; ChannelIdx++)
|
|
{
|
|
for (int32 RangeIdx = 0; RangeIdx < OutTotalRangeNum; RangeIdx++)
|
|
{
|
|
const int32 OutOffset = OutFrameAttribute.FrameRangeSet.GetAllRangeOffsets()[RangeIdx];
|
|
const int32 LhsOffset = LhsOffsets[RangeIdx];
|
|
const int32 Length = OutFrameAttribute.FrameRangeSet.GetAllRangeLengths()[RangeIdx];
|
|
|
|
Array::Copy(
|
|
OutFrameAttribute.GetChannelRangeAttributeData(ChannelIdx, OutOffset, Length),
|
|
FrameAttribute.GetChannelRangeAttributeData(ChannelIdx, LhsOffset, Length));
|
|
}
|
|
}
|
|
}
|
|
|
|
void NonZeroFrameRangeSet(FFrameRangeSet& OutFrameRangeSet, const FFrameAttribute& FrameAttribute, const int32 ChannelIdx)
|
|
{
|
|
check(ChannelIdx >= 0 && ChannelIdx < FrameAttribute.GetChannelNum());
|
|
|
|
const int32 EntryNum = FrameAttribute.FrameRangeSet.GetEntryNum();
|
|
|
|
OutFrameRangeSet.Empty();
|
|
|
|
TArray<int32> AddedRangeStarts;
|
|
TArray<int32> AddedRangeLengths;
|
|
|
|
int32 RangeOffset = 0;
|
|
for (int32 EntryIdx = 0; EntryIdx < EntryNum; EntryIdx++)
|
|
{
|
|
const int32 RangeNum = FrameAttribute.FrameRangeSet.GetEntryRangeNum(EntryIdx);
|
|
const int32 Sequence = FrameAttribute.FrameRangeSet.GetEntrySequence(EntryIdx);
|
|
|
|
AddedRangeStarts.Reset();
|
|
AddedRangeLengths.Reset();
|
|
|
|
for (int32 RangeIdx = 0; RangeIdx < RangeNum; RangeIdx++)
|
|
{
|
|
const int32 FrameNum = FrameAttribute.FrameRangeSet.GetEntryRangeLength(EntryIdx, RangeIdx);
|
|
const int32 StartFrame = FrameAttribute.FrameRangeSet.GetEntryRangeStart(EntryIdx, RangeIdx);
|
|
const int32 FrameOffset = FrameAttribute.FrameRangeSet.GetEntryRangeOffset(EntryIdx, RangeIdx);
|
|
|
|
int32 StartFrameIndex = INDEX_NONE;
|
|
|
|
for (int32 FrameIdx = 0; FrameIdx < FrameNum; FrameIdx++)
|
|
{
|
|
const float FrameValue = FrameAttribute.GetChannelAttributeDataAtFrame(ChannelIdx, FrameOffset + FrameIdx);
|
|
|
|
if (StartFrameIndex == INDEX_NONE && FrameValue == 1.0f)
|
|
{
|
|
StartFrameIndex = FrameIdx;
|
|
}
|
|
else if (StartFrameIndex == INDEX_NONE && FrameValue == 0.0f) {}
|
|
else if (StartFrameIndex != INDEX_NONE && FrameValue == 1.0f) {}
|
|
else if (StartFrameIndex != INDEX_NONE && FrameValue == 0.0f)
|
|
{
|
|
check(FrameIdx - StartFrameIndex > 0);
|
|
AddedRangeStarts.Add(StartFrame + StartFrameIndex);
|
|
AddedRangeLengths.Add(StartFrame + FrameIdx - StartFrameIndex);
|
|
StartFrameIndex = INDEX_NONE;
|
|
}
|
|
}
|
|
|
|
if (StartFrameIndex != INDEX_NONE)
|
|
{
|
|
check(FrameNum - StartFrameIndex > 0);
|
|
AddedRangeStarts.Add(StartFrame + StartFrameIndex);
|
|
AddedRangeLengths.Add(StartFrame + FrameNum - StartFrameIndex);
|
|
}
|
|
}
|
|
|
|
OutFrameRangeSet.AddEntry(Sequence, AddedRangeStarts, AddedRangeLengths);
|
|
}
|
|
}
|
|
|
|
void ReduceOp(
|
|
const FFrameAttribute& In,
|
|
const ReduceOpFunction Op)
|
|
{
|
|
Op(In, In.FrameRangeSet.GetAllRangeOffsets(), In.FrameRangeSet.GetAllRangeLengths());
|
|
}
|
|
|
|
void NullaryOp(
|
|
FFrameAttribute& Out,
|
|
const int32 OutChannelNum,
|
|
const FFrameRangeSet& FrameRangeSet,
|
|
const NullaryOpFunction Op)
|
|
{
|
|
Out.FrameRangeSet = FrameRangeSet;
|
|
Out.AttributeData.SetNumUninitialized({ OutChannelNum, FrameRangeSet.GetTotalFrameNum() });
|
|
|
|
Op(Out, Out.FrameRangeSet.GetAllRangeOffsets(), Out.FrameRangeSet.GetAllRangeLengths());
|
|
}
|
|
|
|
void UnaryOp(
|
|
FFrameAttribute& Out,
|
|
const int32 OutChannelNum,
|
|
const FFrameAttribute& In,
|
|
const UnaryOpFunction Op)
|
|
{
|
|
Out.FrameRangeSet = In.FrameRangeSet;
|
|
Out.AttributeData.SetNumUninitialized({ OutChannelNum, In.FrameRangeSet.GetTotalFrameNum() });
|
|
|
|
Op(Out, In, Out.FrameRangeSet.GetAllRangeOffsets(), Out.FrameRangeSet.GetAllRangeLengths());
|
|
}
|
|
|
|
void BinaryOp(
|
|
FFrameAttribute& Out,
|
|
const int32 OutChannelNum,
|
|
const FFrameAttribute& Lhs,
|
|
const FFrameAttribute& Rhs,
|
|
const BinaryOpFunction Op)
|
|
{
|
|
// Fast Path for when FrameRangeSets are Equal
|
|
|
|
if (FrameRangeSet::Equal(Lhs.FrameRangeSet, Rhs.FrameRangeSet))
|
|
{
|
|
Out.FrameRangeSet = Lhs.FrameRangeSet;
|
|
Out.AttributeData.SetNumUninitialized({ OutChannelNum, Lhs.GetTotalFrameNum() });
|
|
|
|
Op(Out, Lhs, Rhs,
|
|
Out.FrameRangeSet.GetAllRangeOffsets(),
|
|
Lhs.FrameRangeSet.GetAllRangeOffsets(),
|
|
Rhs.FrameRangeSet.GetAllRangeOffsets(),
|
|
Out.FrameRangeSet.GetAllRangeLengths());
|
|
|
|
return;
|
|
}
|
|
|
|
// Slow Path for when FrameRangeSets are not equal and we need to compute the intersection
|
|
|
|
TLearningArray<1, int32> LhsRangeOffsets;
|
|
TLearningArray<1, int32> RhsRangeOffsets;
|
|
LhsRangeOffsets.SetNumUninitialized({ Lhs.FrameRangeSet.GetTotalRangeNum() + Rhs.FrameRangeSet.GetTotalRangeNum() });
|
|
RhsRangeOffsets.SetNumUninitialized({ Lhs.FrameRangeSet.GetTotalRangeNum() + Rhs.FrameRangeSet.GetTotalRangeNum() });
|
|
|
|
const int32 OutTotalRangeNum = UE::Learning::FrameRangeSet::IntersectionWithOffsets(
|
|
Out.FrameRangeSet,
|
|
LhsRangeOffsets,
|
|
RhsRangeOffsets,
|
|
Lhs.FrameRangeSet,
|
|
Rhs.FrameRangeSet);
|
|
|
|
// Resize back to correct size
|
|
LhsRangeOffsets.SetNumUninitialized({ OutTotalRangeNum });
|
|
RhsRangeOffsets.SetNumUninitialized({ OutTotalRangeNum });
|
|
|
|
// Allocate Attribute Data
|
|
Out.AttributeData.SetNumUninitialized({ OutChannelNum, Out.FrameRangeSet.GetTotalFrameNum() });
|
|
|
|
Op(Out, Lhs, Rhs,
|
|
Out.FrameRangeSet.GetAllRangeOffsets(),
|
|
LhsRangeOffsets,
|
|
RhsRangeOffsets,
|
|
Out.FrameRangeSet.GetAllRangeLengths());
|
|
}
|
|
|
|
void NaryOp(
|
|
FFrameAttribute& Out,
|
|
const int32 OutChannelNum,
|
|
const TArrayView<const ConstFrameAttributePtr> Inputs,
|
|
const NaryOpFunction Op)
|
|
{
|
|
if (Inputs.Num() == 0)
|
|
{
|
|
Out.Empty();
|
|
Op(Out, {}, {}, {}, {});
|
|
}
|
|
|
|
// Check All Equal
|
|
|
|
const int32 InputNum = Inputs.Num();
|
|
|
|
bool bAllEqual = true;
|
|
for (int32 InputIdx = 1; InputIdx < InputNum; InputIdx++)
|
|
{
|
|
bAllEqual &= FrameRangeSet::Equal(Inputs[0]->FrameRangeSet, Inputs[InputIdx]->FrameRangeSet);
|
|
}
|
|
|
|
if (bAllEqual)
|
|
{
|
|
Out.FrameRangeSet = Inputs[0]->FrameRangeSet;
|
|
Out.AttributeData.SetNumUninitialized({ OutChannelNum, Inputs[0]->FrameRangeSet.GetTotalFrameNum() });
|
|
|
|
TArray<TLearningArrayView<1, const int32>, TInlineAllocator<8>> InputRangeOffsetsViews;
|
|
InputRangeOffsetsViews.SetNumUninitialized(InputNum);
|
|
for (int32 InputIdx = 0; InputIdx < InputNum; InputIdx++)
|
|
{
|
|
InputRangeOffsetsViews[InputIdx] = Inputs[InputIdx]->FrameRangeSet.GetAllRangeOffsets();
|
|
}
|
|
|
|
Op(Out, Inputs,
|
|
Out.FrameRangeSet.GetAllRangeOffsets(),
|
|
InputRangeOffsetsViews,
|
|
Out.FrameRangeSet.GetAllRangeLengths());
|
|
}
|
|
else
|
|
{
|
|
// Currently we don't support the case where things are not equal.
|
|
|
|
checkNoEntry();
|
|
Out.Empty();
|
|
return;
|
|
}
|
|
}
|
|
|
|
bool FindMinimum(
|
|
int32& OutChannelIdx,
|
|
int32& OutFrameIdx,
|
|
float& OutMinimumValue,
|
|
const FFrameAttribute& In)
|
|
{
|
|
return Private::FindMinimum(OutChannelIdx, OutFrameIdx, OutMinimumValue, In.GetAttributeData());
|
|
}
|
|
|
|
bool FindMaximum(
|
|
int32& OutChannelIdx,
|
|
int32& OutFrameIdx,
|
|
float& OutMaximumValue,
|
|
const FFrameAttribute& In)
|
|
{
|
|
return Private::FindMaximum(OutChannelIdx, OutFrameIdx, OutMaximumValue, In.GetAttributeData());
|
|
}
|
|
|
|
void Zeros(FFrameAttribute& Out, const FFrameRangeSet& FrameRangeSet, const int32 ChannelNum)
|
|
{
|
|
Out.FrameRangeSet = FrameRangeSet;
|
|
Out.AttributeData.SetNumUninitialized({ ChannelNum, FrameRangeSet.GetTotalFrameNum() });
|
|
Array::Zero(Out.AttributeData);
|
|
}
|
|
|
|
void Ones(FFrameAttribute& Out, const FFrameRangeSet& FrameRangeSet, const int32 ChannelNum)
|
|
{
|
|
Out.FrameRangeSet = FrameRangeSet;
|
|
Out.AttributeData.SetNumUninitialized({ ChannelNum, FrameRangeSet.GetTotalFrameNum() });
|
|
Array::Set(Out.AttributeData, 1.0f);
|
|
}
|
|
|
|
void Fill(FFrameAttribute& Out, const FFrameRangeSet& FrameRangeSet, const TLearningArrayView<1, const float> Values)
|
|
{
|
|
const int32 ChannelNum = Values.Num();
|
|
|
|
Out.FrameRangeSet = FrameRangeSet;
|
|
Out.AttributeData.SetNumUninitialized({ ChannelNum, FrameRangeSet.GetTotalFrameNum() });
|
|
for (int32 ChannelIdx = 0; ChannelIdx < ChannelNum; ChannelIdx++)
|
|
{
|
|
Array::Set(Out.AttributeData[ChannelIdx], Values[ChannelIdx]);
|
|
}
|
|
}
|
|
|
|
void Add(FFrameAttribute& Out, const FFrameAttribute& Lhs, const FFrameAttribute& Rhs)
|
|
{
|
|
check(Lhs.GetChannelNum() == Rhs.GetChannelNum());
|
|
|
|
BinaryOp(Out, Lhs.GetChannelNum(), Lhs, Rhs, [](
|
|
FFrameAttribute& Out,
|
|
const FFrameAttribute& Lhs,
|
|
const FFrameAttribute& Rhs,
|
|
const TLearningArrayView<1, const int32> OutRangeOffsets,
|
|
const TLearningArrayView<1, const int32> LhsRangeOffsets,
|
|
const TLearningArrayView<1, const int32> RhsRangeOffsets,
|
|
const TLearningArrayView<1, const int32> RangeLengths) {
|
|
|
|
const int32 ChannelNum = Out.GetChannelNum();
|
|
const int32 RangeNum = RangeLengths.Num();
|
|
for (int32 ChannelIdx = 0; ChannelIdx < ChannelNum; ChannelIdx++)
|
|
{
|
|
for (int32 RangeIdx = 0; RangeIdx < RangeNum; RangeIdx++)
|
|
{
|
|
Private::Add(
|
|
Out.GetChannelRangeAttributeData(ChannelIdx, OutRangeOffsets[RangeIdx], RangeLengths[RangeIdx]),
|
|
Lhs.GetChannelRangeAttributeData(ChannelIdx, LhsRangeOffsets[RangeIdx], RangeLengths[RangeIdx]),
|
|
Rhs.GetChannelRangeAttributeData(ChannelIdx, RhsRangeOffsets[RangeIdx], RangeLengths[RangeIdx]));
|
|
}
|
|
}
|
|
});
|
|
}
|
|
|
|
void Sub(FFrameAttribute& Out, const FFrameAttribute& Lhs, const FFrameAttribute& Rhs)
|
|
{
|
|
check(Lhs.GetChannelNum() == Rhs.GetChannelNum());
|
|
|
|
BinaryOp(Out, Lhs.GetChannelNum(), Lhs, Rhs, [](
|
|
FFrameAttribute& Out,
|
|
const FFrameAttribute& Lhs,
|
|
const FFrameAttribute& Rhs,
|
|
const TLearningArrayView<1, const int32> OutRangeOffsets,
|
|
const TLearningArrayView<1, const int32> LhsRangeOffsets,
|
|
const TLearningArrayView<1, const int32> RhsRangeOffsets,
|
|
const TLearningArrayView<1, const int32> RangeLengths) {
|
|
|
|
const int32 ChannelNum = Out.GetChannelNum();
|
|
const int32 RangeNum = RangeLengths.Num();
|
|
for (int32 ChannelIdx = 0; ChannelIdx < ChannelNum; ChannelIdx++)
|
|
{
|
|
for (int32 RangeIdx = 0; RangeIdx < RangeNum; RangeIdx++)
|
|
{
|
|
Private::Sub(
|
|
Out.GetChannelRangeAttributeData(ChannelIdx, OutRangeOffsets[RangeIdx], RangeLengths[RangeIdx]),
|
|
Lhs.GetChannelRangeAttributeData(ChannelIdx, LhsRangeOffsets[RangeIdx], RangeLengths[RangeIdx]),
|
|
Rhs.GetChannelRangeAttributeData(ChannelIdx, RhsRangeOffsets[RangeIdx], RangeLengths[RangeIdx]));
|
|
}
|
|
}
|
|
});
|
|
}
|
|
|
|
void Mul(FFrameAttribute& Out, const FFrameAttribute& Lhs, const FFrameAttribute& Rhs)
|
|
{
|
|
check(Lhs.GetChannelNum() == Rhs.GetChannelNum());
|
|
|
|
BinaryOp(Out, Lhs.GetChannelNum(), Lhs, Rhs, [](
|
|
FFrameAttribute& Out,
|
|
const FFrameAttribute& Lhs,
|
|
const FFrameAttribute& Rhs,
|
|
const TLearningArrayView<1, const int32> OutRangeOffsets,
|
|
const TLearningArrayView<1, const int32> LhsRangeOffsets,
|
|
const TLearningArrayView<1, const int32> RhsRangeOffsets,
|
|
const TLearningArrayView<1, const int32> RangeLengths) {
|
|
|
|
const int32 ChannelNum = Out.GetChannelNum();
|
|
const int32 RangeNum = RangeLengths.Num();
|
|
for (int32 ChannelIdx = 0; ChannelIdx < ChannelNum; ChannelIdx++)
|
|
{
|
|
for (int32 RangeIdx = 0; RangeIdx < RangeNum; RangeIdx++)
|
|
{
|
|
Private::Mul(
|
|
Out.GetChannelRangeAttributeData(ChannelIdx, OutRangeOffsets[RangeIdx], RangeLengths[RangeIdx]),
|
|
Lhs.GetChannelRangeAttributeData(ChannelIdx, LhsRangeOffsets[RangeIdx], RangeLengths[RangeIdx]),
|
|
Rhs.GetChannelRangeAttributeData(ChannelIdx, RhsRangeOffsets[RangeIdx], RangeLengths[RangeIdx]));
|
|
}
|
|
}
|
|
});
|
|
}
|
|
|
|
void Div(FFrameAttribute& Out, const FFrameAttribute& Lhs, const FFrameAttribute& Rhs)
|
|
{
|
|
check(Lhs.GetChannelNum() == Rhs.GetChannelNum());
|
|
|
|
BinaryOp(Out, Lhs.GetChannelNum(), Lhs, Rhs, [](
|
|
FFrameAttribute& Out,
|
|
const FFrameAttribute& Lhs,
|
|
const FFrameAttribute& Rhs,
|
|
const TLearningArrayView<1, const int32> OutRangeOffsets,
|
|
const TLearningArrayView<1, const int32> LhsRangeOffsets,
|
|
const TLearningArrayView<1, const int32> RhsRangeOffsets,
|
|
const TLearningArrayView<1, const int32> RangeLengths) {
|
|
|
|
const int32 ChannelNum = Out.GetChannelNum();
|
|
const int32 RangeNum = RangeLengths.Num();
|
|
for (int32 ChannelIdx = 0; ChannelIdx < ChannelNum; ChannelIdx++)
|
|
{
|
|
for (int32 RangeIdx = 0; RangeIdx < RangeNum; RangeIdx++)
|
|
{
|
|
Private::Div(
|
|
Out.GetChannelRangeAttributeData(ChannelIdx, OutRangeOffsets[RangeIdx], RangeLengths[RangeIdx]),
|
|
Lhs.GetChannelRangeAttributeData(ChannelIdx, LhsRangeOffsets[RangeIdx], RangeLengths[RangeIdx]),
|
|
Rhs.GetChannelRangeAttributeData(ChannelIdx, RhsRangeOffsets[RangeIdx], RangeLengths[RangeIdx]));
|
|
}
|
|
}
|
|
});
|
|
}
|
|
|
|
void Dot(FFrameAttribute& Out, const FFrameAttribute& Lhs, const FFrameAttribute& Rhs)
|
|
{
|
|
check(Lhs.GetChannelNum() == Rhs.GetChannelNum());
|
|
|
|
BinaryOp(Out, 1, Lhs, Rhs, [](
|
|
FFrameAttribute& Out,
|
|
const FFrameAttribute& Lhs,
|
|
const FFrameAttribute& Rhs,
|
|
const TLearningArrayView<1, const int32> OutRangeOffsets,
|
|
const TLearningArrayView<1, const int32> LhsRangeOffsets,
|
|
const TLearningArrayView<1, const int32> RhsRangeOffsets,
|
|
const TLearningArrayView<1, const int32> RangeLengths) {
|
|
|
|
Array::Zero(Out.GetAttributeData());
|
|
|
|
const int32 ChannelNum = Out.GetChannelNum();
|
|
const int32 RangeNum = RangeLengths.Num();
|
|
|
|
for (int32 ChannelIdx = 0; ChannelIdx < ChannelNum; ChannelIdx++)
|
|
{
|
|
for (int32 RangeIdx = 0; RangeIdx < RangeNum; RangeIdx++)
|
|
{
|
|
Private::Dot(
|
|
Out.GetChannelRangeAttributeData(0, OutRangeOffsets[RangeIdx], RangeLengths[RangeIdx]),
|
|
Lhs.GetChannelRangeAttributeData(ChannelIdx, LhsRangeOffsets[RangeIdx], RangeLengths[RangeIdx]),
|
|
Rhs.GetChannelRangeAttributeData(ChannelIdx, RhsRangeOffsets[RangeIdx], RangeLengths[RangeIdx]));
|
|
}
|
|
}
|
|
});
|
|
}
|
|
|
|
void Neg(FFrameAttribute& Out, const FFrameAttribute& In)
|
|
{
|
|
UnaryOp(Out, In.GetChannelNum(), In, [](
|
|
FFrameAttribute& Out,
|
|
const FFrameAttribute& In,
|
|
const TLearningArrayView<1, const int32> RangeOffsets,
|
|
const TLearningArrayView<1, const int32> RangeLengths) {
|
|
|
|
const int32 ChannelNum = Out.GetChannelNum();
|
|
|
|
for (int32 ChannelIdx = 0; ChannelIdx < ChannelNum; ChannelIdx++)
|
|
{
|
|
Private::Neg(
|
|
Out.GetChannelAttributeData(ChannelIdx),
|
|
In.GetChannelAttributeData(ChannelIdx));
|
|
}
|
|
});
|
|
}
|
|
|
|
void Inv(FFrameAttribute& Out, const FFrameAttribute& In)
|
|
{
|
|
UnaryOp(Out, In.GetChannelNum(), In, [](
|
|
FFrameAttribute& Out,
|
|
const FFrameAttribute& In,
|
|
const TLearningArrayView<1, const int32> RangeOffsets,
|
|
const TLearningArrayView<1, const int32> RangeLengths) {
|
|
|
|
const int32 ChannelNum = Out.GetChannelNum();
|
|
|
|
for (int32 ChannelIdx = 0; ChannelIdx < ChannelNum; ChannelIdx++)
|
|
{
|
|
Private::Inv(
|
|
Out.GetChannelAttributeData(ChannelIdx),
|
|
In.GetChannelAttributeData(ChannelIdx));
|
|
}
|
|
});
|
|
}
|
|
|
|
void Abs(FFrameAttribute& Out, const FFrameAttribute& In)
|
|
{
|
|
UnaryOp(Out, In.GetChannelNum(), In, [](
|
|
FFrameAttribute& Out,
|
|
const FFrameAttribute& In,
|
|
const TLearningArrayView<1, const int32> RangeOffsets,
|
|
const TLearningArrayView<1, const int32> RangeLengths) {
|
|
|
|
const int32 ChannelNum = Out.GetChannelNum();
|
|
|
|
for (int32 ChannelIdx = 0; ChannelIdx < ChannelNum; ChannelIdx++)
|
|
{
|
|
Private::Abs(
|
|
Out.GetChannelAttributeData(ChannelIdx),
|
|
In.GetChannelAttributeData(ChannelIdx));
|
|
}
|
|
});
|
|
}
|
|
|
|
void Log(FFrameAttribute& Out, const FFrameAttribute& In)
|
|
{
|
|
UnaryOp(Out, In.GetChannelNum(), In, [](
|
|
FFrameAttribute& Out,
|
|
const FFrameAttribute& In,
|
|
const TLearningArrayView<1, const int32> RangeOffsets,
|
|
const TLearningArrayView<1, const int32> RangeLengths) {
|
|
|
|
const int32 ChannelNum = Out.GetChannelNum();
|
|
|
|
for (int32 ChannelIdx = 0; ChannelIdx < ChannelNum; ChannelIdx++)
|
|
{
|
|
Private::Log(
|
|
Out.GetChannelAttributeData(ChannelIdx),
|
|
In.GetChannelAttributeData(ChannelIdx));
|
|
}
|
|
});
|
|
}
|
|
|
|
void Exp(FFrameAttribute& Out, const FFrameAttribute& In)
|
|
{
|
|
UnaryOp(Out, In.GetChannelNum(), In, [](
|
|
FFrameAttribute& Out,
|
|
const FFrameAttribute& In,
|
|
const TLearningArrayView<1, const int32> RangeOffsets,
|
|
const TLearningArrayView<1, const int32> RangeLengths) {
|
|
|
|
const int32 ChannelNum = Out.GetChannelNum();
|
|
|
|
for (int32 ChannelIdx = 0; ChannelIdx < ChannelNum; ChannelIdx++)
|
|
{
|
|
Private::Exp(
|
|
Out.GetChannelAttributeData(ChannelIdx),
|
|
In.GetChannelAttributeData(ChannelIdx));
|
|
}
|
|
});
|
|
}
|
|
|
|
void Length(FFrameAttribute& Out, const FFrameAttribute& In)
|
|
{
|
|
UnaryOp(Out, 1, In, [](
|
|
FFrameAttribute& Out,
|
|
const FFrameAttribute& In,
|
|
const TLearningArrayView<1, const int32> RangeOffsets,
|
|
const TLearningArrayView<1, const int32> RangeLengths) {
|
|
|
|
const int32 ChannelNum = Out.GetChannelNum();
|
|
|
|
Array::Zero(Out.GetAttributeData());
|
|
|
|
for (int32 ChannelIdx = 0; ChannelIdx < ChannelNum; ChannelIdx++)
|
|
{
|
|
Private::LengthSquared(
|
|
Out.GetChannelAttributeData(0),
|
|
In.GetChannelAttributeData(ChannelIdx));
|
|
}
|
|
|
|
Private::SqrtInplace(Out.GetChannelAttributeData(0));
|
|
});
|
|
}
|
|
|
|
void Normalize(FFrameAttribute& Out, const FFrameAttribute& In)
|
|
{
|
|
UnaryOp(Out, In.GetChannelNum(), In, [](
|
|
FFrameAttribute& Out,
|
|
const FFrameAttribute& In,
|
|
const TLearningArrayView<1, const int32> RangeOffsets,
|
|
const TLearningArrayView<1, const int32> RangeLengths) {
|
|
|
|
Private::Normalize(Out.GetAttributeData(), In.GetAttributeData());
|
|
|
|
});
|
|
}
|
|
|
|
void Index(FFrameAttribute& Out, const FFrameAttribute& In, const int32 ChannelIdx)
|
|
{
|
|
check(ChannelIdx >= 0);
|
|
check(ChannelIdx < In.GetChannelNum());
|
|
|
|
UnaryOp(Out, 1, In, [ChannelIdx](
|
|
FFrameAttribute& Out,
|
|
const FFrameAttribute& In,
|
|
const TLearningArrayView<1, const int32> RangeOffsets,
|
|
const TLearningArrayView<1, const int32> RangeLengths) {
|
|
|
|
Array::Copy(Out.GetChannelAttributeData(0), In.GetChannelAttributeData(ChannelIdx));
|
|
|
|
});
|
|
}
|
|
|
|
void AddConstant(FFrameAttribute& Out, const FFrameAttribute& Lhs, const TLearningArrayView<1, const float> Rhs)
|
|
{
|
|
UnaryOp(Out, Lhs.GetChannelNum(), Lhs, [Rhs](
|
|
FFrameAttribute& Out,
|
|
const FFrameAttribute& In,
|
|
const TLearningArrayView<1, const int32> RangeOffsets,
|
|
const TLearningArrayView<1, const int32> RangeLengths) {
|
|
|
|
const int32 ChannelNum = Out.GetChannelNum();
|
|
|
|
for (int32 ChannelIdx = 0; ChannelIdx < ChannelNum; ChannelIdx++)
|
|
{
|
|
Private::AddConstant(
|
|
Out.GetChannelAttributeData(ChannelIdx),
|
|
In.GetChannelAttributeData(ChannelIdx),
|
|
Rhs[ChannelIdx]);
|
|
}
|
|
});
|
|
}
|
|
|
|
void SubConstant(FFrameAttribute& Out, const FFrameAttribute& Lhs, const TLearningArrayView<1, const float> Rhs)
|
|
{
|
|
UnaryOp(Out, Lhs.GetChannelNum(), Lhs, [Rhs](
|
|
FFrameAttribute& Out,
|
|
const FFrameAttribute& In,
|
|
const TLearningArrayView<1, const int32> RangeOffsets,
|
|
const TLearningArrayView<1, const int32> RangeLengths) {
|
|
|
|
const int32 ChannelNum = Out.GetChannelNum();
|
|
|
|
for (int32 ChannelIdx = 0; ChannelIdx < ChannelNum; ChannelIdx++)
|
|
{
|
|
Private::SubConstant(
|
|
Out.GetChannelAttributeData(ChannelIdx),
|
|
In.GetChannelAttributeData(ChannelIdx),
|
|
Rhs[ChannelIdx]);
|
|
}
|
|
});
|
|
}
|
|
|
|
void MulConstant(FFrameAttribute& Out, const FFrameAttribute& Lhs, const TLearningArrayView<1, const float> Rhs)
|
|
{
|
|
UnaryOp(Out, Lhs.GetChannelNum(), Lhs, [Rhs](
|
|
FFrameAttribute& Out,
|
|
const FFrameAttribute& In,
|
|
const TLearningArrayView<1, const int32> RangeOffsets,
|
|
const TLearningArrayView<1, const int32> RangeLengths) {
|
|
|
|
const int32 ChannelNum = Out.GetChannelNum();
|
|
|
|
for (int32 ChannelIdx = 0; ChannelIdx < ChannelNum; ChannelIdx++)
|
|
{
|
|
Private::MulConstant(
|
|
Out.GetChannelAttributeData(ChannelIdx),
|
|
In.GetChannelAttributeData(ChannelIdx),
|
|
Rhs[ChannelIdx]);
|
|
}
|
|
});
|
|
}
|
|
|
|
void DivConstant(FFrameAttribute& Out, const FFrameAttribute& Lhs, const TLearningArrayView<1, const float> Rhs)
|
|
{
|
|
UnaryOp(Out, Lhs.GetChannelNum(), Lhs, [Rhs](
|
|
FFrameAttribute& Out,
|
|
const FFrameAttribute& In,
|
|
const TLearningArrayView<1, const int32> RangeOffsets,
|
|
const TLearningArrayView<1, const int32> RangeLengths) {
|
|
|
|
const int32 ChannelNum = Out.GetChannelNum();
|
|
|
|
for (int32 ChannelIdx = 0; ChannelIdx < ChannelNum; ChannelIdx++)
|
|
{
|
|
Private::DivConstant(
|
|
Out.GetChannelAttributeData(ChannelIdx),
|
|
In.GetChannelAttributeData(ChannelIdx),
|
|
Rhs[ChannelIdx]);
|
|
}
|
|
});
|
|
}
|
|
|
|
void ConstantAdd(FFrameAttribute& Out, const TLearningArrayView<1, const float> Lhs, const FFrameAttribute& Rhs)
|
|
{
|
|
UnaryOp(Out, Rhs.GetChannelNum(), Rhs, [Lhs](
|
|
FFrameAttribute& Out,
|
|
const FFrameAttribute& In,
|
|
const TLearningArrayView<1, const int32> RangeOffsets,
|
|
const TLearningArrayView<1, const int32> RangeLengths) {
|
|
|
|
const int32 ChannelNum = Out.GetChannelNum();
|
|
|
|
for (int32 ChannelIdx = 0; ChannelIdx < ChannelNum; ChannelIdx++)
|
|
{
|
|
Private::ConstantAdd(
|
|
Out.GetChannelAttributeData(ChannelIdx),
|
|
Lhs[ChannelIdx],
|
|
In.GetChannelAttributeData(ChannelIdx));
|
|
}
|
|
});
|
|
}
|
|
|
|
void ConstantSub(FFrameAttribute& Out, const TLearningArrayView<1, const float> Lhs, const FFrameAttribute& Rhs)
|
|
{
|
|
UnaryOp(Out, Rhs.GetChannelNum(), Rhs, [Lhs](
|
|
FFrameAttribute& Out,
|
|
const FFrameAttribute& In,
|
|
const TLearningArrayView<1, const int32> RangeOffsets,
|
|
const TLearningArrayView<1, const int32> RangeLengths) {
|
|
|
|
const int32 ChannelNum = Out.GetChannelNum();
|
|
|
|
for (int32 ChannelIdx = 0; ChannelIdx < ChannelNum; ChannelIdx++)
|
|
{
|
|
Private::ConstantSub(
|
|
Out.GetChannelAttributeData(ChannelIdx),
|
|
Lhs[ChannelIdx],
|
|
In.GetChannelAttributeData(ChannelIdx));
|
|
}
|
|
});
|
|
}
|
|
|
|
void ConstantMul(FFrameAttribute& Out, const TLearningArrayView<1, const float> Lhs, const FFrameAttribute& Rhs)
|
|
{
|
|
UnaryOp(Out, Rhs.GetChannelNum(), Rhs, [Lhs](
|
|
FFrameAttribute& Out,
|
|
const FFrameAttribute& In,
|
|
const TLearningArrayView<1, const int32> RangeOffsets,
|
|
const TLearningArrayView<1, const int32> RangeLengths) {
|
|
|
|
const int32 ChannelNum = Out.GetChannelNum();
|
|
|
|
for (int32 ChannelIdx = 0; ChannelIdx < ChannelNum; ChannelIdx++)
|
|
{
|
|
Private::ConstantMul(
|
|
Out.GetChannelAttributeData(ChannelIdx),
|
|
Lhs[ChannelIdx],
|
|
In.GetChannelAttributeData(ChannelIdx));
|
|
}
|
|
});
|
|
}
|
|
|
|
void ConstantDiv(FFrameAttribute& Out, const TLearningArrayView<1, const float> Lhs, const FFrameAttribute& Rhs)
|
|
{
|
|
UnaryOp(Out, Rhs.GetChannelNum(), Rhs, [Lhs](
|
|
FFrameAttribute& Out,
|
|
const FFrameAttribute& In,
|
|
const TLearningArrayView<1, const int32> RangeOffsets,
|
|
const TLearningArrayView<1, const int32> RangeLengths) {
|
|
|
|
const int32 ChannelNum = Out.GetChannelNum();
|
|
|
|
for (int32 ChannelIdx = 0; ChannelIdx < ChannelNum; ChannelIdx++)
|
|
{
|
|
Private::ConstantDiv(
|
|
Out.GetChannelAttributeData(ChannelIdx),
|
|
Lhs[ChannelIdx],
|
|
In.GetChannelAttributeData(ChannelIdx));
|
|
}
|
|
});
|
|
}
|
|
|
|
void Sum(FFrameAttribute& Out, const TArrayView<const ConstFrameAttributePtr> Inputs)
|
|
{
|
|
const int32 InputNum = Inputs.Num();
|
|
|
|
if (InputNum == 0)
|
|
{
|
|
Out.Empty();
|
|
}
|
|
else if (InputNum == 1)
|
|
{
|
|
Out = *Inputs[0];
|
|
}
|
|
else
|
|
{
|
|
FFrameAttribute Tmp = *Inputs[0];
|
|
|
|
for (int32 InputIdx = 1; InputIdx < InputNum; InputIdx++)
|
|
{
|
|
Add(Out, Tmp, *Inputs[InputIdx]);
|
|
Tmp = Out;
|
|
}
|
|
}
|
|
}
|
|
|
|
void Prod(FFrameAttribute& Out, const TArrayView<const ConstFrameAttributePtr> Inputs)
|
|
{
|
|
const int32 InputNum = Inputs.Num();
|
|
|
|
if (InputNum == 0)
|
|
{
|
|
Out.Empty();
|
|
}
|
|
else if (InputNum == 1)
|
|
{
|
|
Out = *Inputs[0];
|
|
}
|
|
else
|
|
{
|
|
FFrameAttribute Tmp = *Inputs[0];
|
|
|
|
for (int32 InputIdx = 1; InputIdx < InputNum; InputIdx++)
|
|
{
|
|
Mul(Out, Tmp, *Inputs[InputIdx]);
|
|
Tmp = Out;
|
|
}
|
|
}
|
|
}
|
|
|
|
void LogicalAnd(FFrameAttribute& Out, const FFrameAttribute& Lhs, const FFrameAttribute& Rhs)
|
|
{
|
|
check(Lhs.GetChannelNum() == Rhs.GetChannelNum());
|
|
|
|
BinaryOp(Out, Lhs.GetChannelNum(), Lhs, Rhs, [](
|
|
FFrameAttribute& Out,
|
|
const FFrameAttribute& Lhs,
|
|
const FFrameAttribute& Rhs,
|
|
const TLearningArrayView<1, const int32> OutRangeOffsets,
|
|
const TLearningArrayView<1, const int32> LhsRangeOffsets,
|
|
const TLearningArrayView<1, const int32> RhsRangeOffsets,
|
|
const TLearningArrayView<1, const int32> RangeLengths) {
|
|
|
|
const int32 ChannelNum = Out.GetChannelNum();
|
|
const int32 RangeNum = RangeLengths.Num();
|
|
for (int32 ChannelIdx = 0; ChannelIdx < ChannelNum; ChannelIdx++)
|
|
{
|
|
for (int32 RangeIdx = 0; RangeIdx < RangeNum; RangeIdx++)
|
|
{
|
|
Private::LogicalAnd(
|
|
Out.GetChannelRangeAttributeData(ChannelIdx, OutRangeOffsets[RangeIdx], RangeLengths[RangeIdx]),
|
|
Lhs.GetChannelRangeAttributeData(ChannelIdx, LhsRangeOffsets[RangeIdx], RangeLengths[RangeIdx]),
|
|
Rhs.GetChannelRangeAttributeData(ChannelIdx, RhsRangeOffsets[RangeIdx], RangeLengths[RangeIdx]));
|
|
}
|
|
}
|
|
});
|
|
}
|
|
|
|
void LogicalOr(FFrameAttribute& Out, const FFrameAttribute& Lhs, const FFrameAttribute& Rhs)
|
|
{
|
|
check(Lhs.GetChannelNum() == Rhs.GetChannelNum());
|
|
|
|
BinaryOp(Out, Lhs.GetChannelNum(), Lhs, Rhs, [](
|
|
FFrameAttribute& Out,
|
|
const FFrameAttribute& Lhs,
|
|
const FFrameAttribute& Rhs,
|
|
const TLearningArrayView<1, const int32> OutRangeOffsets,
|
|
const TLearningArrayView<1, const int32> LhsRangeOffsets,
|
|
const TLearningArrayView<1, const int32> RhsRangeOffsets,
|
|
const TLearningArrayView<1, const int32> RangeLengths) {
|
|
|
|
const int32 ChannelNum = Out.GetChannelNum();
|
|
const int32 RangeNum = RangeLengths.Num();
|
|
for (int32 ChannelIdx = 0; ChannelIdx < ChannelNum; ChannelIdx++)
|
|
{
|
|
for (int32 RangeIdx = 0; RangeIdx < RangeNum; RangeIdx++)
|
|
{
|
|
Private::LogicalOr(
|
|
Out.GetChannelRangeAttributeData(ChannelIdx, OutRangeOffsets[RangeIdx], RangeLengths[RangeIdx]),
|
|
Lhs.GetChannelRangeAttributeData(ChannelIdx, LhsRangeOffsets[RangeIdx], RangeLengths[RangeIdx]),
|
|
Rhs.GetChannelRangeAttributeData(ChannelIdx, RhsRangeOffsets[RangeIdx], RangeLengths[RangeIdx]));
|
|
}
|
|
}
|
|
});
|
|
}
|
|
|
|
void LogicalNot(FFrameAttribute& Out, const FFrameAttribute& In)
|
|
{
|
|
UnaryOp(Out, In.GetChannelNum(), In, [](
|
|
FFrameAttribute& Out,
|
|
const FFrameAttribute& In,
|
|
const TLearningArrayView<1, const int32> RangeOffsets,
|
|
const TLearningArrayView<1, const int32> RangeLengths) {
|
|
|
|
const int32 ChannelNum = Out.GetChannelNum();
|
|
|
|
for (int32 ChannelIdx = 0; ChannelIdx < ChannelNum; ChannelIdx++)
|
|
{
|
|
Private::LogicalNot(
|
|
Out.GetChannelAttributeData(ChannelIdx),
|
|
In.GetChannelAttributeData(ChannelIdx));
|
|
}
|
|
});
|
|
}
|
|
|
|
void Gt(FFrameAttribute& Out, const FFrameAttribute& Lhs, const FFrameAttribute& Rhs)
|
|
{
|
|
check(Lhs.GetChannelNum() == Rhs.GetChannelNum());
|
|
|
|
BinaryOp(Out, Lhs.GetChannelNum(), Lhs, Rhs, [](
|
|
FFrameAttribute& Out,
|
|
const FFrameAttribute& Lhs,
|
|
const FFrameAttribute& Rhs,
|
|
const TLearningArrayView<1, const int32> OutRangeOffsets,
|
|
const TLearningArrayView<1, const int32> LhsRangeOffsets,
|
|
const TLearningArrayView<1, const int32> RhsRangeOffsets,
|
|
const TLearningArrayView<1, const int32> RangeLengths) {
|
|
|
|
const int32 ChannelNum = Out.GetChannelNum();
|
|
const int32 RangeNum = RangeLengths.Num();
|
|
for (int32 ChannelIdx = 0; ChannelIdx < ChannelNum; ChannelIdx++)
|
|
{
|
|
for (int32 RangeIdx = 0; RangeIdx < RangeNum; RangeIdx++)
|
|
{
|
|
Private::Gt(
|
|
Out.GetChannelRangeAttributeData(ChannelIdx, OutRangeOffsets[RangeIdx], RangeLengths[RangeIdx]),
|
|
Lhs.GetChannelRangeAttributeData(ChannelIdx, LhsRangeOffsets[RangeIdx], RangeLengths[RangeIdx]),
|
|
Rhs.GetChannelRangeAttributeData(ChannelIdx, RhsRangeOffsets[RangeIdx], RangeLengths[RangeIdx]));
|
|
}
|
|
}
|
|
});
|
|
}
|
|
|
|
void Ge(FFrameAttribute& Out, const FFrameAttribute& Lhs, const FFrameAttribute& Rhs)
|
|
{
|
|
check(Lhs.GetChannelNum() == Rhs.GetChannelNum());
|
|
|
|
BinaryOp(Out, Lhs.GetChannelNum(), Lhs, Rhs, [](
|
|
FFrameAttribute& Out,
|
|
const FFrameAttribute& Lhs,
|
|
const FFrameAttribute& Rhs,
|
|
const TLearningArrayView<1, const int32> OutRangeOffsets,
|
|
const TLearningArrayView<1, const int32> LhsRangeOffsets,
|
|
const TLearningArrayView<1, const int32> RhsRangeOffsets,
|
|
const TLearningArrayView<1, const int32> RangeLengths) {
|
|
|
|
const int32 ChannelNum = Out.GetChannelNum();
|
|
const int32 RangeNum = RangeLengths.Num();
|
|
for (int32 ChannelIdx = 0; ChannelIdx < ChannelNum; ChannelIdx++)
|
|
{
|
|
for (int32 RangeIdx = 0; RangeIdx < RangeNum; RangeIdx++)
|
|
{
|
|
Private::Ge(
|
|
Out.GetChannelRangeAttributeData(ChannelIdx, OutRangeOffsets[RangeIdx], RangeLengths[RangeIdx]),
|
|
Lhs.GetChannelRangeAttributeData(ChannelIdx, LhsRangeOffsets[RangeIdx], RangeLengths[RangeIdx]),
|
|
Rhs.GetChannelRangeAttributeData(ChannelIdx, RhsRangeOffsets[RangeIdx], RangeLengths[RangeIdx]));
|
|
}
|
|
}
|
|
});
|
|
}
|
|
|
|
void Lt(FFrameAttribute& Out, const FFrameAttribute& Lhs, const FFrameAttribute& Rhs)
|
|
{
|
|
check(Lhs.GetChannelNum() == Rhs.GetChannelNum());
|
|
|
|
BinaryOp(Out, Lhs.GetChannelNum(), Lhs, Rhs, [](
|
|
FFrameAttribute& Out,
|
|
const FFrameAttribute& Lhs,
|
|
const FFrameAttribute& Rhs,
|
|
const TLearningArrayView<1, const int32> OutRangeOffsets,
|
|
const TLearningArrayView<1, const int32> LhsRangeOffsets,
|
|
const TLearningArrayView<1, const int32> RhsRangeOffsets,
|
|
const TLearningArrayView<1, const int32> RangeLengths) {
|
|
|
|
const int32 ChannelNum = Out.GetChannelNum();
|
|
const int32 RangeNum = RangeLengths.Num();
|
|
for (int32 ChannelIdx = 0; ChannelIdx < ChannelNum; ChannelIdx++)
|
|
{
|
|
for (int32 RangeIdx = 0; RangeIdx < RangeNum; RangeIdx++)
|
|
{
|
|
Private::Lt(
|
|
Out.GetChannelRangeAttributeData(ChannelIdx, OutRangeOffsets[RangeIdx], RangeLengths[RangeIdx]),
|
|
Lhs.GetChannelRangeAttributeData(ChannelIdx, LhsRangeOffsets[RangeIdx], RangeLengths[RangeIdx]),
|
|
Rhs.GetChannelRangeAttributeData(ChannelIdx, RhsRangeOffsets[RangeIdx], RangeLengths[RangeIdx]));
|
|
}
|
|
}
|
|
});
|
|
}
|
|
|
|
void Le(FFrameAttribute& Out, const FFrameAttribute& Lhs, const FFrameAttribute& Rhs)
|
|
{
|
|
check(Lhs.GetChannelNum() == Rhs.GetChannelNum());
|
|
|
|
BinaryOp(Out, Lhs.GetChannelNum(), Lhs, Rhs, [](
|
|
FFrameAttribute& Out,
|
|
const FFrameAttribute& Lhs,
|
|
const FFrameAttribute& Rhs,
|
|
const TLearningArrayView<1, const int32> OutRangeOffsets,
|
|
const TLearningArrayView<1, const int32> LhsRangeOffsets,
|
|
const TLearningArrayView<1, const int32> RhsRangeOffsets,
|
|
const TLearningArrayView<1, const int32> RangeLengths) {
|
|
|
|
const int32 ChannelNum = Out.GetChannelNum();
|
|
const int32 RangeNum = RangeLengths.Num();
|
|
for (int32 ChannelIdx = 0; ChannelIdx < ChannelNum; ChannelIdx++)
|
|
{
|
|
for (int32 RangeIdx = 0; RangeIdx < RangeNum; RangeIdx++)
|
|
{
|
|
Private::Le(
|
|
Out.GetChannelRangeAttributeData(ChannelIdx, OutRangeOffsets[RangeIdx], RangeLengths[RangeIdx]),
|
|
Lhs.GetChannelRangeAttributeData(ChannelIdx, LhsRangeOffsets[RangeIdx], RangeLengths[RangeIdx]),
|
|
Rhs.GetChannelRangeAttributeData(ChannelIdx, RhsRangeOffsets[RangeIdx], RangeLengths[RangeIdx]));
|
|
}
|
|
}
|
|
});
|
|
}
|
|
|
|
void Eq(FFrameAttribute& Out, const FFrameAttribute& Lhs, const FFrameAttribute& Rhs)
|
|
{
|
|
check(Lhs.GetChannelNum() == Rhs.GetChannelNum());
|
|
|
|
BinaryOp(Out, Lhs.GetChannelNum(), Lhs, Rhs, [](
|
|
FFrameAttribute& Out,
|
|
const FFrameAttribute& Lhs,
|
|
const FFrameAttribute& Rhs,
|
|
const TLearningArrayView<1, const int32> OutRangeOffsets,
|
|
const TLearningArrayView<1, const int32> LhsRangeOffsets,
|
|
const TLearningArrayView<1, const int32> RhsRangeOffsets,
|
|
const TLearningArrayView<1, const int32> RangeLengths) {
|
|
|
|
const int32 ChannelNum = Out.GetChannelNum();
|
|
const int32 RangeNum = RangeLengths.Num();
|
|
for (int32 ChannelIdx = 0; ChannelIdx < ChannelNum; ChannelIdx++)
|
|
{
|
|
for (int32 RangeIdx = 0; RangeIdx < RangeNum; RangeIdx++)
|
|
{
|
|
Private::Eq(
|
|
Out.GetChannelRangeAttributeData(ChannelIdx, OutRangeOffsets[RangeIdx], RangeLengths[RangeIdx]),
|
|
Lhs.GetChannelRangeAttributeData(ChannelIdx, LhsRangeOffsets[RangeIdx], RangeLengths[RangeIdx]),
|
|
Rhs.GetChannelRangeAttributeData(ChannelIdx, RhsRangeOffsets[RangeIdx], RangeLengths[RangeIdx]));
|
|
}
|
|
}
|
|
});
|
|
}
|
|
|
|
void Neq(FFrameAttribute& Out, const FFrameAttribute& Lhs, const FFrameAttribute& Rhs)
|
|
{
|
|
check(Lhs.GetChannelNum() == Rhs.GetChannelNum());
|
|
|
|
BinaryOp(Out, Lhs.GetChannelNum(), Lhs, Rhs, [](
|
|
FFrameAttribute& Out,
|
|
const FFrameAttribute& Lhs,
|
|
const FFrameAttribute& Rhs,
|
|
const TLearningArrayView<1, const int32> OutRangeOffsets,
|
|
const TLearningArrayView<1, const int32> LhsRangeOffsets,
|
|
const TLearningArrayView<1, const int32> RhsRangeOffsets,
|
|
const TLearningArrayView<1, const int32> RangeLengths) {
|
|
|
|
const int32 ChannelNum = Out.GetChannelNum();
|
|
const int32 RangeNum = RangeLengths.Num();
|
|
for (int32 ChannelIdx = 0; ChannelIdx < ChannelNum; ChannelIdx++)
|
|
{
|
|
for (int32 RangeIdx = 0; RangeIdx < RangeNum; RangeIdx++)
|
|
{
|
|
Private::Neq(
|
|
Out.GetChannelRangeAttributeData(ChannelIdx, OutRangeOffsets[RangeIdx], RangeLengths[RangeIdx]),
|
|
Lhs.GetChannelRangeAttributeData(ChannelIdx, LhsRangeOffsets[RangeIdx], RangeLengths[RangeIdx]),
|
|
Rhs.GetChannelRangeAttributeData(ChannelIdx, RhsRangeOffsets[RangeIdx], RangeLengths[RangeIdx]));
|
|
}
|
|
}
|
|
});
|
|
}
|
|
|
|
void GtConstant(FFrameAttribute& Out, const FFrameAttribute& Lhs, const TLearningArrayView<1, const float> Rhs)
|
|
{
|
|
UnaryOp(Out, Lhs.GetChannelNum(), Lhs, [Rhs](
|
|
FFrameAttribute& Out,
|
|
const FFrameAttribute& In,
|
|
const TLearningArrayView<1, const int32> RangeOffsets,
|
|
const TLearningArrayView<1, const int32> RangeLengths) {
|
|
|
|
const int32 ChannelNum = Out.GetChannelNum();
|
|
|
|
for (int32 ChannelIdx = 0; ChannelIdx < ChannelNum; ChannelIdx++)
|
|
{
|
|
Private::GtConstant(
|
|
Out.GetChannelAttributeData(ChannelIdx),
|
|
In.GetChannelAttributeData(ChannelIdx),
|
|
Rhs[ChannelIdx]);
|
|
}
|
|
});
|
|
}
|
|
|
|
void GeConstant(FFrameAttribute& Out, const FFrameAttribute& Lhs, const TLearningArrayView<1, const float> Rhs)
|
|
{
|
|
UnaryOp(Out, Lhs.GetChannelNum(), Lhs, [Rhs](
|
|
FFrameAttribute& Out,
|
|
const FFrameAttribute& In,
|
|
const TLearningArrayView<1, const int32> RangeOffsets,
|
|
const TLearningArrayView<1, const int32> RangeLengths) {
|
|
|
|
const int32 ChannelNum = Out.GetChannelNum();
|
|
|
|
for (int32 ChannelIdx = 0; ChannelIdx < ChannelNum; ChannelIdx++)
|
|
{
|
|
Private::GeConstant(
|
|
Out.GetChannelAttributeData(ChannelIdx),
|
|
In.GetChannelAttributeData(ChannelIdx),
|
|
Rhs[ChannelIdx]);
|
|
}
|
|
});
|
|
}
|
|
|
|
void LtConstant(FFrameAttribute& Out, const FFrameAttribute& Lhs, const TLearningArrayView<1, const float> Rhs)
|
|
{
|
|
UnaryOp(Out, Lhs.GetChannelNum(), Lhs, [Rhs](
|
|
FFrameAttribute& Out,
|
|
const FFrameAttribute& In,
|
|
const TLearningArrayView<1, const int32> RangeOffsets,
|
|
const TLearningArrayView<1, const int32> RangeLengths) {
|
|
|
|
const int32 ChannelNum = Out.GetChannelNum();
|
|
|
|
for (int32 ChannelIdx = 0; ChannelIdx < ChannelNum; ChannelIdx++)
|
|
{
|
|
Private::LtConstant(
|
|
Out.GetChannelAttributeData(ChannelIdx),
|
|
In.GetChannelAttributeData(ChannelIdx),
|
|
Rhs[ChannelIdx]);
|
|
}
|
|
});
|
|
}
|
|
|
|
void LeConstant(FFrameAttribute& Out, const FFrameAttribute& Lhs, const TLearningArrayView<1, const float> Rhs)
|
|
{
|
|
UnaryOp(Out, Lhs.GetChannelNum(), Lhs, [Rhs](
|
|
FFrameAttribute& Out,
|
|
const FFrameAttribute& In,
|
|
const TLearningArrayView<1, const int32> RangeOffsets,
|
|
const TLearningArrayView<1, const int32> RangeLengths) {
|
|
|
|
const int32 ChannelNum = Out.GetChannelNum();
|
|
|
|
for (int32 ChannelIdx = 0; ChannelIdx < ChannelNum; ChannelIdx++)
|
|
{
|
|
Private::LeConstant(
|
|
Out.GetChannelAttributeData(ChannelIdx),
|
|
In.GetChannelAttributeData(ChannelIdx),
|
|
Rhs[ChannelIdx]);
|
|
}
|
|
});
|
|
}
|
|
|
|
void EqConstant(FFrameAttribute& Out, const FFrameAttribute& Lhs, const TLearningArrayView<1, const float> Rhs)
|
|
{
|
|
UnaryOp(Out, Lhs.GetChannelNum(), Lhs, [Rhs](
|
|
FFrameAttribute& Out,
|
|
const FFrameAttribute& In,
|
|
const TLearningArrayView<1, const int32> RangeOffsets,
|
|
const TLearningArrayView<1, const int32> RangeLengths) {
|
|
|
|
const int32 ChannelNum = Out.GetChannelNum();
|
|
|
|
for (int32 ChannelIdx = 0; ChannelIdx < ChannelNum; ChannelIdx++)
|
|
{
|
|
Private::EqConstant(
|
|
Out.GetChannelAttributeData(ChannelIdx),
|
|
In.GetChannelAttributeData(ChannelIdx),
|
|
Rhs[ChannelIdx]);
|
|
}
|
|
});
|
|
}
|
|
|
|
void NeqConstant(FFrameAttribute& Out, const FFrameAttribute& Lhs, const TLearningArrayView<1, const float> Rhs)
|
|
{
|
|
UnaryOp(Out, Lhs.GetChannelNum(), Lhs, [Rhs](
|
|
FFrameAttribute& Out,
|
|
const FFrameAttribute& In,
|
|
const TLearningArrayView<1, const int32> RangeOffsets,
|
|
const TLearningArrayView<1, const int32> RangeLengths) {
|
|
|
|
const int32 ChannelNum = Out.GetChannelNum();
|
|
|
|
for (int32 ChannelIdx = 0; ChannelIdx < ChannelNum; ChannelIdx++)
|
|
{
|
|
Private::NeqConstant(
|
|
Out.GetChannelAttributeData(ChannelIdx),
|
|
In.GetChannelAttributeData(ChannelIdx),
|
|
Rhs[ChannelIdx]);
|
|
}
|
|
});
|
|
}
|
|
|
|
void ConstantGt(FFrameAttribute& Out, const TLearningArrayView<1, const float> Lhs, const FFrameAttribute& Rhs)
|
|
{
|
|
UnaryOp(Out, Rhs.GetChannelNum(), Rhs, [Lhs](
|
|
FFrameAttribute& Out,
|
|
const FFrameAttribute& In,
|
|
const TLearningArrayView<1, const int32> RangeOffsets,
|
|
const TLearningArrayView<1, const int32> RangeLengths) {
|
|
|
|
const int32 ChannelNum = Out.GetChannelNum();
|
|
|
|
for (int32 ChannelIdx = 0; ChannelIdx < ChannelNum; ChannelIdx++)
|
|
{
|
|
Private::ConstantGt(
|
|
Out.GetChannelAttributeData(ChannelIdx),
|
|
Lhs[ChannelIdx],
|
|
In.GetChannelAttributeData(ChannelIdx));
|
|
}
|
|
});
|
|
}
|
|
|
|
void ConstantGe(FFrameAttribute& Out, const TLearningArrayView<1, const float> Lhs, const FFrameAttribute& Rhs)
|
|
{
|
|
UnaryOp(Out, Rhs.GetChannelNum(), Rhs, [Lhs](
|
|
FFrameAttribute& Out,
|
|
const FFrameAttribute& In,
|
|
const TLearningArrayView<1, const int32> RangeOffsets,
|
|
const TLearningArrayView<1, const int32> RangeLengths) {
|
|
|
|
const int32 ChannelNum = Out.GetChannelNum();
|
|
|
|
for (int32 ChannelIdx = 0; ChannelIdx < ChannelNum; ChannelIdx++)
|
|
{
|
|
Private::ConstantGe(
|
|
Out.GetChannelAttributeData(ChannelIdx),
|
|
Lhs[ChannelIdx],
|
|
In.GetChannelAttributeData(ChannelIdx));
|
|
}
|
|
});
|
|
}
|
|
|
|
void ConstantLt(FFrameAttribute& Out, const TLearningArrayView<1, const float> Lhs, const FFrameAttribute& Rhs)
|
|
{
|
|
UnaryOp(Out, Rhs.GetChannelNum(), Rhs, [Lhs](
|
|
FFrameAttribute& Out,
|
|
const FFrameAttribute& In,
|
|
const TLearningArrayView<1, const int32> RangeOffsets,
|
|
const TLearningArrayView<1, const int32> RangeLengths) {
|
|
|
|
const int32 ChannelNum = Out.GetChannelNum();
|
|
|
|
for (int32 ChannelIdx = 0; ChannelIdx < ChannelNum; ChannelIdx++)
|
|
{
|
|
Private::ConstantLt(
|
|
Out.GetChannelAttributeData(ChannelIdx),
|
|
Lhs[ChannelIdx],
|
|
In.GetChannelAttributeData(ChannelIdx));
|
|
}
|
|
});
|
|
}
|
|
|
|
void ConstantLe(FFrameAttribute& Out, const TLearningArrayView<1, const float> Lhs, const FFrameAttribute& Rhs)
|
|
{
|
|
UnaryOp(Out, Rhs.GetChannelNum(), Rhs, [Lhs](
|
|
FFrameAttribute& Out,
|
|
const FFrameAttribute& In,
|
|
const TLearningArrayView<1, const int32> RangeOffsets,
|
|
const TLearningArrayView<1, const int32> RangeLengths) {
|
|
|
|
const int32 ChannelNum = Out.GetChannelNum();
|
|
|
|
for (int32 ChannelIdx = 0; ChannelIdx < ChannelNum; ChannelIdx++)
|
|
{
|
|
Private::ConstantLe(
|
|
Out.GetChannelAttributeData(ChannelIdx),
|
|
Lhs[ChannelIdx],
|
|
In.GetChannelAttributeData(ChannelIdx));
|
|
}
|
|
});
|
|
}
|
|
|
|
void ConstantEq(FFrameAttribute& Out, const TLearningArrayView<1, const float> Lhs, const FFrameAttribute& Rhs)
|
|
{
|
|
UnaryOp(Out, Rhs.GetChannelNum(), Rhs, [Lhs](
|
|
FFrameAttribute& Out,
|
|
const FFrameAttribute& In,
|
|
const TLearningArrayView<1, const int32> RangeOffsets,
|
|
const TLearningArrayView<1, const int32> RangeLengths) {
|
|
|
|
const int32 ChannelNum = Out.GetChannelNum();
|
|
|
|
for (int32 ChannelIdx = 0; ChannelIdx < ChannelNum; ChannelIdx++)
|
|
{
|
|
Private::ConstantEq(
|
|
Out.GetChannelAttributeData(ChannelIdx),
|
|
Lhs[ChannelIdx],
|
|
In.GetChannelAttributeData(ChannelIdx));
|
|
}
|
|
});
|
|
}
|
|
|
|
void ConstantNeq(FFrameAttribute& Out, const TLearningArrayView<1, const float> Lhs, const FFrameAttribute& Rhs)
|
|
{
|
|
UnaryOp(Out, Rhs.GetChannelNum(), Rhs, [Lhs](
|
|
FFrameAttribute& Out,
|
|
const FFrameAttribute& In,
|
|
const TLearningArrayView<1, const int32> RangeOffsets,
|
|
const TLearningArrayView<1, const int32> RangeLengths) {
|
|
|
|
const int32 ChannelNum = Out.GetChannelNum();
|
|
|
|
for (int32 ChannelIdx = 0; ChannelIdx < ChannelNum; ChannelIdx++)
|
|
{
|
|
Private::ConstantNeq(
|
|
Out.GetChannelAttributeData(ChannelIdx),
|
|
Lhs[ChannelIdx],
|
|
In.GetChannelAttributeData(ChannelIdx));
|
|
}
|
|
});
|
|
}
|
|
|
|
void FilterGaussian(FFrameAttribute& Out, const FFrameAttribute& In, const float StdInFrames)
|
|
{
|
|
UnaryOp(Out, In.GetChannelNum(), In, [StdInFrames](
|
|
FFrameAttribute& Out,
|
|
const FFrameAttribute& In,
|
|
const TLearningArrayView<1, const int32> RangeOffsets,
|
|
const TLearningArrayView<1, const int32> RangeLengths) {
|
|
|
|
const int32 ChannelNum = Out.GetChannelNum();
|
|
const int32 RangeNum = RangeLengths.Num();
|
|
for (int32 ChannelIdx = 0; ChannelIdx < ChannelNum; ChannelIdx++)
|
|
{
|
|
for (int32 RangeIdx = 0; RangeIdx < RangeNum; RangeIdx++)
|
|
{
|
|
Private::FilterGaussian(
|
|
Out.GetChannelRangeAttributeData(ChannelIdx, RangeOffsets[RangeIdx], RangeLengths[RangeIdx]),
|
|
In.GetChannelRangeAttributeData(ChannelIdx, RangeOffsets[RangeIdx], RangeLengths[RangeIdx]),
|
|
StdInFrames);
|
|
}
|
|
}
|
|
});
|
|
}
|
|
|
|
void FilterMajorityVote(FFrameAttribute& Out, const FFrameAttribute& In, const int32 FilterWidthFrames)
|
|
{
|
|
UnaryOp(Out, In.GetChannelNum(), In, [FilterWidthFrames](
|
|
FFrameAttribute& Out,
|
|
const FFrameAttribute& In,
|
|
const TLearningArrayView<1, const int32> RangeOffsets,
|
|
const TLearningArrayView<1, const int32> RangeLengths) {
|
|
|
|
const int32 ChannelNum = Out.GetChannelNum();
|
|
const int32 RangeNum = RangeLengths.Num();
|
|
for (int32 ChannelIdx = 0; ChannelIdx < ChannelNum; ChannelIdx++)
|
|
{
|
|
for (int32 RangeIdx = 0; RangeIdx < RangeNum; RangeIdx++)
|
|
{
|
|
Private::FilterMajorityVote(
|
|
Out.GetChannelRangeAttributeData(ChannelIdx, RangeOffsets[RangeIdx], RangeLengths[RangeIdx]),
|
|
In.GetChannelRangeAttributeData(ChannelIdx, RangeOffsets[RangeIdx], RangeLengths[RangeIdx]),
|
|
FilterWidthFrames);
|
|
}
|
|
}
|
|
});
|
|
}
|
|
|
|
void MeanStd(TLearningArrayView<1, float> OutMean, TLearningArrayView<1, float> OutStd, const FFrameAttribute& In)
|
|
{
|
|
ReduceOp(In, [&OutMean, &OutStd](
|
|
const FFrameAttribute& In,
|
|
const TLearningArrayView<1, const int32> RangeOffsets,
|
|
const TLearningArrayView<1, const int32> RangeLengths) {
|
|
|
|
const int32 ChannelNum = In.GetChannelNum();
|
|
|
|
for (int32 ChannelIdx = 0; ChannelIdx < ChannelNum; ChannelIdx++)
|
|
{
|
|
Private::MeanStd(OutMean[ChannelIdx], OutStd[ChannelIdx], In.GetChannelAttributeData(ChannelIdx));
|
|
}
|
|
});
|
|
}
|
|
|
|
void LogMeanStd(TLearningArrayView<1, float> OutMean, TLearningArrayView<1, float> OutLogStd, const FFrameAttribute& In)
|
|
{
|
|
ReduceOp(In, [&OutMean, &OutLogStd](
|
|
const FFrameAttribute& In,
|
|
const TLearningArrayView<1, const int32> RangeOffsets,
|
|
const TLearningArrayView<1, const int32> RangeLengths) {
|
|
|
|
const int32 ChannelNum = In.GetChannelNum();
|
|
|
|
for (int32 ChannelIdx = 0; ChannelIdx < ChannelNum; ChannelIdx++)
|
|
{
|
|
Private::LogMeanStd(OutMean[ChannelIdx], OutLogStd[ChannelIdx], In.GetChannelAttributeData(ChannelIdx));
|
|
}
|
|
});
|
|
}
|
|
|
|
void QuatMul(FFrameAttribute& Out, const FFrameAttribute& Lhs, const FFrameAttribute& Rhs)
|
|
{
|
|
check(Lhs.GetChannelNum() == 4);
|
|
check(Rhs.GetChannelNum() == 4);
|
|
|
|
BinaryOp(Out, 4, Lhs, Rhs, [](
|
|
FFrameAttribute& Out,
|
|
const FFrameAttribute& Lhs,
|
|
const FFrameAttribute& Rhs,
|
|
const TLearningArrayView<1, const int32> OutRangeOffsets,
|
|
const TLearningArrayView<1, const int32> LhsRangeOffsets,
|
|
const TLearningArrayView<1, const int32> RhsRangeOffsets,
|
|
const TLearningArrayView<1, const int32> RangeLengths) {
|
|
|
|
const int32 RangeNum = RangeLengths.Num();
|
|
|
|
for (int32 RangeIdx = 0; RangeIdx < RangeNum; RangeIdx++)
|
|
{
|
|
Private::QuatMul(
|
|
Out.GetChannelRangeAttributeData(0, OutRangeOffsets[RangeIdx], RangeLengths[RangeIdx]),
|
|
Out.GetChannelRangeAttributeData(1, OutRangeOffsets[RangeIdx], RangeLengths[RangeIdx]),
|
|
Out.GetChannelRangeAttributeData(2, OutRangeOffsets[RangeIdx], RangeLengths[RangeIdx]),
|
|
Out.GetChannelRangeAttributeData(3, OutRangeOffsets[RangeIdx], RangeLengths[RangeIdx]),
|
|
Lhs.GetChannelRangeAttributeData(0, LhsRangeOffsets[RangeIdx], RangeLengths[RangeIdx]),
|
|
Lhs.GetChannelRangeAttributeData(1, LhsRangeOffsets[RangeIdx], RangeLengths[RangeIdx]),
|
|
Lhs.GetChannelRangeAttributeData(2, LhsRangeOffsets[RangeIdx], RangeLengths[RangeIdx]),
|
|
Lhs.GetChannelRangeAttributeData(3, LhsRangeOffsets[RangeIdx], RangeLengths[RangeIdx]),
|
|
Rhs.GetChannelRangeAttributeData(0, RhsRangeOffsets[RangeIdx], RangeLengths[RangeIdx]),
|
|
Rhs.GetChannelRangeAttributeData(1, RhsRangeOffsets[RangeIdx], RangeLengths[RangeIdx]),
|
|
Rhs.GetChannelRangeAttributeData(2, RhsRangeOffsets[RangeIdx], RangeLengths[RangeIdx]),
|
|
Rhs.GetChannelRangeAttributeData(3, RhsRangeOffsets[RangeIdx], RangeLengths[RangeIdx]));
|
|
}
|
|
});
|
|
}
|
|
|
|
void QuatDiv(FFrameAttribute& Out, const FFrameAttribute& Lhs, const FFrameAttribute& Rhs)
|
|
{
|
|
QuatMulInv(Out, Lhs, Rhs);
|
|
}
|
|
|
|
void QuatInv(FFrameAttribute& Out, const FFrameAttribute& In)
|
|
{
|
|
check(In.GetChannelNum() == 4);
|
|
|
|
UnaryOp(Out, 4, In, [](
|
|
FFrameAttribute& Out,
|
|
const FFrameAttribute& In,
|
|
const TLearningArrayView<1, const int32> RangeOffsets,
|
|
const TLearningArrayView<1, const int32> RangeLengths) {
|
|
|
|
Private::QuatInv(Out.GetAttributeData(), In.GetAttributeData());
|
|
});
|
|
}
|
|
|
|
void QuatAbs(FFrameAttribute& Out, const FFrameAttribute& In)
|
|
{
|
|
check(In.GetChannelNum() == 4);
|
|
|
|
UnaryOp(Out, 4, In, [](
|
|
FFrameAttribute& Out,
|
|
const FFrameAttribute& In,
|
|
const TLearningArrayView<1, const int32> RangeOffsets,
|
|
const TLearningArrayView<1, const int32> RangeLengths) {
|
|
|
|
Private::QuatAbs(Out.GetAttributeData(), In.GetAttributeData());
|
|
});
|
|
}
|
|
|
|
void QuatToRotationVector(FFrameAttribute& Out, const FFrameAttribute& In)
|
|
{
|
|
check(In.GetChannelNum() == 4);
|
|
|
|
UnaryOp(Out, 3, In, [](
|
|
FFrameAttribute& Out,
|
|
const FFrameAttribute& In,
|
|
const TLearningArrayView<1, const int32> RangeOffsets,
|
|
const TLearningArrayView<1, const int32> RangeLengths) {
|
|
|
|
Private::QuatToRotationVector(Out.GetAttributeData(), In.GetAttributeData());
|
|
});
|
|
}
|
|
|
|
void QuatFromRotationVector(FFrameAttribute& Out, const FFrameAttribute& In)
|
|
{
|
|
check(In.GetChannelNum() == 3);
|
|
|
|
UnaryOp(Out, 4, In, [](
|
|
FFrameAttribute& Out,
|
|
const FFrameAttribute& In,
|
|
const TLearningArrayView<1, const int32> RangeOffsets,
|
|
const TLearningArrayView<1, const int32> RangeLengths) {
|
|
|
|
Private::QuatFromRotationVector(Out.GetAttributeData(), In.GetAttributeData());
|
|
});
|
|
}
|
|
|
|
void QuatInvMul(FFrameAttribute& Out, const FFrameAttribute& Lhs, const FFrameAttribute& Rhs)
|
|
{
|
|
check(Lhs.GetChannelNum() == 4);
|
|
check(Rhs.GetChannelNum() == 4);
|
|
|
|
BinaryOp(Out, 4, Lhs, Rhs, [](
|
|
FFrameAttribute& Out,
|
|
const FFrameAttribute& Lhs,
|
|
const FFrameAttribute& Rhs,
|
|
const TLearningArrayView<1, const int32> OutRangeOffsets,
|
|
const TLearningArrayView<1, const int32> LhsRangeOffsets,
|
|
const TLearningArrayView<1, const int32> RhsRangeOffsets,
|
|
const TLearningArrayView<1, const int32> RangeLengths) {
|
|
|
|
const int32 RangeNum = RangeLengths.Num();
|
|
|
|
for (int32 RangeIdx = 0; RangeIdx < RangeNum; RangeIdx++)
|
|
{
|
|
Private::QuatInvMul(
|
|
Out.GetChannelRangeAttributeData(0, OutRangeOffsets[RangeIdx], RangeLengths[RangeIdx]),
|
|
Out.GetChannelRangeAttributeData(1, OutRangeOffsets[RangeIdx], RangeLengths[RangeIdx]),
|
|
Out.GetChannelRangeAttributeData(2, OutRangeOffsets[RangeIdx], RangeLengths[RangeIdx]),
|
|
Out.GetChannelRangeAttributeData(3, OutRangeOffsets[RangeIdx], RangeLengths[RangeIdx]),
|
|
Lhs.GetChannelRangeAttributeData(0, LhsRangeOffsets[RangeIdx], RangeLengths[RangeIdx]),
|
|
Lhs.GetChannelRangeAttributeData(1, LhsRangeOffsets[RangeIdx], RangeLengths[RangeIdx]),
|
|
Lhs.GetChannelRangeAttributeData(2, LhsRangeOffsets[RangeIdx], RangeLengths[RangeIdx]),
|
|
Lhs.GetChannelRangeAttributeData(3, LhsRangeOffsets[RangeIdx], RangeLengths[RangeIdx]),
|
|
Rhs.GetChannelRangeAttributeData(0, RhsRangeOffsets[RangeIdx], RangeLengths[RangeIdx]),
|
|
Rhs.GetChannelRangeAttributeData(1, RhsRangeOffsets[RangeIdx], RangeLengths[RangeIdx]),
|
|
Rhs.GetChannelRangeAttributeData(2, RhsRangeOffsets[RangeIdx], RangeLengths[RangeIdx]),
|
|
Rhs.GetChannelRangeAttributeData(3, RhsRangeOffsets[RangeIdx], RangeLengths[RangeIdx]));
|
|
}
|
|
});
|
|
}
|
|
|
|
void QuatMulInv(FFrameAttribute& Out, const FFrameAttribute& Lhs, const FFrameAttribute& Rhs)
|
|
{
|
|
check(Lhs.GetChannelNum() == 4);
|
|
check(Rhs.GetChannelNum() == 4);
|
|
|
|
BinaryOp(Out, 4, Lhs, Rhs, [](
|
|
FFrameAttribute& Out,
|
|
const FFrameAttribute& Lhs,
|
|
const FFrameAttribute& Rhs,
|
|
const TLearningArrayView<1, const int32> OutRangeOffsets,
|
|
const TLearningArrayView<1, const int32> LhsRangeOffsets,
|
|
const TLearningArrayView<1, const int32> RhsRangeOffsets,
|
|
const TLearningArrayView<1, const int32> RangeLengths) {
|
|
|
|
const int32 RangeNum = RangeLengths.Num();
|
|
|
|
for (int32 RangeIdx = 0; RangeIdx < RangeNum; RangeIdx++)
|
|
{
|
|
Private::QuatMulInv(
|
|
Out.GetChannelRangeAttributeData(0, OutRangeOffsets[RangeIdx], RangeLengths[RangeIdx]),
|
|
Out.GetChannelRangeAttributeData(1, OutRangeOffsets[RangeIdx], RangeLengths[RangeIdx]),
|
|
Out.GetChannelRangeAttributeData(2, OutRangeOffsets[RangeIdx], RangeLengths[RangeIdx]),
|
|
Out.GetChannelRangeAttributeData(3, OutRangeOffsets[RangeIdx], RangeLengths[RangeIdx]),
|
|
Lhs.GetChannelRangeAttributeData(0, LhsRangeOffsets[RangeIdx], RangeLengths[RangeIdx]),
|
|
Lhs.GetChannelRangeAttributeData(1, LhsRangeOffsets[RangeIdx], RangeLengths[RangeIdx]),
|
|
Lhs.GetChannelRangeAttributeData(2, LhsRangeOffsets[RangeIdx], RangeLengths[RangeIdx]),
|
|
Lhs.GetChannelRangeAttributeData(3, LhsRangeOffsets[RangeIdx], RangeLengths[RangeIdx]),
|
|
Rhs.GetChannelRangeAttributeData(0, RhsRangeOffsets[RangeIdx], RangeLengths[RangeIdx]),
|
|
Rhs.GetChannelRangeAttributeData(1, RhsRangeOffsets[RangeIdx], RangeLengths[RangeIdx]),
|
|
Rhs.GetChannelRangeAttributeData(2, RhsRangeOffsets[RangeIdx], RangeLengths[RangeIdx]),
|
|
Rhs.GetChannelRangeAttributeData(3, RhsRangeOffsets[RangeIdx], RangeLengths[RangeIdx]));
|
|
}
|
|
});
|
|
}
|
|
|
|
void QuatRotate(FFrameAttribute& Out, const FFrameAttribute& Lhs, const FFrameAttribute& Rhs)
|
|
{
|
|
check(Lhs.GetChannelNum() == 4);
|
|
check(Rhs.GetChannelNum() == 3);
|
|
|
|
BinaryOp(Out, 3, Lhs, Rhs, [](
|
|
FFrameAttribute& Out,
|
|
const FFrameAttribute& Lhs,
|
|
const FFrameAttribute& Rhs,
|
|
const TLearningArrayView<1, const int32> OutRangeOffsets,
|
|
const TLearningArrayView<1, const int32> LhsRangeOffsets,
|
|
const TLearningArrayView<1, const int32> RhsRangeOffsets,
|
|
const TLearningArrayView<1, const int32> RangeLengths) {
|
|
|
|
const int32 RangeNum = RangeLengths.Num();
|
|
|
|
for (int32 RangeIdx = 0; RangeIdx < RangeNum; RangeIdx++)
|
|
{
|
|
Private::QuatRotate(
|
|
Out.GetChannelRangeAttributeData(0, OutRangeOffsets[RangeIdx], RangeLengths[RangeIdx]),
|
|
Out.GetChannelRangeAttributeData(1, OutRangeOffsets[RangeIdx], RangeLengths[RangeIdx]),
|
|
Out.GetChannelRangeAttributeData(2, OutRangeOffsets[RangeIdx], RangeLengths[RangeIdx]),
|
|
Lhs.GetChannelRangeAttributeData(0, LhsRangeOffsets[RangeIdx], RangeLengths[RangeIdx]),
|
|
Lhs.GetChannelRangeAttributeData(1, LhsRangeOffsets[RangeIdx], RangeLengths[RangeIdx]),
|
|
Lhs.GetChannelRangeAttributeData(2, LhsRangeOffsets[RangeIdx], RangeLengths[RangeIdx]),
|
|
Lhs.GetChannelRangeAttributeData(3, LhsRangeOffsets[RangeIdx], RangeLengths[RangeIdx]),
|
|
Rhs.GetChannelRangeAttributeData(0, RhsRangeOffsets[RangeIdx], RangeLengths[RangeIdx]),
|
|
Rhs.GetChannelRangeAttributeData(1, RhsRangeOffsets[RangeIdx], RangeLengths[RangeIdx]),
|
|
Rhs.GetChannelRangeAttributeData(2, RhsRangeOffsets[RangeIdx], RangeLengths[RangeIdx]));
|
|
}
|
|
});
|
|
}
|
|
|
|
void QuatUnrotate(FFrameAttribute& Out, const FFrameAttribute& Lhs, const FFrameAttribute& Rhs)
|
|
{
|
|
check(Lhs.GetChannelNum() == 4);
|
|
check(Rhs.GetChannelNum() == 3);
|
|
|
|
BinaryOp(Out, 3, Lhs, Rhs, [](
|
|
FFrameAttribute& Out,
|
|
const FFrameAttribute& Lhs,
|
|
const FFrameAttribute& Rhs,
|
|
const TLearningArrayView<1, const int32> OutRangeOffsets,
|
|
const TLearningArrayView<1, const int32> LhsRangeOffsets,
|
|
const TLearningArrayView<1, const int32> RhsRangeOffsets,
|
|
const TLearningArrayView<1, const int32> RangeLengths) {
|
|
|
|
const int32 RangeNum = RangeLengths.Num();
|
|
|
|
for (int32 RangeIdx = 0; RangeIdx < RangeNum; RangeIdx++)
|
|
{
|
|
Private::QuatUnrotate(
|
|
Out.GetChannelRangeAttributeData(0, OutRangeOffsets[RangeIdx], RangeLengths[RangeIdx]),
|
|
Out.GetChannelRangeAttributeData(1, OutRangeOffsets[RangeIdx], RangeLengths[RangeIdx]),
|
|
Out.GetChannelRangeAttributeData(2, OutRangeOffsets[RangeIdx], RangeLengths[RangeIdx]),
|
|
Lhs.GetChannelRangeAttributeData(0, LhsRangeOffsets[RangeIdx], RangeLengths[RangeIdx]),
|
|
Lhs.GetChannelRangeAttributeData(1, LhsRangeOffsets[RangeIdx], RangeLengths[RangeIdx]),
|
|
Lhs.GetChannelRangeAttributeData(2, LhsRangeOffsets[RangeIdx], RangeLengths[RangeIdx]),
|
|
Lhs.GetChannelRangeAttributeData(3, LhsRangeOffsets[RangeIdx], RangeLengths[RangeIdx]),
|
|
Rhs.GetChannelRangeAttributeData(0, RhsRangeOffsets[RangeIdx], RangeLengths[RangeIdx]),
|
|
Rhs.GetChannelRangeAttributeData(1, RhsRangeOffsets[RangeIdx], RangeLengths[RangeIdx]),
|
|
Rhs.GetChannelRangeAttributeData(2, RhsRangeOffsets[RangeIdx], RangeLengths[RangeIdx]));
|
|
}
|
|
});
|
|
}
|
|
|
|
void QuatBetween(FFrameAttribute& Out, const FFrameAttribute& Lhs, const FFrameAttribute& Rhs)
|
|
{
|
|
check(Lhs.GetChannelNum() == 3);
|
|
check(Rhs.GetChannelNum() == 3);
|
|
|
|
BinaryOp(Out, 4, Lhs, Rhs, [](
|
|
FFrameAttribute& Out,
|
|
const FFrameAttribute& Lhs,
|
|
const FFrameAttribute& Rhs,
|
|
const TLearningArrayView<1, const int32> OutRangeOffsets,
|
|
const TLearningArrayView<1, const int32> LhsRangeOffsets,
|
|
const TLearningArrayView<1, const int32> RhsRangeOffsets,
|
|
const TLearningArrayView<1, const int32> RangeLengths) {
|
|
|
|
const int32 RangeNum = RangeLengths.Num();
|
|
|
|
for (int32 RangeIdx = 0; RangeIdx < RangeNum; RangeIdx++)
|
|
{
|
|
Private::QuatBetween(
|
|
Out.GetChannelRangeAttributeData(0, OutRangeOffsets[RangeIdx], RangeLengths[RangeIdx]),
|
|
Out.GetChannelRangeAttributeData(1, OutRangeOffsets[RangeIdx], RangeLengths[RangeIdx]),
|
|
Out.GetChannelRangeAttributeData(2, OutRangeOffsets[RangeIdx], RangeLengths[RangeIdx]),
|
|
Out.GetChannelRangeAttributeData(3, OutRangeOffsets[RangeIdx], RangeLengths[RangeIdx]),
|
|
Lhs.GetChannelRangeAttributeData(0, LhsRangeOffsets[RangeIdx], RangeLengths[RangeIdx]),
|
|
Lhs.GetChannelRangeAttributeData(1, LhsRangeOffsets[RangeIdx], RangeLengths[RangeIdx]),
|
|
Lhs.GetChannelRangeAttributeData(2, LhsRangeOffsets[RangeIdx], RangeLengths[RangeIdx]),
|
|
Rhs.GetChannelRangeAttributeData(0, RhsRangeOffsets[RangeIdx], RangeLengths[RangeIdx]),
|
|
Rhs.GetChannelRangeAttributeData(1, RhsRangeOffsets[RangeIdx], RangeLengths[RangeIdx]),
|
|
Rhs.GetChannelRangeAttributeData(2, RhsRangeOffsets[RangeIdx], RangeLengths[RangeIdx]));
|
|
}
|
|
});
|
|
}
|
|
|
|
void QuatMulConstant(FFrameAttribute& Out, const FFrameAttribute& Lhs, const FQuat4f Rhs)
|
|
{
|
|
check(Lhs.GetChannelNum() == 4);
|
|
|
|
UnaryOp(Out, 4, Lhs, [Rhs](
|
|
FFrameAttribute& Out,
|
|
const FFrameAttribute& Lhs,
|
|
const TLearningArrayView<1, const int32> RangeOffsets,
|
|
const TLearningArrayView<1, const int32> RangeLengths) {
|
|
|
|
Private::QuatMulConstant(
|
|
Out.GetAttributeData(),
|
|
Lhs.GetAttributeData(),
|
|
Rhs);
|
|
});
|
|
}
|
|
|
|
void QuatDivConstant(FFrameAttribute& Out, const FFrameAttribute& Lhs, const FQuat4f Rhs)
|
|
{
|
|
QuatMulInvConstant(Out, Lhs, Rhs);
|
|
}
|
|
|
|
void QuatInvMulConstant(FFrameAttribute& Out, const FFrameAttribute& Lhs, const FQuat4f Rhs)
|
|
{
|
|
check(Lhs.GetChannelNum() == 4);
|
|
|
|
UnaryOp(Out, 4, Lhs, [Rhs](
|
|
FFrameAttribute& Out,
|
|
const FFrameAttribute& Lhs,
|
|
const TLearningArrayView<1, const int32> RangeOffsets,
|
|
const TLearningArrayView<1, const int32> RangeLengths) {
|
|
|
|
Private::QuatInvMulConstant(
|
|
Out.GetAttributeData(),
|
|
Lhs.GetAttributeData(),
|
|
Rhs);
|
|
});
|
|
}
|
|
|
|
void QuatMulInvConstant(FFrameAttribute& Out, const FFrameAttribute& Lhs, const FQuat4f Rhs)
|
|
{
|
|
check(Lhs.GetChannelNum() == 4);
|
|
|
|
UnaryOp(Out, 4, Lhs, [Rhs](
|
|
FFrameAttribute& Out,
|
|
const FFrameAttribute& Lhs,
|
|
const TLearningArrayView<1, const int32> RangeOffsets,
|
|
const TLearningArrayView<1, const int32> RangeLengths) {
|
|
|
|
Private::QuatMulInvConstant(
|
|
Out.GetAttributeData(),
|
|
Lhs.GetAttributeData(),
|
|
Rhs);
|
|
});
|
|
}
|
|
|
|
void QuatRotateConstant(FFrameAttribute& Out, const FFrameAttribute& Lhs, const FVector3f Rhs)
|
|
{
|
|
check(Lhs.GetChannelNum() == 4);
|
|
|
|
UnaryOp(Out, 3, Lhs, [Rhs](
|
|
FFrameAttribute& Out,
|
|
const FFrameAttribute& Lhs,
|
|
const TLearningArrayView<1, const int32> RangeOffsets,
|
|
const TLearningArrayView<1, const int32> RangeLengths) {
|
|
|
|
Private::QuatRotateConstant(
|
|
Out.GetAttributeData(),
|
|
Lhs.GetAttributeData(),
|
|
Rhs);
|
|
});
|
|
}
|
|
|
|
void QuatUnrotateConstant(FFrameAttribute& Out, const FFrameAttribute& Lhs, const FVector3f Rhs)
|
|
{
|
|
check(Lhs.GetChannelNum() == 4);
|
|
|
|
UnaryOp(Out, 3, Lhs, [Rhs](
|
|
FFrameAttribute& Out,
|
|
const FFrameAttribute& Lhs,
|
|
const TLearningArrayView<1, const int32> RangeOffsets,
|
|
const TLearningArrayView<1, const int32> RangeLengths) {
|
|
|
|
Private::QuatUnrotateConstant(
|
|
Out.GetAttributeData(),
|
|
Lhs.GetAttributeData(),
|
|
Rhs);
|
|
});
|
|
}
|
|
|
|
void QuatBetweenConstant(FFrameAttribute& Out, const FFrameAttribute& Lhs, const FVector3f Rhs)
|
|
{
|
|
check(Lhs.GetChannelNum() == 3);
|
|
|
|
UnaryOp(Out, 4, Lhs, [Rhs](
|
|
FFrameAttribute& Out,
|
|
const FFrameAttribute& Lhs,
|
|
const TLearningArrayView<1, const int32> RangeOffsets,
|
|
const TLearningArrayView<1, const int32> RangeLengths) {
|
|
|
|
Private::QuatBetweenConstant(
|
|
Out.GetAttributeData(),
|
|
Lhs.GetAttributeData(),
|
|
Rhs);
|
|
});
|
|
}
|
|
|
|
void QuatConstantMul(FFrameAttribute& Out, const FQuat4f Lhs, const FFrameAttribute& Rhs)
|
|
{
|
|
check(Rhs.GetChannelNum() == 4);
|
|
|
|
UnaryOp(Out, 4, Rhs, [Lhs](
|
|
FFrameAttribute& Out,
|
|
const FFrameAttribute& Rhs,
|
|
const TLearningArrayView<1, const int32> RangeOffsets,
|
|
const TLearningArrayView<1, const int32> RangeLengths) {
|
|
|
|
Private::QuatConstantMul(
|
|
Out.GetAttributeData(),
|
|
Lhs,
|
|
Rhs.GetAttributeData());
|
|
});
|
|
}
|
|
|
|
void QuatConstantDiv(FFrameAttribute& Out, const FQuat4f Lhs, const FFrameAttribute& Rhs)
|
|
{
|
|
QuatConstantMulInv(Out, Lhs, Rhs);
|
|
}
|
|
|
|
void QuatConstantInvMul(FFrameAttribute& Out, const FQuat4f Lhs, const FFrameAttribute& Rhs)
|
|
{
|
|
check(Rhs.GetChannelNum() == 4);
|
|
|
|
UnaryOp(Out, 4, Rhs, [Lhs](
|
|
FFrameAttribute& Out,
|
|
const FFrameAttribute& Rhs,
|
|
const TLearningArrayView<1, const int32> RangeOffsets,
|
|
const TLearningArrayView<1, const int32> RangeLengths) {
|
|
|
|
Private::QuatConstantInvMul(
|
|
Out.GetAttributeData(),
|
|
Lhs,
|
|
Rhs.GetAttributeData());
|
|
});
|
|
}
|
|
|
|
void QuatConstantMulInv(FFrameAttribute& Out, const FQuat4f Lhs, const FFrameAttribute& Rhs)
|
|
{
|
|
check(Rhs.GetChannelNum() == 4);
|
|
|
|
UnaryOp(Out, 4, Rhs, [Lhs](
|
|
FFrameAttribute& Out,
|
|
const FFrameAttribute& Rhs,
|
|
const TLearningArrayView<1, const int32> RangeOffsets,
|
|
const TLearningArrayView<1, const int32> RangeLengths) {
|
|
|
|
Private::QuatConstantMulInv(
|
|
Out.GetAttributeData(),
|
|
Lhs,
|
|
Rhs.GetAttributeData());
|
|
});
|
|
}
|
|
|
|
void QuatConstantRotate(FFrameAttribute& Out, const FQuat4f Lhs, const FFrameAttribute& Rhs)
|
|
{
|
|
check(Rhs.GetChannelNum() == 3);
|
|
|
|
UnaryOp(Out, 3, Rhs, [Lhs](
|
|
FFrameAttribute& Out,
|
|
const FFrameAttribute& Rhs,
|
|
const TLearningArrayView<1, const int32> RangeOffsets,
|
|
const TLearningArrayView<1, const int32> RangeLengths) {
|
|
|
|
Private::QuatConstantRotate(
|
|
Out.GetAttributeData(),
|
|
Lhs,
|
|
Rhs.GetAttributeData());
|
|
});
|
|
}
|
|
|
|
void QuatConstantUnrotate(FFrameAttribute& Out, const FQuat4f Lhs, const FFrameAttribute& Rhs)
|
|
{
|
|
check(Rhs.GetChannelNum() == 3);
|
|
|
|
UnaryOp(Out, 3, Rhs, [Lhs](
|
|
FFrameAttribute& Out,
|
|
const FFrameAttribute& Rhs,
|
|
const TLearningArrayView<1, const int32> RangeOffsets,
|
|
const TLearningArrayView<1, const int32> RangeLengths) {
|
|
|
|
Private::QuatConstantUnrotate(
|
|
Out.GetAttributeData(),
|
|
Lhs,
|
|
Rhs.GetAttributeData());
|
|
});
|
|
}
|
|
|
|
void QuatConstantBetween(FFrameAttribute& Out, const FVector3f Lhs, const FFrameAttribute& Rhs)
|
|
{
|
|
check(Rhs.GetChannelNum() == 3);
|
|
|
|
UnaryOp(Out, 4, Rhs, [Lhs](
|
|
FFrameAttribute& Out,
|
|
const FFrameAttribute& Rhs,
|
|
const TLearningArrayView<1, const int32> RangeOffsets,
|
|
const TLearningArrayView<1, const int32> RangeLengths) {
|
|
|
|
Private::QuatConstantBetween(
|
|
Out.GetAttributeData(),
|
|
Lhs,
|
|
Rhs.GetAttributeData());
|
|
});
|
|
}
|
|
|
|
void QuatMeanStd(FQuat4f& OutMean, FVector3f& OutStd, const FFrameAttribute& In)
|
|
{
|
|
check(In.GetChannelNum() == 4);
|
|
|
|
ReduceOp(In, [&OutMean, &OutStd](
|
|
const FFrameAttribute& In,
|
|
const TLearningArrayView<1, const int32> RangeOffsets,
|
|
const TLearningArrayView<1, const int32> RangeLengths) {
|
|
|
|
Private::QuatMeanStd(OutMean, OutStd, In.GetAttributeData());
|
|
});
|
|
}
|
|
|
|
}
|
|
}
|