Skip to content

Commit

Permalink
Use same index format for Decimal64 & 128
Browse files Browse the repository at this point in the history
  • Loading branch information
AlexPeshkoff committed Mar 6, 2017
1 parent d7b6b57 commit 7af54d7
Show file tree
Hide file tree
Showing 5 changed files with 75 additions and 110 deletions.
155 changes: 69 additions & 86 deletions src/common/DecFloat.cpp
Expand Up @@ -158,75 +158,6 @@ void make(unsigned int* key,
}
}

struct tab { UCHAR rshift, lshift; };
tab table[4] =
{
{ 2, 6 },
{ 4, 4 },
{ 6, 2 },
{ 8, 0 }
};

ULONG indexKey(char* key, unsigned pMax, const int bias, unsigned char* coeff, int sign, int exp)
{
// normalize coeff & exponent
unsigned dig = digits(pMax, coeff, exp);

// exponent bias and sign
exp += (bias + 1);
if (!dig)
exp = 0;
if (sign)
exp = -exp;
exp += 2 * (bias + 1); // make it positive
fb_assert(exp >= 0 && exp < 64 * 1024);

// encode exp
char* k = key;
*k++ = exp >> 8;
*k++ = exp & 0xff;

// invert negative
unsigned char* const end = &coeff[dig];
if (sign && dig)
{
fb_assert(end[-1]);
--end[-1];

for (unsigned char* p = coeff; p < end; ++p)
*p = 9 - *p;
}

// Some 0's in the end - caller, do not forget to reserve additional space on stack
end[0] = end[1] = 0;

// Avoid bad data in k in case when coeff is zero
*k = 0;

// compress coeff - 3 decimal digits (999) per 10 bits (1023)
unsigned char* p = coeff;
for (tab* t = table; p < end; p += 3)
{
USHORT val = p[0] * 100 + p[1] * 10 + p[2];
fb_assert(val < 1000); // 1024, 10 bit
*k |= (val >> t->rshift);
++k;
*k = (val << t->lshift);
if (!t->lshift)
{
++k;
*k = 0;
t = table;
}
else
++t;
}
if (*k)
++k;

return k - key;
}

void grab(unsigned int* key,
const unsigned pMax, const int bias, const unsigned decSize,
unsigned char* bcd, int& sign, int& exp)
Expand Down Expand Up @@ -446,22 +377,6 @@ void Decimal64::grabKey(unsigned int* key)
decDoubleFromBCD(&dec, exp, bcd, sign);
}

ULONG Decimal64::getIndexKeyLength()
{
return 9;
}

ULONG Decimal64::makeIndexKey(vary* buf)
{
unsigned char coeff[DECDOUBLE_Pmax + 2];
int sign = decDoubleGetCoefficient(&dec, coeff);
int exp = decDoubleGetExponent(&dec);

buf->vary_length = indexKey(buf->vary_string, DECDOUBLE_Pmax, DECDOUBLE_Bias, coeff, sign, exp);
return buf->vary_length;
}


Decimal128 Decimal128::set(Decimal64 d64)
{
decDoubleToWider(&d64.dec, &dec);
Expand Down Expand Up @@ -802,8 +717,76 @@ ULONG Decimal128::makeIndexKey(vary* buf)
unsigned char coeff[DECQUAD_Pmax + 2];
int sign = decQuadGetCoefficient(&dec, coeff);
int exp = decQuadGetExponent(&dec);
const int bias = DECQUAD_Bias;
const unsigned pMax = DECQUAD_Pmax;

// normalize coeff & exponent
unsigned dig = digits(pMax, coeff, exp);

// exponent bias and sign
exp += (bias + 1);
if (!dig)
exp = 0;
if (sign)
exp = -exp;
exp += 2 * (bias + 1); // make it positive
fb_assert(exp >= 0 && exp < 64 * 1024);

// encode exp
char* k = buf->vary_string;
*k++ = exp >> 8;
*k++ = exp & 0xff;

// invert negative
unsigned char* const end = &coeff[dig];
if (sign && dig)
{
fb_assert(end[-1]);
--end[-1];

for (unsigned char* p = coeff; p < end; ++p)
*p = 9 - *p;
}

// Some 0's in the end - caller, do not forget to reserve additional space on stack
end[0] = end[1] = 0;

// Avoid bad data in k in case when coeff is zero
*k = 0;

//
struct tab { UCHAR rshift, lshift; };
static tab table[4] =
{
{ 2, 6 },
{ 4, 4 },
{ 6, 2 },
{ 8, 0 }
};

// compress coeff - 3 decimal digits (999) per 10 bits (1023)
unsigned char* p = coeff;
for (tab* t = table; p < end; p += 3)
{
USHORT val = p[0] * 100 + p[1] * 10 + p[2];
fb_assert(val < 1000); // 1024, 10 bit
*k |= (val >> t->rshift);
++k;
*k = (val << t->lshift);
if (!t->lshift)
{
++k;
*k = 0;
t = table;
}
else
++t;
}
if (*k)
++k;

buf->vary_length = indexKey(buf->vary_string, DECQUAD_Pmax, DECQUAD_Bias, coeff, sign, exp);
// done
buf->vary_length = k - buf->vary_string;
return buf->vary_length;
}

