Coverage Report

Created: 2025-11-09 07:01

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libxaac/encoder/ixheaace_psy_configuration.c
Line
Count
Source
1
/******************************************************************************
2
 *                                                                            *
3
 * Copyright (C) 2023 The Android Open Source Project
4
 *
5
 * Licensed under the Apache License, Version 2.0 (the "License");
6
 * you may not use this file except in compliance with the License.
7
 * You may obtain a copy of the License at:
8
 *
9
 * http://www.apache.org/licenses/LICENSE-2.0
10
 *
11
 * Unless required by applicable law or agreed to in writing, software
12
 * distributed under the License is distributed on an "AS IS" BASIS,
13
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
 * See the License for the specific language governing permissions and
15
 * limitations under the License.
16
 *
17
 *****************************************************************************
18
 * Originally developed and contributed by Ittiam Systems Pvt. Ltd, Bangalore
19
 */
20
21
#include <stdlib.h>
22
#include <math.h>
23
24
#include "ixheaac_type_def.h"
25
#include "ixheaac_constants.h"
26
#include "impd_drc_common_enc.h"
27
#include "impd_drc_uni_drc.h"
28
#include "impd_drc_tables.h"
29
#include "impd_drc_api.h"
30
#include "ixheaace_api.h"
31
#include "ixheaace_aac_constants.h"
32
#include "ixheaac_basic_ops32.h"
33
#include "ixheaac_basic_ops16.h"
34
#include "ixheaac_basic_ops40.h"
35
#include "ixheaac_basic_ops.h"
36
#include "ixheaac_error_standards.h"
37
#include "ixheaace_error_codes.h"
38
#include "ixheaace_psy_const.h"
39
#include "ixheaace_tns.h"
40
#include "ixheaace_tns_params.h"
41
#include "ixheaace_rom.h"
42
#include "ixheaace_common_rom.h"
43
#include "ixheaace_bitbuffer.h"
44
#include "ixheaace_psy_configuration.h"
45
46
#include "ixheaace_adjust_threshold_data.h"
47
#include "ixheaace_tns_params.h"
48
#include "ixheaace_dynamic_bits.h"
49
#include "ixheaace_qc_data.h"
50
#include "ixheaace_block_switch.h"
51
#include "ixheaace_psy_data.h"
52
#include "ixheaace_interface.h"
53
#include "ixheaace_adjust_threshold.h"
54
#include "ixheaace_common_utils.h"
55
56
static IA_ERRORCODE ia_enhaacplus_enc_init_sfb_table(ixheaace_psycho_tables *pstr_psycho_tab,
57
                                                     WORD32 sample_rate, WORD32 aot,
58
                                                     WORD32 block_type, WORD32 *ptr_sfb_offset,
59
9.84k
                                                     WORD32 *sfb_cnt, WORD32 long_frame_len) {
60
9.84k
  const UWORD8 *ptr_sfb_param = NULL;
61
9.84k
  UWORD32 i;
62
9.84k
  WORD32 spec_start_offset, spec_lines = 0;
63
64
  /* sfb_info_tab[] */
65
53.4k
  for (i = 0; i < sizeof(pstr_psycho_tab->sfb_info_tab) / sizeof(ixheaace_sfb_info_tab); i++) {
66
53.4k
    if (pstr_psycho_tab->sfb_info_tab[i].sample_rate == sample_rate) {
67
9.84k
      switch (block_type) {
68
6.01k
        case LONG_WINDOW:
69
6.01k
        case START_WINDOW:
70
6.01k
        case STOP_WINDOW:
71
6.01k
          if (aot == AOT_AAC_LC || aot == AOT_SBR || aot == AOT_PS) {
72
3.83k
            if (long_frame_len == FRAME_LEN_960) {
73
1.24k
              ptr_sfb_param = pstr_psycho_tab->sfb_info_tab[i].param_long_960;
74
2.58k
            } else {
75
2.58k
              ptr_sfb_param = pstr_psycho_tab->sfb_info_tab[i].param_long;
76
2.58k
            }
77
3.83k
            spec_lines = long_frame_len;
78
3.83k
            break;
79
3.83k
          } else if (aot == AOT_AAC_LD || aot == AOT_AAC_ELD) {
80
2.17k
            if (long_frame_len == FRAME_LEN_480)
81
1.04k
              ptr_sfb_param = pstr_psycho_tab->sfb_info_tab[i].param_long_480_ld;
82
1.13k
            else
83
1.13k
              ptr_sfb_param = pstr_psycho_tab->sfb_info_tab[i].param_long_512_ld;
84
2.17k
            spec_lines = long_frame_len;
85
2.17k
            break;
86
2.17k
          }
87
88
3.83k
        case SHORT_WINDOW:
89
3.83k
          if (long_frame_len == FRAME_LEN_SHORT_120) {
90
1.24k
            ptr_sfb_param = pstr_psycho_tab->sfb_info_tab[i].param_short_120;
91
2.58k
          } else {
92
2.58k
            ptr_sfb_param = pstr_psycho_tab->sfb_info_tab[i].param_short;
93
2.58k
          }
94
3.83k
          spec_lines = long_frame_len;
95
3.83k
          break;
96
9.84k
      }
97
9.84k
      break;
98
9.84k
    }
99
53.4k
  }
100
101
9.84k
  if (ptr_sfb_param == NULL) {
102
0
    return IA_EXHEAACE_INIT_FATAL_SCALE_FACTOR_BAND_NOT_SUPPORTED;
103
0
  }
104
105
9.84k
  *sfb_cnt = 0;
106
9.84k
  spec_start_offset = 0;
107
108
294k
  do {
109
294k
    ptr_sfb_offset[*sfb_cnt] = spec_start_offset;
110
111
294k
    spec_start_offset += ptr_sfb_param[*sfb_cnt];
112
113
294k
    (*sfb_cnt)++;
114
294k
  } while (spec_start_offset < spec_lines);
115
116
9.84k
  if (spec_start_offset != spec_lines) {
117
0
    return IA_EXHEAACE_INIT_FATAL_SFB_TABLE_INIT_FAILED;
118
0
  }
119
120
9.84k
  ptr_sfb_offset[*sfb_cnt] = spec_start_offset;
121
122
9.84k
  return IA_NO_ERROR;
123
9.84k
}
124
125
732k
FLOAT32 iaace_atan_approx(FLOAT32 val) {
126
732k
  if (val < (FLOAT32)1.0f) {
127
492k
    return (val / ((FLOAT32)1.0f + (FLOAT32)0.280872f * val * val));
128
492k
  } else {
129
239k
    return ((FLOAT32)1.57079633f - val / ((FLOAT32)0.280872f + val * val));
130
239k
  }
131
732k
}
132
133
294k
static FLOAT32 iaace_calc_bark_line_value(WORD32 num_lines, WORD32 fft_line, WORD32 sample_rate) {
134
294k
  FLOAT32 center_freq, temp, b_value;
135
294k
  center_freq = (FLOAT32)fft_line * ((FLOAT32)sample_rate * (FLOAT32)0.5f) / (FLOAT32)num_lines;
136
294k
  temp = (FLOAT32)iaace_atan_approx((FLOAT32)1.3333333e-4f * center_freq);
137
294k
  b_value = (FLOAT32)13.3f * iaace_atan_approx((FLOAT32)0.00076f * center_freq) +
138
294k
            (FLOAT32)3.5f * temp * temp;
139
294k
  return (b_value);
140
294k
}
141
142
static VOID iaace_thr_quiet_init(WORD32 sfb_count, WORD32 *ptr_sfb_offset, FLOAT32 *ptr_bark_val,
143
                                 FLOAT32 *ptr_thr_quiet, const FLOAT32 *ptr_bark_quiet_thr_val,
144
9.84k
                                 WORD32 aot) {
145
9.84k
  WORD32 i;
146
9.84k
  FLOAT32 bark_thr_quiet;
147
148
304k
  for (i = 0; i < sfb_count; i++) {
149
294k
    if (aot == AOT_AAC_ELD) {
150
48.6k
      ptr_thr_quiet[i] = (FLOAT32)(ptr_sfb_offset[i + 1] - ptr_sfb_offset[i]) * 42;
151
246k
    } else {
152
246k
      WORD32 b_val1, b_val2;
153
154
246k
      if (i > 0) {
155
237k
        b_val1 = (WORD32)(ptr_bark_val[i] + ptr_bark_val[i - 1]) >> 1;
156
237k
      } else {
157
8.24k
        b_val1 = (WORD32)(ptr_bark_val[i]) >> 1;
158
8.24k
      }
159
160
246k
      if (i < sfb_count - 1) {
161
237k
        b_val2 = (WORD32)(ptr_bark_val[i] + ptr_bark_val[i + 1]) >> 1;
162
237k
      } else {
163
8.24k
        b_val2 = (WORD32)(ptr_bark_val[i]);
164
8.24k
      }
165
246k
      b_val1 = MIN(b_val1, (WORD32)MAX_BARK_VALUE);
166
246k
      b_val2 = MIN(b_val2, (WORD32)MAX_BARK_VALUE);
167
246k
      bark_thr_quiet = MIN(ptr_bark_quiet_thr_val[b_val1], ptr_bark_quiet_thr_val[b_val2]);
168
169
246k
      ptr_thr_quiet[i] = (FLOAT32)db_lin_scale(bark_thr_quiet - 20.0f) * 16887.8f *
170
246k
                         (FLOAT32)(ptr_sfb_offset[i + 1] - ptr_sfb_offset[i]);
171
246k
    }
172
294k
  }
173
9.84k
}
174
175
static VOID iaace_spreading_init(WORD32 sfb_count, FLOAT32 *ptr_bark_val,
176
                                 FLOAT32 *ptr_mask_low_fac, FLOAT32 *ptr_mask_high_fac,
177
                                 FLOAT32 *ptr_mask_low_fac_spr_energy,
178
                                 FLOAT32 *ptr_mask_high_fac_spr_energy, const WORD32 bit_rate,
179
9.84k
                                 WORD32 block_type) {
180
9.84k
  WORD32 i;
181
9.84k
  FLOAT32 mask_low_spr_energy, mask_high_spr_energy;
182
183
9.84k
  if (block_type != SHORT_WINDOW) {
184
6.01k
    mask_low_spr_energy = MASK_LOW_SP_ENERGY_L;
185
6.01k
    mask_high_spr_energy = (bit_rate > MASK_HIGH_SP_BITRATE_THRESH) ? MASK_HIGH_SP_ENERGY_L
186
6.01k
                                                                    : MASK_HIGH_SP_ENERGY_L_LBR;
187
6.01k
  } else {
188
3.83k
    mask_low_spr_energy = MASK_LOW_SP_ENERGY_S;
189
3.83k
    mask_high_spr_energy = MASK_HIGH_SP_ENERGY_S;
190
3.83k
  }
191
192
304k
  for (i = 0; i < sfb_count; i++) {
193
294k
    if (i > 0) {
194
285k
      FLOAT32 db_val;
195
285k
      FLOAT32 diff_val = (ptr_bark_val[i] - ptr_bark_val[i - 1]);
196
197
285k
      db_val = MASK_HIGH_FAC * diff_val;
198
285k
      ptr_mask_high_fac[i] = (FLOAT32)pow(10.0f, -db_val);
199
285k
      db_val = MASK_LOW_FAC * diff_val;
200
285k
      ptr_mask_low_fac[i - 1] = (FLOAT32)pow(10.0f, -db_val);
201
285k
      db_val = mask_high_spr_energy * diff_val;
202
285k
      ptr_mask_high_fac_spr_energy[i] = (FLOAT32)pow(10.0f, -db_val);
203
285k
      db_val = mask_low_spr_energy * diff_val;
204
285k
      ptr_mask_low_fac_spr_energy[i - 1] = (FLOAT32)pow(10.0f, -db_val);
205
285k
    } else {
206
9.84k
      ptr_mask_high_fac[i] = 0.0f;
207
9.84k
      ptr_mask_low_fac[sfb_count - 1] = 0.0f;
208
9.84k
      ptr_mask_high_fac_spr_energy[i] = 0.0f;
209
9.84k
      ptr_mask_low_fac_spr_energy[sfb_count - 1] = 0.0f;
210
9.84k
    }
211
294k
  }
212
9.84k
  return;
213
9.84k
}
214
215
static VOID iaace_bark_values_init(WORD32 sfb_count, WORD32 *ptr_sfb_offset, WORD32 num_lines,
216
9.84k
                                   WORD32 sample_rate, FLOAT32 *ptr_b_value, WORD32 aot) {
217
9.84k
  WORD32 i;
218
9.84k
  FLOAT32 b_val0, b_val1;
219
9.84k
  b_val0 = 0.0f;
220
221
304k
  for (i = 0; i < sfb_count; i++) {
222
294k
    b_val1 = iaace_calc_bark_line_value(num_lines, ptr_sfb_offset[i + 1], sample_rate);
223
294k
    ptr_b_value[i] = (b_val0 + b_val1) * (FLOAT32)0.5f;
224
294k
    if (aot == AOT_AAC_ELD) {
225
48.6k
      if (ptr_b_value[i] > MAX_BARK_VALUE) {
226
0
        ptr_b_value[i] = MAX_BARK_VALUE;
227
0
      }
228
48.6k
    }
229
230
294k
    b_val0 = b_val1;
231
294k
  }
232
9.84k
}
233
234
9.84k
static FLOAT32 iaace_bits_to_pe(const FLOAT32 bits) { return (bits * 1.18f); }
235
static VOID iaace_min_snr_init(const WORD32 bit_rate, const WORD32 sample_rate,
236
                               const WORD32 num_lines, const WORD32 *ptr_sfb_offset,
237
                               const FLOAT32 *ptr_bark_value, const WORD32 sfb_active,
238
9.84k
                               FLOAT32 *ptr_sfb_min_snr) {
239
9.84k
  WORD32 sfb;
240
9.84k
  FLOAT32 bark_fac;
241
9.84k
  FLOAT32 bark_width;
242
9.84k
  FLOAT32 pe_per_window, pe_part;
243
9.84k
  FLOAT32 snr;
244
9.84k
  FLOAT32 b_val0, b_val1;
245
246
9.84k
  bark_fac = (FLOAT32)1.0 / MIN(ptr_bark_value[sfb_active - 1] / MAX_BARK_VALUE, (FLOAT32)1.0);
247
9.84k
  pe_per_window = iaace_bits_to_pe((FLOAT32)bit_rate / (FLOAT32)sample_rate * (FLOAT32)num_lines);
248
9.84k
  b_val0 = (FLOAT32)0.0f;
249
250
241k
  for (sfb = 0; sfb < sfb_active; sfb++) {
251
231k
    b_val1 = (FLOAT32)2.0 * ptr_bark_value[sfb] - b_val0;
252
231k
    bark_width = b_val1 - b_val0;
253
231k
    b_val0 = b_val1;
254
255
231k
    pe_part = pe_per_window * (FLOAT32)0.024f * bark_fac;
256
231k
    pe_part *= bark_width;
257
231k
    pe_part /= (FLOAT32)(ptr_sfb_offset[sfb + 1] - ptr_sfb_offset[sfb]);
258
231k
    snr = (FLOAT32)pow(2.0f, pe_part) - 1.5f;
259
231k
    snr = 1.0f / MAX(snr, 1.0f);
260
231k
    snr = MIN(snr, 0.8f);
261
231k
    snr = MAX(snr, 0.003f);
262
231k
    ptr_sfb_min_snr[sfb] = snr;
263
231k
  }
264
9.84k
}
265
266
IA_ERRORCODE ia_enhaacplus_enc_init_psy_configuration(
267
    WORD32 bit_rate, WORD32 sample_rate, WORD32 bandwidth, WORD32 aot,
268
    ixheaace_psy_configuration_long *pstr_psy_conf, ixheaace_aac_tables *pstr_aac_tables,
269
6.01k
    WORD32 long_frame_len) {
270
6.01k
  WORD32 sfb;
271
6.01k
  FLOAT32 sfb_bark_val[MAXIMUM_SCALE_FACTOR_BAND_LONG];
272
6.01k
  IA_ERRORCODE error;
273
6.01k
  error = ia_enhaacplus_enc_init_sfb_table(pstr_aac_tables->pstr_psycho_tab, sample_rate, aot,
274
6.01k
                                           LONG_WINDOW, pstr_psy_conf->sfb_offsets,
275
6.01k
                                           &(pstr_psy_conf->sfb_cnt), long_frame_len);
276
6.01k
  if (error != IA_NO_ERROR) {
277
0
    return error;
278
0
  }
279
280
  /*   calculate bark values for each pb */
281
6.01k
  iaace_bark_values_init(pstr_psy_conf->sfb_cnt, pstr_psy_conf->sfb_offsets,
282
6.01k
                         pstr_psy_conf->sfb_offsets[pstr_psy_conf->sfb_cnt], sample_rate,
283
6.01k
                         sfb_bark_val, aot);
284
285
  /*init thresholds in quiet  */
286
287
6.01k
  iaace_thr_quiet_init(pstr_psy_conf->sfb_cnt, pstr_psy_conf->sfb_offsets, sfb_bark_val,
288
6.01k
                       pstr_psy_conf->sfb_threshold_quiet,
289
6.01k
                       pstr_aac_tables->pstr_psycho_tab->ixheaace_bark_quiet_thr_val, aot);
290
291
  /*  calculate spreading function */
292
293
6.01k
  iaace_spreading_init(pstr_psy_conf->sfb_cnt, sfb_bark_val, pstr_psy_conf->sfb_mask_low_factor,
294
6.01k
                       pstr_psy_conf->sfb_mask_high_factor,
295
6.01k
                       pstr_psy_conf->sfb_mask_low_factor_spread_nrg,
296
6.01k
                       pstr_psy_conf->sfb_mask_high_factor_spread_nrg, bit_rate, LONG_WINDOW);
297
298
  /*
299
    init ratio
300
  */
301
302
6.01k
  pstr_psy_conf->min_remaining_threshold_factor = MIN_THRESH_FAC;
303
304
6.01k
  pstr_psy_conf->clip_energy = CLIP_ENERGY_VALUE_LONG;
305
6.01k
  if (aot == AOT_AAC_LC || aot == AOT_SBR || aot == AOT_PS) {
306
3.83k
    pstr_psy_conf->ratio_float = C_RATIO;
307
3.83k
  } else if (aot == AOT_AAC_LD || aot == AOT_AAC_ELD) {
308
2.17k
    if (aot == AOT_AAC_ELD) {
309
1.59k
      pstr_psy_conf->ratio_float = C_RATIO;
310
1.59k
    } else {
311
581
      pstr_psy_conf->ratio_float = SNR_FLOAT;
312
581
    }
313
2.17k
  }
314
315
6.01k
  pstr_psy_conf->lowpass_line = (WORD32)((2 * bandwidth * long_frame_len) / sample_rate);
316
317
  /* pstr_psy_conf->pstr_sfb_offset[] */
318
194k
  for (sfb = 0; sfb < pstr_psy_conf->sfb_cnt; sfb++) {
319
194k
    if (pstr_psy_conf->sfb_offsets[sfb] >= pstr_psy_conf->lowpass_line) break;
320
194k
  }
321
6.01k
  pstr_psy_conf->sfb_active = sfb;
322
323
  /*
324
    calculate minSnr
325
  */
326
6.01k
  iaace_min_snr_init(bit_rate, sample_rate, pstr_psy_conf->sfb_offsets[pstr_psy_conf->sfb_cnt],
327
6.01k
                     pstr_psy_conf->sfb_offsets, sfb_bark_val, pstr_psy_conf->sfb_active,
328
6.01k
                     pstr_psy_conf->sfb_min_snr);
329
330
6.01k
  return IA_NO_ERROR;
331
6.01k
}
332
333
IA_ERRORCODE ia_enhaacplus_enc_init_psy_configuration_short(
334
    WORD32 bit_rate, WORD32 sample_rate, WORD32 bandwidth, WORD32 aot,
335
    ixheaace_psy_configuration_short *pstr_psy_conf, ixheaace_aac_tables *pstr_aac_tables,
336
3.83k
    WORD32 long_frame_len) {
337
3.83k
  WORD32 sfb;
338
3.83k
  FLOAT32 sfb_bark_val[MAXIMUM_SCALE_FACTOR_BAND_SHORT] = {0};
339
3.83k
  IA_ERRORCODE error;
340
  /*
341
    init sfb table
342
  */
343
3.83k
  error = ia_enhaacplus_enc_init_sfb_table(pstr_aac_tables->pstr_psycho_tab, sample_rate, aot,
344
3.83k
                                           SHORT_WINDOW, pstr_psy_conf->sfb_offsets,
345
3.83k
                                           &(pstr_psy_conf->sfb_cnt), long_frame_len);
346
347
3.83k
  if (error != IA_NO_ERROR) {
348
0
    return error;
349
0
  }
350
351
3.83k
  iaace_bark_values_init(pstr_psy_conf->sfb_cnt, pstr_psy_conf->sfb_offsets,
352
3.83k
                         pstr_psy_conf->sfb_offsets[pstr_psy_conf->sfb_cnt], sample_rate,
353
3.83k
                         sfb_bark_val, aot);
354
355
3.83k
  iaace_thr_quiet_init(pstr_psy_conf->sfb_cnt, pstr_psy_conf->sfb_offsets, sfb_bark_val,
356
3.83k
                       pstr_psy_conf->sfb_threshold_quiet,
357
3.83k
                       pstr_aac_tables->pstr_psycho_tab->ixheaace_bark_quiet_thr_val, aot);
358
359
  /*
360
    calculate spreading function
361
  */
362
3.83k
  iaace_spreading_init(pstr_psy_conf->sfb_cnt, sfb_bark_val, pstr_psy_conf->sfb_mask_low_factor,
363
3.83k
                       pstr_psy_conf->sfb_mask_high_factor,
364
3.83k
                       pstr_psy_conf->sfb_mask_low_factor_spread_nrg,
365
3.83k
                       pstr_psy_conf->sfb_mask_high_factor_spread_nrg, bit_rate, SHORT_WINDOW);
366
367
  /*
368
    init ratio
369
  */
370
371
3.83k
  pstr_psy_conf->min_remaining_threshold_factor = 0.01f;
372
373
3.83k
  pstr_psy_conf->clip_energy = CLIP_ENERGY_VALUE_LONG / (TRANS_FAC * TRANS_FAC);
374
3.83k
  switch (aot) {
375
1.34k
    case AOT_AAC_LC:
376
3.52k
    case AOT_SBR:
377
3.83k
    case AOT_PS:
378
3.83k
      pstr_psy_conf->ratio_float = C_RATIO;
379
3.83k
      break;
380
381
0
    case AOT_AAC_LD:
382
0
    case AOT_AAC_ELD:
383
0
      pstr_psy_conf->ratio_float = SNR_FLOAT;
384
0
      break;
385
3.83k
  }
386
387
3.83k
  pstr_psy_conf->lowpass_line = (WORD32)((2 * bandwidth * long_frame_len) / sample_rate);
388
46.7k
  for (sfb = 0; sfb < pstr_psy_conf->sfb_cnt; sfb++) {
389
45.9k
    if (pstr_psy_conf->sfb_offsets[sfb] >= pstr_psy_conf->lowpass_line) break;
390
45.9k
  }
391
3.83k
  pstr_psy_conf->sfb_active = sfb;
392
393
3.83k
  iaace_min_snr_init(bit_rate, sample_rate, pstr_psy_conf->sfb_offsets[pstr_psy_conf->sfb_cnt],
394
3.83k
                     pstr_psy_conf->sfb_offsets, sfb_bark_val, pstr_psy_conf->sfb_active,
395
3.83k
                     pstr_psy_conf->sfb_min_snr);
396
397
3.83k
  return IA_NO_ERROR;
398
3.83k
}
399
400
WORD32 ia_enhaacplus_enc_power2(WORD32 power, WORD q_power, WORD *q_result,
401
                                const WORD32 *power_of_2_table_neg,
402
0
                                const WORD32 *power_of_2_table_pos) {
403
0
  WORD32 int_part, frac_part;
404
0
  WORD32 result;
405
0
  WORD16 sign = 0;
406
407
0
  if (power < 0) {
408
0
    sign = 1;
409
0
    power = ixheaac_negate32(power);
410
0
  }
411
412
0
  if (q_power < 32)
413
0
    int_part = ixheaac_shr32(power, q_power);
414
0
  else
415
0
    int_part = 0;
416
417
0
  if (q_power < 39) {
418
0
    power = ixheaac_shr32_dir(power, q_power - 8);
419
0
    frac_part = power & 0xFF;
420
0
  } else
421
0
    frac_part = 0;
422
423
0
  if (!sign) {
424
0
    result = power_of_2_table_pos[frac_part];
425
0
    *q_result = Q_POWER2_TABLE - int_part;
426
0
  } else {
427
0
    result = power_of_2_table_neg[frac_part];
428
0
    *q_result = Q_POWER2_TABLE + int_part;
429
0
  }
430
431
0
  return (result);
432
0
}