LCOV - code coverage report
Current view: top level - raid - combo.h (source / functions) Hit Total Coverage
Test: lcov.info Lines: 30 30 100.0 %
Date: 2017-11-06 22:14:04 Functions: 0 0 -

          Line data    Source code
       1             : /*
       2             :  * Copyright (C) 2013 Andrea Mazzoleni
       3             :  *
       4             :  * This program is free software: you can redistribute it and/or modify
       5             :  * it under the terms of the GNU General Public License as published by
       6             :  * the Free Software Foundation, either version 2 of the License, or
       7             :  * (at your option) any later version.
       8             :  *
       9             :  * This program 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
      12             :  * GNU General Public License for more details.
      13             :  */
      14             : 
      15             : #ifndef __RAID_COMBO_H
      16             : #define __RAID_COMBO_H
      17             : 
      18             : #include <assert.h>
      19             : 
      20             : /**
      21             :  * Get the first permutation with repetition of r of n elements.
      22             :  *
      23             :  * Typical use is with permutation_next() in the form :
      24             :  *
      25             :  * int i[R];
      26             :  * permutation_first(R, N, i);
      27             :  * do {
      28             :  *    code using i[0], i[1], ..., i[R-1]
      29             :  * } while (permutation_next(R, N, i));
      30             :  *
      31             :  * It's equivalent at the code :
      32             :  *
      33             :  * for(i[0]=0;i[0]<N;++i[0])
      34             :  *     for(i[1]=0;i[1]<N;++i[1])
      35             :  *        ...
      36             :  *            for(i[R-2]=0;i[R-2]<N;++i[R-2])
      37             :  *                for(i[R-1]=0;i[R-1]<N;++i[R-1])
      38             :  *                    code using i[0], i[1], ..., i[R-1]
      39             :  */
      40             : static __always_inline void permutation_first(int r, int n, int *c)
      41             : {
      42             :         int i;
      43             : 
      44             :         (void)n; /* unused, but kept for clarity */
      45          18 :         assert(0 < r && r <= n);
      46             : 
      47          81 :         for (i = 0; i < r; ++i)
      48          63 :                 c[i] = 0;
      49             : }
      50             : 
      51             : /**
      52             :  * Get the next permutation with repetition of r of n elements.
      53             :  * Return ==0 when finished.
      54             :  */
      55             : static __always_inline int permutation_next(int r, int n, int *c)
      56             : {
      57      167958 :         int i = r - 1; /* present position */
      58             : 
      59             : recurse:
      60             :         /* next element at position i */
      61      201528 :         ++c[i];
      62             : 
      63             :         /* if the position has reached the max */
      64      201528 :         if (c[i] >= n) {
      65             : 
      66             :                 /* if we are at the first level, we have finished */
      67       33588 :                 if (i == 0)
      68          18 :                         return 0;
      69             : 
      70             :                 /* increase the previous position */
      71       33570 :                 --i;
      72             :                 goto recurse;
      73             :         }
      74             : 
      75      167940 :         ++i;
      76             : 
      77             :         /* initialize all the next positions, if any */
      78      201465 :         while (i < r) {
      79       33525 :                 c[i] = 0;
      80       33525 :                 ++i;
      81             :         }
      82             : 
      83      167940 :         return 1;
      84             : }
      85             : 
      86             : /**
      87             :  * Get the first combination without repetition of r of n elements.
      88             :  *
      89             :  * Typical use is with combination_next() in the form :
      90             :  *
      91             :  * int i[R];
      92             :  * combination_first(R, N, i);
      93             :  * do {
      94             :  *    code using i[0], i[1], ..., i[R-1]
      95             :  * } while (combination_next(R, N, i));
      96             :  *
      97             :  * It's equivalent at the code :
      98             :  *
      99             :  * for(i[0]=0;i[0]<N-(R-1);++i[0])
     100             :  *     for(i[1]=i[0]+1;i[1]<N-(R-2);++i[1])
     101             :  *        ...
     102             :  *            for(i[R-2]=i[R-3]+1;i[R-2]<N-1;++i[R-2])
     103             :  *                for(i[R-1]=i[R-2]+1;i[R-1]<N;++i[R-1])
     104             :  *                    code using i[0], i[1], ..., i[R-1]
     105             :  */
     106             : static __always_inline void combination_first(int r, int n, int *c)
     107             : {
     108             :         int i;
     109             : 
     110             :         (void)n; /* unused, but kept for clarity */
     111      208022 :         assert(0 < r && r <= n);
     112             : 
     113      689674 :         for (i = 0; i < r; ++i)
     114      481652 :                 c[i] = i;
     115             : }
     116             : 
     117             : /**
     118             :  * Get the next combination without repetition of r of n elements.
     119             :  * Return ==0 when finished.
     120             :  */
     121             : static __always_inline int combination_next(int r, int n, int *c)
     122             : {
     123       52408 :         int i = r - 1; /* present position */
     124       52408 :         int h = n; /* high limit for this position */
     125             : 
     126             : recurse:
     127             :         /* next element at position i */
     128       85281 :         ++c[i];
     129             : 
     130             :         /* if the position has reached the max */
     131       85281 :         if (c[i] >= h) {
     132             : 
     133             :                 /* if we are at the first level, we have finished */
     134       45103 :                 if (i == 0)
     135       12230 :                         return 0;
     136             : 
     137             :                 /* increase the previous position */
     138       32873 :                 --i;
     139       32873 :                 --h;
     140             :                 goto recurse;
     141             :         }
     142             : 
     143       40178 :         ++i;
     144             : 
     145             :         /* initialize all the next positions, if any */
     146       62723 :         while (i < r) {
     147             :                 /* each position start at the next value of the previous one */
     148       22545 :                 c[i] = c[i - 1] + 1;
     149       22545 :                 ++i;
     150             :         }
     151             : 
     152       40178 :         return 1;
     153             : }
     154             : #endif
     155             : 

Generated by: LCOV version 1.13