portable stdckdint.h

Liste des GroupesRevenir à l c 
Sujet : portable stdckdint.h
De : thiago.adams (at) *nospam* gmail.com (Thiago Adams)
Groupes : comp.lang.c
Date : 05. Aug 2024, 01:13:58
Autres entêtes
Organisation : A noiseless patient Spider
Message-ID : <v8p1vm$9gap$1@dont-email.me>
User-Agent : Mozilla Thunderbird
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)))\
         )
#define ckc_sub(r, a, b)\
_Generic(*(&r),\
         signed char: CHAR_check(&r, sub(a >= 0, b >= 0, (a < 0 ? -a :
a), (b < 0 ? -b: b))),\
         unsigned char: UCHAR_check(&r, sub(a >= 0, b >= 0, (a < 0 ? -a :
a), (b < 0 ? -b: b))),\
         signed short: SHORT_check(&r, sub(a >= 0, b >= 0, (a < 0 ? -a :
a), (b < 0 ? -b: b))),\
         unsigned short: USHORT_check(&r, sub(a >= 0, b >= 0, (a < 0 ? -a
: a), (b < 0 ? -b: b))),\
         signed int : INT_check(&r, sub(a >= 0, b >= 0, (a < 0 ? -a : a),
(b < 0 ? -b: b))),\
         unsigned int : UINT_check(&r, sub(a >= 0, b >= 0, (a < 0 ? -a :
a), (b < 0 ? -b: b))),\
         signed long : LONG_check(&r, sub(a >= 0, b >= 0, (a < 0 ? -a :
a), (b < 0 ? -b: b))),\
         unsigned long : ULONG_check(&r, sub(a >= 0, b >= 0, (a < 0 ? -a
: a), (b < 0 ? -b: b))),\
         signed long long : LLONG_check(&r, sub(a >= 0, b >= 0, (a < 0 ?
-a : a), (b < 0 ? -b: b))),\
         unsigned long long : ULLONG_check(&r, sub(a >= 0, b >= 0, (a < 0
? -a : a), (b < 0 ? -b: b)))\
         )
#define ckc_mul(r, a, b)\
_Generic(*(&r),\
         signed char: CHAR_check(&r, mul(a >= 0, b >= 0, (a < 0 ? -a :
a), (b < 0 ? -b: b))),\
         unsigned char: UCHAR_check(&r, mul(a >= 0, b >= 0, (a < 0 ? -a :
a), (b < 0 ? -b: b))),\
         signed short: SHORT_check(&r, mul(a >= 0, b >= 0, (a < 0 ? -a :
a), (b < 0 ? -b: b))),\
         unsigned short: USHORT_check(&r, mul(a >= 0, b >= 0, (a < 0 ? -a
: a), (b < 0 ? -b: b))),\
         signed int : INT_check(&r, mul(a >= 0, b >= 0, (a < 0 ? -a : a),
(b < 0 ? -b: b))),\
         unsigned int : UINT_check(&r, mul(a >= 0, b >= 0, (a < 0 ? -a :
a), (b < 0 ? -b: b))),\
         signed long : LONG_check(&r, mul(a >= 0, b >= 0, (a < 0 ? -a :
a), (b < 0 ? -b: b))),\
         unsigned long : ULONG_check(&r, mul(a >= 0, b >= 0, (a < 0 ? -a
: a), (b < 0 ? -b: b))),\
         signed long long : LLONG_check(&r, mul(a >= 0, b >= 0, (a < 0 ?
-a : a), (b < 0 ? -b: b))),\
         unsigned long long : ULLONG_check(&r, mul(a >= 0, b >= 0, (a < 0
? -a : a), (b < 0 ? -b: b)))\
         )
-------------------------------------------------------------------

Date Sujet#  Auteur
5 Aug 24 o portable stdckdint.h1Thiago Adams

Haut de la page

Les messages affichés proviennent d'usenet.

NewsPortal