/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 | } |