mailing list of musl libc
 help / color / mirror / code / Atom feed
* [musl] [C23 128 bit 0/4] implement the library part of 128 bit support
@ 2023-05-31 14:15 Jens Gustedt
  2023-05-31 14:15 ` [musl] [C23 128 bit 1/4] add an emulation for 128 bit arithmetic as needed for C library support Jens Gustedt
                   ` (3 more replies)
  0 siblings, 4 replies; 23+ messages in thread
From: Jens Gustedt @ 2023-05-31 14:15 UTC (permalink / raw)
  To: musl

This does not implement full featured support for 128 bit types or
functions. It only enables the support that is necessary, such that
compilers can claim [u]int128_t types and their functionality.

All 128 types and arithmetic has to be provided by the compilers.

Jens Gustedt (4):
  add an emulation for 128 bit arithmetic as needed for C library
    support
  C23: implement w128 and wf128 support for printf
  C23: implement w128 and wf128 for scanf and similar
  C23: implement proper support for int128_t and uint128_t

 include/inttypes.h                 |  55 ++++++++
 include/stdint.h                   |  37 +++++
 src/internal/intscan.c             | 105 +++++++++++---
 src/internal/intscan.h             |   4 +-
 src/internal/uwide128.c            | 213 +++++++++++++++++++++++++++++
 src/internal/uwide128.h            |  57 ++++++++
 src/internal/x86_64/uwide128_pop.s |  27 ++++
 src/stdio/vfprintf.c               | 113 +++++++++------
 src/stdio/vfscanf.c                |  25 ++--
 src/stdio/vfwprintf.c              |  45 +++---
 src/stdio/vfwscanf.c               |  19 ++-
 src/stdlib/strtol.c                |  12 +-
 src/stdlib/wcstol.c                |  12 +-
 13 files changed, 611 insertions(+), 113 deletions(-)
 create mode 100644 src/internal/uwide128.c
 create mode 100644 src/internal/uwide128.h
 create mode 100644 src/internal/x86_64/uwide128_pop.s

-- 
2.34.1


^ permalink raw reply	[flat|nested] 23+ messages in thread

* [musl] [C23 128 bit 1/4] add an emulation for 128 bit arithmetic as needed for C library support
  2023-05-31 14:15 [musl] [C23 128 bit 0/4] implement the library part of 128 bit support Jens Gustedt
@ 2023-05-31 14:15 ` Jens Gustedt
  2023-05-31 14:15 ` [musl] [C23 128 bit 2/4] C23: implement w128 and wf128 support for printf Jens Gustedt
                   ` (2 subsequent siblings)
  3 siblings, 0 replies; 23+ messages in thread
From: Jens Gustedt @ 2023-05-31 14:15 UTC (permalink / raw)
  To: musl

With C23 it will be possible for compilers to add extended integer
types that are wider than `intmax_t`, in particular for the
`[u]int128_t` types. This patch enables the minimal support for these
types that is needed to implement the necessary bits in `printf` and
`scanf` like interfaces. This support is added unconditionally, but
only compilers that effectively implement the types will be able to
profit from this new setting.

The usage of these types is then even independent of whether or not a
given compiler has full support for `[u]int128_t`; just the types
indicated by gcc' `__int128` are needed for this to be useful.

We provide two implementations for most of the functions, but which
both have the same ABI. One that uses gcc' `__int128` types underneath
and anotherone that hand-codes minimal operations by sticking them
together from different sub-words of the 128 entity.

The hand-coded version is not complete, it lacks a important bit in
terms of a function

      uwide128 __uwide128_pop(va_list *ap);

that is used by `vfprintf` and similar to pop a 128 bit value from the
variable argument list. (`uwide128` is an internal structure type that
is used for the emulation)

This version *must* be completed for each architecture that we support
by a .s file. For architectures that have a compiler that implements
`__int128`, it is relatively simple to generate such a file: just
compile the file uwide128.c with -S option and extract this one and
only function into a platform specific subdirectory.
---
 src/internal/uwide128.c            | 213 +++++++++++++++++++++++++++++
 src/internal/uwide128.h            |  57 ++++++++
 src/internal/x86_64/uwide128_pop.s |  27 ++++
 3 files changed, 297 insertions(+)
 create mode 100644 src/internal/uwide128.c
 create mode 100644 src/internal/uwide128.h
 create mode 100644 src/internal/x86_64/uwide128_pop.s

diff --git a/src/internal/uwide128.c b/src/internal/uwide128.c
new file mode 100644
index 00000000..6e4b08bf
--- /dev/null
+++ b/src/internal/uwide128.c
@@ -0,0 +1,213 @@
+#include <uwide128.h>
+#include <stdarg.h>
+
+#if __SIZEOF_INT128__
+
+union u { unsigned __int128 x; uwide128 s; };
+
+__attribute__((__weak__))
+uwide128 __uwide128_neg(uwide128 a) {
+	union u both = { .s = a, };
+	both.x = -both.x;
+	return both.s;
+}
+
+__attribute__((__weak__))
+uwide128 __uwide128_add(uwide128 a, uint8_t b) {
+	union u both = { .s = a, };
+	both.x += b;
+	return both.s;
+}
+
+__attribute__((__weak__))
+uwide128 __uwide128_sub(uwide128 a, uint8_t b) {
+	union u both = { .s = a, };
+	both.x -= b;
+	return both.s;
+}
+
+__attribute__((__weak__))
+uwide128 __uwide128_mul(uwide128 a, uint8_t b) {
+	union u both = { .s = a, };
+	both.x *= b;
+	return both.s;
+}
+
+__attribute__((__weak__))
+uint8_t __uwide128_div10(uwide128* a) {
+	union u both = { .s = *a, };
+	uint8_t ret = both.x % 10;
+	both.x /= 10;
+	*a = both.s;
+	return ret;
+}
+
+__attribute__((__weak__))
+uint8_t __uwide128_div2(uwide128* a) {
+	union u both = { .s = *a, };
+	uint8_t ret = both.x % 2;
+	both.x /= 2;
+	*a = both.s;
+	return ret;
+}
+
+__attribute__((__weak__))
+uint8_t __uwide128_div8(uwide128* a) {
+	union u both = { .s = *a, };
+	uint8_t ret = both.x % 8;
+	both.x /= 8;
+	*a = both.s;
+	return ret;
+}
+
+__attribute__((__weak__))
+uint8_t __uwide128_div16(uwide128* a) {
+	union u both = { .s = *a, };
+	uint8_t ret = both.x % 16;
+	both.x /= 16;
+	*a = both.s;
+	return ret;
+}
+
+__attribute__((__weak__))
+_Bool  __uwide128_le(uwide128 a, uwide128 b) {
+	union u botha = { .s = a, };
+	union u bothb = { .s = b, };
+	return botha.x <= bothb.x;
+}
+
+__attribute__((__weak__))
+_Bool  __uwide128_iszero(uwide128 a) {
+	union u both = { .s = a, };
+	return !both.x;
+}
+
+uwide128 __uwide128_pop(va_list *ap)
+{
+	return (union u){ .x = va_arg(*ap, __int128) }.s;
+}
+
+#else
+
+__attribute__((__weak__))
+_Bool __uwide128_le(uwide128 a, uwide128 b) {
+	return (a.v64[hi64] > b.v64[hi64])
+	  ? false
+	  : ((a.v64[hi64] < b.v64[hi64])
+	     ? true
+	     : (a.v64[lo64] <= b.v64[lo64]));
+}
+
+__attribute__((__weak__))
+_Bool __uwide128_iszero(uwide128 a)
+{
+	return !a.v64[0] && !a.v64[1];
+}
+
+__attribute__((__weak__))
+uwide128 __uwide128_neg(uwide128 a)
+{
+	uwide128 ret = { .v64 = { [0] = ~a.v64[0], [1] = ~a.v64[1], }, };
+	if (!a.v64[lo64]) ret.v64[hi64]--;
+	ret.v64[lo64]--;
+	return ret;
+}
+
+uwide128 __uwide128_add(uwide128 a, uint8_t b)
+{
+	uwide128 ret;
+	uint64_t carry = a.v32[wo32_0];
+	carry += b;
+	ret.v32[wo32_0] = carry;
+	carry >>= 32;
+	carry += a.v32[wo32_1];
+	ret.v32[wo32_1] = carry;
+	carry >>= 32;
+	carry += a.v32[wo32_2];
+	ret.v32[wo32_2] = carry;
+	carry >>= 32;
+	carry += a.v32[wo32_3];
+	ret.v32[wo32_3] = carry;
+	return ret;
+}
+
+uwide128 __uwide128_sub(uwide128 a, uint8_t b)
+{
+	uwide128 ret;
+	int64_t carry = a.v32[wo32_0];
+	carry -= b;
+	ret.v32[wo32_0] = carry;
+	carry /= UINT64_C(0x100000000);
+	carry += a.v32[wo32_1];
+	ret.v32[wo32_1] = carry;
+	carry /= UINT64_C(0x100000000);
+	carry += a.v32[wo32_2];
+	ret.v32[wo32_2] = carry;
+	carry /= UINT64_C(0x100000000);
+	carry += a.v32[wo32_3];
+	ret.v32[wo32_3] = carry;
+	return ret;
+}
+
+uwide128 __uwide128_mul(uwide128 a, uint8_t b)
+{
+	uwide128 ret;
+	uint64_t carry;
+	uint64_t prod = a.v32[wo32_0];
+	prod *= b;
+	carry = prod;
+	ret.v32[wo32_0] = carry;
+	carry >>= 32;
+	prod = a.v32[wo32_1];
+	prod *= b;
+	carry += prod;
+	ret.v32[wo32_1] = carry;
+	carry >>= 32;
+	prod = a.v32[wo32_2];
+	prod *= b;
+	carry += prod;
+	ret.v32[wo32_2] = carry;
+	carry >>= 32;
+	prod = a.v32[wo32_3];
+	prod *= b;
+	carry += prod;
+	ret.v32[wo32_3] = carry;
+	return ret;
+}
+
+static uint8_t __uwide128_div(uwide128* a, uint8_t b)
+{
+	uint64_t rest = a->v64[hi64] % b;
+	a->v64[hi64] /= b;
+	rest <<= 32;
+	rest |= a->v32[wo32_1];
+	a->v32[wo32_1] = rest / b;
+	rest %= b;
+	rest <<= 32;
+	rest |= a->v32[wo32_0];
+	a->v32[wo32_0] = rest / b;
+	rest %= b;
+	return rest;
+}
+
+uint8_t __uwide128_div10(uwide128* a)
+{
+	return __uwide128_div(a, 10);
+}
+
+uint8_t __uwide128_div2(uwide128* a)
+{
+	return __uwide128_div(a, 2);
+}
+
+uint8_t __uwide128_div8(uwide128* a)
+{
+	return __uwide128_div(a, 8);
+}
+
+uint8_t __uwide128_div16(uwide128* a)
+{
+	return __uwide128_div(a, 16);
+}
+
+#endif
diff --git a/src/internal/uwide128.h b/src/internal/uwide128.h
new file mode 100644
index 00000000..f6a02934
--- /dev/null
+++ b/src/internal/uwide128.h
@@ -0,0 +1,57 @@
+#include <features.h>
+#include <stdint.h>
+#include <stdbool.h>
+#include <stdarg.h>
+
+typedef union uwide128 uwide128;
+union uwide128 {
+	uint64_t v64[2];
+	uint32_t v32[4];
+};
+
+#define word64(X) (__BYTE_ORDER == __LITTLE_ENDIAN ? (X) : (2-(X)))
+#define lo64 word64(0)
+#define hi64 word64(1)
+
+#define word32(X) (__BYTE_ORDER == __LITTLE_ENDIAN ? (X) : (4-(X)))
+#define wo32_0 word32(0)
+#define wo32_1 word32(1)
+#define wo32_2 word32(2)
+#define wo32_3 word32(3)
+
+
+#define comp2(LO, HI) { { [lo64] = (LO), [hi64] = (HI), }, }
+
+#if __STDC_VERSION__ >= 202311L
+constexpr uwide128 __uwide128_max = { -1, -1, };
+#define UWIDE128_MAX __uwide128_max
+#else
+#define UWIDE128_MAX ((void)0, (uwide128)comp2(-1, -1))
+#endif
+
+static __inline uwide128 __uwide128_i64(int64_t a)  __unsequenced;
+static __inline uwide128 __uwide128_u64(uint64_t a) __unsequenced;
+
+static __inline uwide128 __uwide128_i64(int64_t a)
+{
+	return (uwide128)comp2(a, (a < 0) ? UINT64_MAX : 0);
+}
+
+static __inline uwide128 __uwide128_u64(uint64_t a)
+{
+	return (uwide128)comp2(a, 0);
+}
+
+_Bool __uwide128_le(uwide128, uwide128)    __unsequenced; // intscan
+_Bool __uwide128_iszero(uwide128)          __unsequenced; // vfprintf
+uwide128 __uwide128_neg(uwide128)          __unsequenced; // intscan
+uwide128 __uwide128_add(uwide128, uint8_t) __unsequenced; // intscan
+uwide128 __uwide128_sub(uwide128, uint8_t) __unsequenced; // intscan
+uwide128 __uwide128_mul(uwide128, uint8_t) __unsequenced; // intscan
+uint8_t __uwide128_div10(uwide128*);           // vfprintf
+uint8_t __uwide128_div2(uwide128*);            // vfprintf
+uint8_t __uwide128_div8(uwide128*);            // vfprintf
+uint8_t __uwide128_div16(uwide128*);           // vfprintf
+uwide128 __uwide128_pop(va_list *ap);          // vfprintf
+uwide128 __uwide128_i64(int64_t);              // vfprintf
+uwide128 __uwide128_u64(uint64_t);             // vfprintf
diff --git a/src/internal/x86_64/uwide128_pop.s b/src/internal/x86_64/uwide128_pop.s
new file mode 100644
index 00000000..f9f84348
--- /dev/null
+++ b/src/internal/x86_64/uwide128_pop.s
@@ -0,0 +1,27 @@
+.text
+.global __uwide128_pop
+.weak	__uwide128_pop
+.type	__uwide128_pop, @function
+__uwide128_pop:
+	endbr64
+	movl	(%rdi), %edx
+	cmpl	$39, %edx
+	ja	1
+	movl	%edx, %eax
+	addl	$16, %edx
+	addq	16(%rdi), %rax
+	movl	%edx, (%rdi)
+	movq	8(%rax), %rdx
+	movq	(%rax), %rax
+	ret
+	.p2align 4,,10
+	.p2align 3
+1:
+	movq	8(%rdi), %rax
+	addq	$15, %rax
+	andq	$-16, %rax
+	leaq	16(%rax), %rdx
+	movq	%rdx, 8(%rdi)
+	movq	8(%rax), %rdx
+	movq	(%rax), %rax
+	ret
-- 
2.34.1


^ permalink raw reply	[flat|nested] 23+ messages in thread

* [musl] [C23 128 bit 2/4] C23: implement w128 and wf128 support for printf
  2023-05-31 14:15 [musl] [C23 128 bit 0/4] implement the library part of 128 bit support Jens Gustedt
  2023-05-31 14:15 ` [musl] [C23 128 bit 1/4] add an emulation for 128 bit arithmetic as needed for C library support Jens Gustedt
