Skip to content
GitLab
  • Menu
Projects Groups Snippets
  • Help
    • Help
    • Support
    • Community forum
    • Submit feedback
    • Contribute to GitLab
    • Switch to GitLab Next
  • Sign in / Register
  • eigen eigen
  • Project information
    • Project information
    • Activity
    • Labels
    • Members
  • Repository
    • Repository
    • Files
    • Commits
    • Branches
    • Tags
    • Contributors
    • Graph
    • Compare
    • Locked Files
  • Issues 653
    • Issues 653
    • List
    • Boards
    • Service Desk
    • Milestones
    • Iterations
    • Requirements
  • Custom issue tracker
    • Custom issue tracker
  • Merge requests 17
    • Merge requests 17
  • CI/CD
    • CI/CD
    • Pipelines
    • Jobs
    • Schedules
    • Test Cases
  • Deployments
    • Deployments
    • Environments
    • Releases
  • Packages & Registries
    • Packages & Registries
    • Package Registry
    • Container Registry
    • Infrastructure Registry
  • Monitor
    • Monitor
    • Incidents
  • Analytics
    • Analytics
    • Value stream
    • CI/CD
    • Code review
    • Insights
    • Issue
    • Repository
  • Snippets
    • Snippets
  • Activity
  • Graph
  • Create a new issue
  • Jobs
  • Commits
  • Issue Boards
Collapse sidebar
  • libeigen
  • eigeneigen
  • Issues
  • #2263
Closed
Open
Created May 26, 2021 by sarah@kitegi

usage of signed zeros leads to wrong results with -ffast-math

found in files:

Eigen/src/Geometry/arch/Geometry_SIMD.h
Eigen/src/Core/arch/MSA/MathFunctions.h
Eigen/src/Core/arch/Default/GenericPacketMathFunctions.h
Eigen/src/Core/arch/ZVector/PacketMath.h
Eigen/src/Core/arch/AltiVec/PacketMath.h
Eigen/src/Core/arch/NEON/PacketMath.h
Eigen/src/LU/arch/InverseSize4.h

this was the buggy program that led to discovering this

#include <Eigen/Core>
#include <Eigen/LU>
#include <iostream>

using std::cout;
using std::endl;

int main() {
  Eigen::Matrix<double, 4, 4, Eigen::RowMajor> M;
  M << 1.275, 0, 0, 0, 0, 0.910, 0, -0, 0, -0.159, 0.923, 0, 0, -0.137, -0.137,
      0.934;

  Eigen::Matrix<double, 4, 4, Eigen::RowMajor> Minv = M.inverse();

  cout << "M:" << endl;
  cout << M << endl << endl;
  cout << "Minv:" << endl;
  cout << Minv << endl << endl;
  cout << "M*Minv:" << endl;
  cout << M * Minv << endl << endl;
}

the result ends up being wrong when compiled on g++-{9,10} -O3 -DNDEBUG -ffast-math
i believe this is due to the reliance on bit tricks for flipping the signs of floats in InverseSize4.h

    const double sign_mask1[2] = {0.0, -0.0};
    const double sign_mask2[2] = {-0.0, 0.0};
    const Packet2d sign_PN = pset<Packet2d>(sign_mask1);
    const Packet2d sign_NP = pset<Packet2d>(sign_mask2);
    d1 = pxor(rd, sign_PN);
    d2 = pxor(rd, sign_NP);
    // printing d1 and d2 at this point shows them to be equal
    // since the compiler can ignore the signs on zeros,
    // and ends up using `sign_PN` for both
Assignee
Assign to
Time tracking