查表法是通常采用的一种以空间(内存空间)换时间(运行时间)的程序加速方法
,基本过程是把需要经常查询数据库或复杂浮点计算的结果保存到一个数据结构中
(数组最为常见),以后只要根据条件取出相应的数据即可。比如把1-360度的正
切值保存到数组中,当输入45度时,只需取出第45个元素。这样就节约了不必要的
计算时间。
对于作为基本定义使用的表,数据不经常改变的数据表也可以使用这种方法。
注意:
1.表的数据常发生变化不能使用此方法,否则会造成错误.
2.对于结果数组,适当采用排序和二分查找更能提高查询速度.
例:用查表优化的方阵校验算法
/*数据到校验码映射*/
static byte s__D2E[16] =
{
1, /*0x0 0000*/
0, /*0x1 0001*/
0, /*0x2 0010*/
1, /*0x3 0011*/
0, /*0x4 0100*/
1, /*0x5 0101*/
1, /*0x6 0110*/
0, /*0x7 0111*/
0, /*0x8 1000*/
1, /*0x9 1001*/
1, /*0xA 1010*/
0, /*0xB 1011*/
1, /*0xC 1100*/
0, /*0xD 1101*/
0, /*0xE 1110*/
1 /*0xF 1111*/
};
/*校验数据的异或结果检查表,超过1个不同,为不可恢复用4表示,1位不同表达位置,5为相同*/
#define EOR_GOOD (5)
#define EOR_BAD (4)
static byte s__E2C[16] =
{
EOR_GOOD, /*0,没有不同*/
0, /*1,0001--*/
1, /*2,0010--*/
EOR_BAD, /*3,0011*/
2, /*4,0100--*/
EOR_BAD, /*5,0101*/
EOR_BAD, /*6,0110*/
EOR_BAD, /*7,0111*/
3, /*8,1000--*/
EOR_BAD, /*9,1001*/
EOR_BAD, /*10,1010*/
EOR_BAD, /*11,1011*/
EOR_BAD, /*12,1100*/
EOR_BAD, /*13,1101*/
EOR_BAD, /*14,1110*/
EOR_BAD, /*15,1111*/
};
/*------------------------------------------------------------------------------
方阵编码,能纠正连续4位中1位错误,
也就是16位中4位不同行、列错误
位目标的32位数据提供2位不同行列纠错能力
编码编好后供后续解码(纠错)使用
eh (j )
ll4 . . . . x 0 |
lh4 . . . . x 1 |
hl4 . . . . x 2 |
hh4 . . . . x 3 V
ev x x x x
(i)0 1 2 3
------->
输入:16位
返回:8位,高4位为eh,低4位位ev
todo:用汇编指令进行优化
------------------------------------------------------------------------------*/
#define SQUARE_RANG (4)
byte _SquareEc(word nD)
{
byte i, j;
byte m;
byte eh = ZERO; /*横*/
byte ev = ZERO; /*纵*/
byte n[4];
n[0] = _low4(_low8(nD));
n[1] = _high4(_low8(nD));
n[2] = _low4(_high8(nD));
n[3] = _high4(_high8(nD));
for (j = ZERO; j < SQUARE_RANG; j++)
{
/*算出m再查表*/
m = 0;
for (i = ZERO; i < SQUARE_RANG; i++)
{
if (n[i] & (ONE << j))
{
m = (byte)(m | (1 << i));
}
}
ev = (byte)(ev | (s__D2E[m] << j));
eh = (byte)(eh | (s__D2E[n[j]] << j));
}
return (byte)((eh << SQUARE_RANG) + ev);
}
/*------------------------------------------------------------------------------
方阵解码,能纠正连续4位中1位错误
也就是16位中4位不同行、列错误
位目标的32位数据提供2位不同行列纠错能力
解码也就是纠错的原理:
获得的数据(4 x 4 = 16位)新生成的校验(2个4位)
与原有自带的校验(2个4位)比较,那一位出错,
就代表该行或该列中有一个错
行列中交叉点位置的错修改过来即可。
无法纠那种连续4位中错误2位的错误。
新eh (j ) eh_org(高4)
ll4 . . . . x 0 | x
lh4 . . . . x 1 | x
hl4 . . . . x 2 | x
hh4 . . . . x 3 V x
新ev x x x x
(i)0 1 2 3
------->
ev_org x x x x (低4)
输入:原数据,原编码,新编码,
输出:新数据
返回:恢复OK返回BTRUE,如果无法恢复,返回BFALSE
todo:用汇编指令进行优化
------------------------------------------------------------------------------*/
boolean _SquareDc(word nOrg, byte nOrgEc, byte nNewEc, word* pNew)
{
byte eh_eor;
byte ev_eor;
byte n[4];
*pNew = nOrg;
if (nOrgEc == nNewEc)
{/*相等*/
return BTRUE;
}
/*异或求出差别位置*/
eh_eor = (byte)(_high4(nOrgEc) ^ _high4(nNewEc));
ev_eor = (byte)(_low4(nOrgEc) ^ _low4(nNewEc));
/*用转换数组定位*/
eh_eor = s__E2C[eh_eor];
ev_eor = s__E2C[ev_eor];
if ((EOR_BAD == eh_eor) || (EOR_BAD == ev_eor))
{/*任何一个差别超过2位,无法恢复*/
return BFALSE;
}
/*最多1位差别*/
if ((EOR_GOOD == eh_eor) || (EOR_GOOD == ev_eor))
{/*其中一个只差1位,另一个无差别,ecc错,数据未错*/
return BTRUE;
}
/*修复*/
n[0] = _low4(_low8(nOrg));
n[1] = _high4(_low8(nOrg));
n[2] = _low4(_high8(nOrg));
n[3] = _high4(_high8(nOrg));
if (n[eh_eor] & (1 << ev_eor))
{
n[eh_eor] = (byte)((n[eh_eor] & (~(1 << ev_eor))) & 0xF);
}
else
{
n[eh_eor] = (byte)(n[eh_eor] | (1 << ev_eor));
}
*pNew = (word)((n[3] << 12) | (n[2] << 8) | (n[1] << 4) | n[0]);
return BTRUE;
}
static void _OobEncode(NstlOob* pOob)
{
pOob->nEccL = _SquareEc(pOob->nLBN);
pOob->nEccP = _SquareEc(pOob->nPBN);
}
static boolean _OobDecode(NstlOob* pOob)
{
byte nL, nP;
word nNewL, nNewP;
nL = _SquareEc(pOob->nLBN);
nP = _SquareEc(pOob->nPBN);
if (!_SquareDc(pOob->nLBN, pOob->nEccL, nL, &nNewL))
{
return BFALSE;
}
if (!_SquareDc(pOob->nPBN, pOob->nEccP, nP, &nNewP))
{
return BFALSE;
}
pOob->nLBN = nNewL;
pOob->nPBN = nNewP;
return BTRUE;
}