@ 2023-05-31 14:15 ` Jens Gustedt
  2023-05-31 14:15 ` [musl] [C23 128 bit 3/4] C23: implement w128 and wf128 for scanf and similar Jens Gustedt
  2023-05-31 14:15 ` [musl] [C23 128 bit 4/4] C23: implement proper support for int128_t and uint128_t Jens Gustedt
  3 siblings, 0 replies; 23+ messages in thread
From: Jens Gustedt @ 2023-05-31 14:15 UTC (permalink / raw)
  To: musl

C23 now allows extended integer types wider than `intmax_t` for the
case that they are used to implement some fixed-width integer
type. The length specifer wN can then be used for `printf` and friends
to print the type.

Gcc and clang provide `__int128` types for many architectures (in
particular x86_64) since a long time, and adding these types
"officially" is a recurrent user request. They are particularly nice
to have for bitsets.

Implementing w128 (and wf128) is a first step to provide `int128_t`
and `uint128_t` natively, independently of the fact if there already
is a compiler that implements these types.

This implementation hopefully only adds a very mild overhead in size
and processing time for those architectures where this type is
present. The impact is

- one extra state array for the 128 bit type (some 60 static byte or so)
- a widening of the local buffer needed to collect digits (512 bytes
  on the stack)
- widening of the static format functions to accept the 128 type
  (probably some byte for some extra load instructions)

These functions then are possibly a bit slower, since they use wider
instructions and/or combine several instructions. There was already an
optimization in place for the 'u' format, because here division and
modulo base 10 is needed, which could be a bit costly. We now apply
similar tricks for the other integer formats to avoid passing into the
128 bit emulation if that is possible.
---
 src/stdio/vfprintf.c  | 113 ++++++++++++++++++++++++++----------------
 src/stdio/vfwprintf.c |  45 ++++++++++-------
 2 files changed, 97 insertions(+), 61 deletions(-)

diff --git a/src/stdio/vfprintf.c b/src/stdio/vfprintf.c
index a531a513..aac065fc 100644
--- a/src/stdio/vfprintf.c
+++ b/src/stdio/vfprintf.c
@@ -1,4 +1,5 @@
 #include "stdio_impl.h"
+#include "uwide128.h"
 #include <errno.h>
 #include <ctype.h>
 #include <limits.h>
@@ -35,10 +36,12 @@ enum {
 	BARE, LPRE, LLPRE, HPRE, HHPRE, BIGLPRE,
 	ZTPRE, JPRE, WPRE,
 	STOP,
+	WWPRE,
 	PTR, INT, UINT, ULLONG,
 	LONG, ULONG,
 	SHORT, USHORT, CHAR, UCHAR,
 	LLONG, SIZET, IMAX, UMAX, PDIFF, UIPTR,
+	INT128, UINT128,
 	DBL, LDBL,
 	NOARG,
 	MAXSTATE
@@ -114,7 +117,7 @@ static const unsigned char states[]['z'-'A'+1] = {
 
 union arg
 {
-	uintmax_t i;
+	uwide128 i;
 	long double f;
 	void *p;
 };
@@ -122,22 +125,24 @@ union arg
 static void pop_arg(union arg *arg, int type, va_list *ap)
 {
 	switch (type) {
-	       case PTR:	arg->p = va_arg(*ap, void *);
-	break; case INT:	arg->i = va_arg(*ap, int);
-	break; case UINT:	arg->i = va_arg(*ap, unsigned int);
-	break; case LONG:	arg->i = va_arg(*ap, long);
-	break; case ULONG:	arg->i = va_arg(*ap, unsigned long);
-	break; case ULLONG:	arg->i = va_arg(*ap, unsigned long long);
-	break; case SHORT:	arg->i = (short)va_arg(*ap, int);
-	break; case USHORT:	arg->i = (unsigned short)va_arg(*ap, int);
-	break; case CHAR:	arg->i = (signed char)va_arg(*ap, int);
-	break; case UCHAR:	arg->i = (unsigned char)va_arg(*ap, int);
-	break; case LLONG:	arg->i = va_arg(*ap, long long);
-	break; case SIZET:	arg->i = va_arg(*ap, size_t);
-	break; case IMAX:	arg->i = va_arg(*ap, intmax_t);
-	break; case UMAX:	arg->i = va_arg(*ap, uintmax_t);
-	break; case PDIFF:	arg->i = va_arg(*ap, ptrdiff_t);
-	break; case UIPTR:	arg->i = (uintptr_t)va_arg(*ap, void *);
+		case PTR:	arg->p = va_arg(*ap, void *);
+	break; case INT:	arg->i = __uwide128_i64(va_arg(*ap, int));
+	break; case UINT:	arg->i = __uwide128_u64(va_arg(*ap, unsigned int));
+	break; case LONG:	arg->i = __uwide128_i64(va_arg(*ap, long));
+	break; case ULONG:	arg->i = __uwide128_u64(va_arg(*ap, unsigned long));
+	break; case ULLONG:	arg->i = __uwide128_u64(va_arg(*ap, unsigned long long));
+	break; case SHORT:	arg->i = __uwide128_i64((short)va_arg(*ap, int));
+	break; case USHORT:	arg->i = __uwide128_u64((unsigned short)va_arg(*ap, int));
+	break; case CHAR:	arg->i = __uwide128_i64((signed char)va_arg(*ap, int));
+	break; case UCHAR:	arg->i = __uwide128_u64((unsigned char)va_arg(*ap, int));
+	break; case LLONG:	arg->i = __uwide128_i64(va_arg(*ap, long long));
+	break; case SIZET:	arg->i = __uwide128_u64(va_arg(*ap, size_t));
+	break; case IMAX:	arg->i = __uwide128_i64(va_arg(*ap, intmax_t));
+	break; case UMAX:	arg->i = __uwide128_u64(va_arg(*ap, uintmax_t));
+	break; case PDIFF:	arg->i = __uwide128_i64(va_arg(*ap, ptrdiff_t));
+	break; case UIPTR:	arg->i = __uwide128_u64((uintptr_t)va_arg(*ap, void *));
+	break; case INT128:	arg->i = __uwide128_pop(ap);
+	break; case UINT128:	arg->i = __uwide128_pop(ap);
 	break; case DBL:	arg->f = va_arg(*ap, double);
 	break; case LDBL:	arg->f = va_arg(*ap, long double);
 	}
@@ -163,29 +168,51 @@ static const char xdigits[16] = {
 	"0123456789ABCDEF"
 };
 
-static char *fmt_x(uintmax_t x, char *s, int lower)
+static char *fmt_u(unsigned long long x, char *s)
 {
-	for (; x; x>>=4) *--s = xdigits[(x&15)]|lower;
+	unsigned long y;
+	for (   ; x>ULONG_MAX; x/=10) *--s = '0' + x%10;
+	for (y=x;           y; y/=10) *--s = '0' + y%10;
 	return s;
 }
 
-static char *fmt_b(uintmax_t x, char *s)
+static char *fmt128_x(uwide128 x, char *s, int lower)
 {
-	for (; x; x>>=1) *--s = '0' + (x&1);
+	uint32_t y;
+	uint64_t z;
+	while (x.v64[hi64]) *--s = xdigits[__uwide128_div16(&x)]|lower;
+	for (z = x.v64[lo64]; z>UINT32_MAX; z>>=4) *--s = xdigits[(z&15)]|lower;
+	for (y=z;           y; y>>=4) *--s = xdigits[(y&15)]|lower;
 	return s;
 }
 
-static char *fmt_o(uintmax_t x, char *s)
+static char *fmt128_b(uwide128 x, char *s)
 {
-	for (; x; x>>=3) *--s = '0' + (x&7);
+	uint64_t z;
+	uint32_t y;
+	while (x.v64[hi64]) *--s = '0' + __uwide128_div2(&x);
+	for (z = x.v64[lo64]; z>UINT32_MAX; z>>=1) *--s = '0' + z%2;
+	for (y=z;           y; y>>=1) *--s = '0' + y%2;
 	return s;
 }
 
-static char *fmt_u(uintmax_t x, char *s)
+static char *fmt128_o(uwide128 x, char *s)
 {
-	unsigned long y;
-	for (   ; x>ULONG_MAX; x/=10) *--s = '0' + x%10;
-	for (y=x;           y; y/=10) *--s = '0' + y%10;
+	uint64_t z;
+	uint32_t y;
+	while (x.v64[hi64]) *--s = '0' + __uwide128_div8(&x);
+	for (z = x.v64[lo64]; z>UINT32_MAX; z>>=3) *--s = '0' + z%8;
+	for (y=z;           y; y>>=3) *--s = '0' + y%8;
+	return s;
+}
+
+static char *fmt128_u(uwide128 x, char *s)
+{
+	uint64_t z;
+	uint32_t y;
+	while (x.v64[hi64]) *--s = '0' + __uwide128_div10(&x);
+	for (z = x.v64[lo64]; z>UINT32_MAX; z/=10) *--s = '0' + z%10;
+	for (y=z;           y; y/=10) *--s = '0' + y%10;
 	return s;
 }
 
@@ -456,7 +483,7 @@ static int printf_core(FILE *f, const char *fmt, va_list *ap, union arg *nl_arg,
 	unsigned st, ps, width=0;
 	int cnt=0, l=0;
 	size_t i;
-	char buf[sizeof(uintmax_t)*CHAR_BIT+3+LDBL_MANT_DIG/4];
+	char buf[sizeof(uwide128)*CHAR_BIT+3+LDBL_MANT_DIG/4];
 	const char *prefix;
 	int t, pl;
 	wchar_t wc[2], *ws;
@@ -498,7 +525,7 @@ static int printf_core(FILE *f, const char *fmt, va_list *ap, union arg *nl_arg,
 			if (isdigit(s[1]) && s[2]=='$') {
 				l10n=1;
 				if (!f) nl_type[s[1]-'0'] = INT, w = 0;
-				else w = nl_arg[s[1]-'0'].i;
+				else w = nl_arg[s[1]-'0'].i.v64[lo64];
 				s+=3;
 			} else if (!l10n) {
 				w = f ? va_arg(*ap, int) : 0;
@@ -511,7 +538,7 @@ static int printf_core(FILE *f, const char *fmt, va_list *ap, union arg *nl_arg,
 		if (*s=='.' && s[1]=='*') {
 			if (isdigit(s[2]) && s[3]=='$') {
 				if (!f) nl_type[s[2]-'0'] = INT, p = 0;
-				else p = nl_arg[s[2]-'0'].i;
+				else p = nl_arg[s[2]-'0'].i.v64[lo64];
 				s+=4;
 			} else if (!l10n) {
 				p = f ? va_arg(*ap, int) : 0;
@@ -552,6 +579,7 @@ static int printf_core(FILE *f, const char *fmt, va_list *ap, union arg *nl_arg,
 #else
 		case 64:  ps = LLPRE; st = (st == UINT) ? ULLONG : ((st == INT) ? LLONG : PTR); break;
 #endif
+		case 128: ps = WWPRE; st = (st == UINT) ? UINT128 : ((st == INT) ? INT128 : PTR); break;
 		default:  goto inval;
 		}
 
@@ -592,6 +620,7 @@ static int printf_core(FILE *f, const char *fmt, va_list *ap, union arg *nl_arg,
 			case HHPRE: *(unsigned char *)arg.p = cnt; break;
 			case ZTPRE: *(size_t *)arg.p = cnt; break;
 			case JPRE: *(uintmax_t *)arg.p = cnt; break;
+			case WWPRE: *(uwide128 *)arg.p = __uwide128_i64(cnt); break;
 			}
 			continue;
 		case 'p':
@@ -599,39 +628,39 @@ static int printf_core(FILE *f, const char *fmt, va_list *ap, union arg *nl_arg,
 			t = 'x';
 			fl |= ALT_FORM;
 		case 'x': case 'X':
-			a = fmt_x(arg.i, z, t&32);
-			if (arg.i && (fl & ALT_FORM)) prefix+=(t>>4), pl=2;
+			a = fmt128_x(arg.i, z, t&32);
+			if (!__uwide128_iszero(arg.i) && (fl & ALT_FORM)) prefix+=(t>>4), pl=2;
 			if (0) {
 		case 'b': case 'B':
-			a = fmt_b(arg.i, z);
-			if (arg.i && (fl & ALT_FORM)) prefix = (t == 'b' ? "0b" : "0B"), pl=2;
+			a = fmt128_b(arg.i, z);
+			if (!__uwide128_iszero(arg.i) && (fl & ALT_FORM)) prefix = (t == 'b' ? "0b" : "0B"), pl=2;
 			} if (0) {
 		case 'o':
-			a = fmt_o(arg.i, z);
+			a = fmt128_o(arg.i, z);
 			if ((fl&ALT_FORM) && p<z-a+1) p=z-a+1;
 			} if (0) {
 		case 'd': case 'i':
 			pl=1;
-			if (arg.i>INTMAX_MAX) {
-				arg.i=-arg.i;
+			if (arg.i.v64[hi64]>INT64_MAX) {
+				arg.i=__uwide128_neg(arg.i);
 			} else if (fl & MARK_POS) {
 				prefix++;
 			} else if (fl & PAD_POS) {
 				prefix+=2;
 			} else pl=0;
 		case 'u':
-			a = fmt_u(arg.i, z);
+			a = fmt128_u(arg.i, z);
 			}
 			if (xp && p<0) goto overflow;
 			if (xp) fl &= ~ZERO_PAD;
-			if (!arg.i && !p) {
+			if (__uwide128_iszero(arg.i) && !p) {
 				a=z;
 				break;
 			}
-			p = MAX(p, z-a + !arg.i);
+			p = MAX(p, z-a + __uwide128_iszero(arg.i));
 			break;
 		case 'c':
-			*(a=z-(p=1))=arg.i;
+			*(a=z-(p=1))=arg.i.v64[lo64];
 			fl &= ~ZERO_PAD;
 			break;
 		case 'm':
@@ -644,7 +673,7 @@ static int printf_core(FILE *f, const char *fmt, va_list *ap, union arg *nl_arg,
 			fl &= ~ZERO_PAD;
 			break;
 		case 'C':
-			wc[0] = arg.i;
+			wc[0] = arg.i.v64[lo64];
 			wc[1] = 0;
 			arg.p = wc;
 			p = -1;
diff --git a/src/stdio/vfwprintf.c b/src/stdio/vfwprintf.c
index 3689c2d5..d510233f 100644
--- a/src/stdio/vfwprintf.c
+++ b/src/stdio/vfwprintf.c
@@ -1,4 +1,5 @@
 #include "stdio_impl.h"
+#include "uwide128.h"
 #include <errno.h>
 #include <ctype.h>
 #include <limits.h>
@@ -28,10 +29,12 @@ enum {
 	BARE, LPRE, LLPRE, HPRE, HHPRE, BIGLPRE,
 	ZTPRE, JPRE, WPRE,
 	STOP,
+	WWPRE,
 	PTR, INT, UINT, ULLONG,
 	LONG, ULONG,
 	SHORT, USHORT, CHAR, UCHAR,
 	LLONG, SIZET, IMAX, UMAX, PDIFF, UIPTR,
+	INT128, UINT128,
 	DBL, LDBL,
 	NOARG,
 	MAXSTATE
@@ -107,7 +110,7 @@ static const unsigned char states[]['z'-'A'+1] = {
 
 union arg
 {
-	uintmax_t i;
+	uwide128 i;
 	long double f;
 	void *p;
 };
@@ -116,21 +119,23 @@ static void pop_arg(union arg *arg, int type, va_list *ap)
 {
 	switch (type) {
 	       case PTR:	arg->p = va_arg(*ap, void *);
-	break; case INT:	arg->i = va_arg(*ap, int);
-	break; case UINT:	arg->i = va_arg(*ap, unsigned int);
-	break; case LONG:	arg->i = va_arg(*ap, long);
-	break; case ULONG:	arg->i = va_arg(*ap, unsigned long);
-	break; case ULLONG:	arg->i = va_arg(*ap, unsigned long long);
-	break; case SHORT:	arg->i = (short)va_arg(*ap, int);
-	break; case USHORT:	arg->i = (unsigned short)va_arg(*ap, int);
-	break; case CHAR:	arg->i = (signed char)va_arg(*ap, int);
-	break; case UCHAR:	arg->i = (unsigned char)va_arg(*ap, int);
-	break; case LLONG:	arg->i = va_arg(*ap, long long);
-	break; case SIZET:	arg->i = va_arg(*ap, size_t);
-	break; case IMAX:	arg->i = va_arg(*ap, intmax_t);
-	break; case UMAX:	arg->i = va_arg(*ap, uintmax_t);
-	break; case PDIFF:	arg->i = va_arg(*ap, ptrdiff_t);
-	break; case UIPTR:	arg->i = (uintptr_t)va_arg(*ap, void *);
+	break; case INT:	arg->i = __uwide128_i64(va_arg(*ap, int));
+	break; case UINT:	arg->i = __uwide128_u64(va_arg(*ap, unsigned int));
+	break; case LONG:	arg->i = __uwide128_i64(va_arg(*ap, long));
+	break; case ULONG:	arg->i = __uwide128_u64(va_arg(*ap, unsigned long));
+	break; case ULLONG:	arg->i = __uwide128_u64(va_arg(*ap, unsigned long long));
+	break; case SHORT:	arg->i = __uwide128_i64((short)va_arg(*ap, int));
+	break; case USHORT:	arg->i = __uwide128_u64((unsigned short)va_arg(*ap, int));
+	break; case CHAR:	arg->i = __uwide128_i64((signed char)va_arg(*ap, int));
+	break; case UCHAR:	arg->i = __uwide128_u64((unsigned char)va_arg(*ap, int));
+	break; case LLONG:	arg->i = __uwide128_i64(va_arg(*ap, long long));
+	break; case SIZET:	arg->i = __uwide128_u64(va_arg(*ap, size_t));
+	break; case IMAX:	arg->i = __uwide128_i64(va_arg(*ap, intmax_t));
+	break; case UMAX:	arg->i = __uwide128_u64(va_arg(*ap, uintmax_t));
+	break; case PDIFF:	arg->i = __uwide128_i64(va_arg(*ap, ptrdiff_t));
+	break; case UIPTR:	arg->i = __uwide128_u64((uintptr_t)va_arg(*ap, void *));
+	break; case INT128:	arg->i = __uwide128_pop(ap);
+	break; case UINT128:	arg->i = __uwide128_pop(ap);
 	break; case DBL:	arg->f = va_arg(*ap, double);
 	break; case LDBL:	arg->f = va_arg(*ap, long double);
 	}
@@ -213,7 +218,7 @@ static int wprintf_core(FILE *f, const wchar_t *fmt, va_list *ap, union arg *nl_
 			if (iswdigit(s[1]) && s[2]=='$') {
 				l10n=1;
 				nl_type[s[1]-'0'] = INT;
-				w = nl_arg[s[1]-'0'].i;
+				w = nl_arg[s[1]-'0'].i.v64[lo64];
 				s+=3;
 			} else if (!l10n) {
 				w = f ? va_arg(*ap, int) : 0;
@@ -226,7 +231,7 @@ static int wprintf_core(FILE *f, const wchar_t *fmt, va_list *ap, union arg *nl_
 		if (*s=='.' && s[1]=='*') {
 			if (isdigit(s[2]) && s[3]=='$') {
 				nl_type[s[2]-'0'] = INT;
-				p = nl_arg[s[2]-'0'].i;
+				p = nl_arg[s[2]-'0'].i.v64[lo64];
 				s+=4;
 			} else if (!l10n) {
 				p = f ? va_arg(*ap, int) : 0;
@@ -267,6 +272,7 @@ static int wprintf_core(FILE *f, const wchar_t *fmt, va_list *ap, union arg *nl_
 #else
 		case 64:  ps = LLPRE; st = (st == UINT) ? ULLONG : ((st == INT) ? LLONG : PTR); break;
 #endif
+		case 128: ps = WWPRE; st = (st == UINT) ? UINT128 : ((st == INT) ? INT128 : PTR); break;
 		default:  goto inval;
 		}
 
@@ -297,13 +303,14 @@ static int wprintf_core(FILE *f, const wchar_t *fmt, va_list *ap, union arg *nl_
 			case HHPRE: *(unsigned char *)arg.p = cnt; break;
 			case ZTPRE: *(size_t *)arg.p = cnt; break;
 			case JPRE: *(uintmax_t *)arg.p = cnt; break;
+			case WWPRE: *(uwide128 *)arg.p = __uwide128_i64(cnt); break;
 			}
 			continue;
 		case 'c':
 		case 'C':
 			if (w<1) w=1;
 			pad(f, w-1, fl);
-			out(f, &(wchar_t){t=='C' ? arg.i : btowc(arg.i)}, 1);
+			out(f, &(wchar_t){t=='C' ? arg.i.v64[lo64] : btowc(arg.i.v64[lo64])}, 1);
 			pad(f, w-1, fl^LEFT_ADJ);
 			l = w;
 			continue;
-- 
2.34.1


^ permalink raw reply	[flat|nested] 23+ messages in thread

* [musl] [C23 128 bit 3/4] C23: implement w128 and wf128 for scanf and similar
  2023-05-31 14:15 [musl] [C23 128 bit 0/4] implement the library part of 128 bit support Jens Gustedt
  2023-05-31 14:15 ` [musl] [C23 128 bit 1/4] add an emulation for 128 bit arithmetic as needed for C library support Jens Gustedt
  2023-05-31 14:15 ` [musl] [C23 128 bit 2/4] C23: implement w128 and wf128 support for printf Jens Gustedt
@ 2023-05-31 14:15 ` Jens Gustedt
  2023-05-31 14:15 ` [musl] [C23 128 bit 4/4] C23: implement proper support for int128_t and uint128_t Jens Gustedt
  3 siblings, 0 replies; 23+ messages in thread
From: Jens Gustedt @ 2023-05-31 14:15 UTC (permalink / raw)
  To: musl

These functions are possibly a bit slower with 128 bit support
enabled, since the core function `__intscan` uses wider data formats
and instructions in some places. There was already an optimization in
place for all formats which we now extend:

 - first with `unsigned`, then
 - switch to `uint64_t` if the value extends `UINT_MAX`, then
 - switch to `uwide128` (an internal 128 bit structure) if that is unavoidable.

If the scan is erroneous because there are more digits than expected,
the error might be noticed a bit later than previously, but the
`errno` number should be the same.
---
 src/internal/intscan.c | 105 ++++++++++++++++++++++++++++++++---------
 src/internal/intscan.h |   4 +-
 src/stdio/vfscanf.c    |  25 ++++++----
 src/stdio/vfwscanf.c   |  19 +++++---
 src/stdlib/strtol.c    |  12 ++---
 src/stdlib/wcstol.c    |  12 ++---
 6 files changed, 125 insertions(+), 52 deletions(-)

diff --git a/src/internal/intscan.c b/src/internal/intscan.c
index 57424554..c7c1e47e 100644
--- a/src/internal/intscan.c
+++ b/src/internal/intscan.c
@@ -1,6 +1,7 @@
 #include <limits.h>
 #include <errno.h>
 #include <ctype.h>
+#include "uwide128.h"
 #include "shgetc.h"
 
 /* Lookup table for digit values. -1==255>=36 -> invalid */
@@ -23,15 +24,59 @@ static const unsigned char table[] = { -1,
 -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
 };
 
-unsigned long long __intscan(FILE *f, unsigned base, int pok, unsigned long long lim)
+static uwide128 const uwide128_max  = { { -1, -1, } };
+static uwide128 const uwide128_zero = { {  0,  0, } };
+
+static const uwide128 __uwide128_limit[37] = {
+	comp2(0,	0),
+	comp2(-1,	-1),
+	comp2(-1,	9223372036854775807),
+	comp2(6148914691236517205,	6148914691236517205),
+	comp2(-1,	4611686018427387903),
+	comp2(3689348814741910323,	3689348814741910323),
+	comp2(-6148914691236517206,	3074457345618258602),
+	comp2(5270498306774157604,	2635249153387078802),
+	comp2(-1,	2305843009213693951),
+	comp2(-4099276460824344804,	2049638230412172401),
+	comp2(-7378697629483820647,	1844674407370955161),
+	comp2(8384883669867978007,	1676976733973595601),
+	comp2(6148914691236517205,	1537228672809129301),
+	comp2(4256940940086819603,	1418980313362273201),
+	comp2(2635249153387078802,	1317624576693539401),
+	comp2(1229782938247303441,	1229782938247303441),
+	comp2(-1,	1152921504606846975),
+	comp2(1085102592571150095,	1085102592571150095),
+	comp2(-2049638230412172402,	1024819115206086200),
+	comp2(-1941762534074689644,	970881267037344821),
+	comp2(-3689348814741910324,	922337203685477580),
+	comp2(-4392081922311798004,	878416384462359600),
+	comp2(-5030930201920786805,	838488366986797800),
+	comp2(4812194106185100421,	802032351030850070),
+	comp2(-6148914691236517206,	768614336404564650),
+	comp2(-6640827866535438582,	737869762948382064),
+	comp2(-7094901566811366007,	709490156681136600),
+	comp2(-1366425486941448268,	683212743470724133),
+	comp2(-7905747460161236407,	658812288346769700),
+	comp2(-3180473116156819245,	636094623231363848),
+	comp2(-8608480567731124088,	614891469123651720),
+	comp2(-8925843906633654008,	595056260442243600),
+	comp2(-1,	576460752303423487),
+	comp2(8943875914525843207,	558992244657865200),
+	comp2(-8680820740569200761,	542551296285575047),
+	comp2(8432797290838652167,	527049830677415760),
+	comp2(8198552921648689607,	512409557603043100),
+};
+
+uwide128 __intscan(FILE *f, unsigned base, int pok, uwide128 lim)
 {
 	const unsigned char *val = table+1;
 	int c, neg=0;
 	unsigned x;
-	unsigned long long y;
+	uint64_t z;
+	uwide128 y;
 	if (base > 36 || base == 1) {
 		errno = EINVAL;
-		return 0;
+		return uwide128_zero;
 	}
 	while (isspace((c=shgetc(f))));
 	if (c=='+' || c=='-') {
@@ -46,7 +91,7 @@ unsigned long long __intscan(FILE *f, unsigned base, int pok, unsigned long long
 				shunget(f);
 				if (pok) shunget(f);
 				else shlim(f, 0);
-				return 0;
+				return uwide128_zero;
 			}
 			base = 16;
 		} else if ((c|32)=='b' && base != 16) {
@@ -55,7 +100,7 @@ unsigned long long __intscan(FILE *f, unsigned base, int pok, unsigned long long
 				shunget(f);
 				if (pok) shunget(f);
 				else shlim(f, 0);
-				return 0;
+				return uwide128_zero;
 			}
 			base = 2;
 		} else if (base == 0) {
@@ -67,43 +112,59 @@ unsigned long long __intscan(FILE *f, unsigned base, int pok, unsigned long long
 			shunget(f);
 			shlim(f, 0);
 			errno = EINVAL;
-			return 0;
+			return uwide128_zero;
 		}
 	}
 	if (base == 10) {
 		for (x=0; c-'0'<10U && x<=UINT_MAX/10-1; c=shgetc(f))
 			x = x*10 + (c-'0');
-		for (y=x; c-'0'<10U && y<=ULLONG_MAX/10 && 10*y<=ULLONG_MAX-(c-'0'); c=shgetc(f))
-			y = y*10 + (c-'0');
+		for (z=x; c-'0'<10U && z<=UINT64_MAX/10-1; c=shgetc(f))
+			z = z*10 + (c-'0');
+		y=__uwide128_u64(x);
+		if (c-'0'<10U) {
+			uwide128 y10 = __uwide128_mul(y, 10);
+			while (c-'0'<10U
+				&& __uwide128_le(y, __uwide128_limit[10])
+				&& __uwide128_le(y10, __uwide128_sub(uwide128_max, (c-'0')))) {
+				y = __uwide128_add(y10, (c-'0'));
+				y10 = __uwide128_mul(y, 10);
+				c=shgetc(f);
+			}
+		}
 		if (c-'0'>=10U) goto done;
-	} else if (!(base & base-1)) {
-		int bs = "\0\1\2\4\7\3\6\5"[(0x17*base)>>5&7];
-		for (x=0; val[c]<base && x<=UINT_MAX/32; c=shgetc(f))
-			x = x<<bs | val[c];
-		for (y=x; val[c]<base && y<=ULLONG_MAX>>bs; c=shgetc(f))
-			y = y<<bs | val[c];
 	} else {
 		for (x=0; val[c]<base && x<=UINT_MAX/36-1; c=shgetc(f))
 			x = x*base + val[c];
-		for (y=x; val[c]<base && y<=ULLONG_MAX/base && base*y<=ULLONG_MAX-val[c]; c=shgetc(f))
-			y = y*base + val[c];
+		for (z=x; val[c]<base && z<=UINT64_MAX/36-1; c=shgetc(f))
+			z = z*base + val[c];
+		y=__uwide128_u64(z);
+		if (val[c]<base) {
+			uwide128 yBase = __uwide128_mul(y, base);
+			while (val[c]<base
+				&& __uwide128_le(y, __uwide128_limit[base])
+				&& __uwide128_le(yBase, __uwide128_sub(uwide128_max, val[c]))) {
+				y = __uwide128_add(yBase, val[c]);
+				yBase = __uwide128_mul(y, base);
+				c=shgetc(f);
+			}
+		}
 	}
 	if (val[c]<base) {
 		for (; val[c]<base; c=shgetc(f));
 		errno = ERANGE;
 		y = lim;
-		if (lim&1) neg = 0;
+		if (lim.v64[word64(0)]&1) neg = 0;
 	}
 done:
 	shunget(f);
-	if (y>=lim) {
-		if (!(lim&1) && !neg) {
+	if (__uwide128_le(lim, y)) {
+		if (!(lim.v64[word64(0)]&1) && !neg) {
 			errno = ERANGE;
-			return lim-1;
-		} else if (y>lim) {
+			return __uwide128_sub(lim, 1);
+		} else if (!__uwide128_le(y, lim)) {
 			errno = ERANGE;
 			return lim;
 		}
 	}
-	return (y^neg)-neg;
+	return neg ? __uwide128_neg(y) : y;
 }
diff --git a/src/internal/intscan.h b/src/internal/intscan.h
index ccf9f112..cf7a9d8f 100644
--- a/src/internal/intscan.h
+++ b/src/internal/intscan.h
@@ -1,8 +1,10 @@
 #ifndef INTSCAN_H
 #define INTSCAN_H
 
+#include "stdio_impl.h"
 #include <stdio.h>
+#include "uwide128.h"
 
-hidden unsigned long long __intscan(FILE *, unsigned, int, unsigned long long);
+hidden uwide128 __intscan(FILE *, unsigned, int, uwide128);
 
 #endif
diff --git a/src/stdio/vfscanf.c b/src/stdio/vfscanf.c
index f8ace92f..be922f82 100644
--- a/src/stdio/vfscanf.c
+++ b/src/stdio/vfscanf.c
@@ -18,25 +18,29 @@
 #define SIZE_l   1
 #define SIZE_L   2
 #define SIZE_ll  3
+#define SIZE_128 4
 
-static void store_int(void *dest, int size, unsigned long long i)
+static void store_int(void *dest, int size, uwide128 i)
 {
 	if (!dest) return;
 	switch (size) {
 	case SIZE_hh:
-		*(char *)dest = i;
+		*(char *)dest = i.v64[lo64];
 		break;
 	case SIZE_h:
-		*(short *)dest = i;
+		*(short *)dest = i.v64[lo64];
 		break;
 	case SIZE_def:
-		*(int *)dest = i;
+		*(int *)dest = i.v64[lo64];
 		break;
 	case SIZE_l:
-		*(long *)dest = i;
+		*(long *)dest = i.v64[lo64];
 		break;
 	case SIZE_ll:
-		*(long long *)dest = i;
+		*(long long *)dest = i.v64[lo64];
+		break;
+	case SIZE_128:
+		*(uwide128 *)dest = i;
 		break;
 	}
 }
@@ -77,7 +81,7 @@ int vfscanf(FILE *restrict f, const char *restrict fmt, va_list ap)
 	void *dest=NULL;
 	int invert;
 	int matches=0;
-	unsigned long long x;
+	uwide128 x;
 	long double y;
 	off_t pos = 0;
 	unsigned char scanset[257];
@@ -178,6 +182,7 @@ int vfscanf(FILE *restrict f, const char *restrict fmt, va_list ap)
 #else
 			case 64: size = SIZE_ll; break;
 #endif
+			case 128: size = SIZE_128; break;
 			}
 			break;
 		case 'b': case 'd': case 'i': case 'o': case 'u': case 'x':
@@ -206,7 +211,7 @@ int vfscanf(FILE *restrict f, const char *restrict fmt, va_list ap)
 		case '[':
 			break;
 		case 'n':
-			store_int(dest, size, pos);
+			store_int(dest, size, __uwide128_u64(pos));
 			/* do not increment match count, etc! */
 			continue;
 		default:
@@ -326,9 +331,9 @@ int vfscanf(FILE *restrict f, const char *restrict fmt, va_list ap)
 		case 'i':
 			base = 0;
 		int_common:
-			x = __intscan(f, base, 0, ULLONG_MAX);
+			x = __intscan(f, base, 0, UWIDE128_MAX);
 			if (!shcnt(f)) goto match_fail;
-			if (t=='p' && dest) *(void **)dest = (void *)(uintptr_t)x;
+			if (t=='p' && dest) *(void **)dest = (void *)(uintptr_t)x.v64[lo64];
 			else store_int(dest, size, x);
 			break;
 		case 'a': case 'A':
diff --git a/src/stdio/vfwscanf.c b/src/stdio/vfwscanf.c
index 6fe2749c..f70d83a1 100644
--- a/src/stdio/vfwscanf.c
+++ b/src/stdio/vfwscanf.c
@@ -18,25 +18,29 @@
 #define SIZE_l   1
 #define SIZE_L   2
 #define SIZE_ll  3
+#define SIZE_128 4
 
-static void store_int(void *dest, int size, unsigned long long i)
+static void store_int(void *dest, int size, uwide128 i)
 {
 	if (!dest) return;
 	switch (size) {
 	case SIZE_hh:
-		*(char *)dest = i;
+		*(char *)dest = i.v64[lo64];
 		break;
 	case SIZE_h:
-		*(short *)dest = i;
+		*(short *)dest = i.v64[lo64];
 		break;
 	case SIZE_def:
-		*(int *)dest = i;
+		*(int *)dest = i.v64[lo64];
 		break;
 	case SIZE_l:
-		*(long *)dest = i;
+		*(long *)dest = i.v64[lo64];
 		break;
 	case SIZE_ll:
-		*(long long *)dest = i;
+		*(long long *)dest = i.v64[lo64];
+		break;
+	case SIZE_128:
+		*(uwide128 *)dest = i;
 		break;
 	}
 }
@@ -201,6 +205,7 @@ int vfwscanf(FILE *restrict f, const wchar_t *restrict fmt, va_list ap)
 #else
 			case 64: size = SIZE_ll; break;
 #endif
+			case 128: size = SIZE_128; break;
 			}
 			break;
 		case 'b': case 'd': case 'i': case 'o': case 'u': case 'x':
@@ -234,7 +239,7 @@ int vfwscanf(FILE *restrict f, const wchar_t *restrict fmt, va_list ap)
 
 		switch (t) {
 		case 'n':
-			store_int(dest, size, pos);
+			store_int(dest, size, __uwide128_i64(pos));
 			/* do not increment match count, etc! */
 			continue;
 
diff --git a/src/stdlib/strtol.c b/src/stdlib/strtol.c
index bfefea69..db5acadb 100644
--- a/src/stdlib/strtol.c
+++ b/src/stdlib/strtol.c
@@ -5,12 +5,12 @@
 #include <limits.h>
 #include <ctype.h>
 
-static unsigned long long strtox(const char *s, char **p, int base, unsigned long long lim)
+static unsigned long long strtox(const char *s, char **p, int base, uwide128 lim)
 {
 	FILE f;
 	sh_fromstring(&f, s);
 	shlim(&f, 0);
-	unsigned long long y = __intscan(&f, base, 1, lim);
+	unsigned long long y = __intscan(&f, base, 1, lim).v64[lo64];
 	if (p) {
 		size_t cnt = shcnt(&f);
 		*p = (char *)s + cnt;
@@ -20,22 +20,22 @@ static unsigned long long strtox(const char *s, char **p, int base, unsigned lon
 
 unsigned long long strtoull(const char *restrict s, char **restrict p, int base)
 {
-	return strtox(s, p, base, ULLONG_MAX);
+	return strtox(s, p, base, __uwide128_u64(ULLONG_MAX));
 }
 
 long long strtoll(const char *restrict s, char **restrict p, int base)
 {
-	return strtox(s, p, base, LLONG_MIN);
+	return strtox(s, p, base, __uwide128_u64(0ULL+LLONG_MIN));
 }
 
 unsigned long strtoul(const char *restrict s, char **restrict p, int base)
 {
-	return strtox(s, p, base, ULONG_MAX);
+	return strtox(s, p, base, __uwide128_u64(ULONG_MAX));
 }
 
 long strtol(const char *restrict s, char **restrict p, int base)
 {
-	return strtox(s, p, base, 0UL+LONG_MIN);
+	return strtox(s, p, base, __uwide128_u64(0UL+LONG_MIN));
 }
 
 intmax_t strtoimax(const char *restrict s, char **restrict p, int base)
diff --git a/src/stdlib/wcstol.c b/src/stdlib/wcstol.c
index 1eeb495f..d7662562 100644
--- a/src/stdlib/wcstol.c
+++ b/src/stdlib/wcstol.c
@@ -29,7 +29,7 @@ static size_t do_read(FILE *f, unsigned char *buf, size_t len)
 	return 0;
 }
 
-static unsigned long long wcstox(const wchar_t *s, wchar_t **p, int base, unsigned long long lim)
+static unsigned long long wcstox(const wchar_t *s, wchar_t **p, int base, uwide128 lim)
 {
 	wchar_t *t = (wchar_t *)s;
 	unsigned char buf[64];
@@ -42,7 +42,7 @@ static unsigned long long wcstox(const wchar_t *s, wchar_t **p, int base, unsign
 	while (iswspace(*t)) t++;
 	f.cookie = (void *)t;
 	shlim(&f, 0);
-	unsigned long long y = __intscan(&f, base, 1, lim);
+	unsigned long long y = __intscan(&f, base, 1, lim).v64[lo64];
 	if (p) {
 		size_t cnt = shcnt(&f);
 		*p = cnt ? t + cnt : (wchar_t *)s;
@@ -52,22 +52,22 @@ static unsigned long long wcstox(const wchar_t *s, wchar_t **p, int base, unsign
 
 unsigned long long wcstoull(const wchar_t *restrict s, wchar_t **restrict p, int base)
 {
-	return wcstox(s, p, base, ULLONG_MAX);
+	return wcstox(s, p, base, __uwide128_u64(ULLONG_MAX));
 }
 
 long long wcstoll(const wchar_t *restrict s, wchar_t **restrict p, int base)
 {
-	return wcstox(s, p, base, LLONG_MIN);
+	return wcstox(s, p, base, __uwide128_u64(0ULL+LLONG_MIN));
 }
 
 unsigned long wcstoul(const wchar_t *restrict s, wchar_t **restrict p, int base)
 {
-	return wcstox(s, p, base, ULONG_MAX);
+	return wcstox(s, p, base, __uwide128_u64(ULONG_MAX));
 }
 
 long wcstol(const wchar_t *restrict s, wchar_t **restrict p, int base)
 {
-	return wcstox(s, p, base, 0UL+LONG_MIN);
+	return wcstox(s, p, base, __uwide128_u64(0UL+LONG_MIN));
 }
 
 intmax_t wcstoimax(const wchar_t *restrict s, wchar_t **restrict p, int base)
-- 
2.34.1


^ permalink raw reply	[flat|nested] 23+ messages in thread

* [musl] [C23 128 bit 4/4] C23: implement proper support for int128_t and uint128_t
  2023-05-31 14:15 [musl] [C23 128 bit 0/4] implement the library part of 128 bit support Jens Gustedt
                   ` (2 preceding siblings ...)
  2023-05-31 14:15 ` [musl] [C23 128 bit 3/4] C23: implement w128 and wf128 for scanf and similar Jens Gustedt
@ 2023-05-31 14:15 ` Jens Gustedt
  2023-05-31 14:27   ` Rich Felker
  3 siblings, 1 reply; 23+ messages in thread
From: Jens Gustedt @ 2023-05-31 14:15 UTC (permalink / raw)
  To: musl

By implementing support for w128 length specifiers for printf and
scanf, the only final bit that we need to be able to support these
types officially as extended integer type and map them to the
fixed-width types are the integer literals. In C23, the new types
`_IntBit(N)` and their literals are mandatory. Most commonly they will
support N >= 128. The maximum value for N can be queried with
`BITINT_MAXWIDTH`. If we have such literals, use them to construct the
constants for `[U]INT128_C` and provide the rest of the macros for
these types.
---
 include/inttypes.h | 55 ++++++++++++++++++++++++++++++++++++++++++++++
 include/stdint.h   | 37 +++++++++++++++++++++++++++++++
 2 files changed, 92 insertions(+)

diff --git a/include/inttypes.h b/include/inttypes.h
index 780c2bb0..0d81029b 100644
--- a/include/inttypes.h
+++ b/include/inttypes.h
@@ -272,6 +272,61 @@ uintmax_t wcstoumax(const wchar_t *__restrict, wchar_t **__restrict, int);
 #define SCNuPTR __PRIPTR "u"
 #define SCNxPTR __PRIPTR "x"
 
+#if __has_int128_t
+#define __PRILEAST128 "w128"
+
+#define PRIdLEAST128 __PRILEAST128 "d"
+#define PRIiLEAST128 __PRILEAST128 "i"
+#define PRIoLEAST128 __PRILEAST128 "o"
+#define PRIuLEAST128 __PRILEAST128 "u"
+#define PRIxLEAST128 __PRILEAST128 "x"
+#define PRIXLEAST128 __PRILEAST128 "X"
+#define PRIbLEAST128 __PRILEAST128 "b"
+#define PRIBLEAST128 __PRILEAST128 "B"
+
+#define SCNbLEAST128 __PRILEAST128 "b"
+#define SCNdLEAST128 __PRILEAST128 "d"
+#define SCNiLEAST128 __PRILEAST128 "i"
+#define SCNoLEAST128 __PRILEAST128 "o"
+#define SCNuLEAST128 __PRILEAST128 "u"
+#define SCNxLEAST128 __PRILEAST128 "x"
+
+#define PRId128 PRIdLEAST128
+#define PRIi128 PRIiLEAST128
+#define PRIo128 PRIoLEAST128
+#define PRIu128 PRIuLEAST128
+#define PRIx128 PRIxLEAST128
+#define PRIX128 PRIXLEAST128
+#define PRIb128 PRIbLEAST128
+#define PRIB128 PRIBLEAST128
+
+#define SCNb128 SCNbLEAST128
+#define SCNd128 SCNdLEAST128
+#define SCNi128 SCNiLEAST128
+#define SCNo128 SCNoLEAST128
+#define SCNu128 SCNuLEAST128
+#define SCNx128 SCNxLEAST128
+
+#define __PRIFAST128 "wf128"
+
+#define PRIdFAST128 __PRIFAST128 "d"
+#define PRIiFAST128 __PRIFAST128 "i"
+#define PRIoFAST128 __PRIFAST128 "o"
+#define PRIuFAST128 __PRIFAST128 "u"
+#define PRIxFAST128 __PRIFAST128 "x"
+#define PRIXFAST128 __PRIFAST128 "X"
+#define PRIbFAST128 __PRIFAST128 "b"
+#define PRIBFAST128 __PRIFAST128 "B"
+
+#define SCNbFAST128 __PRIFAST128 "b"
+#define SCNdFAST128 __PRIFAST128 "d"
+#define SCNiFAST128 __PRIFAST128 "i"
+#define SCNoFAST128 __PRIFAST128 "o"
+#define SCNuFAST128 __PRIFAST128 "u"
+#define SCNxFAST128 __PRIFAST128 "x"
+
+#endif
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/include/stdint.h b/include/stdint.h
index 1f68b3bb..8dda9991 100644
--- a/include/stdint.h
+++ b/include/stdint.h
@@ -187,4 +187,41 @@ typedef uint64_t uint_least64_t;
 #define BITINT_MAXWIDTH __BITINT_MAXWIDTH__
 #endif
 
+#if __has_int128_t
+typedef __int128 int128_t;
+typedef int128_t int_fast128_t;
+typedef int128_t int_least128_t;
+
+typedef unsigned __int128 uint128_t;
+typedef uint128_t uint_fast128_t;
+typedef uint128_t uint_least128_t;
+
+#define INT128_WIDTH  128
+#define INT_LEAST128_WIDTH  128
+#define INT_FAST128_WIDTH  128
+#define UINT128_WIDTH  128
+#define UINT_LEAST128_WIDTH  128
+#define UINT_FAST128_WIDTH  128
+
+// This uses the new integer constants for _BitInt(N) types for the
+// 128 bit type and is the only thing that we need in addition to the
+// types themselves to enable 128 bit support officially. Usually this
+// will not be fit for preprocessor arithmetic, but we should do an
+// effort to make this possible.
+#define INT128_C(X)  ((int128_t)+(X ## wb))
+#define UINT128_C(X)  ((uint128_t)+(X ## wbu))
+
+#define INT128_MAX  INT128_C(0x7fffffffffffffffffffffffffffffff)
+#define INT128_MIN  (-1-INT128_MAX)
+#define UINT128_MAX UINT128_C(0xffffffffffffffffffffffffffffffff)
+
+#define INT_LEAST128_MAX INT128_MAX
+#define INT_LEAST128_MIN INT128_MIN
+#define INT_FAST128_MAX INT128_MAX
+#define INT_FAST128_MIN INT128_MIN
+#define UINT_LEAST128_MAX UINT128_MAX
+#define UINT_FAST128_MAX UINT128_MAX
+
+#endif
+
 #endif
-- 
2.34.1


^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [musl] [C23 128 bit 4/4] C23: implement proper support for int128_t and uint128_t
  2023-05-31 14:15 ` [musl] [C23 128 bit 4/4] C23: implement proper support for int128_t and uint128_t Jens Gustedt
