0001
0002
0003
0004
0005
0006 #include "phy_qmath.h"
0007
0008
0009
0010
0011
0012
0013 u16 qm_mulu16(u16 op1, u16 op2)
0014 {
0015 return (u16) (((u32) op1 * (u32) op2) >> 16);
0016 }
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026 s16 qm_muls16(s16 op1, s16 op2)
0027 {
0028 s32 result;
0029 if (op1 == (s16) 0x8000 && op2 == (s16) 0x8000)
0030 result = 0x7fffffff;
0031 else
0032 result = ((s32) (op1) * (s32) (op2));
0033
0034 return (s16) (result >> 15);
0035 }
0036
0037
0038
0039
0040
0041
0042 s32 qm_add32(s32 op1, s32 op2)
0043 {
0044 s32 result;
0045 result = op1 + op2;
0046 if (op1 < 0 && op2 < 0 && result > 0)
0047 result = 0x80000000;
0048 else if (op1 > 0 && op2 > 0 && result < 0)
0049 result = 0x7fffffff;
0050
0051 return result;
0052 }
0053
0054
0055
0056
0057
0058
0059 s16 qm_add16(s16 op1, s16 op2)
0060 {
0061 s16 result;
0062 s32 temp = (s32) op1 + (s32) op2;
0063 if (temp > (s32) 0x7fff)
0064 result = (s16) 0x7fff;
0065 else if (temp < (s32) 0xffff8000)
0066 result = (s16) 0xffff8000;
0067 else
0068 result = (s16) temp;
0069
0070 return result;
0071 }
0072
0073
0074
0075
0076
0077
0078 s16 qm_sub16(s16 op1, s16 op2)
0079 {
0080 s16 result;
0081 s32 temp = (s32) op1 - (s32) op2;
0082 if (temp > (s32) 0x7fff)
0083 result = (s16) 0x7fff;
0084 else if (temp < (s32) 0xffff8000)
0085 result = (s16) 0xffff8000;
0086 else
0087 result = (s16) temp;
0088
0089 return result;
0090 }
0091
0092
0093
0094
0095
0096
0097
0098 s32 qm_shl32(s32 op, int shift)
0099 {
0100 int i;
0101 s32 result;
0102 result = op;
0103 if (shift > 31)
0104 shift = 31;
0105 else if (shift < -31)
0106 shift = -31;
0107 if (shift >= 0) {
0108 for (i = 0; i < shift; i++)
0109 result = qm_add32(result, result);
0110 } else {
0111 result = result >> (-shift);
0112 }
0113
0114 return result;
0115 }
0116
0117
0118
0119
0120
0121
0122
0123 s16 qm_shl16(s16 op, int shift)
0124 {
0125 int i;
0126 s16 result;
0127 result = op;
0128 if (shift > 15)
0129 shift = 15;
0130 else if (shift < -15)
0131 shift = -15;
0132 if (shift > 0) {
0133 for (i = 0; i < shift; i++)
0134 result = qm_add16(result, result);
0135 } else {
0136 result = result >> (-shift);
0137 }
0138
0139 return result;
0140 }
0141
0142
0143
0144
0145
0146
0147 s16 qm_shr16(s16 op, int shift)
0148 {
0149 return qm_shl16(op, -shift);
0150 }
0151
0152
0153
0154
0155
0156 s16 qm_norm32(s32 op)
0157 {
0158 u16 u16extraSignBits;
0159 if (op == 0) {
0160 return 31;
0161 } else {
0162 u16extraSignBits = 0;
0163 while ((op >> 31) == (op >> 30)) {
0164 u16extraSignBits++;
0165 op = op << 1;
0166 }
0167 }
0168 return u16extraSignBits;
0169 }
0170
0171
0172 static const s16 log_table[] = {
0173 0,
0174 1455,
0175 2866,
0176 4236,
0177 5568,
0178 6863,
0179 8124,
0180 9352,
0181 10549,
0182 11716,
0183 12855,
0184 13968,
0185 15055,
0186 16117,
0187 17156,
0188 18173,
0189 19168,
0190 20143,
0191 21098,
0192 22034,
0193 22952,
0194 23852,
0195 24736,
0196 25604,
0197 26455,
0198 27292,
0199 28114,
0200 28922,
0201 29717,
0202 30498,
0203 31267,
0204 32024,
0205 32767
0206 };
0207
0208 #define LOG_TABLE_SIZE 32
0209 #define LOG2_LOG_TABLE_SIZE 5
0210 #define Q_LOG_TABLE 15
0211 #define LOG10_2 19728
0212
0213
0214
0215
0216
0217
0218
0219
0220
0221
0222
0223
0224
0225
0226
0227
0228
0229
0230
0231
0232 void qm_log10(s32 N, s16 qN, s16 *log10N, s16 *qLog10N)
0233 {
0234 s16 s16norm, s16tableIndex, s16errorApproximation;
0235 u16 u16offset;
0236 s32 s32log;
0237
0238
0239 s16norm = qm_norm32(N);
0240 N = N << s16norm;
0241
0242
0243
0244
0245
0246
0247
0248 qN = qN + s16norm - 30;
0249
0250
0251
0252 s16tableIndex = (s16) (N >> (32 - (2 + LOG2_LOG_TABLE_SIZE)));
0253
0254
0255 s16tableIndex =
0256 s16tableIndex & (s16) ((1 << LOG2_LOG_TABLE_SIZE) - 1);
0257
0258
0259 N = N & ((1 << (32 - (2 + LOG2_LOG_TABLE_SIZE))) - 1);
0260
0261
0262
0263 u16offset = (u16) (N >> (32 - (2 + LOG2_LOG_TABLE_SIZE + 16)));
0264
0265
0266 s32log = log_table[s16tableIndex];
0267
0268
0269 s16errorApproximation = (s16) qm_mulu16(u16offset,
0270 (u16) (log_table[s16tableIndex + 1] -
0271 log_table[s16tableIndex]));
0272
0273
0274 s32log = qm_add16((s16) s32log, s16errorApproximation);
0275
0276
0277
0278
0279 s32log = qm_add32(s32log, ((s32) -qN) << 15);
0280
0281
0282 s16norm = qm_norm32(s32log);
0283
0284
0285
0286 s32log = qm_shl32(s32log, s16norm - 16);
0287
0288
0289
0290
0291
0292 *log10N = qm_muls16((s16) s32log, (s16) LOG10_2);
0293
0294
0295 *qLog10N = 15 + s16norm - 16 + 1;
0296
0297 return;
0298 }