Re: [PATCH v5 3/5] lib/bitmap: Introduce bitmap_scatter() and bitmap_gather() helpers

2024-02-29 Thread Andy Shevchenko
On Thu, Feb 29, 2024 at 03:15:51PM +0100, Herve Codina wrote:
> From: Andy Shevchenko 
> 
> These helpers scatters or gathers a bitmap with the help of the mask
> position bits parameter.
> 
> bitmap_scatter() does the following:
>   src:  01011010
>   ||
>+--+|
>|  ++
>|  |++|||
>|  ||   +-+||
>|  ||   |  ||
>   mask: ...v..vv...v..vv
> ...0..11...0..10
>   dst:  00110010
> 
> and bitmap_gather() performs this one:
>mask: ...v..vv...v..vv
>src:  00110010
> ^  ^^   ^   0
> |  ||   |  10
> |  ||   > 010
> |  |+--> 1010
> |  +--> 11010
> +> 011010
>dst:  00011010
> 
> bitmap_gather() can the seen as the reverse bitmap_scatter() operation.

> The original work was done by Andy Shevchenko.

As I said, it's too much credit :-)

...

> + * A relationship exists between bitmap_gather() and bitmap_scatter(). See
> + * bitmap_scatter() for the bitmap scatter detailed operations.
> + * Suppose scattered computed using bitmap_scatter(scattered, src, mask, n).
> + * The operation bitmap_gather(result, scattered, mask, n) leads to a result
> + * equal or equivalent to src.
> + *
> + * The result can be 'equivalent' because bitmap_scatter() and 
> bitmap_gather()
> + * are not bijective.
> + * The result and src values are equivalent in that sense that a call to

> + * bitmap_scatter(res, src, mask, n) and a call to bitmap_scatter(res, 
> result,
> + * mask, n) will lead to the same res value.

For better readability I wouldn't break API calls, hence

 The result and src values are equivalent in that sense that a call to
 bitmap_scatter(res, src, mask, n) and a call to
 bitmap_scatter(res, result, mask, n) will lead to the same res value.

-- 
With Best Regards,
Andy Shevchenko




[PATCH v5 3/5] lib/bitmap: Introduce bitmap_scatter() and bitmap_gather() helpers

2024-02-29 Thread Herve Codina
From: Andy Shevchenko 

These helpers scatters or gathers a bitmap with the help of the mask
position bits parameter.

bitmap_scatter() does the following:
  src:  01011010
  ||
   +--+|
   |  ++
   |  |++|||
   |  ||   +-+||
   |  ||   |  ||
  mask: ...v..vv...v..vv
...0..11...0..10
  dst:  00110010

and bitmap_gather() performs this one:
   mask: ...v..vv...v..vv
   src:  00110010
^  ^^   ^   0
|  ||   |  10
|  ||   > 010
|  |+--> 1010
|  +--> 11010
+> 011010
   dst:  00011010

bitmap_gather() can the seen as the reverse bitmap_scatter() operation.

The original work was done by Andy Shevchenko.

Signed-off-by: Andy Shevchenko 
Link: 
https://lore.kernel.org/lkml/20230926052007.3917389-3-andriy.shevche...@linux.intel.com/
Co-developed-by: Herve Codina 
Signed-off-by: Herve Codina 
---
 include/linux/bitmap.h | 101 +
 lib/test_bitmap.c  |  42 +
 2 files changed, 143 insertions(+)

diff --git a/include/linux/bitmap.h b/include/linux/bitmap.h
index 99451431e4d6..6d3f6ff1b4d6 100644
--- a/include/linux/bitmap.h
+++ b/include/linux/bitmap.h
@@ -62,6 +62,8 @@ struct device;
  *  bitmap_shift_left(dst, src, n, nbits)   *dst = *src << n
  *  bitmap_cut(dst, src, first, n, nbits)   Cut n bits from first, copy 
rest
  *  bitmap_replace(dst, old, new, mask, nbits)  *dst = (*old & ~(*mask)) | 