@ 2023-05-31 14:27   ` Rich Felker
  2023-05-31 14:29     ` Rich Felker
                       ` (2 more replies)
  0 siblings, 3 replies; 23+ messages in thread
From: Rich Felker @ 2023-05-31 14:27 UTC (permalink / raw)
  To: Jens Gustedt; +Cc: musl

On Wed, May 31, 2023 at 04:15:50PM +0200, Jens Gustedt wrote:
> By implementing support for w128 length specifiers for printf and
> scanf, the only final bit that we need to be able to support these
> types officially as extended integer type and map them to the
> fixed-width types are the integer literals. In C23, the new types
> `_IntBit(N)` and their literals are mandatory. Most commonly they will
> support N >= 128. The maximum value for N can be queried with
> `BITINT_MAXWIDTH`. If we have such literals, use them to construct the
> constants for `[U]INT128_C` and provide the rest of the macros for
> these types.

Unless the rules in C23 changed, I don't think yoou can define uintN_t
where N is larger than width of intmax_t; these can only be accessible
as _BitInt types not intN_t. (This was the whole reason _BitInt was
added, no?)

Rich

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [musl] [C23 128 bit 4/4] C23: implement proper support for int128_t and uint128_t
  2023-05-31 14:27   ` Rich Felker
@ 2023-05-31 14:29     ` Rich Felker
  2023-05-31 14:36     ` Jₑₙₛ Gustedt
  2023-05-31 14:42     ` Jₑₙₛ Gustedt
  2 siblings, 0 replies; 23+ messages in thread
From: Rich Felker @ 2023-05-31 14:29 UTC (permalink / raw)
  To: Jens Gustedt; +Cc: musl

On Wed, May 31, 2023 at 10:27:44AM -0400, Rich Felker wrote:
> On Wed, May 31, 2023 at 04:15:50PM +0200, Jens Gustedt wrote:
> > By implementing support for w128 length specifiers for printf and
> > scanf, the only final bit that we need to be able to support these
> > types officially as extended integer type and map them to the
> > fixed-width types are the integer literals. In C23, the new types
> > `_IntBit(N)` and their literals are mandatory. Most commonly they will
> > support N >= 128. The maximum value for N can be queried with
> > `BITINT_MAXWIDTH`. If we have such literals, use them to construct the
> > constants for `[U]INT128_C` and provide the rest of the macros for
> > these types.
> 
> Unless the rules in C23 changed, I don't think yoou can define uintN_t
> where N is larger than width of intmax_t; these can only be accessible
> as _BitInt types not intN_t. (This was the whole reason _BitInt was
> added, no?)

And, as I'm reading it, this also means printf and scanf do not need
to support w128. 7.23.6.1 ¶7:

    "All minimum-width integer types (7.22.1.2) and exact-width
    integer types (7.22.1.1) de- fined in the header <stdint.h> shall
    be supported. Other supported values of N are
    implementation-defined."

Rich

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [musl] [C23 128 bit 4/4] C23: implement proper support for int128_t and uint128_t
  2023-05-31 14:27   ` Rich Felker
  2023-05-31 14:29     ` Rich Felker
@ 2023-05-31 14:36     ` Jₑₙₛ Gustedt
  2023-05-31 14:41       ` Rich Felker
  2023-05-31 14:42     ` Jₑₙₛ Gustedt
  2 siblings, 1 reply; 23+ messages in thread
