summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorVadim Yanitskiy <axilirator@gmail.com>2017-06-19 06:16:37 +0700
committerVadim Yanitskiy <axilirator@gmail.com>2017-06-19 14:35:22 +0000
commit0876ef899e6f2ce3d2cd999cce62da77f282dcd0 (patch)
tree8fccd9c1a50b30952b1908787d79a75552409483
parent1ac56fb2928b256363905202adeb554334b018b8 (diff)
core/conv/conv_acc.c: use static allocation for trellis
Allocation of a new memory is an expensive operation, which takes place when it's initially unknown, how much memory will we need, or in order to decrease total memory usage. The trellis struct wasn't require dynamic allocation itself, so let's allocate one statically inside the vdecoder structure. Change-Id: Ib8e448823ca5548a05a45824b0b1c06743dfe5a4
-rw-r--r--src/conv_acc.c50
1 files changed, 23 insertions, 27 deletions
diff --git a/src/conv_acc.c b/src/conv_acc.c
index f45d50f0..13b220b0 100644
--- a/src/conv_acc.c
+++ b/src/conv_acc.c
@@ -164,7 +164,7 @@ struct vdecoder {
int len;
int recursive;
int intrvl;
- struct vtrellis *trellis;
+ struct vtrellis trellis;
int16_t **paths;
void (*metric_func)(const int8_t *, const int16_t *,
@@ -372,41 +372,38 @@ static void free_trellis(struct vtrellis *trellis)
vdec_free(trellis->outputs);
vdec_free(trellis->sums);
free(trellis->vals);
- free(trellis);
}
-/* Allocate and initialize the trellis object
+/* Initialize the trellis object
* Initialization consists of generating the outputs and output value of a
* given state. Due to trellis symmetry and anti-symmetry, only one of the
* transition paths is utilized by the butterfly operation in the forward
* recursion, so only one set of N outputs is required per state variable.
*/
-static struct vtrellis *generate_trellis(const struct osmo_conv_code *code)
+static int generate_trellis(struct vdecoder *dec,
+ const struct osmo_conv_code *code)
{
- int i, rc = -1;
- struct vtrellis *trellis;
+ struct vtrellis *trellis = &dec->trellis;
int16_t *outputs;
+ int i, rc;
int ns = NUM_STATES(code->K);
- int recursive = conv_code_recursive(code);
int olen = (code->N == 2) ? 2 : 4;
- trellis = (struct vtrellis *) calloc(1, sizeof(struct vtrellis));
- if (!trellis)
- goto fail;
-
trellis->num_states = ns;
trellis->sums = vdec_malloc(ns);
trellis->outputs = vdec_malloc(ns * olen);
trellis->vals = (uint8_t *) malloc(ns * sizeof(uint8_t));
- if (!trellis->sums || !trellis->outputs || !trellis->vals)
+ if (!trellis->sums || !trellis->outputs || !trellis->vals) {
+ rc = -ENOMEM;
goto fail;
+ }
/* Populate the trellis state objects */
for (i = 0; i < ns; i++) {
outputs = &trellis->outputs[olen * i];
- if (recursive) {
+ if (dec->recursive) {
rc = gen_recursive_state_info(&trellis->vals[i],
i, outputs, code);
} else {
@@ -429,11 +426,11 @@ static struct vtrellis *generate_trellis(const struct osmo_conv_code *code)
if (code->term != CONV_TERM_TAIL_BITING)
trellis->sums[0] = INT8_MAX * code->N * code->K;
- return trellis;
+ return 0;
fail:
free_trellis(trellis);
- return NULL;
+ return rc;
}
static void _traceback(struct vdecoder *dec,
@@ -444,7 +441,7 @@ static void _traceback(struct vdecoder *dec,
for (i = len - 1; i >= 0; i--) {
path = dec->paths[i][state] + 1;
- out[i] = dec->trellis->vals[state];
+ out[i] = dec->trellis.vals[state];
state = vstate_lshift(state, dec->k, path);
}
}
@@ -457,7 +454,7 @@ static void _traceback_rec(struct vdecoder *dec,
for (i = len - 1; i >= 0; i--) {
path = dec->paths[i][state] + 1;
- out[i] = path ^ dec->trellis->vals[state];
+ out[i] = path ^ dec->trellis.vals[state];
state = vstate_lshift(state, dec->k, path);
}
}
@@ -472,8 +469,8 @@ static int traceback(struct vdecoder *dec, uint8_t *out, int term, int len)
unsigned path, state = 0;
if (term != CONV_TERM_FLUSH) {
- for (i = 0; i < dec->trellis->num_states; i++) {
- sum = dec->trellis->sums[i];
+ for (i = 0; i < dec->trellis.num_states; i++) {
+ sum = dec->trellis.sums[i];
if (sum > max) {
max = sum;
state = i;
@@ -503,7 +500,7 @@ static void vdec_deinit(struct vdecoder *dec)
if (!dec)
return;
- free_trellis(dec->trellis);
+ free_trellis(&dec->trellis);
if (dec->paths != NULL) {
vdec_free(dec->paths[0]);
@@ -517,7 +514,7 @@ static void vdec_deinit(struct vdecoder *dec)
*/
static int vdec_init(struct vdecoder *dec, const struct osmo_conv_code *code)
{
- int i, ns;
+ int i, ns, rc;
ns = NUM_STATES(code->K);
@@ -563,9 +560,9 @@ static int vdec_init(struct vdecoder *dec, const struct osmo_conv_code *code)
else
dec->len = code->len;
- dec->trellis = generate_trellis(code);
- if (!dec->trellis)
- goto enomem;
+ rc = generate_trellis(dec, code);
+ if (rc)
+ return rc;
dec->paths = (int16_t **) malloc(sizeof(int16_t *) * dec->len);
if (!dec->paths)
@@ -610,13 +607,12 @@ static int depuncture(const int8_t *in, const int *punc, int8_t *out, int len)
*/
static void forward_traverse(struct vdecoder *dec, const int8_t *seq)
{
- struct vtrellis *trellis = dec->trellis;
int i;
for (i = 0; i < dec->len; i++) {
dec->metric_func(&seq[dec->n * i],
- trellis->outputs,
- trellis->sums,
+ dec->trellis.outputs,
+ dec->trellis.sums,
dec->paths[i],
!(i % dec->intrvl));
}