static void read_residual_block(BitstreamReader *br, const struct alac_parameters *params, unsigned sample_size, unsigned block_size, int residual[]) { const unsigned maximum_k = params->maximum_K; const unsigned history_multiplier = params->history_multiplier; int history = params->initial_history; unsigned sign_modifier = 0; int i = 0; while (i < block_size) { /*get an unsigned residual based on "history" and on "sample_size" as a last resort*/ const unsigned k = LOG2((history >> 9) + 3); const unsigned unsigned_residual = read_residual(br, MIN(k, maximum_k), sample_size) + sign_modifier; /*clear out old sign modifier, if any */ sign_modifier = 0; /*change unsigned residual into a signed residual and append it to "residuals"*/ if (unsigned_residual & 1) { residual[i++] = -((unsigned_residual + 1) >> 1); } else {
/** Access the successors of a vertex. * * This operation is not thread-safe and heavily modifies the random access * iterator. (Don't worry though, it doesn't touch the underlying graph, so * please do use one random iterator for each thread in your code.) * * @param[in] ri a random access iterator for the graph * @param[in] x the index of the node (i in [0,g->n-1]) * @param[out] start a pointer to internal memory for an array of length * len for the successors. DO NOT MODIFY THIS ARRAY. * @param[out] len the node degree. * @return 0 on success */ int bvgraph_random_successors(bvgraph_random_iterator *ri, int64_t x, int64_t** start, uint64_t *length) { if (x<0 || x >= ri->g->n) { return (bvgraph_vertex_out_of_range); } else if (ri->offset_step <= 0) { return (bvgraph_requires_offsets); } else { int64_t ref, ref_index; int64_t i, extra_count, block_count = 0; bvgraph_int_vector *block = &ri->block, *left = &ri->left, *len = &ri->len; bvgraph *g = ri->g; bitfile *bf = &ri->bf; uint64_t d; //degree int64_t* temp = NULL; int64_t* ref_links = NULL; uint64_t outd_ref = 0LL; int64_t interval_count; int64_t buf1_index, buf2_index; int cyclic_buffer_size; { int rval = position_bvgraph(ri, x, &d); if (rval) { return (rval); } } *length = d; if (d == 0) { *start = NULL; return (0); } // read a reference only if the window is bigger than 0 if (g->window_size > 0) { ref = read_reference(g, bf); } else { ref = -1; } // get successors of referred node if (ref > 0) { // get the reference links first bvgraph_random_successors(ri, x-ref, &temp, &outd_ref); // copy the reference successors cause ri->successors.a might be cleared ref_links = malloc(sizeof(int64_t)*outd_ref); memcpy(ref_links, temp, sizeof(int64_t)*outd_ref); // re-assigned the original node and position to ri since ri has been changed ri->curr = x; position_bvgraph(ri, x, &d); if (g->window_size > 0) { ref = read_reference(g, bf); } else { ref = -1; } } cyclic_buffer_size = g->window_size + 1; // in our case, window isn't set at all, so we need to use the position // method to set the file pointer, this could modify ri itself. // this step requires offsets // ri->outd_cache[x%ri->cyclic_buffer_size] = d; ri->curr_outd = d; if (d > (unsigned)ri->max_outd) { ri->max_outd = d; } int_vector_ensure_size(&ri->successors, d); int_vector_ensure_size(&ri->buf1, d); int_vector_ensure_size(&ri->buf2, d); ref_index = (x-ref + cyclic_buffer_size)%(cyclic_buffer_size); if (ref > 0) { // total number of successors copied and total number specified int64_t copied, total; if ( (block_count = read_block_count(g, bf)) != 0 ) { // TODO: test success int_vector_ensure_size(&ri->block, block_count); } TRACE((DEBUG_DEEP, "block_count = %"PRINTF_INT64_MODIFIER"\n", block_count)); copied = 0; total = 0; for (i = 0; i < block_count; i++) { block->a[i] = read_block(g, bf) + (i == 0 ? 0 : 1); // TODO: test success total += block->a[i]; if (i % 2 == 0) { copied += block->a[i]; } } if (block_count%2 == 0) { // TODO: add check for window // TODO: test success copied += (outd_ref - total); ri->outd_cache[ref_index] = outd_ref; } // TODO: error on copied > d extra_count = d - copied; } else { extra_count = d; } interval_count = 0; if (extra_count > 0) { if (g->min_interval_length != 0 && (interval_count = bitfile_read_gamma(bf)) != 0) { int64_t prev = 0; // TODO: test success int_vector_ensure_size(left, interval_count); int_vector_ensure_size(len, interval_count); // now read the intervals left->a[0] = prev = nat2int(bitfile_read_gamma(bf)) + x; len->a[0] = bitfile_read_gamma(bf) + g->min_interval_length; prev += len->a[0]; extra_count -= len->a[0]; for (i=1; i < interval_count; i++) { left->a[i] = prev = bitfile_read_gamma(bf) + prev + 1; len->a[i] = bitfile_read_gamma(bf) + g->min_interval_length; prev += len->a[i]; extra_count -= len->a[i]; } } } buf1_index = 0; buf2_index = 0; TRACE((DEBUG_DEEP, "extra_count = %"PRINTF_INT64_MODIFIER"\n" "interval_count = %"PRINTF_INT64_MODIFIER"\n" "ref = %"PRINTF_INT64_MODIFIER"\n", extra_count, interval_count, ref)); // read the residuals into a buffer { int64_t prev = -1; int64_t residual_count = extra_count; while (residual_count > 0) { residual_count--; if (prev == -1) { ri->buf1.a[buf1_index++] = prev = x + nat2int(read_residual(g, bf)); } else { ri->buf1.a[buf1_index++] = prev = read_residual(g, bf) + prev + 1; } } } if (interval_count == 0) { // don't do anything } else { // copy the extra interval data for (i = 0; i < interval_count; i++) { int64_t j, cur_left = ri->left.a[i]; for (j = 0; j < ri->len.a[i]; j++) { ri->buf2.a[buf2_index++] = cur_left + j; } } if (extra_count > 0) { // merge buf1, buf2 into arcs merge_int_arrays(ri->buf1.a, buf1_index, ri->buf2.a, buf2_index, ri->successors.a, ri->successors.elements); // now copy arcs back to buffer1, and free buffer2 buf1_index = buf1_index + buf2_index; buf2_index = 0; memcpy(ri->buf1.a, ri->successors.a, buf1_index*sizeof(int64_t)); } else { memcpy(ri->buf1.a, ri->buf2.a, buf2_index*sizeof(int64_t)); buf1_index = buf2_index; buf2_index = 0; } } if (ref <= 0) { // don't do anything except copy // the data to arcs if (interval_count == 0 || extra_count == 0) { memcpy(ri->successors.a, ri->buf1.a, sizeof(int64_t)*buf1_index); } } else { // TODO clean this code up // copy the information from the masked iterator int64_t mask_index = 0; // this variable is intended to shadow the vector len int64_t len = 0; for (i=0; i < (signed)outd_ref; ) { if (len <= 0) { if (block_count == mask_index) { if (block_count % 2 == 0) { len = ri->outd_cache[ref_index] - i; } else { break; } } else { if (mask_index % 2 == 0) { len = ri->block.a[mask_index++]; } else { i += ri->block.a[mask_index++]; continue; } } // in the case that length is 0, we continue. if (len == 0) { continue; } } ri->buf2.a[buf2_index++] = ref_links[i]; len--; i++; } merge_int_arrays(ri->buf1.a, buf1_index, ri->buf2.a, buf2_index, ri->successors.a, ri->successors.elements); buf1_index = buf1_index + buf2_index; buf2_index = 0; // free the successors of referred node free(ref_links); } } if (start){ *start = ri->successors.a; } return (0); }