From: Jₑₙₛ Gustedt @ 2023-05-31 14:36 UTC (permalink / raw)
  To: Rich Felker; +Cc: musl

[-- Attachment #1: Type: text/plain, Size: 513 bytes --]

Rich,

on Wed, 31 May 2023 10:27:44 -0400 you (Rich Felker <dalias@libc.org>)
wrote:

> Unless the rules in C23 changed,

They did change, this is what this is all about.


Thanks
Jₑₙₛ

-- 
:: ICube :::::::::::::::::::::::::::::: deputy director ::
:: Université de Strasbourg :::::::::::::::::::::: ICPS ::
:: INRIA Nancy Grand Est :::::::::::::::::::::::: Camus ::
:: :::::::::::::::::::::::::::::::::::: ☎ +33 368854536 ::
:: https://icube-icps.unistra.fr/index.php/Jens_Gustedt ::

[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 195 bytes --]

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [musl] [C23 128 bit 4/4] C23: implement proper support for int128_t and uint128_t
  2023-05-31 14:36     ` Jₑₙₛ Gustedt
@ 2023-05-31 14:41       ` Rich Felker
  2023-05-31 14:55         ` Jₑₙₛ Gustedt
  0 siblings, 1 reply; 23+ messages in thread
From: Rich Felker @ 2023-05-31 14:41 UTC (permalink / raw)
  To: Jₑₙₛ Gustedt; +Cc: musl

On Wed, May 31, 2023 at 04:36:43PM +0200, Jₑₙₛ Gustedt wrote:
> Rich,
> 
> on Wed, 31 May 2023 10:27:44 -0400 you (Rich Felker <dalias@libc.org>)
> wrote:
> 
> > Unless the rules in C23 changed,
> 
> They did change, this is what this is all about.

Can you cite that? Because I don't see it. I still see that intmax_t
has to be at least as wide as all the intN_t. And AIUI this is the
whole reason _BitInt was added -- to give implementations the freedom
to add types larger than intmax_t.

Rich

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [musl] [C23 128 bit 4/4] C23: implement proper support for int128_t and uint128_t
  2023-05-31 14:27   ` Rich Felker
  2023-05-31 14:29     ` Rich Felker
  2023-05-31 14:36     ` Jₑₙₛ Gustedt
@ 2023-05-31 14:42     ` Jₑₙₛ Gustedt
  2023-05-31 14:47       ` Rich Felker
  2 siblings, 1 reply; 23+ messages in thread
From: Jₑₙₛ Gustedt @ 2023-05-31 14:42 UTC (permalink / raw)
  To: Rich Felker; +Cc: musl

[-- Attachment #1: Type: text/plain, Size: 1002 bytes --]

Rich,

on Wed, 31 May 2023 10:27:44 -0400 you (Rich Felker <dalias@libc.org>)
wrote:

> (This was the whole reason _BitInt was added, no?)

No, not at all. These are added to have

 - types for any width, not only multiples of 8
 - potentially have types that have thousands of bits (clang seems to
   be keen to do so)
 - types that have different rules for conversions, in particular no promotion.

These are explicitly not allowed to be used for the [u]intXXX_t types.

They only appear in the patches I propose as a means to encode number
literals of the appropriate width. These are used with casts, such
that they end up with the correct types.

Thanks
Jₑₙₛ

-- 
:: ICube :::::::::::::::::::::::::::::: deputy director ::
:: Université de Strasbourg :::::::::::::::::::::: ICPS ::
:: INRIA Nancy Grand Est :::::::::::::::::::::::: Camus ::
:: :::::::::::::::::::::::::::::::::::: ☎ +33 368854536 ::
:: https://icube-icps.unistra.fr/index.php/Jens_Gustedt ::

[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 195 bytes --]

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [musl] [C23 128 bit 4/4] C23: implement proper support for int128_t and uint128_t
  2023-05-31 14:42     ` Jₑₙₛ Gustedt
@ 2023-05-31 14:47       ` Rich Felker
  0 siblings, 0 replies; 23+ messages in thread
From: Rich Felker @ 2023-05-31 14:47 UTC (permalink / raw)
  To: Jₑₙₛ Gustedt; +Cc: musl

On Wed, May 31, 2023 at 04:42:54PM +0200, Jₑₙₛ Gustedt wrote:
> Rich,
> 
> on Wed, 31 May 2023 10:27:44 -0400 you (Rich Felker <dalias@libc.org>)
> wrote:
> 
> > (This was the whole reason _BitInt was added, no?)
> 
> No, not at all. These are added to have
> 
>  - types for any width, not only multiples of 8
>  - potentially have types that have thousands of bits (clang seems to
>    be keen to do so)
>  - types that have different rules for conversions, in particular no promotion.
> 
> These are explicitly not allowed to be used for the [u]intXXX_t types.
> 
> They only appear in the patches I propose as a means to encode number
> literals of the appropriate width. These are used with casts, such
> that they end up with the correct types.

OK, well the motivations behind _BitInt are really aside from the key
question here, which is whether intN_t wider than intmax_t is
permitted. As I read the spec, it's still not. And even if it were
permitted, I don't see where an int128_t type is mandated. J.5.6 even
gives __int128 as an example of an "other arithmetic type" that's not
an "extended integer type" by virtue of not aligning with the intmax_t
requirements.

Rich

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [musl] [C23 128 bit 4/4] C23: implement proper support for int128_t and uint128_t
  2023-05-31 14:41       ` Rich Felker
@ 2023-05-31 14:55         ` Jₑₙₛ Gustedt
  2023-05-31 14:57           ` Rich Felker
  0 siblings, 1 reply; 23+ messages in thread
From: Jₑₙₛ Gustedt @ 2023-05-31 14:55 UTC (permalink / raw)
  To: Rich Felker; +Cc: musl

[-- Attachment #1: Type: text/plain, Size: 1333 bytes --]

Rich,

on Wed, 31 May 2023 10:41:29 -0400 you (Rich Felker <dalias@libc.org>)
wrote:

> On Wed, May 31, 2023 at 04:36:43PM +0200, Jₑₙₛ Gustedt wrote:
> > Rich,
> > 
> > on Wed, 31 May 2023 10:27:44 -0400 you (Rich Felker
> > <dalias@libc.org>) wrote:
> >   
> > > Unless the rules in C23 changed,  
> > 
> > They did change, this is what this is all about.  
> 
> Can you cite that?

sure, almost by heart, since I wrote that ;-)

  … with the possible exceptions of signed bit-precise integer types
  and of signed extended integer types that are wider than `long long`
  and that are referred by the type definition for an exact width
  integer type

> Because I don't see it. I still see that intmax_t
> has to be at least as wide as all the intN_t.

I seems that you read that the wrong way around.

> And AIUI this is the whole reason _BitInt was added -- to give
> implementations the freedom to add types larger than intmax_t.

Nope, see my other mail.

Thanks
Jₑₙₛ

-- 
:: ICube :::::::::::::::::::::::::::::: deputy director ::
:: Université de Strasbourg :::::::::::::::::::::: ICPS ::
:: INRIA Nancy Grand Est :::::::::::::::::::::::: Camus ::
:: :::::::::::::::::::::::::::::::::::: ☎ +33 368854536 ::
:: https://icube-icps.unistra.fr/index.php/Jens_Gustedt ::

[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 195 bytes --]

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [musl] [C23 128 bit 4/4] C23: implement proper support for int128_t and uint128_t
  2023-05-31 14:55         ` Jₑₙₛ Gustedt
@ 2023-05-31 14:57           ` Rich Felker
  2023-05-31 15:07             ` Jₑₙₛ Gustedt
  0 siblings, 1 reply; 23+ messages in thread
From: Rich Felker @ 2023-05-31 14:57 UTC (permalink / raw)
  To: Jₑₙₛ Gustedt; +Cc: musl

On Wed, May 31, 2023 at 04:55:45PM +0200, Jₑₙₛ Gustedt wrote:
> Rich,
> 
> on Wed, 31 May 2023 10:41:29 -0400 you (Rich Felker <dalias@libc.org>)
> wrote:
> 
> > On Wed, May 31, 2023 at 04:36:43PM +0200, Jₑₙₛ Gustedt wrote:
> > > Rich,
> > > 
> > > on Wed, 31 May 2023 10:27:44 -0400 you (Rich Felker
> > > <dalias@libc.org>) wrote:
> > >   
> > > > Unless the rules in C23 changed,  
> > > 
> > > They did change, this is what this is all about.  
> > 
> > Can you cite that?
> 
> sure, almost by heart, since I wrote that ;-)
> 
>   … with the possible exceptions of signed bit-precise integer types
>   and of signed extended integer types that are wider than `long long`
>   and that are referred by the type definition for an exact width
>   integer type
> 
> > Because I don't see it. I still see that intmax_t
> > has to be at least as wide as all the intN_t.
> 
> I seems that you read that the wrong way around.

OK, so AIUI based on this exception it's permitted but not required to
offer int128_t.

Rich

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [musl] [C23 128 bit 4/4] C23: implement proper support for int128_t and uint128_t
  2023-05-31 14:57           ` Rich Felker
@ 2023-05-31 15:07             ` Jₑₙₛ Gustedt
  2023-05-31 15:14               ` Rich Felker
  0 siblings, 1 reply; 23+ messages in thread
From: Jₑₙₛ Gustedt @ 2023-05-31 15:07 UTC (permalink / raw)
  To: Rich Felker; +Cc: musl

[-- Attachment #1: Type: text/plain, Size: 1831 bytes --]

Rich,

on Wed, 31 May 2023 10:57:24 -0400 you (Rich Felker <dalias@libc.org>)
wrote:

> On Wed, May 31, 2023 at 04:55:45PM +0200, Jₑₙₛ Gustedt wrote:
> > Rich,
> > 
> > on Wed, 31 May 2023 10:41:29 -0400 you (Rich Felker
> > <dalias@libc.org>) wrote:
> >   
> > > On Wed, May 31, 2023 at 04:36:43PM +0200, Jₑₙₛ Gustedt wrote:  
>  [...]  
>  [...]  
>  [...]  
> > > 
> > > Can you cite that?  
> > 
> > sure, almost by heart, since I wrote that ;-)
> > 
> >   … with the possible exceptions of signed bit-precise integer types
> >   and of signed extended integer types that are wider than `long
> > long` and that are referred by the type definition for an exact
> > width integer type
> >   
> > > Because I don't see it. I still see that intmax_t
> > > has to be at least as wide as all the intN_t.  
> > 
> > I seems that you read that the wrong way around.  
> 
> OK, so AIUI based on this exception it's permitted but not required to
> offer int128_t.

yes

But compilers can never offer it if there is not minimal C library
support, which we are doing here. This is the only way we found in
yearlong discussions in WG14 to get us out of this intmax_t ABI trap.

For the 128 bit types in particular this answers numerous requests by
users who want to have these in different contexts and where quite
frustrated that compilers have these since decades but where not able
to announce them officially, not even as extended integer types.

Thanks
Jₑₙₛ

-- 
:: ICube :::::::::::::::::::::::::::::: deputy director ::
:: Université de Strasbourg :::::::::::::::::::::: ICPS ::
:: INRIA Nancy Grand Est :::::::::::::::::::::::: Camus ::
:: :::::::::::::::::::::::::::::::::::: ☎ +33 368854536 ::
:: https://icube-icps.unistra.fr/index.php/Jens_Gustedt ::

[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 195 bytes --]

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [musl] [C23 128 bit 4/4] C23: implement proper support for int128_t and uint128_t
  2023-05-31 15:07             ` Jₑₙₛ Gustedt
@ 2023-05-31 15:14               ` Rich Felker
  2023-05-31 15:37                 ` Jₑₙₛ Gustedt
  0 siblings, 1 reply; 23+ messages in thread
From: Rich Felker @ 2023-05-31 15:14 UTC (permalink / raw)
  To: Jₑₙₛ Gustedt; +Cc: musl

On Wed, May 31, 2023 at 05:07:00PM +0200, Jₑₙₛ Gustedt wrote:
> Rich,
> 
> on Wed, 31 May 2023 10:57:24 -0400 you (Rich Felker <dalias@libc.org>)
> wrote:
> 
> > On Wed, May 31, 2023 at 04:55:45PM +0200, Jₑₙₛ Gustedt wrote:
> > > Rich,
> > > 
> > > on Wed, 31 May 2023 10:41:29 -0400 you (Rich Felker
> > > <dalias@libc.org>) wrote:
> > >   
> > > > On Wed, May 31, 2023 at 04:36:43PM +0200, Jₑₙₛ Gustedt wrote:  
> >  [...]  
> >  [...]  
> >  [...]  
> > > > 
> > > > Can you cite that?  
> > > 
> > > sure, almost by heart, since I wrote that ;-)
> > > 
> > >   … with the possible exceptions of signed bit-precise integer types
> > >   and of signed extended integer types that are wider than `long
> > > long` and that are referred by the type definition for an exact
> > > width integer type
> > >   
> > > > Because I don't see it. I still see that intmax_t
> > > > has to be at least as wide as all the intN_t.  
> > > 
> > > I seems that you read that the wrong way around.  
> > 
> > OK, so AIUI based on this exception it's permitted but not required to
> > offer int128_t.
> 
> yes
> 
> But compilers can never offer it if there is not minimal C library
> support, which we are doing here. This is the only way we found in
> yearlong discussions in WG14 to get us out of this intmax_t ABI trap.
> 
> For the 128 bit types in particular this answers numerous requests by
> users who want to have these in different contexts and where quite
> frustrated that compilers have these since decades but where not able
> to announce them officially, not even as extended integer types.

