LCOV - code coverage report
Current view: top level - src/utils - smp.c (source / functions) Hit Total Coverage
Test: FreeTDS coverage Lines: 99 103 96.1 %
Date: 2025-01-18 12:13:41 Functions: 12 12 100.0 %

          Line data    Source code
       1             : /* Simple multiprecision - small MP library for testing
       2             :  * Copyright (C) 2022-2024 Frediano Ziglio
       3             :  *
       4             :  * This library is free software; you can redistribute it and/or
       5             :  * modify it under the terms of the GNU Library General Public
       6             :  * License as published by the Free Software Foundation; either
       7             :  * version 2 of the License, or (at your option) any later version.
       8             :  *
       9             :  * This library is distributed in the hope that it will be useful,
      10             :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      11             :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      12             :  * Library General Public License for more details.
      13             :  *
      14             :  * You should have received a copy of the GNU Library General Public
      15             :  * License along with this library; if not, write to the
      16             :  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
      17             :  * Boston, MA 02111-1307, USA.
      18             :  */
      19             : 
      20             : #undef NDEBUG
      21             : #include <config.h>
      22             : 
      23             : #include <assert.h>
      24             : #include <string.h>
      25             : 
      26             : #include <freetds/utils/smp.h>
      27             : #include <freetds/sysdep_private.h>
      28             : 
      29             : #define SMP_NUM_COMPONENTS \
      30             :         (sizeof(((smp*)0)->comp) / sizeof(((smp*)0)->comp[0]))
      31             : 
      32             : const smp smp_zero = {
      33             :         { 0, 0, 0, 0, 0, 0, 0, 0 },
      34             : };
      35             : 
      36             : const smp smp_one = {
      37             :         { 1, 0, 0, 0, 0, 0, 0, 0 },
      38             : };
      39             : 
      40             : smp
      41     6052232 : smp_add(smp a, smp b)
      42             : {
      43             :         int i;
      44     6052232 :         uint32_t carry = 0;
      45             :         smp res;
      46             : 
      47    54470088 :         for (i = 0; i < SMP_NUM_COMPONENTS; ++i) {
      48    48417856 :                 uint32_t sum = carry + a.comp[i] + b.comp[i];
      49    48417856 :                 res.comp[i] = (uint16_t) (sum & 0xffffu);
      50    48417856 :                 carry = sum >> 16;
      51             :         }
      52     6052232 :         assert(smp_is_negative(a) != smp_is_negative(b) || smp_is_negative(a) == smp_is_negative(res));
      53     6052232 :         return res;
      54             : }
      55             : 
      56             : smp
      57      771848 : smp_not(smp a)
      58             : {
      59             :         int i;
      60             :         smp res;
      61     6946632 :         for (i = 0; i < SMP_NUM_COMPONENTS; ++i)
      62     6174784 :                 res.comp[i] = a.comp[i] ^ 0xffffu;
      63      771848 :         return res;
      64             : }
      65             : 
      66             : smp
      67      771848 : smp_negate(smp a)
      68             : {
      69      771848 :         return smp_add(smp_not(a), smp_one);
      70             : }
      71             : 
      72             : smp
      73     1445104 : smp_from_int(int64_t n)
      74             : {
      75             :         int i;
      76             :         uint64_t un;
      77             :         smp res;
      78             : 
      79     1445104 :         if (n >= 0) {
      80     1160120 :                 un = (uint64_t) n;
      81             :         } else {
      82      284984 :                 un = (uint64_t) -n;
      83             :         }
      84    11560832 :         for (i = 0; i < SMP_NUM_COMPONENTS; ++i) {
      85    11560832 :                 res.comp[i] = (uint16_t) (un & 0xffffu);
      86    11560832 :                 un = un >> 16;
      87             :         }
      88     1445104 :         if (n < 0)
      89      284984 :                 return smp_negate(res);
      90     1160120 :         return res;
      91             : }
      92             : 
      93             : bool
      94    23735752 : smp_is_negative(smp a)
      95             : {
      96    23735752 :         return (a.comp[SMP_NUM_COMPONENTS-1] >> 15) != 0;
      97             : }
      98             : 
      99             : bool
     100     6375480 : smp_is_zero(smp a)
     101             : {
     102             :         int i;
     103     6375480 :         uint16_t or = 0;
     104             : 
     105    57379320 :         for (i = 0; i < SMP_NUM_COMPONENTS; ++i)
     106    51003840 :                 or |= a.comp[i];
     107     6375480 :         return or == 0;
     108             : }
     109             : 
     110             : smp
     111         432 : smp_sub(smp a, smp b)
     112             : {
     113         432 :         smp c = smp_negate(b);
     114         432 :         return smp_add(a, c);
     115             : }
     116             : 
     117             : double
     118       95200 : smp_to_double(smp a)
     119             : {
     120             :         int i;
     121       95200 :         double n = 0;
     122       95200 :         double mult = 1.0;
     123       95200 :         smp b = a;
     124       95200 :         if (smp_is_negative(a))
     125       47504 :                 b = smp_negate(b);
     126      856800 :         for (i = 0; i < SMP_NUM_COMPONENTS; ++i) {
     127      761600 :                 n += b.comp[i] * mult;
     128      761600 :                 mult = mult * 65536.0;
     129             :         }
     130       95200 :         if (smp_is_negative(a))
     131       47504 :                 return -n;
     132             :         return n;
     133             : }
     134             : 
     135             : int
     136          24 : smp_cmp(smp a, smp b)
     137             : {
     138          24 :         smp diff = smp_sub(a, b);
     139          24 :         if (smp_is_negative(diff))
     140             :                 return -1;
     141          16 :         if (smp_is_zero(diff))
     142             :                 return 0;
     143           8 :         return 1;
     144             : }
     145             : 
     146             : // divide and return remainder
     147             : static uint16_t
     148             : div_small(smp *n, uint16_t div)
     149             : {
     150             :         int i;
     151     6349248 :         uint32_t remainder = 0;
     152    63492480 :         for (i = SMP_NUM_COMPONENTS; --i >= 0;) {
     153    50793984 :                 uint32_t comp = remainder * 0x10000u + n->comp[i];
     154    50793984 :                 remainder = comp % div;
     155    50793984 :                 n->comp[i] = (uint16_t) (comp / div);
     156             :         }
     157             :         return (uint16_t) remainder;
     158             : }
     159             : 
     160             : char *
     161      692416 : smp_to_string(smp a)
     162             : {
     163             :         char buf[SMP_NUM_COMPONENTS * 16 * 4 / 10 + 2];
     164      692416 :         char *p = buf+sizeof(buf);
     165      692416 :         const bool negative = smp_is_negative(a);
     166      692416 :         smp n = negative ? smp_negate(a) : a;
     167             : 
     168      692416 :         *--p = 0;
     169             :         do
     170     6349248 :                 *--p = div_small(&n, 10) + '0';
     171     6349248 :         while (!smp_is_zero(n));
     172      692416 :         if (negative)
     173      345304 :                 *--p = '-';
     174      692416 :         return strdup(p);
     175             : }
     176             : 
     177             : // multiple a number
     178             : static void
     179      843920 : mul_small(smp *n, uint16_t factor)
     180             : {
     181             :         int i;
     182      843920 :         uint32_t carry = 0;
     183     7595280 :         for (i = 0; i < SMP_NUM_COMPONENTS; ++i) {
     184     6751360 :                 uint32_t comp = (uint32_t) n->comp[i] * factor + carry;
     185     6751360 :                 carry = comp >> 16;
     186     6751360 :                 n->comp[i] = (uint16_t) (comp & 0xffffu);
     187             :         }
     188      843920 :         assert(carry == 0);
     189      843920 : }
     190             : 
     191             : smp
     192       91816 : smp_from_string(const char *s)
     193             : {
     194       91816 :         bool negative = false;
     195       91816 :         smp n = smp_zero;
     196       91816 :         uint16_t base = 10;
     197             : 
     198       91816 :         switch (*s) {
     199       45760 :         case '-':
     200       45760 :                 negative = true;
     201       45760 :         case '+':
     202       45760 :                 ++s;
     203             :         }
     204       91816 :         if (*s == '0') {
     205         264 :                 base = 8;
     206         264 :                 ++s;
     207         264 :                 if (*s == 'x' || *s == 'X') {
     208          48 :                         ++s;
     209          48 :                         base = 16;
     210             :                 }
     211             :         }
     212      844008 :         for (;*s; ++s) {
     213      844008 :                 int digit = 0;
     214      844008 :                 if (*s == '\'')
     215          88 :                         continue;
     216      843920 :                 mul_small(&n, base);
     217      843920 :                 if (*s >= '0' && *s <= '9')
     218      843920 :                         digit = *s - '0';
     219           0 :                 else if (*s >= 'a' && *s <= 'z')
     220           0 :                         digit = *s - 'a' + 10;
     221           0 :                 else if (*s >= 'A' && *s <= 'Z')
     222           0 :                         digit = *s - 'A' + 10;
     223             :                 else
     224             :                         assert(!!"Invalid digit entered");
     225      843920 :                 n = smp_add(n, smp_from_int(digit));
     226             :         }
     227       91816 :         if (negative)
     228       45760 :                 return smp_negate(n);
     229       46056 :         return n;
     230             : }

Generated by: LCOV version 1.13