Expand Down
2 changes: 0 additions & 2 deletions src/common/DecFloat.h
Expand Up @@ -76,8 +76,6 @@ class Decimal64

void makeKey(unsigned int* key) const;
void grabKey(unsigned int* key);
static ULONG getIndexKeyLength();
ULONG makeIndexKey(vary* buf);

#ifdef DEV_BUILD
int show();
Expand Down
22 changes: 4 additions & 18 deletions src/jrd/btr.cpp
Expand Up @@ -1373,11 +1373,7 @@ USHORT BTR_key_length(thread_db* tdbb, jrd_rel* relation, index_desc* idx)
length = sizeof(UCHAR);
break;

case idx_dec64:
length = Decimal64::getIndexKeyLength();
break;

case idx_dec128:
case idx_decimal:
length = Decimal128::getIndexKeyLength();
break;

Expand Down Expand Up @@ -1433,10 +1429,7 @@ USHORT BTR_key_length(thread_db* tdbb, jrd_rel* relation, index_desc* idx)
case idx_boolean:
length = sizeof(UCHAR);
break;
case idx_dec64:
length = Decimal64::getIndexKeyLength();
break;
case idx_dec128:
case idx_decimal:
length = Decimal128::getIndexKeyLength();
break;
default:
Expand Down Expand Up @@ -2437,22 +2430,15 @@ static void compress(thread_db* tdbb,
}

if (itype == idx_string || itype == idx_byte_array || itype == idx_metadata ||
itype == idx_dec64 || itype == idx_dec128 ||
itype >= idx_first_intl_string)
itype == idx_decimal || itype >= idx_first_intl_string)
{
VaryStr<MAX_KEY> buffer;
const UCHAR pad = (itype == idx_string) ? ' ' : 0;
UCHAR* ptr;

size_t length;

if (itype == idx_dec64)
{
Decimal64 dec = MOV_get_dec64(tdbb, desc);
length = dec.makeIndexKey(&buffer);
ptr = reinterpret_cast<UCHAR*>(buffer.vary_string);
}
else if (itype == idx_dec128)
if (itype == idx_decimal)
{
Decimal128 dec = MOV_get_dec128(tdbb, desc);
length = dec.makeIndexKey(&buffer);
Expand Down
3 changes: 1 addition & 2 deletions src/jrd/btr.h
Expand Up @@ -99,8 +99,7 @@ const int idx_sql_time = 6;
const int idx_timestamp = 7;
const int idx_numeric2 = 8; // Introduced for 64-bit Integer support
const int idx_boolean = 9;
const int idx_dec64 = 10;
const int idx_dec128 = 11;
const int idx_decimal = 10;

// idx_itype space for future expansion
const int idx_first_intl_string = 64; // .. MAX (short) Range of computed key strings
Expand Down
3 changes: 1 addition & 2 deletions src/jrd/dfw.epp
Expand Up @@ -1242,9 +1242,8 @@ USHORT DFW_assign_index_type(thread_db* tdbb, const Firebird::MetaName& name, SS
case dtype_boolean:
return idx_boolean;
case dtype_dec64:
return idx_dec64;
case dtype_dec128:
return idx_dec128;
return idx_decimal;
default:
return idx_numeric;
}
Expand Down

0 comments on commit 7af54d7

Please sign in to comment.