OK, well this whole thread/topic then is a request/proposal for
extended functionality, not part of C23 support, and needs to be
considered as such.

I'm sorry there seems to have been a misunderstanding here. I'm trying
to understand where you're coming from, and I think now you were
probably looking at the intmax_t situation as if int128_t was
something we wanted to offer, but couldn't because of ABI
requirements. Whereas I was always looking at compounding library
support for larger and larger types as an odious requirement that
intmax_t helped us avoid.

I *do* think there is demand for being able to compute with
larger-than-int64 integer types, and this is a good thing, but it's a
problem _BitInt solves entirely without imposing any heavy library
requirements. I don't think "printing a 128 bit number in decimal" is
very useful functionality. Hex, maybe, but then 256+ is really what
you would want (for key material etc).

I'm sorry for sending you down a road of implementing this stuff in a
way that'd be plausible for inclusion in musl based on a
misunderstanding that it was a requirement for C23 support.

Rich

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [musl] [C23 128 bit 4/4] C23: implement proper support for int128_t and uint128_t
  2023-05-31 15:14               ` Rich Felker
@ 2023-05-31 15:37                 ` Jₑₙₛ Gustedt
  2023-05-31 15:40                   ` Rich Felker
  0 siblings, 1 reply; 23+ messages in thread
From: Jₑₙₛ Gustedt @ 2023-05-31 15:37 UTC (permalink / raw)
  To: Rich Felker; +Cc: musl

[-- Attachment #1: Type: text/plain, Size: 3418 bytes --]

Rich,

on Wed, 31 May 2023 11:14:06 -0400 you (Rich Felker <dalias@libc.org>)
wrote:

> On Wed, May 31, 2023 at 05:07:00PM +0200, Jₑₙₛ Gustedt wrote:
> > Rich,
> > 
> > on Wed, 31 May 2023 10:57:24 -0400 you (Rich Felker
> > <dalias@libc.org>) wrote:
> >   
> > > On Wed, May 31, 2023 at 04:55:45PM +0200, Jₑₙₛ Gustedt wrote:  
>  [...]  
>  [...]  
> > >  [...]  
> > >  [...]  
> > >  [...]    
>  [...]  
>  [...]  
>  [...]  
>  [...]  
> > > 
> > > OK, so AIUI based on this exception it's permitted but not
> > > required to offer int128_t.  
> > 
> > yes
> > 
> > But compilers can never offer it if there is not minimal C library
> > support, which we are doing here. This is the only way we found in
> > yearlong discussions in WG14 to get us out of this intmax_t ABI
> > trap.
> > 
> > For the 128 bit types in particular this answers numerous requests
> > by users who want to have these in different contexts and where
> > quite frustrated that compilers have these since decades but where
> > not able to announce them officially, not even as extended integer
> > types.  
> 
> OK, well this whole thread/topic then is a request/proposal for
> extended functionality, not part of C23 support, and needs to be
> considered as such.

That's a stretch. It is an optional feature, we implement other
optional features. This a feature that the C standard describes and
that we are able to provide with relatively low effort.

> I'm sorry there seems to have been a misunderstanding here. I'm trying
> to understand where you're coming from, and I think now you were
> probably looking at the intmax_t situation as if int128_t was
> something we wanted to offer, but couldn't because of ABI
> requirements. Whereas I was always looking at compounding library
> support for larger and larger types as an odious requirement that
> intmax_t helped us avoid.
> 
> I *do* think there is demand for being able to compute with
> larger-than-int64 integer types, and this is a good thing, but it's a
> problem _BitInt solves entirely without imposing any heavy library
> requirements. I don't think "printing a 128 bit number in decimal" is
> very useful functionality. Hex, maybe, but then 256+ is really what
> you would want (for key material etc).

I don't think that that particular feature is very useful
functionality, we agree on that. It is just part of the catalogue that
is needed to claim proper 128 bit support.

Other features are probably more useful, such as checked arithmetic
and the bit operation interfaces. These also come with C23, but for
_BitInt types only if there is a fixed width type with the same width.

> I'm sorry for sending you down a road of implementing this stuff in
> a way that'd be plausible for inclusion in musl based on a
> misunderstanding that it was a requirement for C23 support.

This will come in other C libraries, anyhow. And this is not an
extension outside the standard. The standard clearly describes how and
when this has to be or can be done.

Thanks
Jₑₙₛ

-- 
:: ICube :::::::::::::::::::::::::::::: deputy director ::
:: Université de Strasbourg :::::::::::::::::::::: ICPS ::
:: INRIA Nancy Grand Est :::::::::::::::::::::::: Camus ::
:: :::::::::::::::::::::::::::::::::::: ☎ +33 368854536 ::
:: https://icube-icps.unistra.fr/index.php/Jens_Gustedt ::

[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 195 bytes --]

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [musl] [C23 128 bit 4/4] C23: implement proper support for int128_t and uint128_t
  2023-05-31 15:37                 ` Jₑₙₛ Gustedt
