Skip to content
Merged
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
36 changes: 36 additions & 0 deletions src/crt/dcomplex.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@

// (a + ib) + (c + id)
_Complex long double __adddc3(long double a, long double b, long double c, long double d) {
return (a + c) + (b + d) * 1.0iL;
}

// (a + ib) - (c + id)
_Complex long double __subdc3(long double a, long double b, long double c, long double d) {
return (a - c) + (b - d) * 1.0iL;
}

// (a + ib) * (c + id)
_Complex long double __muldc3(long double a, long double b, long double c, long double d) {
return (a * c - b * d) + (a * d + b * c) * 1.0iL;
}

// (a + ib) / (c + id)
// Uses stable algorithm to avoid overflow/underflow issues
_Complex long double __divdc3(long double a, long double b, long double c, long double d) {
long double r, den;
long double real, imag;

if (__builtin_fabsl(c) >= __builtin_fabsl(d)) {
r = d / c;
den = c + d * r;
real = (a + b * r) / den;
imag = (b - a * r) / den;
} else {
r = c / d;
den = d + c * r;
real = (a * r + b) / den;
imag = (b * r - a) / den;
}

return real + imag * 1.0iL;
}
36 changes: 36 additions & 0 deletions src/crt/fcomplex.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@

// (a + ib) + (c + id)
_Complex float __addsc3(float a, float b, float c, float d) {
return (a + c) + (b + d) * 1.0iF;
}

// (a + ib) - (c + id)
_Complex float __subsc3(float a, float b, float c, float d) {
return (a - c) + (b - d) * 1.0iF;
}

// (a + ib) * (c + id)
_Complex float __mulsc3(float a, float b, float c, float d) {
return (a * c - b * d) + (a * d + b * c) * 1.0iF;
}

// (a + ib) / (c + id)
// Uses stable algorithm to avoid overflow/underflow issues
_Complex float __divsc3(float a, float b, float c, float d) {
float r, den;
float real, imag;

if (__builtin_fabsf(c) >= __builtin_fabsf(d)) {
r = d / c;
den = c + d * r;
real = (a + b * r) / den;
imag = (b - a * r) / den;
} else {
r = c / d;
den = d + c * r;
real = (a * r + b) / den;
imag = (b * r - a) / den;
}

return real + imag * 1.0iF;
}
4 changes: 0 additions & 4 deletions src/libc/include/complex.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,6 @@

#else /* __cplusplus */

#ifndef __FAST_MATH__
#warning "-ffast-math is required for complex multiplication and division to work properly at this time"
#endif

#define complex _Complex

#ifdef _Imaginary
Expand Down
4 changes: 2 additions & 2 deletions test/floating_point/complex/makefile
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@ ICON = icon.png
DESCRIPTION = "CE C Toolchain Demo"
COMPRESSED = NO

CFLAGS = -Wall -Wextra -Wshadow -Wimplicit-float-conversion -Wimplicit-int-float-conversion -std=c17 -Ofast
CXXFLAGS = -Wall -Wextra -Wshadow -Wimplicit-float-conversion -Wimplicit-int-float-conversion -std=c++20 -Ofast
CFLAGS = -Wall -Wextra -Wshadow -Wimplicit-float-conversion -Wimplicit-int-float-conversion -std=c17 -Oz
CXXFLAGS = -Wall -Wextra -Wshadow -Wimplicit-float-conversion -Wimplicit-int-float-conversion -std=c++20 -Oz

HAS_MATH_ERRNO = YES
PREFER_OS_LIBC = NO
Expand Down
96 changes: 88 additions & 8 deletions test/floating_point/complex/src/complex_alias.S
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,51 @@

.section .text

.global _T_CMPLXF, _T_CMPLX, _T_CMPLXL
.global _T_creal, _T_crealf, _T_creall
.global _T_cimag, _T_cimagf, _T_cimagl
.global _T_conj, _T_conjf, _T_conjl
.global _T_CMPLXF
.type _T_CMPLXF, @function
.global _T_CMPLX
.type _T_CMPLX, @function
.global _T_CMPLXL
.type _T_CMPLXL, @function

.global _T_creal
.type _T_creal, @function
.global _T_crealf
.type _T_crealf, @function
.global _T_creall
.type _T_creall, @function

.global _T_cimag
.type _T_cimag, @function
.global _T_cimagf
.type _T_cimagf, @function
.global _T_cimagl
.type _T_cimagl, @function

.global _T_conj
.type _T_conj, @function
.global _T_conjf
.type _T_conjf, @function
.global _T_conjl
.type _T_conjl, @function

