/* Write a constant expression in binary form to a buffer. */ int gfc_target_encode_expr (gfc_expr *source, unsigned char *buffer, size_t buffer_size) { if (source == NULL) return 0; if (source->expr_type == EXPR_ARRAY) return encode_array (source, buffer, buffer_size); gcc_assert (source->expr_type == EXPR_CONSTANT || source->expr_type == EXPR_STRUCTURE || source->expr_type == EXPR_SUBSTRING); /* If we already have a target-memory representation, we use that rather than recreating one. */ if (source->representation.string) { memcpy (buffer, source->representation.string, source->representation.length); return source->representation.length; } switch (source->ts.type) { case BT_INTEGER: return encode_integer (source->ts.kind, source->value.integer, buffer, buffer_size); case BT_REAL: return encode_float (source->ts.kind, source->value.real, buffer, buffer_size); case BT_COMPLEX: return encode_complex (source->ts.kind, source->value.complex.r, source->value.complex.i, buffer, buffer_size); case BT_LOGICAL: return encode_logical (source->ts.kind, source->value.logical, buffer, buffer_size); case BT_CHARACTER: if (source->expr_type == EXPR_CONSTANT || source->ref == NULL) return encode_character (source->value.character.length, source->value.character.string, buffer, buffer_size); else { int start, end; gcc_assert (source->expr_type == EXPR_SUBSTRING); gfc_extract_int (source->ref->u.ss.start, &start); gfc_extract_int (source->ref->u.ss.end, &end); return encode_character (MAX(end - start + 1, 0), &source->value.character.string[start-1], buffer, buffer_size); } case BT_DERIVED: return encode_derived (source, buffer, buffer_size); default: gfc_internal_error ("Invalid expression in gfc_target_encode_expr."); return 0; } }
bool checkreturn pb_encode(pb_ostream_t *stream, const pb_field_t fields[], const void *src_struct) { const pb_field_t *field = fields; const void *pData = src_struct; const void *pSize; size_t prev_size = 0; while (field->tag != 0) { pb_encoder_t func = PB_ENCODERS[PB_LTYPE(field->type)]; pData = (const char*)pData + prev_size + field->data_offset; pSize = (const char*)pData + field->size_offset; prev_size = field->data_size; if (PB_HTYPE(field->type) == PB_HTYPE_ARRAY) prev_size *= field->array_size; switch (PB_HTYPE(field->type)) { case PB_HTYPE_REQUIRED: if (!pb_encode_tag_for_field(stream, field)) return false; if (!func(stream, field, pData)) return false; break; case PB_HTYPE_OPTIONAL: if (*(const bool*)pSize) { if (!pb_encode_tag_for_field(stream, field)) return false; if (!func(stream, field, pData)) return false; } break; case PB_HTYPE_ARRAY: if (!encode_array(stream, field, pData, *(const size_t*)pSize, func)) return false; break; case PB_HTYPE_CALLBACK: { const pb_callback_t *callback = (const pb_callback_t*)pData; if (callback->funcs.encode != NULL) { if (!callback->funcs.encode(stream, field, callback->arg)) return false; } break; } } field++; } return true; }
/* Encode a field with static or pointer allocation, i.e. one whose data * is available to the encoder directly. */ static bool checkreturn encode_basic_field(pb_ostream_t *stream, const pb_field_t *field, const void *pData) { pb_encoder_t func; const void *pSize; bool implicit_has = true; func = PB_ENCODERS[PB_LTYPE(field->type)]; if (field->size_offset) pSize = (const char*)pData + field->size_offset; else pSize = &implicit_has; if (PB_ATYPE(field->type) == PB_ATYPE_POINTER) { /* pData is a pointer to the field, which contains pointer to * the data. If the 2nd pointer is NULL, it is interpreted as if * the has_field was false. */ pData = *(const void* const*)pData; implicit_has = (pData != NULL); } switch (PB_HTYPE(field->type)) { case PB_HTYPE_REQUIRED: if (!pData) PB_RETURN_ERROR(stream, "missing required field"); if (!pb_encode_tag_for_field(stream, field)) return false; if (!func(stream, field, pData)) return false; break; case PB_HTYPE_OPTIONAL: if (*(const bool*)pSize) { if (!pb_encode_tag_for_field(stream, field)) return false; if (!func(stream, field, pData)) return false; } break; case PB_HTYPE_REPEATED: if (!encode_array(stream, field, pData, *(const size_t*)pSize, func)) return false; break; default: PB_RETURN_ERROR(stream, "invalid field type"); } return true; }
/* Encode a field with static allocation, i.e. one whose data is stored * in the structure itself. */ static bool checkreturn encode_static_field(pb_ostream_t *stream, const pb_field_t *field, const void *pData) { pb_encoder_t func; const void *pSize; bool dummy = true; func = PB_ENCODERS[PB_LTYPE(field->type)]; if (field->size_offset) pSize = (const char*)pData + field->size_offset; else pSize = &dummy; switch (PB_HTYPE(field->type)) { case PB_HTYPE_REQUIRED: if (!pb_encode_tag_for_field(stream, field)) return false; if (!func(stream, field, pData)) return false; break; case PB_HTYPE_OPTIONAL: if (*(const bool*)pSize) { if (!pb_encode_tag_for_field(stream, field)) return false; if (!func(stream, field, pData)) return false; } break; case PB_HTYPE_REPEATED: if (!encode_array(stream, field, pData, *(const size_t*)pSize, func)) return false; break; default: PB_RETURN_ERROR(stream, "invalid field type"); } return true; }
void write_weights (unsigned total, const wfa_t *wfa, bitfile_t *output) /* * Traverse the transition matrices of the 'wfa' and write #'total' * weights != 0 to stream 'output'. * * No return value. */ { unsigned state, label; /* current label */ unsigned offset1, offset2; /* model offsets. */ unsigned offset3, offset4; /* model offsets. */ unsigned *weights_array; /* array of weights to encode */ unsigned *wptr; /* pointer to current weight */ unsigned *level_array; /* array of corresponding levels */ unsigned *lptr; /* pointer to current corr. level */ int min_level, max_level; /* min and max range level */ int d_min_level, d_max_level; /* min and max delta range level */ bool_t dc, d_dc; /* true if dc or delta dc are used */ bool_t delta_approx = NO; /* true if delta has been used */ unsigned delta_count = 0; /* number of delta ranges */ unsigned bits = bits_processed (output); /* * Check whether delta approximation has been used */ for (state = wfa->basis_states; state < wfa->states; state++) if (wfa->delta_state [state]) { delta_approx = YES; break; } /* * Generate array of corresponding levels (context of probability model) */ min_level = d_min_level = MAXLEVEL; max_level = d_max_level = 0; dc = d_dc = NO; for (state = wfa->basis_states; state < wfa->states; state++) for (label = 0; label < MAXLABELS; label++) if (isrange (wfa->tree [state][label])) { if (delta_approx && wfa->delta_state [state]) /* delta approx. */ { d_min_level = min (d_min_level, wfa->level_of_state [state] - 1); d_max_level = max (d_max_level, wfa->level_of_state [state] - 1); if (wfa->into [state][label][0] == 0) d_dc = YES; } else { min_level = min (min_level, wfa->level_of_state [state] - 1); max_level = max (max_level, wfa->level_of_state [state] - 1); if (wfa->into [state][label][0] == 0) dc = YES; } } if (min_level > max_level) /* no lc found */ max_level = min_level - 1; if (d_min_level > d_max_level) d_max_level = d_min_level - 1; /* * Context model: * 0 DC weight * 1 Delta DC weight * 2-k normal weights per level * k+1 - m Delta weights per level */ offset1 = dc ? 1 : 0; offset2 = offset1 + (d_dc ? 1 : 0); offset3 = offset2 + (max_level - min_level + 1); offset4 = offset3 + (d_max_level - d_min_level + 1); /* * Weights are encoded as follows: * all weights of state n * sorted by label * sorted by domain number */ wptr = weights_array = Calloc (total, sizeof (unsigned)); lptr = level_array = Calloc (total, sizeof (unsigned)); for (state = wfa->basis_states; state < wfa->states; state++) for (label = 0; label < MAXLABELS; label++) if (isrange (wfa->tree [state][label])) { int edge; /* current edge */ int domain; /* current domain (context of model) */ for (edge = 0; isedge (domain = wfa->into [state][label][edge]); edge++) { if (wptr - weights_array >= (int) total) error ("Can't write more than %d weights.", total); if (domain) /* not DC component */ { if (delta_approx && wfa->delta_state [state]) /* delta */ { *wptr++ = rtob (wfa->weight [state][label][edge], wfa->wfainfo->d_rpf); *lptr++ = offset3 + wfa->level_of_state [state] - 1 - d_min_level; delta_count++; } else { *wptr++ = rtob (wfa->weight [state][label][edge], wfa->wfainfo->rpf); *lptr++ = offset2 + wfa->level_of_state [state] - 1 - min_level; } } else /* DC component */ { if (delta_approx && wfa->delta_state [state]) /* delta */ { *wptr++ = rtob (wfa->weight [state][label][edge], wfa->wfainfo->d_dc_rpf); *lptr++ = offset1; } else { *wptr++ = rtob (wfa->weight [state][label][edge], wfa->wfainfo->dc_rpf); *lptr++ = 0; } } } } { unsigned i; unsigned *c_symbols = Calloc (offset4, sizeof (int)); const int scale = 500; /* scaling of probability model */ c_symbols [0] = 1 << (wfa->wfainfo->dc_rpf->mantissa_bits + 1); if (offset1 != offset2) c_symbols [offset1] = 1 << (wfa->wfainfo->d_dc_rpf->mantissa_bits + 1); for (i = offset2; i < offset3; i++) c_symbols [i] = 1 << (wfa->wfainfo->rpf->mantissa_bits + 1); for (; i < offset4; i++) c_symbols [i] = 1 << (wfa->wfainfo->d_rpf->mantissa_bits + 1); encode_array (output, weights_array, level_array, c_symbols, offset4, total, scale); Free (c_symbols); } debug_message ("%d delta weights out of %d.", delta_count, total); debug_message ("weights: %5d bits. (%5d symbols => %5.2f bps)", bits_processed (output) - bits, total, (bits_processed (output) - bits) / (double) total); Free (weights_array); Free (level_array); }