File prod_weighted.c
File List > prod_weighted > src > prod_weighted.c
Go to the documentation of this file
#include "prod_weighted.h"
#include <stddef.h>
#include <stdlib.h>
#include <string.h>
#include <pdgl_defs.h>
/*************************************************************************************************/
/************************** Defines **************************************************************/
/*************************************************************************************************/
#define IMAX_BITS(m) ((m) / ((m) % 255 + 1) / 255 % 255 * 8 + 7 - 86 / ((m) % 255 + 12))
#define RAND_MAX_WIDTH IMAX_BITS(RAND_MAX)
/*************************************************************************************************/
/************************** Private Function Declarations ****************************************/
/*************************************************************************************************/
STATIC_INLINE uint64_t prod_weighted_sum(prod_weighted_pair_t *pairs, size_t pairs_len);
STATIC_INLINE const char *prod_weighted_select(prod_weighted_pair_t *pairs, size_t pairs_len);
STATIC_INLINE uint64_t rand_uint64(void);
/*************************************************************************************************/
/************************** Local Variables ******************************************************/
/*************************************************************************************************/
/*************************************************************************************************/
/************************** Public Function Definitions ******************************************/
/*************************************************************************************************/
/* Docstring in header */
const char * prod_weighted_resolve(const void *config)
{
const char *retval = NULL;
if (NULL != config)
{
const prod_weighted_config_t *typed_cfg = (const prod_weighted_config_t *)config;
if ((0 < typed_cfg->repl_len) && (NULL != typed_cfg->repl_list))
{
retval = prod_weighted_select(typed_cfg->repl_list, typed_cfg->repl_len);
}
}
return retval;
}
/* Docstring in header */
const char * prod_weighted_terminate(const void *config)
{
const char *retval = NULL;
if (NULL != config)
{
const prod_weighted_config_t *typed_cfg = (const prod_weighted_config_t *)config;
if ((0 < typed_cfg->term_len) && (NULL != typed_cfg->term_list))
{
retval = prod_weighted_select(typed_cfg->term_list, typed_cfg->term_len);
}
}
return retval;
}
/*************************************************************************************************/
/************************** Private Function Definitions *****************************************/
/*************************************************************************************************/
STATIC_INLINE uint64_t prod_weighted_sum(prod_weighted_pair_t *pairs, size_t pairs_len)
{
size_t i;
uint64_t retval = 0u;
for (i = 0u; i < pairs_len; i++)
{
if (retval < (UINT64_MAX - pairs[i].weight))
{
retval += pairs[i].weight;
}
else
{
return 0u;
}
}
return retval;
}
STATIC_INLINE const char *prod_weighted_select(prod_weighted_pair_t *pairs, size_t pairs_len)
{
const char *retval = NULL;
uint64_t sum = prod_weighted_sum(pairs, pairs_len);
if (sum != 0)
{
size_t i;
uint64_t idx = rand_uint64();
idx %= sum;
uint64_t part_sum = 0;
for (i = 0; i < pairs_len; i++)
{
part_sum += pairs[i].weight;
if (idx < part_sum)
{
retval = pairs[i].string;
break;
}
}
}
return retval;
}
STATIC_INLINE uint64_t rand_uint64(void)
{
uint64_t retval = 0;
size_t i;
for (i = 0; i < 64; i += RAND_MAX_WIDTH)
{
retval <<= RAND_MAX_WIDTH;
retval ^= (unsigned)rand();
}
return retval;
}