@ 2023-05-31 15:40                   ` Rich Felker
  2023-05-31 15:56                     ` Jₑₙₛ Gustedt
  0 siblings, 1 reply; 23+ messages in thread
From: Rich Felker @ 2023-05-31 15:40 UTC (permalink / raw)
  To: Jₑₙₛ Gustedt; +Cc: musl

On Wed, May 31, 2023 at 05:37:18PM +0200, Jₑₙₛ Gustedt wrote:
> Rich,
> 
> on Wed, 31 May 2023 11:14:06 -0400 you (Rich Felker <dalias@libc.org>)
> wrote:
> 
> > On Wed, May 31, 2023 at 05:07:00PM +0200, Jₑₙₛ Gustedt wrote:
> > > Rich,
> > > 
> > > on Wed, 31 May 2023 10:57:24 -0400 you (Rich Felker
> > > <dalias@libc.org>) wrote:
> > >   
> > > > On Wed, May 31, 2023 at 04:55:45PM +0200, Jₑₙₛ Gustedt wrote:  
> >  [...]  
> >  [...]  
> > > >  [...]  
> > > >  [...]  
> > > >  [...]    
> >  [...]  
> >  [...]  
> >  [...]  
> >  [...]  
> > > > 
> > > > OK, so AIUI based on this exception it's permitted but not
> > > > required to offer int128_t.  
> > > 
> > > yes
> > > 
> > > But compilers can never offer it if there is not minimal C library
> > > support, which we are doing here. This is the only way we found in
> > > yearlong discussions in WG14 to get us out of this intmax_t ABI
> > > trap.
> > > 
> > > For the 128 bit types in particular this answers numerous requests
> > > by users who want to have these in different contexts and where
> > > quite frustrated that compilers have these since decades but where
> > > not able to announce them officially, not even as extended integer
> > > types.  
> > 
> > OK, well this whole thread/topic then is a request/proposal for
> > extended functionality, not part of C23 support, and needs to be
> > considered as such.
> 
> That's a stretch. It is an optional feature, we implement other
> optional features. This a feature that the C standard describes and
> that we are able to provide with relatively low effort.
> 
> > I'm sorry there seems to have been a misunderstanding here. I'm trying
> > to understand where you're coming from, and I think now you were
> > probably looking at the intmax_t situation as if int128_t was
> > something we wanted to offer, but couldn't because of ABI
> > requirements. Whereas I was always looking at compounding library
> > support for larger and larger types as an odious requirement that
> > intmax_t helped us avoid.
> > 
> > I *do* think there is demand for being able to compute with
> > larger-than-int64 integer types, and this is a good thing, but it's a
> > problem _BitInt solves entirely without imposing any heavy library
> > requirements. I don't think "printing a 128 bit number in decimal" is
> > very useful functionality. Hex, maybe, but then 256+ is really what
> > you would want (for key material etc).
> 
> I don't think that that particular feature is very useful
> functionality, we agree on that. It is just part of the catalogue that
> is needed to claim proper 128 bit support.

