| author | |
| committer | |
| log | d0b39c7f2b95522c262a92b97bf5654721ace1c7 |
| tree | 5e2b0a6739be02cb6c61d9b5f23723c298d085a1 |
| parent | c38f9336a3157ae863a795b005db670c6cc04906 |
First time contribution.
Implements hypot for libzigc #30978.
Commands i run:
```
$ stage3/bin/zig build -p stage4 -Denable-llvm -Dno-lib
$ stage4/bin/zig build test-libc -Dlibc-test-path=../../libc-test -Dtest-filter=hypot --summary line -fqemu -fwasmtime
Build Summary: 725/737 steps succeeded (12 skipped)
```
I also changed std.math.hypot becuase some libc-tests raised fp exceptions. Example:
```
../../libc-test/src/math/special/hypot.h:8: bad fp exception: RN hypot(0x1p-1074,0x0p+0)=0x1p-1074, want 0 got INEXACT|UNDERFLOW
../../libc-test/src/math/special/hypot.h:9: bad fp exception: RN hypot(0x1p-1074,-0x0p+0)=0x1p-1074, want 0 got INEXACT|UNDERFLOW
```
I also run this command as a quick sanity check:
```
$ stage4/bin/zig build test-std -Dtest-filter=hypot -Dtest-target-filter=x86_64-linux-musl --summary line
Build Summary: 5/5 steps succeeded; 136/136 tests passed
```
Reviewed-on: https://codeberg.org/ziglang/zig/pulls/31104
Reviewed-by: Andrew Kelley <andrew@ziglang.org>
Co-authored-by: Pivok <pivoc@protonmail.com>
Co-committed-by: Pivok <pivoc@protonmail.com>6 files changed, 9 insertions(+), 119 deletions(-)
lib/c/math.zig+5| ... | @@ -41,6 +41,7 @@ comptime { | ... | @@ -41,6 +41,7 @@ comptime { |
| 41 | @export(&atanl, .{ .name = "atanl", .linkage = common.linkage, .visibility = common.visibility }); | 41 | @export(&atanl, .{ .name = "atanl", .linkage = common.linkage, .visibility = common.visibility }); |
| 42 | @export(&cbrt, .{ .name = "cbrt", .linkage = common.linkage, .visibility = common.visibility }); | 42 | @export(&cbrt, .{ .name = "cbrt", .linkage = common.linkage, .visibility = common.visibility }); |
| 43 | @export(&cbrtf, .{ .name = "cbrtf", .linkage = common.linkage, .visibility = common.visibility }); | 43 | @export(&cbrtf, .{ .name = "cbrtf", .linkage = common.linkage, .visibility = common.visibility }); |
| 44 | @export(&hypot, .{ .name = "hypot", .linkage = common.linkage, .visibility = common.visibility }); | ||
| 44 | @export(&pow, .{ .name = "pow", .linkage = common.linkage, .visibility = common.visibility }); | 45 | @export(&pow, .{ .name = "pow", .linkage = common.linkage, .visibility = common.visibility }); |
| 45 | } | 46 | } |
| 46 | 47 | ||
| ... | @@ -118,6 +119,10 @@ fn cbrtf(x: f32) callconv(.c) f32 { | ... | @@ -118,6 +119,10 @@ fn cbrtf(x: f32) callconv(.c) f32 { |
| 118 | return math.cbrt(x); | 119 | return math.cbrt(x); |
| 119 | } | 120 | } |
| 120 | 121 | ||
| 122 | fn hypot(x: f64, y: f64) callconv(.c) f64 { | ||
| 123 | return math.hypot(x, y); | ||
| 124 | } | ||
| 125 | |||
| 121 | fn pow(x: f64, y: f64) callconv(.c) f64 { | 126 | fn pow(x: f64, y: f64) callconv(.c) f64 { |
| 122 | return math.pow(f64, x, y); | 127 | return math.pow(f64, x, y); |
| 123 | } | 128 | } |
lib/libc/musl/src/math/hypot.c deleted-67| ... | @@ -1,67 +0,0 @@ | ||
| 1 | #include <math.h> | ||
| 2 | #include <stdint.h> | ||
| 3 | #include <float.h> | ||
| 4 | |||
| 5 | #if FLT_EVAL_METHOD > 1U && LDBL_MANT_DIG == 64 | ||
| 6 | #define SPLIT (0x1p32 + 1) | ||
| 7 | #else | ||
| 8 | #define SPLIT (0x1p27 + 1) | ||
| 9 | #endif | ||
| 10 | |||
| 11 | static void sq(double_t *hi, double_t *lo, double x) | ||
| 12 | { | ||
| 13 | 	double_t xh, xl, xc; | ||
| 14 | |||
| 15 | 	xc = (double_t)x*SPLIT; | ||
| 16 | 	xh = x - xc + xc; | ||
| 17 | 	xl = x - xh; | ||
| 18 | 	*hi = (double_t)x*x; | ||
| 19 | 	*lo = xh*xh - *hi + 2*xh*xl + xl*xl; | ||
| 20 | } | ||
| 21 | |||
| 22 | double hypot(double x, double y) | ||
| 23 | { | ||
| 24 | 	union {double f; uint64_t i;} ux = {x}, uy = {y}, ut; | ||
| 25 | 	int ex, ey; | ||
| 26 | 	double_t hx, lx, hy, ly, z; | ||
| 27 | |||
| 28 | 	/* arrange |x| >= |y| */ | ||
| 29 | 	ux.i &= -1ULL>>1; | ||
| 30 | 	uy.i &= -1ULL>>1; | ||
| 31 | 	if (ux.i < uy.i) { | ||
| 32 | 		ut = ux; | ||
| 33 | 		ux = uy; | ||
| 34 | 		uy = ut; | ||
| 35 | 	} | ||
| 36 | |||
| 37 | 	/* special cases */ | ||
| 38 | 	ex = ux.i>>52; | ||
| 39 | 	ey = uy.i>>52; | ||
| 40 | 	x = ux.f; | ||
| 41 | 	y = uy.f; | ||
| 42 | 	/* note: hypot(inf,nan) == inf */ | ||
| 43 | 	if (ey == 0x7ff) | ||
| 44 | 		return y; | ||
| 45 | 	if (ex == 0x7ff || uy.i == 0) | ||
| 46 | 		return x; | ||
| 47 | 	/* note: hypot(x,y) ~= x + y*y/x/2 with inexact for small y/x */ | ||
| 48 | 	/* 64 difference is enough for ld80 double_t */ | ||
| 49 | 	if (ex - ey > 64) | ||
| 50 | 		return x + y; | ||
| 51 | |||
| 52 | 	/* precise sqrt argument in nearest rounding mode without overflow */ | ||
| 53 | 	/* xh*xh must not overflow and xl*xl must not underflow in sq */ | ||
| 54 | 	z = 1; | ||
| 55 | 	if (ex > 0x3ff+510) { | ||
| 56 | 		z = 0x1p700; | ||
| 57 | 		x *= 0x1p-700; | ||
| 58 | 		y *= 0x1p-700; | ||
| 59 | 	} else if (ey < 0x3ff-450) { | ||
| 60 | 		z = 0x1p-700; | ||
| 61 | 		x *= 0x1p700; | ||
| 62 | 		y *= 0x1p700; | ||
| 63 | 	} | ||
| 64 | 	sq(&hx, &lx, x); | ||
| 65 | 	sq(&hy, &ly, y); | ||
| 66 | 	return z*sqrt(ly+lx+hy+hx); | ||
| 67 | } | ||
lib/libc/musl/src/math/i386/hypot.s deleted-45| ... | @@ -1,45 +0,0 @@ | ||
| 1 | .global hypot | ||
| 2 | .type hypot,@function | ||
| 3 | hypot: | ||
| 4 | 	mov 8(%esp),%eax | ||
| 5 | 	mov 16(%esp),%ecx | ||
| 6 | 	add %eax,%eax | ||
| 7 | 	add %ecx,%ecx | ||
| 8 | 	and %eax,%ecx | ||
| 9 | 	cmp $0xffe00000,%ecx | ||
| 10 | 	jae 2f | ||
| 11 | 	or 4(%esp),%eax | ||
| 12 | 	jnz 1f | ||
| 13 | 	fldl 12(%esp) | ||
| 14 | 	fabs | ||
| 15 | 	ret | ||
| 16 | 1:	mov 16(%esp),%eax | ||
| 17 | 	add %eax,%eax | ||
| 18 | 	or 12(%esp),%eax | ||
| 19 | 	jnz 1f | ||
| 20 | 	fldl 4(%esp) | ||
| 21 | 	fabs | ||
| 22 | 	ret | ||
| 23 | 1:	fldl 4(%esp) | ||
| 24 | 	fld %st(0) | ||
| 25 | 	fmulp | ||
| 26 | 	fldl 12(%esp) | ||
| 27 | 	fld %st(0) | ||
| 28 | 	fmulp | ||
| 29 | 	faddp | ||
| 30 | 	fsqrt | ||
| 31 | 	ret | ||
| 32 | 2:	sub $0xffe00000,%eax | ||
| 33 | 	or 4(%esp),%eax | ||
| 34 | 	jnz 1f | ||
| 35 | 	fldl 4(%esp) | ||
| 36 | 	fabs | ||
| 37 | 	ret | ||
| 38 | 1:	mov 16(%esp),%eax | ||
| 39 | 	add %eax,%eax | ||
| 40 | 	sub $0xffe00000,%eax | ||
| 41 | 	or 12(%esp),%eax | ||
| 42 | 	fldl 12(%esp) | ||
| 43 | 	jnz 1f | ||
| 44 | 	fabs | ||
| 45 | 1:	ret | ||
lib/std/math/hypot.zig+4-4| ... | @@ -6,10 +6,10 @@ const isNan = math.isNan; | ... | @@ -6,10 +6,10 @@ const isNan = math.isNan; |
| 6 | const isInf = math.isInf; | 6 | const isInf = math.isInf; |
| 7 | const inf = math.inf; | 7 | const inf = math.inf; |
| 8 | const nan = math.nan; | 8 | const nan = math.nan; |
| 9 | const floatEpsAt = math.floatEpsAt; | ||
| 10 | const floatEps = math.floatEps; | 9 | const floatEps = math.floatEps; |
| 11 | const floatMin = math.floatMin; | 10 | const floatMin = math.floatMin; |
| 12 | const floatMax = math.floatMax; | 11 | const floatMax = math.floatMax; |
| 12 | const floatTrueMin = math.floatTrueMin; | ||
| 13 | 13 | ||
| 14 | /// Returns sqrt(x * x + y * y), avoiding unnecessary overflow and underflow. | 14 | /// Returns sqrt(x * x + y * y), avoiding unnecessary overflow and underflow. |
| 15 | /// | 15 | /// |
| ... | @@ -30,8 +30,7 @@ pub fn hypot(x: anytype, y: anytype) @TypeOf(x, y) { | ... | @@ -30,8 +30,7 @@ pub fn hypot(x: anytype, y: anytype) @TypeOf(x, y) { |
| 30 | } | 30 | } |
| 31 | const lower = @sqrt(floatMin(T)); | 31 | const lower = @sqrt(floatMin(T)); |
| 32 | const upper = @sqrt(floatMax(T) / 2); | 32 | const upper = @sqrt(floatMax(T) / 2); |
| 33 | const incre = @sqrt(floatEps(T) / 2); | 33 | const scale = floatTrueMin(T) * upper; |
| 34 | const scale = floatEpsAt(T, incre); | ||
| 35 | const hypfn = if (emulateFma(T)) hypotUnfused else hypotFused; | 34 | const hypfn = if (emulateFma(T)) hypotUnfused else hypotFused; |
| 36 | var major: T = x; | 35 | var major: T = x; |
| 37 | var minor: T = y; | 36 | var minor: T = y; |
| ... | @@ -46,7 +45,8 @@ pub fn hypot(x: anytype, y: anytype) @TypeOf(x, y) { | ... | @@ -46,7 +45,8 @@ pub fn hypot(x: anytype, y: anytype) @TypeOf(x, y) { |
| 46 | major = minor; | 45 | major = minor; |
| 47 | minor = tempo; | 46 | minor = tempo; |
| 48 | } | 47 | } |
| 49 | if (major * incre >= minor) return major; | 48 | if (minor == 0.0) return major; |
| 49 | if (major - minor == major) return major; | ||
| 50 | if (major > upper) return hypfn(T, major * scale, minor * scale) / scale; | 50 | if (major > upper) return hypfn(T, major * scale, minor * scale) / scale; |
| 51 | if (minor < lower) return hypfn(T, major / scale, minor / scale) * scale; | 51 | if (minor < lower) return hypfn(T, major / scale, minor / scale) * scale; |
| 52 | return hypfn(T, major, minor); | 52 | return hypfn(T, major, minor); |
src/libs/musl.zig-2| ... | @@ -874,7 +874,6 @@ const src_files = [_][]const u8{ | ... | @@ -874,7 +874,6 @@ const src_files = [_][]const u8{ |
| 874 | "musl/src/math/frexp.c", | 874 | "musl/src/math/frexp.c", |
| 875 | "musl/src/math/frexpf.c", | 875 | "musl/src/math/frexpf.c", |
| 876 | "musl/src/math/frexpl.c", | 876 | "musl/src/math/frexpl.c", |
| 877 | "musl/src/math/hypot.c", | ||
| 878 | "musl/src/math/hypotf.c", | 877 | "musl/src/math/hypotf.c", |
| 879 | "musl/src/math/hypotl.c", | 878 | "musl/src/math/hypotl.c", |
| 880 | "musl/src/math/i386/acosf.s", | 879 | "musl/src/math/i386/acosf.s", |
| ... | @@ -890,7 +889,6 @@ const src_files = [_][]const u8{ | ... | @@ -890,7 +889,6 @@ const src_files = [_][]const u8{ |
| 890 | "musl/src/math/i386/expl.s", | 889 | "musl/src/math/i386/expl.s", |
| 891 | "musl/src/math/i386/expm1l.s", | 890 | "musl/src/math/i386/expm1l.s", |
| 892 | "musl/src/math/i386/hypotf.s", | 891 | "musl/src/math/i386/hypotf.s", |
| 893 | "musl/src/math/i386/hypot.s", | ||
| 894 | "musl/src/math/i386/__invtrigl.s", | 892 | "musl/src/math/i386/__invtrigl.s", |
| 895 | "musl/src/math/i386/ldexpf.s", | 893 | "musl/src/math/i386/ldexpf.s", |
| 896 | "musl/src/math/i386/ldexpl.s", | 894 | "musl/src/math/i386/ldexpl.s", |
src/libs/wasi_libc.zig-1| ... | @@ -730,7 +730,6 @@ const libc_top_half_src_files = [_][]const u8{ | ... | @@ -730,7 +730,6 @@ const libc_top_half_src_files = [_][]const u8{ |
| 730 | "musl/src/math/frexp.c", | 730 | "musl/src/math/frexp.c", |
| 731 | "musl/src/math/frexpf.c", | 731 | "musl/src/math/frexpf.c", |
| 732 | "musl/src/math/frexpl.c", | 732 | "musl/src/math/frexpl.c", |
| 733 | "musl/src/math/hypot.c", | ||
| 734 | "musl/src/math/hypotf.c", | 733 | "musl/src/math/hypotf.c", |
| 735 | "musl/src/math/hypotl.c", | 734 | "musl/src/math/hypotl.c", |
| 736 | "musl/src/math/ilogb.c", | 735 | "musl/src/math/ilogb.c", |