Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -345,7 +345,7 @@ class Do_intersect_3

double aprz = CGAL::abs(prz);
double apsz = CGAL::abs(psz);
#ifdef CGAL_USE_SSE2_MAX
#if defined CGAL_USE_SSE2_MAX || defined CGAL_USE_NEON_MAX
CGAL::Max<double> mmax;

maxx = mmax(maxx, aprx, apsx);
Expand All @@ -365,14 +365,14 @@ class Do_intersect_3

double eps = 5.1107127829973299e-15 * maxx * maxy * maxz;

#ifdef CGAL_USE_SSE2_MAX
#if defined CGAL_USE_SSE2_MAX || defined CGAL_USE_NEON_MAX
#if 0
CGAL::Min<double> mmin;
double tmp = mmin(maxx, maxy, maxz);
maxz = mmax(maxx, maxy, maxz);
maxx = tmp;
#else
sse2minmax(maxx,maxy,maxz);
simd_minmax(maxx,maxy,maxz);
// maxy can contain ANY element
#endif
#else
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ class Orientation_3

double aprz = CGAL::abs(prz);
double apsz = CGAL::abs(psz);
#ifdef CGAL_USE_SSE2_MAX
#if defined CGAL_USE_SSE2_MAX || defined CGAL_USE_NEON_MAX
CGAL::Max<double> mmax;

maxx = mmax(maxx, aprx, apsx);
Expand All @@ -105,14 +105,14 @@ class Orientation_3

double eps = 5.1107127829973299e-15 * maxx * maxy * maxz;

#ifdef CGAL_USE_SSE2_MAX
#if defined CGAL_USE_SSE2_MAX || defined CGAL_USE_NEON_MAX
#if 0
CGAL::Min<double> mmin;
double tmp = mmin(maxx, maxy, maxz);
maxz = mmax(maxx, maxy, maxz);
maxx = tmp;
#else
sse2minmax(maxx,maxy,maxz);
simd_minmax(maxx,maxy,maxz);
// maxy can contain ANY element
#endif
#else
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ class Side_of_oriented_sphere_3
double artz = CGAL::abs(rtz);
double astz = CGAL::abs(stz);

#ifdef CGAL_USE_SSE2_MAX
#if defined CGAL_USE_SSE2_MAX || defined CGAL_USE_NEON_MAX
CGAL::Max<double> mmax;
maxx = mmax(maxx, aqtx, artx, astx);
maxy = mmax(maxy, aqty, arty, asty);
Expand All @@ -107,14 +107,14 @@ class Side_of_oriented_sphere_3

double eps = 1.2466136531027298e-13 * maxx * maxy * maxz;

#ifdef CGAL_USE_SSE2_MAX
#if defined CGAL_USE_SSE2_MAX || defined CGAL_USE_NEON_MAX
/*
CGAL::Min<double> mmin;
double tmp = mmin(maxx, maxy, maxz);
maxz = mmax(maxx, maxy, maxz);
maxx = tmp;
*/
sse2minmax(maxx,maxy,maxz);
simd_minmax(maxx,maxy,maxz);
// maxy can contain ANY element

#else
Expand Down
6 changes: 3 additions & 3 deletions Mesh_3/include/CGAL/Mesh_3/Robust_intersection_traits_3.h
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,7 @@ struct Vector_plane_orientation_3_static_filter :
double aprz = CGAL::abs(acz);
double apsz = CGAL::abs(pqz);

#ifdef CGAL_USE_SSE2_MAX
#if defined CGAL_USE_SSE2_MAX || defined CGAL_USE_NEON_MAX
CGAL::Max<double> mmax;

maxx = mmax(maxx, aprx, apsx);
Expand All @@ -140,14 +140,14 @@ struct Vector_plane_orientation_3_static_filter :

double eps = 5.1107127829973299e-15 * maxx * maxy * maxz;

