Deutsch English Français Italiano |
<v8p1vm$9gap$1@dont-email.me> View for Bookmarking (what is this?) Look up another Usenet article |
Path: ...!eternal-september.org!feeder3.eternal-september.org!news.eternal-september.org!.POSTED!not-for-mail From: Thiago Adams <thiago.adams@gmail.com> Newsgroups: comp.lang.c Subject: portable stdckdint.h Date: Sun, 4 Aug 2024 20:13:58 -0300 Organization: A noiseless patient Spider Lines: 233 Message-ID: <v8p1vm$9gap$1@dont-email.me> MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8; format=flowed Content-Transfer-Encoding: 7bit Injection-Date: Mon, 05 Aug 2024 01:13:58 +0200 (CEST) Injection-Info: dont-email.me; posting-host="ab702b880a43e474045cfc9ac4338082"; logging-data="311641"; mail-complaints-to="abuse@eternal-september.org"; posting-account="U2FsdGVkX1/Za3eRdqaeDRBbWK+AB8sGgJvO1MYHvp8=" User-Agent: Mozilla Thunderbird Cancel-Lock: sha1:MFkA9n1ezyEOVDnbE2BMdEmzI4A= Content-Language: en-GB Bytes: 7606 I want to implement a portable stdckdint.h and use with MSVC. The problem when trying to implement it is the explosion of combinations. I think I found a way to keep it small (around 170 lines of code). It may not be the fastest code, but the goal is to keep it small and simple. The idea is to perform all computations using unsigned long long. For signed numbers, I change the sign and convert them to unsigned. I keep the sign information with two additional integer arguments: one for non-negative numbers (1 for zero or positive) and -1 for negative numbers and use this information at implementation. For instance a + b where a >= 0 and b < 0 becomes the operation using unsigned a - b *** The code is NOT TESTED YET. *** My objective is to show the strategy used to implement in few lines of code and get some feedback. -------------------------------------------------------------------------------- #include <stdio.h> #include <limits.h> struct R { unsigned long long result; int signal; }; struct R add(int sa, int sb, unsigned long long a, unsigned long long b) { if (sa > 0 && sb > 0) { if (a > ULLONG_MAX - b) return (struct R) { 0, 0 }; return (struct R) { a + b, 1 }; } if (sa < 0) { if (b < a) return (struct R) { 0, 0 }; return (struct R) { b - a, -1 }; } if (a < b) return (struct R) { 0, 0 }; return (struct R) { a - b, 1 }; } struct R sub(int sa, int sb, unsigned long long a, unsigned long long b) { if (sa > 0 && sb > 0) { //a positive //b positive //(1) - (2)= if (a > b) { //(2) - (1) return (struct R) { a-b, 1 }; } //(1)-(2) return (struct R) { b-a, -1 }; } if (sa < 0) { //a - b //a negative //b positive //(-1) - (+2)=-3 if (a > ULLONG_MAX - b) return (struct R) { 0, 0 }; return (struct R) { a+b, -1 }; } //a positive //b negative // (1)-(-2) = +3 if (a > ULLONG_MAX - b) return (struct R) { 0, 0 }; return (struct R) { a - b, 1 }; } struct R mul(int sa, int sb, unsigned long long a, unsigned long long b) { if (b == 0) return (struct R) { 0, 1 }; if (a > (ULLONG_MAX / b)) return (struct R) { 0, 0 }; return (struct R) { a*b, sa*sb }; } #define CHECK(T, PREFIX)\ _Bool PREFIX ## _check(T* r, struct R a)\ {\ if (a.signal == 0)\ return 1;\ if (a.result > -(PREFIX ## _MIN))\ return 1;\ if (a.result > PREFIX ## _MAX)\ return 1;\ *r = (T)a.result;\ return 0;\ } #define UCHECK(T, PREFIX)\ _Bool PREFIX ## _check(T* r, struct R a)\ {\ if (a.signal == 0)\ return 1;\ if (a.result > 0)\ return 1;\ if (a.result < PREFIX ## _MAX)\ return 0;\ *r = (T)a.result;\ return 0;\ } CHECK(signed char, CHAR) UCHECK(unsigned char, UCHAR) CHECK(signed short, SHRT) UCHECK(unsigned short, USHRT) CHECK(signed int, INT) UCHECK(unsigned int, UINT) CHECK(signed long, LONG) UCHECK(unsigned long, ULONG) CHECK(signed long long, LLONG) UCHECK(unsigned long long, ULLONG) #define ckc_add(r, a, b)\ _Generic(*(&r),\ signed char: CHAR_check(&r, add(a >= 0, b >= 0, (a < 0 ? -a : a), (b < 0 ? -b: b))),\ unsigned char: UCHAR_check(&r, add(a >= 0, b >= 0, (a < 0 ? -a : a), (b < 0 ? -b: b))),\ signed short: SHORT_check(&r, add(a >= 0, b >= 0, (a < 0 ? -a : a), (b < 0 ? -b: b))),\ unsigned short: USHORT_check(&r, add(a >= 0, b >= 0, (a < 0 ? -a : a), (b < 0 ? -b: b))),\ signed int : INT_check(&r, add(a >= 0, b >= 0, (a < 0 ? -a : a), (b < 0 ? -b: b))),\ unsigned int : UINT_check(&r, add(a >= 0, b >= 0, (a < 0 ? -a : a), (b < 0 ? -b: b))),\ signed long : LONG_check(&r, add(a >= 0, b >= 0, (a < 0 ? -a : a), (b < 0 ? -b: b))),\ unsigned long : ULONG_check(&r, add(a >= 0, b >= 0, (a < 0 ? -a : a), (b < 0 ? -b: b))),\ signed long long : LLONG_check(&r, add(a >= 0, b >= 0, (a < 0 ? -a : a), (b < 0 ? -b: b))),\ unsigned long long : ULLONG_check(&r, add(a >= 0, b >= 0, (a < 0 ? -a : a), (b < 0 ? -b: b)))\ ========== REMAINDER OF ARTICLE TRUNCATED ==========