Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Adjust complex sqrt in compiler to use the C functions (#24231)
Follow-up to PR #24127. After #24127, the new `sqrtparams` test started to fail on Mac OS X system. Upon investigating, I identified that the difference in behavior from what the test expects is due to differences in how `std::sqrt` is implemented for complex numbers in libc++ vs stdlibc++. Also, I noticed that the issue is limited to the C++ implementation of the complex square root. This PR changes the implementation to use a C implementation of complex square root since it appears to have more reliable precision. Note that this C implementation required some workarounds for `CMPLX` not being available on all systems (as with PR #24184 and #24211). In particular, `CMPLX` does not seem to be available when using `clang` on Ubuntu 23.10, even though it is available with `gcc` on that system. I filed an issue against libc++ about the problem, but in discussion there it sounds like complex `sqrt` isn't required to have any particular precision. * llvm/llvm-project#78738 Reviewed by @DanilaFe - thanks! - [x] full comm=none testing
- Loading branch information
Showing
5 changed files
with
131 additions
and
29 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,79 @@ | ||
/* | ||
* Copyright 2024 Hewlett Packard Enterprise Development LP | ||
* Other additional copyright holders may be indicated within. | ||
* | ||
* The entirety of this work is licensed under the Apache License, | ||
* Version 2.0 (the "License"); you may not use this file except | ||
* in compliance with the License. | ||
* | ||
* You may obtain a copy of the License at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS IS" BASIS, | ||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
* See the License for the specific language governing permissions and | ||
* limitations under the License. | ||
*/ | ||
|
||
#include "complex-support.h" | ||
|
||
#include <complex.h> | ||
|
||
static double complex makeDoubleComplex(double re, double im) { | ||
// Some test environments don't have a working CMPLX | ||
// so use another way to set if needed. | ||
#if defined(CMPLX) | ||
return CMPLX(re, im); | ||
#else | ||
#ifndef CHPL_DONT_USE_CMPLX_PTR_ALIASING | ||
#define cmplx_re64(c) (((double *)&(c))[0]) | ||
#define cmplx_im64(c) (((double *)&(c))[1]) | ||
double complex val; | ||
cmplx_re64(val) = re; | ||
cmplx_im64(val) = im; | ||
return val; | ||
#else | ||
// This can generate bad values in the face of inf/nan values | ||
return re + im*_Complex_I; | ||
#endif | ||
#endif | ||
} | ||
|
||
static float complex makeFloatComplex(float re, float im) { | ||
// Some test environments don't have a working CMPLXF | ||
// so use another way to set if needed. | ||
#if defined(CMPLXF) | ||
return CMPLXF(re, im); | ||
#else | ||
#ifndef CHPL_DONT_USE_CMPLX_PTR_ALIASING | ||
#define cmplx_re32(c) (((float *)&(c))[0]) | ||
#define cmplx_im32(c) (((float *)&(c))[1]) | ||
float complex val; | ||
cmplx_re32(val) = re; | ||
cmplx_im32(val) = im; | ||
return val; | ||
#else | ||
// This can generate bad values in the face of inf/nan values | ||
return re + im*_Complex_I; | ||
#endif | ||
#endif | ||
} | ||
|
||
struct complex64 complexSqrt64(struct complex64 x) { | ||
float complex c = makeFloatComplex(x.r, x.i); | ||
float complex n = csqrtf(c); | ||
struct complex64 ret; | ||
ret.r = crealf(n); | ||
ret.i = cimagf(n); | ||
return ret; | ||
} | ||
struct complex128 complexSqrt128(struct complex128 x) { | ||
double complex c = makeDoubleComplex(x.r, x.i); | ||
double complex n = csqrt(c); | ||
struct complex128 ret; | ||
ret.r = creal(n); | ||
ret.i = cimag(n); | ||
return ret; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
/* | ||
* Copyright 2024 Hewlett Packard Enterprise Development LP | ||
* Other additional copyright holders may be indicated within. | ||
* | ||
* The entirety of this work is licensed under the Apache License, | ||
* Version 2.0 (the "License"); you may not use this file except | ||
* in compliance with the License. | ||
* | ||
* You may obtain a copy of the License at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS IS" BASIS, | ||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
* See the License for the specific language governing permissions and | ||
* limitations under the License. | ||
*/ | ||
|
||
#ifndef IMMEDIATES_COMPLEX_SQRT_H | ||
#define IMMEDIATES_COMPLEX_SQRT_H | ||
|
||
/* | ||
This header exists to work around a problem with complex square root being | ||
innacurate on libc++ by using C functions to do the complex square root. | ||
*/ | ||
|
||
struct complex64 { | ||
float r; | ||
float i; | ||
}; | ||
struct complex128 { | ||
double r; | ||
double i; | ||
}; | ||
|
||
struct complex64 complexSqrt64(struct complex64 x); | ||
struct complex128 complexSqrt128(struct complex128 x); | ||
|
||
#endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters