Skip to content

GitLab

  • Menu
Projects Groups Snippets
  • Help
    • Help
    • Support
    • Community forum
    • Submit feedback
    • Contribute to GitLab
  • Sign in
  • tnl-dev tnl-dev
  • Project information
    • Project information
    • Activity
    • Labels
    • Members
  • Repository
    • Repository
    • Files
    • Commits
    • Branches
    • Tags
    • Contributors
    • Graph
    • Compare
  • Issues 36
    • Issues 36
    • List
    • Boards
    • Service Desk
    • Milestones
  • Merge requests 4
    • Merge requests 4
  • Deployments
    • Deployments
    • Releases
  • Analytics
    • Analytics
    • Value stream
    • Repository
  • Snippets
    • Snippets
  • Activity
  • Graph
  • Create a new issue
  • Commits
  • Issue Boards
Collapse sidebar
  • TNL
  • tnl-devtnl-dev
  • Issues
  • #79

Closed
Open
Created Jul 11, 2020 by Tomáš Jakubec@jakubecDeveloper

StaticComparison bug

Testing the following code:

#include <iostream>
#include <GTMesh/Debug/Debug.h>
#include <TNL/Containers/StaticVector.h>
#include <TNL/Containers/Vector.h>
using namespace std;
template<int Dim, typename Real>
struct std::numeric_limits<TNL::Containers::StaticVector<Dim, Real>>{
    static constexpr bool is_specialized = true;

    static TNL::Containers::StaticVector<Dim, Real> max(){
        TNL::Containers::StaticVector<Dim, Real> res;
        res = std::numeric_limits<Real>::max();
        return res;
    }
    static TNL::Containers::StaticVector<Dim, Real> lowest(){
        TNL::Containers::StaticVector<Dim, Real> res;
        res = std::numeric_limits<Real>::lowest();
        return res;
    }
};


using namespace TNL;

int main()
{
    TNL::Containers::Vector<TNL::Containers::StaticVector<3,int>, TNL::Devices::Host, size_t> a;

    a.setSize(2);
    a[0] = TNL::Containers::StaticVector<3,int>{5,-3,6};
    a[1] = TNL::Containers::StaticVector<3,int>{8, 1, -5};
    TNL::Containers::StaticVector<3,int> a1 = a[0];
    TNL::Containers::StaticVector<3,int> a2 = a[1];


    DBGVAR(a);                    // == ..\lookup_problem\main.cpp << 36 >> [[ a ]] ==> [ [ 5, -3, 6 ], [ 8, 1, -5 ] ]
    DBGVAR((a1 < a2), (a2 < a1)); // == ..\lookup_problem\main.cpp << 37 >> [[ (a1 < a2) ]] ==> false
                                  // == ..\lookup_problem\main.cpp << 37 >> [[ (a2 < a1) ]] ==> false
    DBGVAR(min(a));               // == ..\lookup_problem\main.cpp << 39 >> [[ min(a) ]] ==> [ 5, -3, -5 ]
    DBGVAR(min(a1,a2), min(a2,a1));// == ..\lookup_problem\main.cpp << 40 >> [[ min(a1,a2) ]] ==> [ 5, -3, 6 ]
                                  // == ..\lookup_problem\main.cpp << 40 >> [[ min(a2,a1) ]] ==> [ 8, 1, -5 ]
    DBGVAR(TNL::min(a1, a2));     // == ..\lookup_problem\main.cpp << 42 >> [[ TNL::min(a1, a2) ]] ==> [ 5, -3, -5 ]
    return 0;
}

The first problem is the comparison of a1 and a2. If the (a1 < a2) is false the (a2 < a1) must be true. However in both cases, the result is false, which is incorrect. The comparison utilizes the StaticCompare::LT defined as:

__cuda_callable__
static bool LT( const T1& a, const T2& b )
{
  TNL_ASSERT_EQ( a.getSize(), b.getSize(), "Sizes of expressions to be compared do not fit." );
  for( int i = 0; i < a.getSize(); i++ )
     if( ! (a[ i ] < b[ i ]) )
        return false;
  return true;
}

This function does not realize a suitable comparison, e.g., lexicographical.

Secondly, there is a difference in call of min. Both min(a) and TNL::min(a1, a2) utilize StaticBinaryExpressionTemplate< ET1, ET2, Min >, which results in retuning a vector with minimum in each element separately (which is awesome). However, min(a1, a2) min from stl is called (the std::min is prioritized over TNL::Containers::Expressions::min) and it employs StaticCompare::LT through operator<. This problem is solved by removing using namespace std (which is partialy my mistake, but worth mentioning). The incorrect implementation of StaticCompare::LT results in dependency of the result on the order of the arguments of min.

The macro DBGVAR is defined in the GTMesh library.

Assignee
Assign to
Time tracking