]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
bitmap: introduce bitmap_weighted_xor()
authorYury Norov <ynorov@nvidia.com>
Mon, 2 Mar 2026 01:11:55 +0000 (20:11 -0500)
committerYury Norov <ynorov@nvidia.com>
Thu, 2 Apr 2026 00:03:07 +0000 (20:03 -0400)
The function helps to XOR bitmaps and calculate Hamming weight of
the result in one pass.

Reviewed-by: Aleksandr Loktionov <aleksandr.loktionov@intel.com>
Reviewed-by: Jacob Keller <jacob.e.keller@intel.com>
Signed-off-by: Yury Norov <ynorov@nvidia.com>
include/linux/bitmap.h
lib/bitmap.c

index 9c0d1de4435003d4167e9fabaacca41a43bc9b65..b007d54a9036a5f657526b70e37f0381c9c573d8 100644 (file)
@@ -46,6 +46,7 @@ struct device;
  *  bitmap_and(dst, src1, src2, nbits)          *dst = *src1 & *src2
  *  bitmap_or(dst, src1, src2, nbits)           *dst = *src1 | *src2
  *  bitmap_weighted_or(dst, src1, src2, nbits) *dst = *src1 | *src2. Returns Hamming Weight of dst
+ *  bitmap_weighted_xor(dst, src1, src2, nbits)        *dst = *src1 ^ *src2. Returns Hamming Weight of dst
  *  bitmap_xor(dst, src1, src2, nbits)          *dst = *src1 ^ *src2
  *  bitmap_andnot(dst, src1, src2, nbits)       *dst = *src1 & ~(*src2)
  *  bitmap_complement(dst, src, nbits)          *dst = ~(*src)
@@ -169,6 +170,8 @@ void __bitmap_or(unsigned long *dst, const unsigned long *bitmap1,
                 const unsigned long *bitmap2, unsigned int nbits);
 unsigned int __bitmap_weighted_or(unsigned long *dst, const unsigned long *bitmap1,
                                  const unsigned long *bitmap2, unsigned int nbits);
+unsigned int __bitmap_weighted_xor(unsigned long *dst, const unsigned long *bitmap1,
+                                 const unsigned long *bitmap2, unsigned int nbits);
 void __bitmap_xor(unsigned long *dst, const unsigned long *bitmap1,
                  const unsigned long *bitmap2, unsigned int nbits);
 bool __bitmap_andnot(unsigned long *dst, const unsigned long *bitmap1,
@@ -353,6 +356,18 @@ unsigned int bitmap_weighted_or(unsigned long *dst, const unsigned long *src1,
        }
 }
 
+static __always_inline
+unsigned int bitmap_weighted_xor(unsigned long *dst, const unsigned long *src1,
+                               const unsigned long *src2, unsigned int nbits)
+{
+       if (small_const_nbits(nbits)) {
+               *dst = *src1 ^ *src2;
+               return hweight_long(*dst & BITMAP_LAST_WORD_MASK(nbits));
+       } else {
+               return __bitmap_weighted_xor(dst, src1, src2, nbits);
+       }
+}
+
 static __always_inline
 void bitmap_xor(unsigned long *dst, const unsigned long *src1,
                const unsigned long *src2, unsigned int nbits)
index 1b897f94e0ffdc5a1a93de3e987d8e50efbcad4b..b9bfa157e0950dc6113375a50665dcfbdaaba2f1 100644 (file)
@@ -363,6 +363,13 @@ unsigned int __bitmap_weighted_or(unsigned long *dst, const unsigned long *bitma
 }
 EXPORT_SYMBOL(__bitmap_weighted_or);
 
+unsigned int __bitmap_weighted_xor(unsigned long *dst, const unsigned long *bitmap1,
+                                 const unsigned long *bitmap2, unsigned int bits)
+{
+       return BITMAP_WEIGHT(({dst[idx] = bitmap1[idx] ^ bitmap2[idx]; dst[idx]; }), bits);
+}
+EXPORT_SYMBOL(__bitmap_weighted_xor);
+
 void __bitmap_set(unsigned long *map, unsigned int start, int len)
 {
        unsigned long *p = map + BIT_WORD(start);