bool VectorType::CompareNotEqual(VectorType v) { return !CompareEqual(v); }
Vec4 ClusterFit::SolveLeastSquares( Vec4& start, Vec4& end ) const { // accumulate all the quantities we need int const count = m_colours->GetCount(); Vec4 alpha2_sum = VEC4_CONST( 0.0f ); Vec4 beta2_sum = VEC4_CONST( 0.0f ); Vec4 alphabeta_sum = VEC4_CONST( 0.0f ); Vec4 alphax_sum = VEC4_CONST( 0.0f ); Vec4 betax_sum = VEC4_CONST( 0.0f ); for( int i = 0; i < count; ++i ) { Vec4 alpha = m_alpha[i]; Vec4 beta = m_beta[i]; Vec4 x = m_weighted[i]; alpha2_sum = MultiplyAdd( alpha, alpha, alpha2_sum ); beta2_sum = MultiplyAdd( beta, beta, beta2_sum ); alphabeta_sum = MultiplyAdd( alpha, beta, alphabeta_sum ); alphax_sum = MultiplyAdd( alpha, x, alphax_sum ); betax_sum = MultiplyAdd( beta, x, betax_sum ); } // select the results Vec4 const zero = VEC4_CONST( 0.0f ); Vec4 beta2_sum_zero = CompareEqual( beta2_sum, zero ); Vec4 alpha2_sum_zero = CompareEqual( alpha2_sum, zero ); Vec4 a1 = alphax_sum*Reciprocal( alpha2_sum ); Vec4 b1 = betax_sum*Reciprocal( beta2_sum ); Vec4 factor = Reciprocal( NegativeMultiplySubtract( alphabeta_sum, alphabeta_sum, alpha2_sum*beta2_sum ) ); Vec4 a2 = NegativeMultiplySubtract( betax_sum, alphabeta_sum, alphax_sum*beta2_sum )*factor; Vec4 b2 = NegativeMultiplySubtract( alphax_sum, alphabeta_sum, betax_sum*alpha2_sum )*factor; Vec4 a = Select( Select( a2, a1, beta2_sum_zero ), zero, alpha2_sum_zero ); Vec4 b = Select( Select( b2, b1, alpha2_sum_zero ), zero, beta2_sum_zero ); // clamp the output to [0, 1] Vec4 const one = VEC4_CONST( 1.0f ); Vec4 const half = VEC4_CONST( 0.5f ); a = Min( one, Max( zero, a ) ); b = Min( one, Max( zero, b ) ); // clamp to the grid Vec4 const grid( 31.0f, 63.0f, 31.0f, 0.0f ); Vec4 const gridrcp( 1.0f/31.0f, 1.0f/63.0f, 1.0f/31.0f, 0.0f ); Vec4 const onethird = VEC4_CONST( 1.0f/3.0f ); Vec4 const twothirds = VEC4_CONST( 2.0f/3.0f ); a = Truncate( MultiplyAdd( grid, a, half ) )*gridrcp; b = Truncate( MultiplyAdd( grid, b, half ) )*gridrcp; // compute the error Vec4 const two = VEC4_CONST( 2.0 ); Vec4 e1 = MultiplyAdd( b*b, beta2_sum, m_xxsum ); Vec4 e2 = MultiplyAdd( a, alphax_sum, b*betax_sum ); Vec4 e3 = MultiplyAdd( a*a, alpha2_sum, e1 ); Vec4 e4 = MultiplyAdd( a*b*alphabeta_sum - e2, two, e3 ); // apply the metric to the error term Vec4 e5 = e4*m_metricSqr; Vec4 error = e5.SplatX() + e5.SplatY() + e5.SplatZ(); // save the start and end start = a; end = b; return error; }
//static bool FJsonValue::CompareEqual( const FJsonValue& Lhs, const FJsonValue& Rhs ) { if (Lhs.Type != Rhs.Type) { return false; } switch (Lhs.Type) { case EJson::None: case EJson::Null: return true; case EJson::String: return Lhs.AsString() == Rhs.AsString(); case EJson::Number: return Lhs.AsNumber() == Rhs.AsNumber(); case EJson::Boolean: return Lhs.AsBool() == Rhs.AsBool(); case EJson::Array: { const TArray< TSharedPtr<FJsonValue> >& LhsArray = Lhs.AsArray(); const TArray< TSharedPtr<FJsonValue> >& RhsArray = Rhs.AsArray(); if (LhsArray.Num() != RhsArray.Num()) { return false; } // compare each element for (int32 i = 0; i < LhsArray.Num(); ++i) { if (!CompareEqual(*LhsArray[i], *RhsArray[i])) { return false; } } } return true; case EJson::Object: { const TSharedPtr<FJsonObject>& LhsObject = Lhs.AsObject(); const TSharedPtr<FJsonObject>& RhsObject = Rhs.AsObject(); if (LhsObject.IsValid() != RhsObject.IsValid()) { return false; } if (LhsObject.IsValid()) { if (LhsObject->Values.Num() != RhsObject->Values.Num()) { return false; } // compare each element for (const auto& It : LhsObject->Values) { const FString& Key = It.Key; const TSharedPtr<FJsonValue>* RhsValue = RhsObject->Values.Find(Key); if (RhsValue == NULL) { // not found in both objects return false; } const TSharedPtr<FJsonValue>& LhsValue = It.Value; if (LhsValue.IsValid() != RhsValue->IsValid()) { return false; } if (LhsValue.IsValid()) { if (!CompareEqual(*LhsValue.Get(), *RhsValue->Get())) { return false; } } } } } return true; default: return false; } }