128-bit support is not a feature we've ever claimed.

> Other features are probably more useful, such as checked arithmetic
> and the bit operation interfaces. These also come with C23, but for
> _BitInt types only if there is a fixed width type with the same width.
> 
> > I'm sorry for sending you down a road of implementing this stuff in
> > a way that'd be plausible for inclusion in musl based on a
> > misunderstanding that it was a requirement for C23 support.
> 
> This will come in other C libraries, anyhow. And this is not an
> extension outside the standard. The standard clearly describes how and
> when this has to be or can be done.

Maybe it will, maybe not. musl is intentionally not on the bleeding
edge of doing extensions. We aim to support the things the standard
guarantees to be present, and things which there is compelling
existing support (by other implementations) and demand (by
applications) for.

Rich

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [musl] [C23 128 bit 4/4] C23: implement proper support for int128_t and uint128_t
  2023-05-31 15:40                   ` Rich Felker
@ 2023-05-31 15:56                     ` Jₑₙₛ Gustedt
  2023-05-31 16:30                       ` Alexander Monakov
  0 siblings, 1 reply; 23+ messages in thread
From: Jₑₙₛ Gustedt @ 2023-05-31 15:56 UTC (permalink / raw)
  To: Rich Felker; +Cc: musl

[-- Attachment #1: Type: text/plain, Size: 3830 bytes --]

Rich,

on Wed, 31 May 2023 11:40:43 -0400 you (Rich Felker <dalias@libc.org>)
wrote:

> On Wed, May 31, 2023 at 05:37:18PM +0200, Jₑₙₛ Gustedt wrote:
> > Rich,
> > 
> > on Wed, 31 May 2023 11:14:06 -0400 you (Rich Felker
> > <dalias@libc.org>) wrote:
> >   
> > > On Wed, May 31, 2023 at 05:07:00PM +0200, Jₑₙₛ Gustedt wrote:  
>  [...]  
>  [...]  
> > >  [...]  
> > >  [...]    
>  [...]  
> > >  [...]  
> > >  [...]  
> > >  [...]  
> > >  [...]    
>  [...]  
>  [...]  
> > > 
> > > OK, well this whole thread/topic then is a request/proposal for
> > > extended functionality, not part of C23 support, and needs to be
> > > considered as such.  
> > 
> > That's a stretch. It is an optional feature, we implement other
> > optional features. This a feature that the C standard describes and
> > that we are able to provide with relatively low effort.
> >   
> > > I'm sorry there seems to have been a misunderstanding here. I'm
> > > trying to understand where you're coming from, and I think now
> > > you were probably looking at the intmax_t situation as if
> > > int128_t was something we wanted to offer, but couldn't because
> > > of ABI requirements. Whereas I was always looking at compounding
> > > library support for larger and larger types as an odious
> > > requirement that intmax_t helped us avoid.
> > > 
> > > I *do* think there is demand for being able to compute with
> > > larger-than-int64 integer types, and this is a good thing, but
> > > it's a problem _BitInt solves entirely without imposing any heavy
> > > library requirements. I don't think "printing a 128 bit number in
> > > decimal" is very useful functionality. Hex, maybe, but then 256+
> > > is really what you would want (for key material etc).  
> > 
> > I don't think that that particular feature is very useful
> > functionality, we agree on that. It is just part of the catalogue
> > that is needed to claim proper 128 bit support.  
> 
> 128-bit support is not a feature we've ever claimed.

And I never said that.

> > Other features are probably more useful, such as checked arithmetic
> > and the bit operation interfaces. These also come with C23, but for
> > _BitInt types only if there is a fixed width type with the same
> > width. 
> > > I'm sorry for sending you down a road of implementing this stuff
> > > in a way that'd be plausible for inclusion in musl based on a
> > > misunderstanding that it was a requirement for C23 support.  
> > 
> > This will come in other C libraries, anyhow. And this is not an
> > extension outside the standard. The standard clearly describes how
> > and when this has to be or can be done.  
> 
> Maybe it will, maybe not. musl is intentionally not on the bleeding
> edge of doing extensions.

Again, this is not an extension but an optional feature, and this has
nothing of bleeding edge. This is present in compilers since ages, and
everybody is using their specific ways to go around the restrictions
of previous C standards.

> We aim to support the things the standard guarantees to be present,
> and things which there is compelling existing support (by other
> implementations) and demand (by applications) for.

This is just a hen-and-egg problem. You will never see demand for
[u]int128_t if you do not provide the tools. Everybody will just raise
their eyebrows, swear on how dammed retarded they think the C
committee would be, and then do some workaround.

Jₑₙₛ

-- 
:: ICube :::::::::::::::::::::::::::::: deputy director ::
:: Université de Strasbourg :::::::::::::::::::::: ICPS ::
:: INRIA Nancy Grand Est :::::::::::::::::::::::: Camus ::
:: :::::::::::::::::::::::::::::::::::: ☎ +33 368854536 ::
:: https://icube-icps.unistra.fr/index.php/Jens_Gustedt ::

[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 195 bytes --]

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [musl] [C23 128 bit 4/4] C23: implement proper support for int128_t and uint128_t
  2023-05-31 15:56                     ` Jₑₙₛ Gustedt
