Coverage Report

Created: 2026-01-25 07:18

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/gettext-0.26/gettext-tools/libgettextpo/gcd.c
Line
Count
Source
1
/* Arithmetic.
2
   Copyright (C) 2001-2002, 2006, 2009-2025 Free Software Foundation, Inc.
3
   Written by Bruno Haible <bruno@clisp.org>, 2001.
4
5
   This program is free software: you can redistribute it and/or modify
6
   it under the terms of the GNU General Public License as published by
7
   the Free Software Foundation, either version 3 of the License, or
8
   (at your option) any later version.
9
10
   This program is distributed in the hope that it will be useful,
11
   but WITHOUT ANY WARRANTY; without even the implied warranty of
12
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
   GNU General Public License for more details.
14
15
   You should have received a copy of the GNU General Public License
16
   along with this program.  If not, see <https://www.gnu.org/licenses/>.  */
17
18
#include <config.h>
19
20
/* This file can also be used to define gcd functions for other unsigned
21
   types, such as 'unsigned long long' or 'uintmax_t'.  */
22
#ifndef WORD_T
23
/* Specification.  */
24
# include "gcd.h"
25
0
# define WORD_T GCD_WORD_T
26
# define GCD gcd
27
#endif
28
29
#include <stdlib.h>
30
31
/* Return the greatest common divisor of a > 0 and b > 0.  */
32
WORD_T
33
GCD (WORD_T a, WORD_T b)
34
0
{
35
  /* Why no division, as in Euclid's algorithm? Because in Euclid's algorithm
36
     the division result floor(a/b) or floor(b/a) is very often = 1 or = 2,
37
     and nearly always < 8.  A sequence of a few subtractions and tests is
38
     faster than a division.  */
39
  /* Why not Euclid's algorithm? Because the two integers can be shifted by 1
40
     bit in a single instruction, and the algorithm uses fewer variables than
41
     Euclid's algorithm.  */
42
43
0
  WORD_T c = a | b;
44
0
  c = c ^ (c - 1);
45
  /* c = largest power of 2 that divides a and b.  */
46
47
0
  if (a & c)
48
0
    {
49
0
      if (b & c)
50
0
        goto odd_odd;
51
0
      else
52
0
        goto odd_even;
53
0
    }
54
0
  else
55
0
    {
56
0
      if (b & c)
57
0
        goto even_odd;
58
0
      else
59
0
        abort ();
60
0
    }
61
62
0
  for (;;)
63
0
    {
64
0
    odd_odd: /* a/c and b/c both odd */
65
0
      if (a == b)
66
0
        break;
67
0
      if (a > b)
68
0
        {
69
0
          a = a - b;
70
0
        even_odd: /* a/c even, b/c odd */
71
0
          do
72
0
            a = a >> 1;
73
0
          while ((a & c) == 0);
74
0
        }
75
0
      else
76
0
        {
77
0
          b = b - a;
78
0
        odd_even: /* a/c odd, b/c even */
79
0
          do
80
0
            b = b >> 1;
81
0
          while ((b & c) == 0);
82
0
        }
83
0
    }
84
85
  /* a = b */
86
0
  return a;
87
0
}