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 ==========