diff --git a/src/basic/hash-funcs.c b/src/basic/hash-funcs.c index db48437be7..6f6832d237 100644 --- a/src/basic/hash-funcs.c +++ b/src/basic/hash-funcs.c @@ -71,7 +71,7 @@ void trivial_hash_func(const void *p, struct siphash *state) { } int trivial_compare_func(const void *a, const void *b) { - return a < b ? -1 : (a > b ? 1 : 0); + return CMP(a, b); } const struct hash_ops trivial_hash_ops = { @@ -87,7 +87,7 @@ int uint64_compare_func(const void *_a, const void *_b) { uint64_t a, b; a = *(const uint64_t*) _a; b = *(const uint64_t*) _b; - return a < b ? -1 : (a > b ? 1 : 0); + return CMP(a, b); } const struct hash_ops uint64_hash_ops = { @@ -104,7 +104,7 @@ int devt_compare_func(const void *_a, const void *_b) { dev_t a, b; a = *(const dev_t*) _a; b = *(const dev_t*) _b; - return a < b ? -1 : (a > b ? 1 : 0); + return CMP(a, b); } const struct hash_ops devt_hash_ops = { diff --git a/src/basic/in-addr-util.c b/src/basic/in-addr-util.c index a21aa149f5..d83658eaa7 100644 --- a/src/basic/in-addr-util.c +++ b/src/basic/in-addr-util.c @@ -581,9 +581,11 @@ void in_addr_data_hash_func(const void *p, struct siphash *state) { int in_addr_data_compare_func(const void *a, const void *b) { const struct in_addr_data *x = a, *y = b; + int r; - if (x->family != y->family) - return x->family - y->family; + r = CMP(x->family, y->family); + if (r != 0) + return r; return memcmp(&x->address, &y->address, FAMILY_ADDRESS_SIZE(x->family)); } diff --git a/src/basic/macro.h b/src/basic/macro.h index 7e0f6b4ab5..24fcdc8400 100644 --- a/src/basic/macro.h +++ b/src/basic/macro.h @@ -7,7 +7,7 @@ #include #include -#define _printf_(a,b) __attribute__ ((format (printf, a, b))) +#define _printf_(a, b) __attribute__ ((format (printf, a, b))) #ifdef __clang__ # define _alloc_(...) #else @@ -22,8 +22,8 @@ #define _packed_ __attribute__ ((packed)) #define _malloc_ __attribute__ ((malloc)) #define _weak_ __attribute__ ((weak)) -#define _likely_(x) (__builtin_expect(!!(x),1)) -#define _unlikely_(x) (__builtin_expect(!!(x),0)) +#define _likely_(x) (__builtin_expect(!!(x), 1)) +#define _unlikely_(x) (__builtin_expect(!!(x), 0)) #define _public_ __attribute__ ((visibility("default"))) #define _hidden_ __attribute__ ((visibility("hidden"))) #define _weakref_(x) __attribute__((weakref(#x))) @@ -146,10 +146,10 @@ static inline unsigned long ALIGN_POWER2(unsigned long u) { # define VOID_0 ((void*)0) #endif -#define ELEMENTSOF(x) \ - __extension__ (__builtin_choose_expr( \ +#define ELEMENTSOF(x) \ + (__builtin_choose_expr( \ !__builtin_types_compatible_p(typeof(x), typeof(&*(x))), \ - sizeof(x)/sizeof((x)[0]), \ + sizeof(x)/sizeof((x)[0]), \ VOID_0)) /* @@ -167,23 +167,23 @@ static inline unsigned long ALIGN_POWER2(unsigned long u) { */ #define container_of(ptr, type, member) __container_of(UNIQ, (ptr), type, member) #define __container_of(uniq, ptr, type, member) \ - __extension__ ({ \ + ({ \ const typeof( ((type*)0)->member ) *UNIQ_T(A, uniq) = (ptr); \ - (type*)( (char *)UNIQ_T(A, uniq) - offsetof(type,member) ); \ + (type*)( (char *)UNIQ_T(A, uniq) - offsetof(type, member) ); \ }) #undef MAX #define MAX(a, b) __MAX(UNIQ, (a), UNIQ, (b)) #define __MAX(aq, a, bq, b) \ - __extension__ ({ \ + ({ \ const typeof(a) UNIQ_T(A, aq) = (a); \ const typeof(b) UNIQ_T(B, bq) = (b); \ - UNIQ_T(A,aq) > UNIQ_T(B,bq) ? UNIQ_T(A,aq) : UNIQ_T(B,bq); \ + UNIQ_T(A, aq) > UNIQ_T(B, bq) ? UNIQ_T(A, aq) : UNIQ_T(B, bq); \ }) /* evaluates to (void) if _A or _B are not constant or of different types */ #define CONST_MAX(_A, _B) \ - __extension__ (__builtin_choose_expr( \ + (__builtin_choose_expr( \ __builtin_constant_p(_A) && \ __builtin_constant_p(_B) && \ __builtin_types_compatible_p(typeof(_A), typeof(_B)), \ @@ -193,47 +193,56 @@ static inline unsigned long ALIGN_POWER2(unsigned long u) { /* takes two types and returns the size of the larger one */ #define MAXSIZE(A, B) (sizeof(union _packed_ { typeof(A) a; typeof(B) b; })) -#define MAX3(x,y,z) \ - __extension__ ({ \ - const typeof(x) _c = MAX(x,y); \ - MAX(_c, z); \ - }) +#define MAX3(x, y, z) \ + ({ \ + const typeof(x) _c = MAX(x, y); \ + MAX(_c, z); \ + }) #undef MIN #define MIN(a, b) __MIN(UNIQ, (a), UNIQ, (b)) #define __MIN(aq, a, bq, b) \ - __extension__ ({ \ + ({ \ const typeof(a) UNIQ_T(A, aq) = (a); \ const typeof(b) UNIQ_T(B, bq) = (b); \ - UNIQ_T(A,aq) < UNIQ_T(B,bq) ? UNIQ_T(A,aq) : UNIQ_T(B,bq); \ + UNIQ_T(A, aq) < UNIQ_T(B, bq) ? UNIQ_T(A, aq) : UNIQ_T(B, bq); \ }) -#define MIN3(x,y,z) \ - __extension__ ({ \ - const typeof(x) _c = MIN(x,y); \ - MIN(_c, z); \ - }) +#define MIN3(x, y, z) \ + ({ \ + const typeof(x) _c = MIN(x, y); \ + MIN(_c, z); \ + }) #define LESS_BY(a, b) __LESS_BY(UNIQ, (a), UNIQ, (b)) #define __LESS_BY(aq, a, bq, b) \ - __extension__ ({ \ + ({ \ const typeof(a) UNIQ_T(A, aq) = (a); \ const typeof(b) UNIQ_T(B, bq) = (b); \ - UNIQ_T(A,aq) > UNIQ_T(B,bq) ? UNIQ_T(A,aq) - UNIQ_T(B,bq) : 0; \ + UNIQ_T(A, aq) > UNIQ_T(B, bq) ? UNIQ_T(A, aq) - UNIQ_T(B, bq) : 0; \ + }) + +#define CMP(a, b) __CMP(UNIQ, (a), UNIQ, (b)) +#define __CMP(aq, a, bq, b) \ + ({ \ + const typeof(a) UNIQ_T(A, aq) = (a); \ + const typeof(b) UNIQ_T(B, bq) = (b); \ + UNIQ_T(A, aq) < UNIQ_T(B, bq) ? -1 : \ + UNIQ_T(A, aq) > UNIQ_T(B, bq) ? 1 : 0; \ }) #undef CLAMP #define CLAMP(x, low, high) __CLAMP(UNIQ, (x), UNIQ, (low), UNIQ, (high)) #define __CLAMP(xq, x, lowq, low, highq, high) \ - __extension__ ({ \ - const typeof(x) UNIQ_T(X,xq) = (x); \ - const typeof(low) UNIQ_T(LOW,lowq) = (low); \ - const typeof(high) UNIQ_T(HIGH,highq) = (high); \ - UNIQ_T(X,xq) > UNIQ_T(HIGH,highq) ? \ - UNIQ_T(HIGH,highq) : \ - UNIQ_T(X,xq) < UNIQ_T(LOW,lowq) ? \ - UNIQ_T(LOW,lowq) : \ - UNIQ_T(X,xq); \ + ({ \ + const typeof(x) UNIQ_T(X, xq) = (x); \ + const typeof(low) UNIQ_T(LOW, lowq) = (low); \ + const typeof(high) UNIQ_T(HIGH, highq) = (high); \ + UNIQ_T(X, xq) > UNIQ_T(HIGH, highq) ? \ + UNIQ_T(HIGH, highq) : \ + UNIQ_T(X, xq) < UNIQ_T(LOW, lowq) ? \ + UNIQ_T(LOW, lowq) : \ + UNIQ_T(X, xq); \ }) /* [(x + y - 1) / y] suffers from an integer overflow, even though the @@ -241,7 +250,7 @@ static inline unsigned long ALIGN_POWER2(unsigned long u) { * [x / y + !!(x % y)]. Note that on "Real CPUs" a division returns both the * quotient and the remainder, so both should be equally fast. */ #define DIV_ROUND_UP(_x, _y) \ - __extension__ ({ \ + ({ \ const typeof(_x) __x = (_x); \ const typeof(_y) __y = (_y); \ (__x / __y + !!(__x % __y)); \ diff --git a/src/basic/process-util.c b/src/basic/process-util.c index 0a5280eb24..d6ee8b62b8 100644 --- a/src/basic/process-util.c +++ b/src/basic/process-util.c @@ -1108,12 +1108,7 @@ int pid_compare_func(const void *a, const void *b) { const pid_t *p = a, *q = b; /* Suitable for usage in qsort() */ - - if (*p < *q) - return -1; - if (*p > *q) - return 1; - return 0; + return CMP(*p, *q); } int ioprio_parse_priority(const char *s, int *ret) { diff --git a/src/core/socket.c b/src/core/socket.c index aedbf51a4c..fb17b3be2d 100644 --- a/src/core/socket.c +++ b/src/core/socket.c @@ -484,11 +484,11 @@ static void peer_address_hash_func(const void *p, struct siphash *state) { static int peer_address_compare_func(const void *a, const void *b) { const SocketPeer *x = a, *y = b; + int r; - if (x->peer.sa.sa_family < y->peer.sa.sa_family) - return -1; - if (x->peer.sa.sa_family > y->peer.sa.sa_family) - return 1; + r = CMP(x->peer.sa.sa_family, y->peer.sa.sa_family); + if (r != 0) + return r; switch(x->peer.sa.sa_family) { case AF_INET: diff --git a/src/journal/catalog.c b/src/journal/catalog.c index f9118f0b62..4ae1136e86 100644 --- a/src/journal/catalog.c +++ b/src/journal/catalog.c @@ -59,12 +59,12 @@ static void catalog_hash_func(const void *p, struct siphash *state) { static int catalog_compare_func(const void *a, const void *b) { const CatalogItem *i = a, *j = b; unsigned k; + int r; for (k = 0; k < ELEMENTSOF(j->id.bytes); k++) { - if (i->id.bytes[k] < j->id.bytes[k]) - return -1; - if (i->id.bytes[k] > j->id.bytes[k]) - return 1; + r = CMP(i->id.bytes[k], j->id.bytes[k]); + if (r != 0) + return r; } return strcmp(i->language, j->language); diff --git a/src/libsystemd-network/lldp-neighbor.c b/src/libsystemd-network/lldp-neighbor.c index 5dcb051373..8295d4d404 100644 --- a/src/libsystemd-network/lldp-neighbor.c +++ b/src/libsystemd-network/lldp-neighbor.c @@ -26,22 +26,15 @@ static int lldp_neighbor_id_compare_func(const void *a, const void *b) { if (r != 0) return r; - if (x->chassis_id_size < y->chassis_id_size) - return -1; - - if (x->chassis_id_size > y->chassis_id_size) - return 1; + r = CMP(x->chassis_id_size, y->chassis_id_size); + if (r != 0) + return r; r = memcmp(x->port_id, y->port_id, MIN(x->port_id_size, y->port_id_size)); if (r != 0) return r; - if (x->port_id_size < y->port_id_size) - return -1; - if (x->port_id_size > y->port_id_size) - return 1; - - return 0; + return CMP(x->port_id_size, y->port_id_size); } const struct hash_ops lldp_neighbor_id_hash_ops = { @@ -52,13 +45,7 @@ const struct hash_ops lldp_neighbor_id_hash_ops = { int lldp_neighbor_prioq_compare_func(const void *a, const void *b) { const sd_lldp_neighbor *x = a, *y = b; - if (x->until < y->until) - return -1; - - if (x->until > y->until) - return 1; - - return 0; + return CMP(x->until, y->until); } _public_ sd_lldp_neighbor *sd_lldp_neighbor_ref(sd_lldp_neighbor *n) { diff --git a/src/libsystemd-network/sd-dhcp-server.c b/src/libsystemd-network/sd-dhcp-server.c index 5ca46b3502..d91849f379 100644 --- a/src/libsystemd-network/sd-dhcp-server.c +++ b/src/libsystemd-network/sd-dhcp-server.c @@ -125,6 +125,7 @@ void client_id_hash_func(const void *p, struct siphash *state) { int client_id_compare_func(const void *_a, const void *_b) { const DHCPClientId *a, *b; + int r; a = _a; b = _b; @@ -132,8 +133,9 @@ int client_id_compare_func(const void *_a, const void *_b) { assert(!a->length || a->data); assert(!b->length || b->data); - if (a->length != b->length) - return a->length < b->length ? -1 : 1; + r = CMP(a->length, b->length); + if (r != 0) + return r; return memcmp(a->data, b->data, a->length); } diff --git a/src/network/networkd-address.c b/src/network/networkd-address.c index 5bddf88e36..eae129b95c 100644 --- a/src/network/networkd-address.c +++ b/src/network/networkd-address.c @@ -144,19 +144,18 @@ static void address_hash_func(const void *b, struct siphash *state) { static int address_compare_func(const void *c1, const void *c2) { const Address *a1 = c1, *a2 = c2; + int r; - if (a1->family < a2->family) - return -1; - if (a1->family > a2->family) - return 1; + r = CMP(a1->family, a2->family); + if (r != 0) + return r; switch (a1->family) { /* use the same notion of equality as the kernel does */ case AF_INET: - if (a1->prefixlen < a2->prefixlen) - return -1; - if (a1->prefixlen > a2->prefixlen) - return 1; + r = CMP(a1->prefixlen, a2->prefixlen); + if (r != 0) + return r; /* compare the peer prefixes */ if (a1->prefixlen != 0) { @@ -174,10 +173,9 @@ static int address_compare_func(const void *c1, const void *c2) { else b2 = be32toh(a2->in_addr.in.s_addr) >> (32 - a1->prefixlen); - if (b1 < b2) - return -1; - if (b1 > b2) - return 1; + r = CMP(b1, b2); + if (r != 0) + return r; } _fallthrough_; diff --git a/src/network/networkd-network.c b/src/network/networkd-network.c index c8f7c4f98a..77ba8c678e 100644 --- a/src/network/networkd-network.c +++ b/src/network/networkd-network.c @@ -36,12 +36,7 @@ static int network_config_compare_func(const void *a, const void *b) { if (r != 0) return r; - if (x->line < y->line) - return -1; - if (x->line > y->line) - return 1; - - return 0; + return CMP(x->line, y->line); } const struct hash_ops network_config_hash_ops = { diff --git a/src/network/networkd-route.c b/src/network/networkd-route.c index b335fdb1bb..aa86ce792d 100644 --- a/src/network/networkd-route.c +++ b/src/network/networkd-route.c @@ -164,34 +164,30 @@ static void route_hash_func(const void *b, struct siphash *state) { static int route_compare_func(const void *_a, const void *_b) { const Route *a = _a, *b = _b; + int r; - if (a->family < b->family) - return -1; - if (a->family > b->family) - return 1; + r = CMP(a->family, b->family); + if (r != 0) + return r; switch (a->family) { case AF_INET: case AF_INET6: - if (a->dst_prefixlen < b->dst_prefixlen) - return -1; - if (a->dst_prefixlen > b->dst_prefixlen) - return 1; + r = CMP(a->dst_prefixlen, b->dst_prefixlen); + if (r != 0) + return r; - if (a->tos < b->tos) - return -1; - if (a->tos > b->tos) - return 1; + r = CMP(a->tos, b->tos); + if (r != 0) + return r; - if (a->priority < b->priority) - return -1; - if (a->priority > b->priority) - return 1; + r = CMP(a->priority, b->priority); + if (r != 0) + return r; - if (a->table < b->table) - return -1; - if (a->table > b->table) - return 1; + r = CMP(a->table, b->table); + if (r != 0) + return r; return memcmp(&a->dst, &b->dst, FAMILY_ADDRESS_SIZE(a->family)); default: diff --git a/src/network/networkd-routing-policy-rule.c b/src/network/networkd-routing-policy-rule.c index 650ea0af52..dbb06a8074 100644 --- a/src/network/networkd-routing-policy-rule.c +++ b/src/network/networkd-routing-policy-rule.c @@ -92,38 +92,32 @@ static int routing_policy_rule_compare_func(const void *_a, const void *_b) { const RoutingPolicyRule *a = _a, *b = _b; int r; - if (a->family < b->family) - return -1; - if (a->family > b->family) - return 1; + r = CMP(a->family, b->family); + if (r != 0) + return r; switch (a->family) { case AF_INET: case AF_INET6: - if (a->from_prefixlen < b->from_prefixlen) - return -1; - if (a->from_prefixlen > b->from_prefixlen) - return 1; + r = CMP(a->from_prefixlen, b->from_prefixlen); + if (r != 0) + return r; - if (a->to_prefixlen < b->to_prefixlen) - return -1; - if (a->to_prefixlen > b->to_prefixlen) - return 1; + r = CMP(a->to_prefixlen, b->to_prefixlen); + if (r != 0) + return r; - if (a->tos < b->tos) - return -1; - if (a->tos > b->tos) - return 1; + r = CMP(a->tos, b->tos); + if (r != 0) + return r; - if (a->fwmask < b->fwmark) - return -1; - if (a->fwmask > b->fwmark) - return 1; + r = CMP(a->fwmask, b->fwmask); + if (r != 0) + return r; - if (a->table < b->table) - return -1; - if (a->table > b->table) - return 1; + r = CMP(a->table, b->table); + if (r != 0) + return r; r = strcmp_ptr(a->iif, b->iif); if (!r) diff --git a/src/resolve/resolved-dns-cache.c b/src/resolve/resolved-dns-cache.c index 403d23d4fb..95e9e072c1 100644 --- a/src/resolve/resolved-dns-cache.c +++ b/src/resolve/resolved-dns-cache.c @@ -228,11 +228,7 @@ void dns_cache_prune(DnsCache *c) { static int dns_cache_item_prioq_compare_func(const void *a, const void *b) { const DnsCacheItem *x = a, *y = b; - if (x->until < y->until) - return -1; - if (x->until > y->until) - return 1; - return 0; + return CMP(x->until, y->until); } static int dns_cache_init(DnsCache *c) { diff --git a/src/resolve/resolved-dns-packet.c b/src/resolve/resolved-dns-packet.c index 097942ee0a..2cc606f363 100644 --- a/src/resolve/resolved-dns-packet.c +++ b/src/resolve/resolved-dns-packet.c @@ -2339,11 +2339,11 @@ static void dns_packet_hash_func(const void *p, struct siphash *state) { static int dns_packet_compare_func(const void *a, const void *b) { const DnsPacket *x = a, *y = b; + int r; - if (x->size < y->size) - return -1; - if (x->size > y->size) - return 1; + r = CMP(x->size, y->size); + if (r != 0) + return r; return memcmp(DNS_PACKET_DATA((DnsPacket*) x), DNS_PACKET_DATA((DnsPacket*) y), x->size); } diff --git a/src/resolve/resolved-dns-rr.c b/src/resolve/resolved-dns-rr.c index cfd0ed214d..e6d997ed97 100644 --- a/src/resolve/resolved-dns-rr.c +++ b/src/resolve/resolved-dns-rr.c @@ -300,15 +300,13 @@ static int dns_resource_key_compare_func(const void *a, const void *b) { if (ret != 0) return ret; - if (x->type < y->type) - return -1; - if (x->type > y->type) - return 1; + ret = CMP(x->type, y->type); + if (ret != 0) + return ret; - if (x->class < y->class) - return -1; - if (x->class > y->class) - return 1; + ret = CMP(x->class, y->class); + if (ret != 0) + return ret; return 0; } @@ -1515,10 +1513,9 @@ static int dns_resource_record_compare_func(const void *a, const void *b) { if (dns_resource_record_equal(x, y)) return 0; - /* This is a bit dirty, we don't implement proper ordering, but - * the hashtable doesn't need ordering anyway, hence we don't - * care. */ - return x < y ? -1 : 1; + /* We still use CMP() here, even though don't implement proper + * ordering, since the hashtable doesn't need ordering anyway. */ + return CMP(x, y); } const struct hash_ops dns_resource_record_hash_ops = { diff --git a/src/resolve/resolved-dns-server.c b/src/resolve/resolved-dns-server.c index eff3dbb275..24164362c4 100644 --- a/src/resolve/resolved-dns-server.c +++ b/src/resolve/resolved-dns-server.c @@ -624,19 +624,17 @@ static int dns_server_compare_func(const void *a, const void *b) { const DnsServer *x = a, *y = b; int r; - if (x->family < y->family) - return -1; - if (x->family > y->family) - return 1; + r = CMP(x->family, y->family); + if (r != 0) + return r; r = memcmp(&x->address, &y->address, FAMILY_ADDRESS_SIZE(x->family)); if (r != 0) return r; - if (x->ifindex < y->ifindex) - return -1; - if (x->ifindex > y->ifindex) - return 1; + r = CMP(x->ifindex, y->ifindex); + if (r != 0) + return r; return 0; } diff --git a/src/shared/dns-domain.c b/src/shared/dns-domain.c index e7730a5175..1ecfb77de2 100644 --- a/src/shared/dns-domain.c +++ b/src/shared/dns-domain.c @@ -503,7 +503,7 @@ int dns_name_compare_func(const void *a, const void *b) { r = dns_label_unescape_suffix(a, &x, la, sizeof(la)); q = dns_label_unescape_suffix(b, &y, lb, sizeof(lb)); if (r < 0 || q < 0) - return r - q; + return CMP(r, q); r = ascii_strcasecmp_nn(la, r, lb, q); if (r != 0) diff --git a/src/test/test-util.c b/src/test/test-util.c index 4d3e5c5b94..7c645d7742 100644 --- a/src/test/test-util.c +++ b/src/test/test-util.c @@ -53,6 +53,12 @@ static void test_max(void) { .a = CONST_MAX(10, 100), }; int d = 0; + unsigned long x = 12345; + unsigned long y = 54321; + const char str[] = "a_string_constant"; + const unsigned long long arr[] = {9999ULL, 10ULL, 0ULL, 3000ULL, 2000ULL, 1000ULL, 100ULL, 9999999ULL}; + void *p = (void *)str; + void *q = (void *)&str[16]; assert_cc(sizeof(val1.b) == sizeof(int) * 100); @@ -80,6 +86,35 @@ static void test_max(void) { assert_se(LESS_BY(4, 8) == 0); assert_se(LESS_BY(16, LESS_BY(8, 4)) == 12); assert_se(LESS_BY(4, LESS_BY(8, 4)) == 0); + assert_se(CMP(-5, 5) == -1); + assert_se(CMP(5, -5) == 1); + assert_se(CMP(5, 5) == 0); + assert_se(CMP(x, y) == -1); + assert_se(CMP(y, x) == 1); + assert_se(CMP(x, x) == 0); + assert_se(CMP(y, y) == 0); + assert_se(CMP(UINT64_MAX, 0L) == 1); + assert_se(CMP(0L, UINT64_MAX) == -1); + assert_se(CMP(UINT64_MAX, UINT64_MAX) == 0); + assert_se(CMP(INT64_MIN, INT64_MAX) == -1); + assert_se(CMP(INT64_MAX, INT64_MIN) == 1); + assert_se(CMP(INT64_MAX, INT64_MAX) == 0); + assert_se(CMP(INT64_MIN, INT64_MIN) == 0); + assert_se(CMP(INT64_MAX, 0L) == 1); + assert_se(CMP(0L, INT64_MIN) == 1); + assert_se(CMP(INT64_MIN, 0L) == -1); + assert_se(CMP(0L, INT64_MAX) == -1); + assert_se(CMP(&str[2], &str[7]) == -1); + assert_se(CMP(&str[2], &str[2]) == 0); + assert_se(CMP(&str[7], (const char *)str) == 1); + assert_se(CMP(str[2], str[7]) == 1); + assert_se(CMP(str[7], *str) == 1); + assert_se(CMP((const unsigned long long *)arr, &arr[3]) == -1); + assert_se(CMP(*arr, arr[3]) == 1); + assert_se(CMP(p, q) == -1); + assert_se(CMP(q, p) == 1); + assert_se(CMP(p, p) == 0); + assert_se(CMP(q, q) == 0); assert_se(CLAMP(-5, 0, 1) == 0); assert_se(CLAMP(5, 0, 1) == 1); assert_se(CLAMP(5, -10, 1) == 1);