2019-05-31 00:01:22 +08:00
|
|
|
/*
|
|
|
|
* zipfian distribution copied from YCSB
|
|
|
|
* https://github.com/brianfrankcooper/YCSB
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <math.h>
|
|
|
|
#include <time.h>
|
|
|
|
#include "zipf.h"
|
|
|
|
|
|
|
|
/* global static */
|
|
|
|
static int items;
|
|
|
|
static int base;
|
|
|
|
static double zipfianconstant;
|
|
|
|
static double alpha, zetan, eta, theta, zeta2theta;
|
|
|
|
static int countforzeta;
|
|
|
|
static int allowitemcountdecrease = 0;
|
|
|
|
|
|
|
|
/* declarations */
|
|
|
|
double zetastatic2(int st, int n, double theta, double initialsum);
|
|
|
|
double zeta2(int st, int n, double theta_val, double initialsum);
|
|
|
|
double zetastatic(int n, double theta);
|
|
|
|
double zeta(int n, double theta_val);
|
|
|
|
|
|
|
|
double rand_double() {
|
2021-03-11 02:06:03 +08:00
|
|
|
return (double)rand() / (double)RAND_MAX;
|
2019-05-31 00:01:22 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
int next_int(int itemcount) {
|
2021-03-11 02:06:03 +08:00
|
|
|
double u, uz;
|
|
|
|
int ret;
|
2019-05-31 00:01:22 +08:00
|
|
|
|
2021-03-11 02:06:03 +08:00
|
|
|
if (itemcount != countforzeta) {
|
|
|
|
zetan = zeta2(countforzeta, itemcount, theta, zetan);
|
|
|
|
} else if ((itemcount < countforzeta) && (allowitemcountdecrease)) {
|
|
|
|
zetan = zeta(itemcount, theta);
|
|
|
|
}
|
|
|
|
eta = (1 - pow(2.0 / items, 1 - theta)) / (1 - zeta2theta / zetan);
|
2019-05-31 00:01:22 +08:00
|
|
|
|
2021-03-11 02:06:03 +08:00
|
|
|
u = rand_double();
|
|
|
|
uz = u * zetan;
|
2019-05-31 00:01:22 +08:00
|
|
|
|
2021-03-11 02:06:03 +08:00
|
|
|
if (uz < 1.0) {
|
|
|
|
return base;
|
|
|
|
}
|
2019-05-31 00:01:22 +08:00
|
|
|
|
2021-03-11 02:06:03 +08:00
|
|
|
if (uz < 1.0 + pow(0.5, theta)) {
|
|
|
|
return base + 1;
|
|
|
|
}
|
2019-05-31 00:01:22 +08:00
|
|
|
|
2021-03-11 02:06:03 +08:00
|
|
|
ret = base + (int)(itemcount * pow(eta * u - eta + 1, alpha));
|
|
|
|
return ret;
|
2019-05-31 00:01:22 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
int zipfian_next() {
|
2021-03-11 02:06:03 +08:00
|
|
|
return next_int(items);
|
2019-05-31 00:01:22 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
double zetastatic2(int st, int n, double theta, double initialsum) {
|
2021-03-11 02:06:03 +08:00
|
|
|
int i;
|
|
|
|
double sum = initialsum;
|
|
|
|
for (i = st; i < n; i++) {
|
|
|
|
sum += 1 / pow(i + 1, theta);
|
|
|
|
}
|
|
|
|
return sum;
|
2019-05-31 00:01:22 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
double zeta2(int st, int n, double theta_val, double initialsum) {
|
2021-03-11 02:06:03 +08:00
|
|
|
countforzeta = n;
|
|
|
|
return zetastatic2(st, n, theta_val, initialsum);
|
2019-05-31 00:01:22 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
double zetastatic(int n, double theta) {
|
2021-03-11 02:06:03 +08:00
|
|
|
return zetastatic2(0, n, theta, 0);
|
2019-05-31 00:01:22 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
double zeta(int n, double theta_val) {
|
2021-03-11 02:06:03 +08:00
|
|
|
countforzeta = n;
|
|
|
|
return zetastatic(n, theta_val);
|
2019-05-31 00:01:22 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
void zipfian_generator4(int min, int max, double _zipfianconstant, double _zetan) {
|
2021-03-11 02:06:03 +08:00
|
|
|
items = max - min + 1;
|
|
|
|
base = min;
|
|
|
|
zipfianconstant = _zipfianconstant;
|
|
|
|
|
|
|
|
theta = zipfianconstant;
|
|
|
|
zeta2theta = zeta(2, theta);
|
|
|
|
alpha = 1.0 / (1.0 - theta);
|
|
|
|
zetan = _zetan;
|
|
|
|
countforzeta = items;
|
|
|
|
eta = (1 - pow(2.0 / items, 1 - theta)) / (1 - zeta2theta / zetan);
|
|
|
|
|
|
|
|
zipfian_next();
|
2019-05-31 00:01:22 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
void zipfian_generator3(int min, int max, double zipfianconstant) {
|
2021-03-11 02:06:03 +08:00
|
|
|
zipfian_generator4(min, max, zipfianconstant, zetastatic(max - min + 1, zipfianconstant));
|
2019-05-31 00:01:22 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
void zipfian_generator2(int min, int max) {
|
2021-03-11 02:06:03 +08:00
|
|
|
zipfian_generator3(min, max, ZIPFIAN_CONSTANT);
|
2019-05-31 00:01:22 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
void zipfian_generator(int items) {
|
2021-03-11 02:06:03 +08:00
|
|
|
zipfian_generator2(0, items - 1);
|
2019-05-31 00:01:22 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
#if 0 /* test */
|
|
|
|
void main() {
|
|
|
|
int i = 0;
|
|
|
|
int histogram[1000] = { 0 };
|
|
|
|
|
|
|
|
srand(time(0));
|
|
|
|
|
|
|
|
zipfian_generator(1000);
|
|
|
|
|
|
|
|
for (i = 0; i < 1000000; i++) {
|
|
|
|
int val = next_value();
|
|
|
|
//printf("%d\n", val);
|
|
|
|
histogram[val]++;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (i = 0; i < 1000; i++) {
|
|
|
|
printf("%d\n", histogram[i]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|