permutation.h 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181
  1. /* Licensed under LGPLv2.1+ - see LICENSE file for details */
  2. #ifndef CCAN_PERMUTATION_H
  3. #define CCAN_PERMUTATION_H
  4. #include <config.h>
  5. #include <stdlib.h>
  6. #include <stdbool.h>
  7. #include <stdint.h>
  8. #include <assert.h>
  9. #include <ccan/build_assert/build_assert.h>
  10. #include <ccan/mem/mem.h>
  11. /*
  12. * We limit the number of elements to 64, to keep our data structures
  13. * neat. That seems low, but even 64! permutations is far too many to
  14. * really generate in practice.
  15. */
  16. #define PERMUTATION_MAX_SHIFT 6
  17. #define PERMUTATION_MAX_ITEMS (1 << PERMUTATION_MAX_SHIFT)
  18. /**
  19. * struct permutation - represents a permutation
  20. *
  21. * The fields here are user visible, but it's allocated internally
  22. * with extra state information appended.
  23. *
  24. * @n: Number of elements in the permutation
  25. * @v: values 0..(n-1) arranged in current permutation
  26. */
  27. struct permutation {
  28. int n;
  29. uint8_t v[];
  30. /* Private state data follows */
  31. };
  32. /**
  33. * permutation_count - determine number of permutations
  34. * @n: Number of elements
  35. *
  36. * Returns the number of permutations of @n elements.
  37. */
  38. unsigned long long permutation_count(int n);
  39. /**
  40. * permutation_swap_t - represents a swap of two items
  41. *
  42. * Encodes a swap of two elements in an array. Should be treated as
  43. * opaque, except that 0 always represents "swap nothing".
  44. */
  45. typedef unsigned permutation_swap_t;
  46. /**
  47. * permutation_swap_a - first item to swap
  48. * permutation_swap_b - second item to swap
  49. */
  50. static inline int permutation_swap_a(permutation_swap_t swap)
  51. {
  52. return swap % PERMUTATION_MAX_ITEMS;
  53. }
  54. static inline int permutation_swap_b(permutation_swap_t swap)
  55. {
  56. return swap / PERMUTATION_MAX_ITEMS;
  57. }
  58. /**
  59. * permutation_swap - swap two elements in an array
  60. * @base: address of array
  61. * @size: size of each array element
  62. * @swap: which elements to swap
  63. *
  64. * Swaps the elements at index permutation_swap_a(@swap) and
  65. * permutation_swap_b(@swap) in the array at @base of items of size
  66. * @size.
  67. */
  68. static inline void permutation_swap_mem(void *base, size_t size,
  69. permutation_swap_t swap)
  70. {
  71. char *ap = (char *)base + (permutation_swap_a(swap) * size);
  72. char *bp = (char *)base + (permutation_swap_b(swap) * size);
  73. BUILD_ASSERT(sizeof(permutation_swap_t) * 8
  74. >= PERMUTATION_MAX_SHIFT * 2);
  75. if (!swap)
  76. return;
  77. memswap(ap, bp, size);
  78. }
  79. /**
  80. * PERMUTATION_SWAP - swap two elements in an array
  81. * @a_: array
  82. * @swap_: which elements to swap
  83. *
  84. * As permutation_swap(), but must act on a C array declared at the
  85. * right size.
  86. */
  87. #define PERMUTATION_SWAP(a_, swap_) \
  88. do { \
  89. permutation_swap((a_), sizeof((a_)[0]), (swap_)); \
  90. } while (0)
  91. /**
  92. * permutation_new - allocates a new identity permutation
  93. * @n: Number of elements
  94. *
  95. * Allocates and initializes a new permutation of @n elements.
  96. * Initially it represents the identity permutation.
  97. */
  98. struct permutation *permutation_new(int n);
  99. /**
  100. * PERMUTATION_NEW - allocates a new identity permutation of an array
  101. * @array_: Array to permute
  102. *
  103. * As permutation_new() but take the number of elements from the
  104. * declaration of @array_.
  105. */
  106. #define PERMUTATION_NEW(array_) (permutation_new(ARRAY_SIZE(array_)))
  107. /**
  108. * permutation_change - Advance to a new permutation
  109. * @pi: Current permutation
  110. *
  111. * Advances @pi to the next permutation by the plain changes method
  112. * (Steinhaus-Johnson-Trotter algorithm).
  113. *
  114. * Returns the elements which were swapped in @pi, or 0 if there are
  115. * no more permutations.
  116. */
  117. permutation_swap_t permutation_change(struct permutation *pi);
  118. /**
  119. * permutation_change_array - Advance an array to a new permutation
  120. * @pi: Current permutation
  121. * @base: Address of array
  122. * @size: Size of array elements
  123. *
  124. * Assuming the array at @base is currently in permutation @pi,
  125. * advances @pi to the next permutation (as permutation_change()) and
  126. * keeps the array in sync.
  127. *
  128. * Returns true if the permutation was advanced, false if there are no
  129. * more permutations.
  130. */
  131. static inline bool permutation_change_array(struct permutation *pi,
  132. void *base, size_t size)
  133. {
  134. permutation_swap_t swap = permutation_change(pi);
  135. permutation_swap_mem(base, size, swap);
  136. return (swap != 0);
  137. }
  138. static inline bool permutation_change_array_check_(struct permutation *pi,
  139. void *base, size_t size,
  140. int n)
  141. {
  142. assert(n == pi->n);
  143. return permutation_change_array(pi, base, size);
  144. }
  145. /**
  146. * PERMUTATION_CHANGE_ARRAY - Advance an array to a new permutation
  147. * @pi_: Current permutation
  148. * @a_: Array
  149. *
  150. * As permutation_change_array(), but operate on array @a_, which must
  151. * be a C array declared with the same number of elements as @pi_.
  152. */
  153. #define PERMUTATION_CHANGE_ARRAY(pi_, a_) \
  154. (permutation_change_array_check_((pi_), (a_), \
  155. sizeof((a_)[0]), ARRAY_SIZE(a_)))
  156. #endif /* CCAN_PERMUTATION_H */