(root)/
coreutils-9.4/
lib/
buffer-lcm.c
       1  /* buffer-lcm.c - compute a good buffer size for dealing with two files
       2  
       3     Copyright (C) 2002-2023 Free Software Foundation, Inc.
       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  /* Written by Paul Eggert.  */
      19  
      20  #include <config.h>
      21  #include "buffer-lcm.h"
      22  
      23  /* Return a buffer size suitable for doing I/O with files whose block
      24     sizes are A and B.  However, never return a value greater than
      25     LCM_MAX.  */
      26  
      27  size_t
      28  buffer_lcm (size_t a, size_t b, size_t lcm_max)
      29  {
      30    size_t size;
      31  
      32    /* Use reasonable values if buffer sizes are zero.  */
      33    if (!a)
      34      size = b ? b : 8 * 1024;
      35    else
      36      {
      37        if (b)
      38          {
      39            /* Return lcm (A, B) if it is in range; otherwise, fall back
      40               on A.  */
      41  
      42            size_t lcm, m, n, q, r;
      43  
      44            /* N = gcd (A, B).  */
      45            for (m = a, n = b;  (r = m % n) != 0;  m = n, n = r)
      46              continue;
      47  
      48            /* LCM = lcm (A, B), if in range.  */
      49            q = a / n;
      50            lcm = q * b;
      51            if (lcm <= lcm_max && lcm / b == q)
      52              return lcm;
      53          }
      54  
      55        size = a;
      56      }
      57  
      58    return size <= lcm_max ? size : lcm_max;
      59  }