LCOV - code coverage report
Current view: top level - src/grpp - grpp_binomial.c (source / functions) Coverage Total Hit
Test: CP2K Regtests (git:936074a) Lines: 91.2 % 34 31
Test Date: 2025-12-04 06:27:48 Functions: 100.0 % 2 2

            Line data    Source code
       1              : /*----------------------------------------------------------------------------*/
       2              : /*  CP2K: A general program to perform molecular dynamics simulations         */
       3              : /*  Copyright 2000-2025 CP2K developers group <https://cp2k.org>              */
       4              : /*                                                                            */
       5              : /*  SPDX-License-Identifier: MIT                                              */
       6              : /*----------------------------------------------------------------------------*/
       7              : 
       8              : /*
       9              :  *  libgrpp - a library for the evaluation of integrals over
      10              :  *            generalized relativistic pseudopotentials.
      11              :  *
      12              :  *  Copyright (C) 2021-2023 Alexander Oleynichenko
      13              :  */
      14              : 
      15              : #include "grpp_binomial.h"
      16              : 
      17              : #include <stdint.h>
      18              : 
      19              : /* The code is borrowed from RosettaCode:
      20              :  * https://rosettacode.org/wiki/Evaluate_binomial_coefficients#C
      21              :  * We go to some effort to handle overflow situations.
      22              :  */
      23              : 
      24              : static uint64_t gcd_ui(uint64_t x, uint64_t y);
      25              : 
      26              : /*
      27              :  * returns binomial coefficient:
      28              :  * ( n )
      29              :  * ( k )
      30              :  */
      31    223426091 : uint64_t libgrpp_binomial(uint64_t n, uint64_t k) {
      32    223426091 :   uint64_t d, g, r = 1;
      33              : 
      34    223426091 :   if (k == 0) {
      35              :     return 1;
      36              :   }
      37    169724120 :   if (k == 1) {
      38              :     return n;
      39              :   }
      40    142204491 :   if (k >= n) {
      41     65667054 :     return (k == n);
      42              :   }
      43     76537437 :   if (k > n / 2) {
      44     37216833 :     k = n - k;
      45              :   }
      46    361244604 :   for (d = 1; d <= k; d++) {
      47    288523203 :     if (r >= UINT64_MAX / n) { /* Possible overflow */
      48      3816036 :       uint64_t nr, dr;         /* reduced numerator / denominator */
      49      3816036 :       g = gcd_ui(n, d);
      50      3816036 :       nr = n / g;
      51      3816036 :       dr = d / g;
      52      3816036 :       g = gcd_ui(r, dr);
      53      3816036 :       r = r / g;
      54      3816036 :       dr = dr / g;
      55      3816036 :       if (r >= UINT64_MAX / nr)
      56              :         return 0; /* Unavoidable overflow */
      57            0 :       r *= nr;
      58            0 :       r /= dr;
      59            0 :       n--;
      60              :     } else {
      61    284707167 :       r *= n--;
      62    284707167 :       r /= d;
      63              :     }
      64              :   }
      65              :   return r;
      66              : }
      67              : 
      68      7632072 : static uint64_t gcd_ui(uint64_t x, uint64_t y) {
      69      7632072 :   uint64_t t;
      70              : 
      71      7632072 :   if (y < x) {
      72      3816036 :     t = x;
      73      3816036 :     x = y;
      74      3816036 :     y = t;
      75              :   }
      76     19080180 :   while (y > 0) {
      77     11448108 :     t = y;
      78     11448108 :     y = x % y;
      79     11448108 :     x = t; /* y1 <- x0 % y0 ; x1 <- y0 */
      80              :   }
      81      7632072 :   return x;
      82              : }
        

Generated by: LCOV version 2.0-1