(*new & *mask)
+ *  bitmap_scatter(dst, src, mask, nbits)  *dst = map(dense, sparse)(src)
+ *  bitmap_gather(dst, src, mask, nbits)   *dst = map(sparse, dense)(src)
  *  bitmap_remap(dst, src, old, new, nbits) *dst = map(old, new)(src)
  *  bitmap_bitremap(oldbit, old, new, nbits)newbit = map(old, new)(oldbit)
  *  bitmap_onto(dst, orig, relmap, nbits)   *dst = orig relative to relmap
@@ -487,6 +489,105 @@ static inline void bitmap_replace(unsigned long *dst,
__bitmap_replace(dst, old, new, mask, nbits);
 }
 
+/**
+ * bitmap_scatter - Scatter a bitmap according to the given mask
+ * @dst: scattered bitmap
+ * @src: gathered bitmap
+ * @mask: mask representing bits to assign to in the scattered bitmap
+ * @nbits: number of bits in each of these bitmaps
+ *
+ * Scatters bitmap with sequential bits according to the given @mask.
+ *
+ * Example:
+ * If @src bitmap = 0x005a, with @mask = 0x1313, @dst will be 0x0302.
+ *
+ * Or in binary form
+ * @src@mask   @dst
+ * 01011010000100110001001100110010
+ *
+ * (Bits 0, 1, 2, 3, 4, 5 are copied to the bits 0, 1, 4, 8, 9, 12)
+ *
+ * A more 'visual' description of the operation:
+ * src:  01011010
+ * ||
+ *  +--+|
+ *  |  ++
+ *  |  |++|||
+ *  |  ||   +-+||
+ *  |  ||   |  ||
+ * mask: ...v..vv...v..vv
+ *   ...0..11...0..10
+ * dst:  00110010
+ *
+ * A relationship exists between bitmap_scatter() and bitmap_gather().
+ * bitmap_gather() can be seen as the 'reverse' bitmap_scatter() operation.
+ * See bitmap_scatter() for details related to this relationship.
+ */
+static inline void bitmap_scatter(unsigned long *dst, const unsigned long *src,
+ const unsigned long *mask, unsigned int nbits)
+{
+   unsigned int n = 0;
+   unsigned int bit;
+
+   bitmap_zero(dst, nbits);
+
+   for_each_set_bit(bit, mask, nbits)
+   __assign_bit(bit, dst, test_bit(n++, src));
+}
+
+/**
+ * bitmap_gather - Gather a bitmap according to given mask
+ * @dst: gathered bitmap
+ * @src: scattered bitmap
+ * @mask: mask representing bits to extract from in the scattered bitmap
+ * @nbits: number of bits in each of these bitmaps
+ *
+ * Gathers bitmap with sparse bits according to the given @mask.
+ *
+ * Example:
+ * If @src bitmap = 0x0302, with @mask = 0x1313, @dst will be 0x001a.
+ *
+ * Or in binary form
+ * @src@mask   @dst
+ * 00110010000100110001001100011010
+ *
+ * (Bits 0, 1, 4, 8, 9, 12 are copied to the bits 0, 1, 2, 3, 4, 5)
+ *
+ * A more 'visual' description of the operation:
+ * mask: ...v..vv...v..vv
+ * src:  00110010
+ *  ^  ^^   ^   0
+ *  |  ||   |  10
+ *  |  ||   > 010
+ *  |  |+--> 1010
+ *  |  +--> 11010
+ *  +> 011010
+ * dst:  00011010
+ *
+ * A relationship exists between bitmap_gather() and bitmap_scatter(). See
+ * bitmap_scatter() for the bitmap scatter detailed operations.
+ * Suppose scattered computed using bitmap_scatter(scattered, src, mask, n).
+ * The operation bitmap_gather(result, scattered, mask, n) leads to a result
+ * equal or equivalent to src.
+ *
+ * The result can be 'equivalent' because bitmap_scatter() and