#ifdef CGAL_USE_SSE2_MAX
#if defined CGAL_USE_SSE2_MAX || defined CGAL_USE_NEON_MAX
#if 0
CGAL::Min<double> mmin;
double tmp = mmin(maxx, maxy, maxz);
maxz = mmax(maxx, maxy, maxz);
maxx = tmp;
#else
sse2minmax(maxx,maxy,maxz);
simd_minmax(maxx,maxy,maxz);
// maxy can contain ANY element
#endif
#else
Expand Down
72 changes: 70 additions & 2 deletions Number_types/include/CGAL/FPU.h
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,9 @@ extern "C" {
# else
# include <cfloat>
# endif
#elif defined _MSC_VER && defined _M_ARM64
// MSVC on ARM64: _controlfp_s is x86-only; fenv.h is the correct interface.
# include <fenv.h>
#elif defined _MSC_VER || defined __sparc__ || \
(defined __i386__ && !defined __PGI && !defined __SUNPRO_CC \
&& !defined __SSE2__)
Expand Down Expand Up @@ -119,6 +122,15 @@ extern "C" {
!defined CGAL_ALWAYS_ROUND_TO_NEAREST
# define CGAL_USE_SSE2 1
#endif

#if defined(__aarch64__) || defined(_M_ARM64)
# include <arm_neon.h>
# define CGAL_HAS_NEON 1
#endif

#if defined(CGAL_HAS_NEON) && !defined(CGAL_ALWAYS_ROUND_TO_NEAREST)
# define CGAL_USE_NEON 1
#endif
#ifdef CGAL_CFG_DENORMALS_COMPILE_BUG
double& get_static_minimin(); // Defined in Interval_arithmetic_impl.h
#endif
Expand Down Expand Up @@ -283,7 +295,49 @@ inline __m128d swap_m128d(__m128d x){
return _mm_shuffle_pd(x, x, 1);
# endif
}
#endif // CGAL_USE_SSE2

// NEON opacify & swap helpers
#ifdef CGAL_USE_NEON

// Prevent the compiler from reordering or constant-folding across a
// fesetround() boundary, same role as IA_opacify128 on SSE2.
inline float64x2_t IA_opacify_neon(float64x2_t x)
{
#if defined __GNUG__ || defined __clang__
// "+w" pins the value in a NEON/FP register.
asm volatile ("" : "+w"(x));
return x;
#else
// MSVC on ARM64: no inline asm available.
// We use the same volatile+memcpy.
volatile float64x2_t e = x;
std::memcpy(&x, (void*)&e, 16);
Comment on lines +314 to +315

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🤞 that this still works...

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I tested this with sample code with compiler explorer. MSVC and GCC produce identical results. The MSVC fallback emits a real memory store/load, matching GCC's behavior for the volatile-copy implementation.

return x;
#endif
}

// Weaker barrier: blocks algebraic reassociation but not fesetround migration.
inline float64x2_t IA_opacify_neon_weak(float64x2_t x)
{
#if defined __GNUG__ || defined __clang__
asm ("" : "+mw"(x));
return x;
#else
// MSVC: fall back to the strong barrier; no weaker option without asm.
return IA_opacify_neon(x);
#endif
}

// Swap the two double lanes: {a, b} -> {b, a}
// Counterpart of swap_m128d(). vextq_f64 with offset 1 rotates the two
// 64-bit elements, which on a 2-element vector is equivalent to a swap.
inline float64x2_t swap_f64x2(float64x2_t x)
{
return vextq_f64(x, x, 1);
}

#endif // CGAL_USE_NEON

// Interval arithmetic needs to protect against double-rounding effects
// caused by excess FPU precision, even if it forces the 53bit mantissa
Expand Down Expand Up @@ -365,7 +419,20 @@ inline double CGAL_IA_SQUARE(double a){
double b = CGAL_IA_STOP_CPROP(a); // only once
return IA_up(b*b);
}
#if defined CGAL_SAFE_SSE2

// Handle MSVC ARM64 first because SSE2 intrinsics and _controlfp_s are x86-only.
// This prevents ARM64 from incorrectly selecting unsupported x86 code paths.
#if defined ( _MSC_VER ) && defined ( _M_ARM64 )
// MSVC on ARM64: <fenv.h> is already included at the top of this file.
#define CGAL_IA_SETFPCW(CW) fesetround(CW)
#define CGAL_IA_GETFPCW(CW) CW = fegetround()
typedef int FPU_CW_t;
#define CGAL_FE_TONEAREST FE_TONEAREST
#define CGAL_FE_TOWARDZERO FE_TOWARDZERO
#define CGAL_FE_UPWARD FE_UPWARD
#define CGAL_FE_DOWNWARD FE_DOWNWARD

#elif defined CGAL_SAFE_SSE2

#define CGAL_IA_SETFPCW(CW) _MM_SET_ROUNDING_MODE(CW)
#define CGAL_IA_GETFPCW(CW) CW = _MM_GET_ROUNDING_MODE()
Expand Down Expand Up @@ -430,7 +497,8 @@ typedef unsigned int FPU_CW_t;
#define CGAL_FE_UPWARD FP_RND_RP
#define CGAL_FE_DOWNWARD FP_RND_RM

#elif defined ( _MSC_VER )
#elif defined ( _MSC_VER ) && !defined ( _M_ARM64 )
// x86/x64 MSVC only: _controlfp_s is not available on ARM64.
#if ( _MSC_VER < 1400)
#define CGAL_IA_SETFPCW(CW) _controlfp (CW, _MCW_RC )
#define CGAL_IA_GETFPCW(CW) CW = _controlfp (0, 0 ) & _MCW_RC
Expand Down
Loading
Loading