.global _T__addsc3
.type _T__addsc3, @function
.global _T__subsc3
.type _T__subsc3, @function
.global _T__mulsc3
.type _T__mulsc3, @function
.global _T__divsc3
.type _T__divsc3, @function

.global _T__adddc3
.type _T__adddc3, @function
.global _T__subdc3
.type _T__subdc3, @function
.global _T__muldc3
.type _T__muldc3, @function
.global _T__divdc3
.type _T__divdc3, @function

_T_CMPLXF:
jp _CMPLXF
Expand Down Expand Up @@ -35,7 +76,46 @@ _T_conjf:
_T_conjl:
jp _conjl

.extern _CMPLXF, _CMPLX, _CMPLXL
.extern _creal, _crealf, _creall
.extern _cimag, _cimagf, _cimagl
.extern _conj, _conjf, _conjl
_T__addsc3:
jp ___addsc3
_T__subsc3:
jp ___subsc3
_T__mulsc3:
jp ___mulsc3
_T__divsc3:
jp ___divsc3

_T__adddc3:
jp ___adddc3
_T__subdc3:
jp ___subdc3
_T__muldc3:
jp ___muldc3
_T__divdc3:
jp ___divdc3

.extern _CMPLXF
.extern _CMPLX
.extern _CMPLXL

.extern _creal
.extern _crealf
.extern _creall

.extern _cimag
.extern _cimagf
.extern _cimagl

.extern _conj
.extern _conjf
.extern _conjl

.extern ___addsc3
.extern ___subsc3
.extern ___mulsc3
.extern ___divsc3

.extern ___adddc3
.extern ___subdc3
.extern ___muldc3
.extern ___divdc3
44 changes: 44 additions & 0 deletions test/floating_point/complex/src/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,16 @@ double _Complex T_conj(double _Complex);
float _Complex T_conjf(float _Complex);
long double _Complex T_conjl(long double _Complex);

_Complex float T__addsc3(float a, float b, float c, float d);
_Complex float T__subsc3(float a, float b, float c, float d);
_Complex float T__mulsc3(float a, float b, float c, float d);
_Complex float T__divsc3(float a, float b, float c, float d);

_Complex long double T__adddc3(long double a, long double b, long double c, long double d);
_Complex long double T__subdc3(long double a, long double b, long double c, long double d);
_Complex long double T__muldc3(long double a, long double b, long double c, long double d);
_Complex long double T__divdc3(long double a, long double b, long double c, long double d);

static size_t run_test(void) {
/* test float _Complex without any Clang chicanery */
{
Expand Down Expand Up @@ -184,6 +194,40 @@ static size_t run_test(void) {
if (cimagl(c64.c) != -CF64_RE) { return __LINE__; }
}

/* test that float complex CRT functions work */
{
complex float val;
val = T__addsc3(1.0f, 2.0f, 4.0f, 8.0f);
if (crealf(val) != 5.0f) { return __LINE__; }
if (cimagf(val) != 10.0f) { return __LINE__; }
val = T__subsc3(1.0f, 2.0f, 4.0f, 8.0f);
if (crealf(val) != -3.0f) { return __LINE__; }
if (cimagf(val) != -6.0f) { return __LINE__; }
val = T__mulsc3(3.0f, 2.0f, 0.25f, -4.0f);
if (crealf(val) != 8.75f) { return __LINE__; }
if (cimagf(val) != -11.5f) { return __LINE__; }
val = T__divsc3(-4.0f, 8.0f, -2.0f, 2.0f);
if (crealf(val) != 3.0f) { return __LINE__; }
if (cimagf(val) != -1.0f) { return __LINE__; }
}

/* test that long double complex CRT functions work */
{
complex long double val;
val = T__adddc3(1.0L, 2.0L, 4.0L, 8.0L);
if (creall(val) != 5.0L) { return __LINE__; }
if (cimagl(val) != 10.0L) { return __LINE__; }
val = T__subdc3(1.0L, 2.0L, 4.0L, 8.0L);
if (creall(val) != -3.0L) { return __LINE__; }
if (cimagl(val) != -6.0L) { return __LINE__; }
val = T__muldc3(3.0L, 2.0L, 0.25L, -4.0L);
if (creall(val) != 8.75L) { return __LINE__; }
if (cimagl(val) != -11.5L) { return __LINE__; }
val = T__divdc3(-4.0L, 8.0L, -2.0L, 2.0L);
if (creall(val) != 3.0L) { return __LINE__; }
if (cimagl(val) != -1.0L) { return __LINE__; }
}

/* passed all */
return SIZE_MAX;
}
Expand Down
Loading