162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * From lib/bitmap.c
462306a36Sopenharmony_ci * Helper functions for bitmap.h.
562306a36Sopenharmony_ci */
662306a36Sopenharmony_ci#include <linux/bitmap.h>
762306a36Sopenharmony_ci
862306a36Sopenharmony_ciunsigned int __bitmap_weight(const unsigned long *bitmap, int bits)
962306a36Sopenharmony_ci{
1062306a36Sopenharmony_ci	unsigned int k, w = 0, lim = bits/BITS_PER_LONG;
1162306a36Sopenharmony_ci
1262306a36Sopenharmony_ci	for (k = 0; k < lim; k++)
1362306a36Sopenharmony_ci		w += hweight_long(bitmap[k]);
1462306a36Sopenharmony_ci
1562306a36Sopenharmony_ci	if (bits % BITS_PER_LONG)
1662306a36Sopenharmony_ci		w += hweight_long(bitmap[k] & BITMAP_LAST_WORD_MASK(bits));
1762306a36Sopenharmony_ci
1862306a36Sopenharmony_ci	return w;
1962306a36Sopenharmony_ci}
2062306a36Sopenharmony_ci
2162306a36Sopenharmony_civoid __bitmap_or(unsigned long *dst, const unsigned long *bitmap1,
2262306a36Sopenharmony_ci		 const unsigned long *bitmap2, int bits)
2362306a36Sopenharmony_ci{
2462306a36Sopenharmony_ci	int k;
2562306a36Sopenharmony_ci	int nr = BITS_TO_LONGS(bits);
2662306a36Sopenharmony_ci
2762306a36Sopenharmony_ci	for (k = 0; k < nr; k++)
2862306a36Sopenharmony_ci		dst[k] = bitmap1[k] | bitmap2[k];
2962306a36Sopenharmony_ci}
3062306a36Sopenharmony_ci
3162306a36Sopenharmony_cisize_t bitmap_scnprintf(unsigned long *bitmap, unsigned int nbits,
3262306a36Sopenharmony_ci			char *buf, size_t size)
3362306a36Sopenharmony_ci{
3462306a36Sopenharmony_ci	/* current bit is 'cur', most recently seen range is [rbot, rtop] */
3562306a36Sopenharmony_ci	unsigned int cur, rbot, rtop;
3662306a36Sopenharmony_ci	bool first = true;
3762306a36Sopenharmony_ci	size_t ret = 0;
3862306a36Sopenharmony_ci
3962306a36Sopenharmony_ci	rbot = cur = find_first_bit(bitmap, nbits);
4062306a36Sopenharmony_ci	while (cur < nbits) {
4162306a36Sopenharmony_ci		rtop = cur;
4262306a36Sopenharmony_ci		cur = find_next_bit(bitmap, nbits, cur + 1);
4362306a36Sopenharmony_ci		if (cur < nbits && cur <= rtop + 1)
4462306a36Sopenharmony_ci			continue;
4562306a36Sopenharmony_ci
4662306a36Sopenharmony_ci		if (!first)
4762306a36Sopenharmony_ci			ret += scnprintf(buf + ret, size - ret, ",");
4862306a36Sopenharmony_ci
4962306a36Sopenharmony_ci		first = false;
5062306a36Sopenharmony_ci
5162306a36Sopenharmony_ci		ret += scnprintf(buf + ret, size - ret, "%d", rbot);
5262306a36Sopenharmony_ci		if (rbot < rtop)
5362306a36Sopenharmony_ci			ret += scnprintf(buf + ret, size - ret, "-%d", rtop);
5462306a36Sopenharmony_ci
5562306a36Sopenharmony_ci		rbot = cur;
5662306a36Sopenharmony_ci	}
5762306a36Sopenharmony_ci	return ret;
5862306a36Sopenharmony_ci}
5962306a36Sopenharmony_ci
6062306a36Sopenharmony_cibool __bitmap_and(unsigned long *dst, const unsigned long *bitmap1,
6162306a36Sopenharmony_ci		 const unsigned long *bitmap2, unsigned int bits)
6262306a36Sopenharmony_ci{
6362306a36Sopenharmony_ci	unsigned int k;
6462306a36Sopenharmony_ci	unsigned int lim = bits/BITS_PER_LONG;
6562306a36Sopenharmony_ci	unsigned long result = 0;
6662306a36Sopenharmony_ci
6762306a36Sopenharmony_ci	for (k = 0; k < lim; k++)
6862306a36Sopenharmony_ci		result |= (dst[k] = bitmap1[k] & bitmap2[k]);
6962306a36Sopenharmony_ci	if (bits % BITS_PER_LONG)
7062306a36Sopenharmony_ci		result |= (dst[k] = bitmap1[k] & bitmap2[k] &
7162306a36Sopenharmony_ci			   BITMAP_LAST_WORD_MASK(bits));
7262306a36Sopenharmony_ci	return result != 0;
7362306a36Sopenharmony_ci}
7462306a36Sopenharmony_ci
7562306a36Sopenharmony_cibool __bitmap_equal(const unsigned long *bitmap1,
7662306a36Sopenharmony_ci		    const unsigned long *bitmap2, unsigned int bits)
7762306a36Sopenharmony_ci{
7862306a36Sopenharmony_ci	unsigned int k, lim = bits/BITS_PER_LONG;
7962306a36Sopenharmony_ci	for (k = 0; k < lim; ++k)
8062306a36Sopenharmony_ci		if (bitmap1[k] != bitmap2[k])
8162306a36Sopenharmony_ci			return false;
8262306a36Sopenharmony_ci
8362306a36Sopenharmony_ci	if (bits % BITS_PER_LONG)
8462306a36Sopenharmony_ci		if ((bitmap1[k] ^ bitmap2[k]) & BITMAP_LAST_WORD_MASK(bits))
8562306a36Sopenharmony_ci			return false;
8662306a36Sopenharmony_ci
8762306a36Sopenharmony_ci	return true;
8862306a36Sopenharmony_ci}
8962306a36Sopenharmony_ci
9062306a36Sopenharmony_cibool __bitmap_intersects(const unsigned long *bitmap1,
9162306a36Sopenharmony_ci			 const unsigned long *bitmap2, unsigned int bits)
9262306a36Sopenharmony_ci{
9362306a36Sopenharmony_ci	unsigned int k, lim = bits/BITS_PER_LONG;
9462306a36Sopenharmony_ci	for (k = 0; k < lim; ++k)
9562306a36Sopenharmony_ci		if (bitmap1[k] & bitmap2[k])
9662306a36Sopenharmony_ci			return true;
9762306a36Sopenharmony_ci
9862306a36Sopenharmony_ci	if (bits % BITS_PER_LONG)
9962306a36Sopenharmony_ci		if ((bitmap1[k] & bitmap2[k]) & BITMAP_LAST_WORD_MASK(bits))
10062306a36Sopenharmony_ci			return true;
10162306a36Sopenharmony_ci	return false;
10262306a36Sopenharmony_ci}
103