/***********************************************************************
* *
* This software is part of the ast package *
* Copyright (c) 2003-2011 AT&T Intellectual Property *
* and is licensed under the *
* Eclipse Public License, Version 1.0 *
* by AT&T Intellectual Property *
* *
* A copy of the License is available at *
* http://www.eclipse.org/org/documents/epl-v10.html *
* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
* *
* Information and Software Systems Research *
* AT&T Research *
* Florham Park NJ *
* *
* Phong Vo <kpv@research.att.com> *
* *
***********************************************************************/
#include "vchdr.h"
/* Function to approximate log_base_2(unsigned int v)".
** Return 0. if v is zero.
**
** The basic idea is to write v = (2^k)*w + r = (2^k)*w*(1 + r/((2^k)*w))
** so that log2(v) = k + log2(w) + log2(1 + r/((2^k)*w)).
** Now find k so that w < 256. Then, k + log2(w) is a pretty good
** approximation of log2(v) up to about 2 decimal places. Both k and log2(w)
** can be computed using table look-up with a couple of small tables.
**
** For further precision, we add the first term of the Taylor expansion of
** log2(1 + r/((2^k)*w)). This term can be computed quickly with a few
** bit masks and divisions.
**
** Compile with -DPRECISE=0 if precision can be fudged.
**
** Written by Kiem-Phong Vo (kpv@research.att.com)
*/
#ifndef PRECISE
#define PRECISE 1
#endif
static unsigned char _Vcpow2[256] = {
0, 0, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3,
4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7
};
static double _Vclog2[256] = {
0.0000000, 0.0000000, 1.0000000, 1.5849625, 2.0000000, 2.3219281, 2.5849625, 2.8073549,
3.0000000, 3.1699250, 3.3219281, 3.4594316, 3.5849625, 3.7004397, 3.8073549, 3.9068906,
4.0000000, 4.0874628, 4.1699250, 4.2479275, 4.3219281, 4.3923174, 4.4594316, 4.5235620,
4.5849625, 4.6438562, 4.7004397, 4.7548875, 4.8073549, 4.8579810, 4.9068906, 4.9541963,
5.0000000, 5.0443941, 5.0874628, 5.1292830, 5.1699250, 5.2094534, 5.2479275, 5.2854022,
5.3219281, 5.3575520, 5.3923174, 5.4262648, 5.4594316, 5.4918531, 5.5235620, 5.5545889,
5.5849625, 5.6147098, 5.6438562, 5.6724253, 5.7004397, 5.7279205, 5.7548875, 5.7813597,
5.8073549, 5.8328900, 5.8579810, 5.8826430, 5.9068906, 5.9307373, 5.9541963, 5.9772799,
6.0000000, 6.0223678, 6.0443941, 6.0660892, 6.0874628, 6.1085245, 6.1292830, 6.1497471,
6.1699250, 6.1898246, 6.2094534, 6.2288187, 6.2479275, 6.2667865, 6.2854022, 6.3037807,
6.3219281, 6.3398500, 6.3575520, 6.3750394, 6.3923174, 6.4093909, 6.4262648, 6.4429435,
6.4594316, 6.4757334, 6.4918531, 6.5077946, 6.5235620, 6.5391588, 6.5545889, 6.5698556,
6.5849625, 6.5999128, 6.6147098, 6.6293566, 6.6438562, 6.6582115, 6.6724253, 6.6865005,
6.7004397, 6.7142455, 6.7279205, 6.7414670, 6.7548875, 6.7681843, 6.7813597, 6.7944159,
6.8073549, 6.8201790, 6.8328900, 6.8454901, 6.8579810, 6.8703647, 6.8826430, 6.8948178,
6.9068906, 6.9188632, 6.9307373, 6.9425145, 6.9541963, 6.9657843, 6.9772799, 6.9886847,
7.0000000, 7.0112273, 7.0223678, 7.0334230, 7.0443941, 7.0552824, 7.0660892, 7.0768156,
7.0874628, 7.0980321, 7.1085245, 7.1189411, 7.1292830, 7.1395514, 7.1497471, 7.1598713,
7.1699250, 7.1799091, 7.1898246, 7.1996723, 7.2094534, 7.2191685, 7.2288187, 7.2384047,
7.2479275, 7.2573878, 7.2667865, 7.2761244, 7.2854022, 7.2946207, 7.3037807, 7.3128830,
7.3219281, 7.3309169, 7.3398500, 7.3487282, 7.3575520, 7.3663222, 7.3750394, 7.3837043,
7.3923174, 7.4008794, 7.4093909, 7.4178525, 7.4262648, 7.4346282, 7.4429435, 7.4512111,
7.4594316, 7.4676056, 7.4757334, 7.4838158, 7.4918531, 7.4998459, 7.5077946, 7.5156998,
7.5235620, 7.5313815, 7.5391588, 7.5468945, 7.5545889, 7.5622424, 7.5698556, 7.5774288,
7.5849625, 7.5924570, 7.5999128, 7.6073303, 7.6147098, 7.6220518, 7.6293566, 7.6366246,
7.6438562, 7.6510517, 7.6582115, 7.6653359, 7.6724253, 7.6794801, 7.6865005, 7.6934870,
7.7004397, 7.7073591, 7.7142455, 7.7210992, 7.7279205, 7.7347096, 7.7414670, 7.7481928,
7.7548875, 7.7615512, 7.7681843, 7.7747871, 7.7813597, 7.7879026, 7.7944159, 7.8008999,
7.8073549, 7.8137812, 7.8201790, 7.8265485, 7.8328900, 7.8392038, 7.8454901, 7.8517490,
7.8579810, 7.8641861, 7.8703647, 7.8765169, 7.8826430, 7.8887432, 7.8948178, 7.9008668,
7.9068906, 7.9128893, 7.9188632, 7.9248125, 7.9307373, 7.9366379, 7.9425145, 7.9483672,
7.9541963, 7.9600019, 7.9657843, 7.9715436, 7.9772799, 7.9829936, 7.9886847, 7.9943534
};
#if __STD_C
size_t vclogi(size_t v)
#else
size_t vclogi(v)
size_t v;
#endif
{
register size_t lg, b;
switch(sizeof(v) ) /* find the left most non-zero byte */
{ default: /* in case sizeof(unsigned int) > 4 */
for(lg = (sizeof(v)-1)*8; lg >= 32; lg -= 8)
if((b = v >> lg) != 0 )
goto got_byte;
case 4: lg = 24; if((b = v >> 24) != 0)
goto got_byte;
case 3: lg = 16; if((b = v >> 16) != 0)
goto got_byte;
case 2: lg = 8; if((b = v >> 8) != 0)
goto got_byte;
case 1: lg = 0; b = v;
}
got_byte: return lg + _Vcpow2[b];
}
#if __STD_C
double vclog(size_t v)
#else
double vclog(v)
size_t v;
#endif
{
register int lg, b;
switch(sizeof(v) ) /* find the left most non-zero byte */
{ default: /* in case sizeof(unsigned int) > 4 */
for(lg = (sizeof(v)-1)*8; lg >= 32; lg -= 8)
if((b = v >> lg) != 0 )
goto got_byte;
case 4: lg = 24; if((b = v >> 24) != 0)
goto got_byte;
case 3: lg = 16; if((b = v >> 16) != 0)
goto got_byte;
case 2: lg = 8; if((b = v >> 8) != 0)
goto got_byte;
case 1: return v == 0 ? 0. : _Vclog2[v];
}
got_byte:
lg = lg + _Vcpow2[b] - 7;
#if PRECISE
#define LOG2 0.6931472 /* natural log of 2 */
b = (1 << lg) - 1;
return lg + _Vclog2[v >> lg] + (v & b)/((v & ~b)*LOG2);
#else
return lg + _Vclog2[v >> lg];
#endif
}
#ifdef TABLE /* code to generate the above _Vc* tables */
#include <stdio.h>
#include <math.h>
main()
{
int i, k, lg, cnt;
printf("static unsigned char _Vcpow2[256] = {\n");
for(i = 2, k = 0, lg = 0, cnt = 0; i <= 256; i <<= 1, lg += 1)
{ for(; k < i; ++k)
{ printf(" %d%c", lg, (k < 255 ? ',' : ' ') );
if((cnt += 1)%16 == 0 )
printf("\n");
}
}
printf("};\n\n");
printf("static double _Vclog2[256] = {\n");
for(i = 0, cnt = 0; i < 256; ++i)
{ printf(" %9.7lf%c", (i == 0 ? 0 : log((double)i)/log(2.)),
(i < 255 ? ',' : ' ') );
if((cnt += 1)%8 == 0)
printf("\n");
}
printf("};\n\n");
}
#endif