@ 2023-05-31 16:30                       ` Alexander Monakov
  2023-05-31 16:58                         ` Jens Gustedt
  0 siblings, 1 reply; 23+ messages in thread
From: Alexander Monakov @ 2023-05-31 16:30 UTC (permalink / raw)
  To: musl; +Cc: Rich Felker

[-- Attachment #1: Type: text/plain, Size: 576 bytes --]


On Wed, 31 May 2023, Jₑₙₛ Gustedt wrote:

> Again, this is not an extension but an optional feature, and this has
> nothing of bleeding edge. This is present in compilers since ages, and
> everybody is using their specific ways to go around the restrictions
> of previous C standards.

So, to make sure, by compiler support do you mean __int128 here? It is
not supported on 32-bit platforms neither by GCC nor by LLVM. On 64-bit
platforms it is piggy-backing on double-word operations support required
for implementing 64-bit 'long long' on 32-bit platforms.

Alexander

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [musl] [C23 128 bit 4/4] C23: implement proper support for int128_t and uint128_t
  2023-05-31 16:30                       ` Alexander Monakov
@ 2023-05-31 16:58                         ` Jens Gustedt
  2023-05-31 17:03                           ` Rich Felker
  2023-05-31 17:09                           ` Alexander Monakov
  0 siblings, 2 replies; 23+ messages in thread
From: Jens Gustedt @ 2023-05-31 16:58 UTC (permalink / raw)
  To: musl

Am 31. Mai 2023 18:30:16 MESZ schrieb Alexander Monakov <amonakov@ispras.ru>:
> 
> On Wed, 31 May 2023, Jₑₙₛ Gustedt wrote:
> 
> > Again, this is not an extension but an optional feature, and this has
> > nothing of bleeding edge. This is present in compilers since ages, and
> > everybody is using their specific ways to go around the restrictions
> > of previous C standards.
> 
> So, to make sure, by compiler support do you mean __int128 here?

yes

> It is
> not supported on 32-bit platforms neither by GCC nor by LLVM. On 64-bit
> platforms it is piggy-backing on double-word operations support required
> for implementing 64-bit 'long long' on 32-bit platforms.

So what? On the arch where it exist, it is used and useful. (And I also think that implementations improved over the state from 20 years ago that you describe.)

Nobody is talking about offering it on compilers where there is no support. With the proposed patches this becomes  an optional feature with feature tests. A real improvement for users, that up to now have to guess on their own.

Jens

-- 
Jens Gustedt - INRIA & ICube, Strasbourg, France

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [musl] [C23 128 bit 4/4] C23: implement proper support for int128_t and uint128_t
  2023-05-31 16:58                         ` Jens Gustedt
@ 2023-05-31 17:03                           ` Rich Felker
  2023-05-31 17:09                           ` Alexander Monakov
  1 sibling, 0 replies; 23+ messages in thread
From: Rich Felker @ 2023-05-31 17:03 UTC (permalink / raw)
  To: Jens Gustedt; +Cc: musl

On Wed, May 31, 2023 at 06:58:15PM +0200, Jens Gustedt wrote:
> Am 31. Mai 2023 18:30:16 MESZ schrieb Alexander Monakov <amonakov@ispras.ru>:
> > 
> > On Wed, 31 May 2023, Jₑₙₛ Gustedt wrote:
> > 
> > > Again, this is not an extension but an optional feature, and this has
> > > nothing of bleeding edge. This is present in compilers since ages, and
> > > everybody is using their specific ways to go around the restrictions
> > > of previous C standards.
> > 
> > So, to make sure, by compiler support do you mean __int128 here?
> 
> yes
> 
> > It is
> > not supported on 32-bit platforms neither by GCC nor by LLVM. On 64-bit
> > platforms it is piggy-backing on double-word operations support required
> > for implementing 64-bit 'long long' on 32-bit platforms.
> 
> So what? On the arch where it exist, it is used and useful. (And I
> also think that implementations improved over the state from 20
> years ago that you describe.)
> 
> Nobody is talking about offering it on compilers where there is no
> support. With the proposed patches this becomes an optional feature
> with feature tests. A real improvement for users, that up to now
> have to guess on their own.

_BitInt, and knowing the max available via BITINT_MAXWIDTH, provides
the same functionality to users without the burden on the library
implementation, which will necessarily keep doubling for the reason
Alexander mentioned -- once you have size N, size 2N gets added as a
consequence of supporting mul/div.

Nobody has been asking to be able to printf 128-bit numbers in
decimal. They've been asking to be able to use 128- or even 256-bit
integers in vector ops, crypto math, ipv6 routing, etc.

Rich

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [musl] [C23 128 bit 4/4] C23: implement proper support for int128_t and uint128_t
  2023-05-31 16:58                         ` Jens Gustedt
  2023-05-31 17:03                           ` Rich Felker
@ 2023-05-31 17:09                           ` Alexander Monakov
  2023-06-01  7:24                             ` Jₑₙₛ Gustedt
  1 sibling, 1 reply; 23+ messages in thread
From: Alexander Monakov @ 2023-05-31 17:09 UTC (permalink / raw)
  To: musl


On Wed, 31 May 2023, Jens Gustedt wrote:

> > It is
> > not supported on 32-bit platforms neither by GCC nor by LLVM. On 64-bit
> > platforms it is piggy-backing on double-word operations support required
> > for implementing 64-bit 'long long' on 32-bit platforms.
> 
> So what? On the arch where it exist, it is used and useful. (And I also think
> that implementations improved over the state from 20 years ago that you
> describe.)

Sorry, I'm not sure what you meant in the parenthetical statement. Improved
in what sense?

Alexander

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [musl] [C23 128 bit 4/4] C23: implement proper support for int128_t and uint128_t
  2023-05-31 17:09                           ` Alexander Monakov
@ 2023-06-01  7:24                             ` Jₑₙₛ Gustedt
  0 siblings, 0 replies; 23+ messages in thread
From: Jₑₙₛ Gustedt @ 2023-06-01  7:24 UTC (permalink / raw)
  To: Alexander Monakov; +Cc: musl

[-- Attachment #1: Type: text/plain, Size: 1274 bytes --]

Alexander,

on Wed, 31 May 2023 20:09:29 +0300 (MSK) you (Alexander Monakov
<amonakov@ispras.ru>) wrote:

> On Wed, 31 May 2023, Jens Gustedt wrote:
> 
> > So what? On the arch where it exist, it is used and useful. (And I
> > also think that implementations improved over the state from 20
> > years ago that you describe.)  
> 
> Sorry, I'm not sure what you meant in the parenthetical statement.
> Improved in what sense?

In the sense that depending on your -march=xxx settings they use all
low level operations that are available. IIRC, bit operation support
is e.g already quite good on most current x86_64, there is
specialization for multiplying or dividing a 128 bit integer with/by a
64 bit integer, and when I did these patches I have seen that division
by a small constant is quite good.

The composition of 64 bit operations is still used as a fallback where
no such native processor support is available, though.

Jₑₙₛ

-- 
:: ICube :::::::::::::::::::::::::::::: deputy director ::
:: Université de Strasbourg :::::::::::::::::::::: ICPS ::
:: INRIA Nancy Grand Est :::::::::::::::::::::::: Camus ::
:: :::::::::::::::::::::::::::::::::::: ☎ +33 368854536 ::
:: https://icube-icps.unistra.fr/index.php/Jens_Gustedt ::

[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 195 bytes --]

^ permalink raw reply	[flat|nested] 23+ messages in thread

end of thread, other threads:[~2023-06-01  7:24 UTC | newest]

Thread overview: 23+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-05-31 14:15 [musl] [C23 128 bit 0/4] implement the library part of 128 bit support Jens Gustedt
2023-05-31 14:15 ` [musl] [C23 128 bit 1/4] add an emulation for 128 bit arithmetic as needed for C library support Jens Gustedt
2023-05-31 14:15 ` [musl] [C23 128 bit 2/4] C23: implement w128 and wf128 support for printf Jens Gustedt
2023-05-31 14:15 ` [musl] [C23 128 bit 3/4] C23: implement w128 and wf128 for scanf and similar Jens Gustedt
2023-05-31 14:15 ` [musl] [C23 128 bit 4/4] C23: implement proper support for int128_t and uint128_t Jens Gustedt
2023-05-31 14:27   ` Rich Felker
2023-05-31 14:29     ` Rich Felker
2023-05-31 14:36     ` Jₑₙₛ Gustedt
2023-05-31 14:41       ` Rich Felker
2023-05-31 14:55         ` Jₑₙₛ Gustedt
2023-05-31 14:57           ` Rich Felker
2023-05-31 15:07             ` Jₑₙₛ Gustedt
2023-05-31 15:14               ` Rich Felker
2023-05-31 15:37                 ` Jₑₙₛ Gustedt
2023-05-31 15:40                   ` Rich Felker
2023-05-31 15:56                     ` Jₑₙₛ Gustedt
2023-05-31 16:30                       ` Alexander Monakov
2023-05-31 16:58                         ` Jens Gustedt
2023-05-31 17:03                           ` Rich Felker
2023-05-31 17:09                           ` Alexander Monakov
2023-06-01  7:24                             ` Jₑₙₛ Gustedt
2023-05-31 14:42     ` Jₑₙₛ Gustedt
2023-05-31 14:47       ` Rich Felker

Code repositories for project(s) associated with this public inbox

	https://git.vuxu.org/mirror/musl/

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).