/*

build this into a Postgres shared library, then

psql -c "create or replace function drive_popcount(count int, num int)   returns bigint strict volatile language c as '\$libdir/drive_popcount.so'"
psql -c "create or replace function drive_popcount64(count int, num int) returns bigint strict volatile language c as '\$libdir/drive_popcount.so'"

select drive_popcount(1000000, 1024);

 */

#include "postgres.h"

#include "fmgr.h"

#include "port/pg_bitutils.h"

PG_MODULE_MAGIC;


/*
 * drive_popcount64(count int, num int) returns bigint
 *
 * num is the number of 64-bit words to use
 */
PG_FUNCTION_INFO_V1(drive_popcount64);
Datum
drive_popcount64(PG_FUNCTION_ARGS)
{

	int			count = PG_GETARG_INT32(0);
	int			num   = PG_GETARG_INT32(1);

	int			len = num * sizeof(uint64);
	uint64 	   *words	= palloc(len);
	int64		popcount;

	for (int i = 0; i < num; i++)
		words[i] = i;

	while (count--)
	{
		popcount = 0;
		for (int i = 0; i < num; i++)
			popcount += pg_popcount64(words[i]);
	}

	PG_RETURN_INT64(popcount);
}

/*
 * drive_popcount(count int, len int) returns bigint
 *
 * num is the number of 64-bit words to use
 */
PG_FUNCTION_INFO_V1(drive_popcount);
Datum
drive_popcount(PG_FUNCTION_ARGS)
{

	int			count = PG_GETARG_INT32(0);
	int			num   = PG_GETARG_INT32(1);

	int			len = num * sizeof(uint64);
	uint64	   *words	= palloc(len);
	int64		popcount;

	for (int i = 0; i < num; i++)
		words[i] = i;

	while (count--)
		popcount = pg_popcount((const char*) words, len);

	PG_RETURN_INT64(popcount);
}
