#include "internal.h"
#include "mathops.h"
#if !defined(OC_ILOG_NODEBRUIJN)&&!defined(OC_CLZ32)
static const unsigned char OC_DEBRUIJN_IDX32[32]={
0, 1,28, 2,29,14,24, 3,30,22,20,15,25,17, 4, 8,
31,27,13,23,21,19,16, 7,26,12,18, 6,11, 5,10, 9
};
#endif
int oc_ilog32(ogg_uint32_t _v){
#if defined(OC_CLZ32)
return _v ? (OC_CLZ32_OFFS-OC_CLZ32(_v)) : 0;
#else
# if defined(OC_ILOG_NODEBRUIJN)
int ret;
int m;
ret=_v>0;
m=(_v>0xFFFFU)<<4;
_v>>=m;
ret|=m;
m=(_v>0xFFU)<<3;
_v>>=m;
ret|=m;
m=(_v>0xFU)<<2;
_v>>=m;
ret|=m;
m=(_v>3)<<1;
_v>>=m;
ret|=m;
ret+=_v>1;
return ret;
# else
int ret;
_v|=_v>>1;
_v|=_v>>2;
_v|=_v>>4;
_v|=_v>>8;
_v|=_v>>16;
ret=_v&1;
_v=(_v>>1)+1;
ret+=OC_DEBRUIJN_IDX32[_v*0x77CB531U>>27&0x1F];
return ret;
# endif
#endif
}
int oc_ilog64(ogg_int64_t _v){
#if defined(CLZ64)
return _v ? CLZ64_OFFS-CLZ64(_v) : 0;
#else
# if defined(OC_ILOG_NODEBRUIJN)|| \
defined(OC_CLZ32)||LONG_MAX<9223372036854775807LL
ogg_uint32_t v;
int ret;
int m;
m=(_v>0xFFFFFFFFU)<<5;
v=(ogg_uint32_t)(_v>>m);
# if defined(OC_CLZ32)
ret=m+OC_CLZ32_OFFS-OC_CLZ32(v)&-!!v;
# elif defined(OC_ILOG_NODEBRUIJN)
ret=v>0|m;
m=(v>0xFFFFU)<<4;
v>>=m;
ret|=m;
m=(v>0xFFU)<<3;
v>>=m;
ret|=m;
m=(v>0xFU)<<2;
v>>=m;
ret|=m;
m=(v>3)<<1;
v>>=m;
ret|=m;
ret+=v>1;
return ret;
# else
v|=v>>1;
v|=v>>2;
v|=v>>4;
v|=v>>8;
v|=v>>16;
ret=v&1|m;
v=(v>>1)+1;
ret+=OC_DEBRUIJN_IDX32[v*0x77CB531U>>27&0x1F];
# endif
return ret;
# else
static const unsigned char OC_DEBRUIJN_IDX64[64]={
0, 1, 2, 7, 3,13, 8,19, 4,25,14,28, 9,34,20,40,
5,17,26,38,15,46,29,48,10,31,35,54,21,50,41,57,
63, 6,12,18,24,27,33,39,16,37,45,47,30,53,49,56,
62,11,23,32,36,44,52,55,61,22,43,51,60,42,59,58
};
int ret;
_v|=_v>>1;
_v|=_v>>2;
_v|=_v>>4;
_v|=_v>>8;
_v|=_v>>16;
_v|=_v>>32;
ret=(int)_v&1;
_v=(_v>>1)+1;
ret+=OC_DEBRUIJN_IDX64[_v*0x218A392CD3D5DBF>>58&0x3F];
return ret;
# endif
#endif
}
static const ogg_int64_t OC_ATANH_LOG2[32]={
0x32B803473F7AD0F4LL,0x2F2A71BD4E25E916LL,0x2E68B244BB93BA06LL,
0x2E39FB9198CE62E4LL,0x2E2E683F68565C8FLL,0x2E2B850BE2077FC1LL,
0x2E2ACC58FE7B78DBLL,0x2E2A9E2DE52FD5F2LL,0x2E2A92A338D53EECLL,
0x2E2A8FC08F5E19B6LL,0x2E2A8F07E51A485ELL,0x2E2A8ED9BA8AF388LL,
0x2E2A8ECE2FE7384ALL,0x2E2A8ECB4D3E4B1ALL,0x2E2A8ECA94940FE8LL,
0x2E2A8ECA6669811DLL,0x2E2A8ECA5ADEDD6ALL,0x2E2A8ECA57FC347ELL,
0x2E2A8ECA57438A43LL,0x2E2A8ECA57155FB4LL,0x2E2A8ECA5709D510LL,
0x2E2A8ECA5706F267LL,0x2E2A8ECA570639BDLL,0x2E2A8ECA57060B92LL,
0x2E2A8ECA57060008LL,0x2E2A8ECA5705FD25LL,0x2E2A8ECA5705FC6CLL,
0x2E2A8ECA5705FC3ELL,0x2E2A8ECA5705FC33LL,0x2E2A8ECA5705FC30LL,
0x2E2A8ECA5705FC2FLL,0x2E2A8ECA5705FC2FLL
};
ogg_int64_t oc_bexp64(ogg_int64_t _z){
ogg_int64_t w;
ogg_int64_t z;
int ipart;
ipart=(int)(_z>>57);
if(ipart<0)return 0;
if(ipart>=63)return 0x7FFFFFFFFFFFFFFFLL;
z=_z-OC_Q57(ipart);
if(z){
ogg_int64_t mask;
long wlo;
int i;
z*=32;
w=0x26A3D0E401DD846DLL;
for(i=0;;i++){
mask=-(z<0);
w+=(w>>i+1)+mask^mask;
z-=OC_ATANH_LOG2[i]+mask^mask;
if(i>=3)break;
z*=2;
}
for(;;i++){
mask=-(z<0);
w+=(w>>i+1)+mask^mask;
z-=OC_ATANH_LOG2[i]+mask^mask;
if(i>=12)break;
z*=2;
}
for(;i<32;i++){
mask=-(z<0);
w+=(w>>i+1)+mask^mask;
z=(z-(OC_ATANH_LOG2[i]+mask^mask))*2;
}
wlo=0;
if(ipart>30){
for(;;i++){
mask=-(z<0);
wlo+=(w>>i)+mask^mask;
z-=OC_ATANH_LOG2[31]+mask^mask;
if(i>=39)break;
z*=2;
}
for(;i<61;i++){
mask=-(z<0);
wlo+=(w>>i)+mask^mask;
z=(z-(OC_ATANH_LOG2[31]+mask^mask))*2;
}
}
w=(w<<1)+wlo;
}
else w=(ogg_int64_t)1<<62;
if(ipart<62)w=(w>>61-ipart)+1>>1;
return w;
}
ogg_int64_t oc_blog64(ogg_int64_t _w){
ogg_int64_t z;
int ipart;
if(_w<=0)return -1;
ipart=OC_ILOGNZ_64(_w)-1;
if(ipart>61)_w>>=ipart-61;
else _w<<=61-ipart;
z=0;
if(_w&_w-1){
ogg_int64_t x;
ogg_int64_t y;
ogg_int64_t u;
ogg_int64_t mask;
int i;
x=_w+((ogg_int64_t)1<<61);
y=_w-((ogg_int64_t)1<<61);
for(i=0;i<4;i++){
mask=-(y<0);
z+=(OC_ATANH_LOG2[i]>>i)+mask^mask;
u=x>>i+1;
x-=(y>>i+1)+mask^mask;
y-=u+mask^mask;
}
for(i--;i<13;i++){
mask=-(y<0);
z+=(OC_ATANH_LOG2[i]>>i)+mask^mask;
u=x>>i+1;
x-=(y>>i+1)+mask^mask;
y-=u+mask^mask;
}
for(i--;i<32;i++){
mask=-(y<0);
z+=(OC_ATANH_LOG2[i]>>i)+mask^mask;
u=x>>i+1;
x-=(y>>i+1)+mask^mask;
y-=u+mask^mask;
}
for(;i<40;i++){
mask=-(y<0);
z+=(OC_ATANH_LOG2[31]>>i)+mask^mask;
u=x>>i+1;
x-=(y>>i+1)+mask^mask;
y-=u+mask^mask;
}
for(i--;i<62;i++){
mask=-(y<0);
z+=(OC_ATANH_LOG2[31]>>i)+mask^mask;
u=x>>i+1;
x-=(y>>i+1)+mask^mask;
y-=u+mask^mask;
}
z=z+8>>4;
}
return OC_Q57(ipart)+z;
}
ogg_uint32_t oc_bexp32_q10(int _z){
unsigned n;
int ipart;
ipart=_z>>10;
n=(_z&(1<<10)-1)<<4;
n=(n*((n*((n*((n*3548>>15)+6817)>>15)+15823)>>15)+22708)>>15)+16384;
return 14-ipart>0?n+(1<<13-ipart)>>14-ipart:n<<ipart-14;
}
int oc_blog32_q10(ogg_uint32_t _w){
int n;
int ipart;
int fpart;
if(_w<=0)return -1;
ipart=OC_ILOGNZ_32(_w);
n=(ipart-16>0?_w>>ipart-16:_w<<16-ipart)-32768-16384;
fpart=(n*((n*((n*((n*-1402>>15)+2546)>>15)-5216)>>15)+15745)>>15)-6793;
return (ipart<<10)+(fpart>>4);
}