#ifndef _RANGES #define _RANGES #include "gen_scheme.h" /* Fast-range summation of +-1 random variables DMAP avoidance of fast range-summation For details see the papers: 1) "Fast Range-Summable Random Variables for Efficient Aggregate Estimation" by F. Rusu and A. Dobra 2) "Pseudo-Random Number Generation for Sketch-Based Estimations" by F. Rusu and A. Dobra Assumption: integers are represented on 32 bits */ /* Fast range-summation algorithm for BCH3 scheme See the pseudocode in paper from point 2) above */ inline double BCH3Interval(unsigned int gamma, unsigned int S0, unsigned int s0) { int i; double sum = 0; if (gamma & 1U == 1U) { gamma -= 1; sum += BCH3(s0, S0, gamma); } for (i = 1; i < 32; i++) { if (gamma == 0U) return sum; if ((S0 >> (i-1)) & 1U == 1U) return sum; else //(S0 >> (i-1)) & 1 == 0 { if ((gamma >> i) & 1U == 1U) { gamma ^= (1U << i); sum += BCH3(s0, S0, gamma) << i; } } } return sum; } inline double BCH3_Range(unsigned int alpha, unsigned int beta, unsigned int S0, unsigned int s0) { double sum = BCH3Interval(beta+1, S0, s0); sum -= BCH3Interval(alpha, S0, s0); return sum; } /* Fast range-summation algorithm for EH3 scheme See the pseudocode in paper from point 2) above */ inline double EH3Interval(unsigned int gamma, unsigned int S0, unsigned int s0) { int i, s_bits_one = 0; double sum = 0; int f_A; unsigned int t_bits; unsigned int s_bits; s_bits = S0 & 3U; if (s_bits == 3U) s_bits_one = 1; t_bits = gamma & 3U; if (t_bits == 1U) { gamma -= 1; sum += EH3(s0, S0, gamma); } else if (t_bits == 2U) { gamma -= 2; sum += EH3(s0, S0, gamma); sum += EH3(s0, S0, gamma+1); } else if (t_bits == 3U) { gamma -= 3; sum += EH3(s0, S0, gamma); sum += EH3(s0, S0, gamma+1); sum += EH3(s0, S0, gamma+2); } for (i = 2; i < 32; i += 2) { if (gamma == 0U) return sum; t_bits = (gamma >> i) & 3U; gamma ^= (t_bits << i); if (t_bits == 1U) { f_A = EH3(s0, S0, gamma); if (s_bits_one % 2 == 1U) sum -= (f_A << (i >> 1)); else sum += (f_A << (i >> 1)); } else if (t_bits == 2U) { f_A = EH3(s0, S0, gamma); if (s_bits_one % 2 == 1U) sum -= (f_A << (i >> 1)); else sum += (f_A << (i >> 1)); f_A = EH3(s0, S0, gamma + (1U << i)); if (s_bits_one % 2 == 1U) sum -= (f_A << (i >> 1)); else sum += (f_A << (i >> 1)); } else if (t_bits == 3U) { f_A = EH3(s0, S0, gamma); if (s_bits_one % 2 == 1U) sum -= (f_A << (i >> 1)); else sum += (f_A << (i >> 1)); f_A = EH3(s0, S0, gamma + (1 << i)); if (s_bits_one % 2 == 1U) sum -= (f_A << (i >> 1)); else sum += (f_A << (i >> 1)); f_A = EH3(s0, S0, gamma + (1U << (i + 1))); if (s_bits_one % 2 == 1U) sum -= (f_A << (i >> 1)); else sum += (f_A << (i >> 1)); } s_bits = (S0 >> i) & 3U; if (s_bits == 3U) s_bits_one += 1; } return sum; } inline double EH3_Range(unsigned int alpha, unsigned int beta, unsigned int S0, unsigned int s0) { double sum = EH3Interval(beta+1, S0, s0); sum -= EH3Interval(alpha, S0, s0); return sum; } /* Dyadic mapping algorithms to avoid the need for fast range-summation Dyadic mapping applies to a larger number of schemes than fast range-summation */ inline double Dyadic_Range_EH3(unsigned int a, unsigned int b, unsigned int i0, unsigned int I1, int dom_size) { double sum = 0; unsigned int pw = 0; unsigned int front_mask = 0; unsigned int map; int alpha = a; int beta = b; while (alpha <= beta) { if (((alpha >> pw) & 1U) == 1U) { map = front_mask ^ (alpha >> pw); sum += EH3(i0, I1, map); alpha += (1 << pw); } if (alpha > beta) return sum; if (((beta >> pw) & 1U) == 0U) { map = front_mask ^ ((beta - (1 << pw) + 1) >> pw); sum += EH3(i0, I1, map); beta -= (1 << pw); } front_mask = (front_mask >> 1) ^ (1U << dom_size); pw += 1; } return sum; } inline double Dyadic_Range_BCH5(unsigned int a, unsigned int b, unsigned int i0, unsigned int I1, unsigned int I2, int dom_size) { double sum = 0; unsigned int pw = 0; unsigned int front_mask = 0; unsigned int map; int alpha = a; int beta = b; while (alpha <= beta) { if (((alpha >> pw) & 1U) == 1U) { map = front_mask ^ (alpha >> pw); sum += BCH5(i0, I1, I2, map); alpha += (1 << pw); } if (alpha > beta) return sum; if (((beta >> pw) & 1U) == 0U) { map = front_mask ^ ((beta - (1 << pw) + 1) >> pw); sum += BCH5(i0, I1, I2, map); beta -= (1 << pw); } front_mask = (front_mask >> 1) ^ (1U << dom_size); pw += 1; } return sum; } inline double Dyadic_Range_CW4(unsigned int aa, unsigned int bb, unsigned long a, unsigned long b, unsigned long c, unsigned long d, int dom_size) { double sum = 0; unsigned int pw = 0; unsigned int front_mask = 0; unsigned int map; int alpha = aa; int beta = bb; while (alpha <= beta) { if (((alpha >> pw) & 1U) == 1U) { map = front_mask ^ (alpha >> pw); sum += CW4(a, b, c, d, map); alpha += (1 << pw); } if (alpha > beta) return sum; if (((beta >> pw) & 1U) == 0U) { map = front_mask ^ ((beta - (1 << pw) + 1) >> pw); sum += CW4(a, b, c, d, map); beta -= (1 << pw); } front_mask = (front_mask >> 1) ^ (1U << dom_size); pw += 1; } return sum; } #endif