diff options
Diffstat (limited to '3rdparty/bimg/3rdparty/astc/astc_weight_align.cpp')
-rw-r--r-- | 3rdparty/bimg/3rdparty/astc/astc_weight_align.cpp | 600 |
1 files changed, 0 insertions, 600 deletions
diff --git a/3rdparty/bimg/3rdparty/astc/astc_weight_align.cpp b/3rdparty/bimg/3rdparty/astc/astc_weight_align.cpp deleted file mode 100644 index 789438fd137..00000000000 --- a/3rdparty/bimg/3rdparty/astc/astc_weight_align.cpp +++ /dev/null @@ -1,600 +0,0 @@ -/*----------------------------------------------------------------------------*/ -/** - * This confidential and proprietary software may be used only as - * authorised by a licensing agreement from ARM Limited - * (C) COPYRIGHT 2011-2012 ARM Limited - * ALL RIGHTS RESERVED - * - * The entire notice above must be reproduced on all authorised - * copies and copies may only be made to the extent permitted - * by a licensing agreement from ARM Limited. - * - * @brief Angular-sum algorithm for weight alignment. - * - * This algorithm works as follows: - * * we compute a complex number P as (cos s*i, sin s*i) for each - * weight, where i is the input value and s is a scaling factor - * based on the spacing between the weights. - * * we then add together complex numbers for all the weights. - * * we then compute the length and angle of the resulting sum. - * - * This should produce the following results: - * * perfect alignment results in a vector whose length is equal to - * the sum of lengths of all inputs - * * even distribution results in a vector of length 0. - * * all samples identical results in perfect alignment for every - * scaling. - * - * For each scaling factor within a given set, we compute an alignment - * factor from 0 to 1. This should then result in some scalings standing - * out as having particularly good alignment factors; we can use this to - * produce a set of candidate scale/shift values for various quantization - * levels; we should then actually try them and see what happens. - * - * Assuming N quantization steps, the scaling factor becomes s=2*PI*(N-1); - * we should probably have about 1 scaling factor for every 1/4 - * quantization step (perhaps 1/8 for low levels of quantization) - */ -/*----------------------------------------------------------------------------*/ - -#define _USE_MATH_DEFINES // for M_PI on windows - -#include <math.h> -#include "astc_codec_internals.h" - -#ifdef DEBUG_PRINT_DIAGNOSTICS - #include <stdio.h> -#endif - -static const float angular_steppings[] = { - 1.0, 1.125, - 1.25, 1.375, - 1.5, 1.625, - 1.75, 1.875, - - 2.0, 2.25, 2.5, 2.75, - 3.0, 3.25, 3.5, 3.75, - 4.0, 4.25, 4.5, 4.75, - 5.0, 5.25, 5.5, 5.75, - 6.0, 6.25, 6.5, 6.75, - 7.0, 7.25, 7.5, 7.75, - - 8.0, 8.5, - 9.0, 9.5, - 10.0, 10.5, - 11.0, 11.5, - 12.0, 12.5, - 13.0, 13.5, - 14.0, 14.5, - 15.0, 15.5, - 16.0, 16.5, - 17.0, 17.5, - 18.0, 18.5, - 19.0, 19.5, - 20.0, 20.5, - 21.0, 21.5, - 22.0, 22.5, - 23.0, 23.5, - 24.0, 24.5, - 25.0, 25.5, - 26.0, 26.5, - 27.0, 27.5, - 28.0, 28.5, - 29.0, 29.5, - 30.0, 30.5, - 31.0, 31.5, - 32.0, 32.5, - 33.0, 33.5, - 34.0, 34.5, - 35.0, 35.5, -}; - -#define ANGULAR_STEPS ((int)(sizeof(angular_steppings)/sizeof(angular_steppings[0]))) - -static float stepsizes[ANGULAR_STEPS]; -static float stepsizes_sqr[ANGULAR_STEPS]; - -static int max_angular_steps_needed_for_quant_level[13]; - -// we store sine/cosine values for 64 possible weight values; this causes -// slight quality loss compared to using sin() and cos() directly. - -#define SINCOS_STEPS 64 - -static float sin_table[SINCOS_STEPS][ANGULAR_STEPS]; -static float cos_table[SINCOS_STEPS][ANGULAR_STEPS]; - -void prepare_angular_tables(void) -{ - int i, j; - int max_angular_steps_needed_for_quant_steps[40]; - for (i = 0; i < ANGULAR_STEPS; i++) - { - stepsizes[i] = 1.0f / angular_steppings[i]; - stepsizes_sqr[i] = stepsizes[i] * stepsizes[i]; - - for (j = 0; j < SINCOS_STEPS; j++) - { - sin_table[j][i] = static_cast < float >(sin((2.0f * M_PI / (SINCOS_STEPS - 1.0f)) * angular_steppings[i] * j)); - cos_table[j][i] = static_cast < float >(cos((2.0f * M_PI / (SINCOS_STEPS - 1.0f)) * angular_steppings[i] * j)); - } - - int p = static_cast < int >(floor(angular_steppings[i])) + 1; - max_angular_steps_needed_for_quant_steps[p] = MIN(i + 1, ANGULAR_STEPS - 1); - } - - - // yes, the next-to-last entry is supposed to have the value 33. This because under - // ASTC, the 32-weight mode leaves a double-sized hole in the middle of the - // weight space, so we are better off matching 33 weights than 32. - static const int steps_of_level[] = { 2, 3, 4, 5, 6, 8, 10, 12, 16, 20, 24, 33, 36 }; - - for (i = 0; i < 13; i++) - max_angular_steps_needed_for_quant_level[i] = max_angular_steps_needed_for_quant_steps[steps_of_level[i]]; - -} - - -union if32 -{ - float f; - int32_t s; - uint32_t u; -}; - - -// function to compute angular sums; then, from the -// angular sums, compute alignment factor and offset. - -/* static inline */ -void compute_angular_offsets(int samplecount, const float *samples, const float *sample_weights, int max_angular_steps, float *offsets) -{ - int i, j; - - float anglesum_x[ANGULAR_STEPS]; - float anglesum_y[ANGULAR_STEPS]; - - for (i = 0; i < max_angular_steps; i++) - { - anglesum_x[i] = 0; - anglesum_y[i] = 0; - } - - - // compute the angle-sums. - for (i = 0; i < samplecount; i++) - { - float sample = samples[i]; - float sample_weight = sample_weights[i]; - if32 p; - p.f = (sample * (SINCOS_STEPS - 1.0f)) + 12582912.0f; - unsigned int isample = p.u & 0x3F; - - const float *sinptr = sin_table[isample]; - const float *cosptr = cos_table[isample]; - - for (j = 0; j < max_angular_steps; j++) - { - float cp = cosptr[j]; - float sp = sinptr[j]; - - anglesum_x[j] += cp * sample_weight; - anglesum_y[j] += sp * sample_weight; - } - } - - // post-process the angle-sums - for (i = 0; i < max_angular_steps; i++) - { - float angle = atan2(anglesum_y[i], anglesum_x[i]); // positive angle -> positive offset - offsets[i] = angle * (stepsizes[i] * (1.0f / (2.0f * (float)M_PI))); - } -} - - - -// for a given step-size and a given offset, compute the -// lowest and highest weight that results from quantizing using the stepsize & offset. -// also, compute the resulting error. - - -/* static inline */ -void compute_lowest_and_highest_weight(int samplecount, const float *samples, const float *sample_weights, - int max_angular_steps, const float *offsets, - int8_t * lowest_weight, int8_t * highest_weight, - float *error, float *cut_low_weight_error, float *cut_high_weight_error) -{ - int i; - - int sp; - - float error_from_forcing_weight_down[60]; - float error_from_forcing_weight_either_way[60]; - for (i = 0; i < 60; i++) - { - error_from_forcing_weight_down[i] = 0; - error_from_forcing_weight_either_way[i] = 0; - } - - // weight + 12 - static const unsigned int idxtab[256] = { - - 12, 13, 14, 15, 16, 17, 18, 19, - 20, 21, 22, 23, 24, 25, 26, 27, - 28, 29, 30, 31, 32, 33, 34, 35, - 36, 37, 38, 39, 40, 41, 42, 43, - 44, 45, 46, 47, 48, 49, 50, 51, - 52, 53, 54, 55, 55, 55, 55, 55, - 55, 55, 55, 55, 55, 55, 55, 55, - 55, 55, 55, 55, 55, 55, 55, 55, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 1, 2, 3, - 4, 5, 6, 7, 8, 9, 10, 11, - - 12, 13, 14, 15, 16, 17, 18, 19, - 20, 21, 22, 23, 24, 25, 26, 27, - 28, 29, 30, 31, 32, 33, 34, 35, - 36, 37, 38, 39, 40, 41, 42, 43, - 44, 45, 46, 47, 48, 49, 50, 51, - 52, 53, 54, 55, 55, 55, 55, 55, - 55, 55, 55, 55, 55, 55, 55, 55, - 55, 55, 55, 55, 55, 55, 55, 55, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 1, 2, 3, - 4, 5, 6, 7, 8, 9, 10, 11 - }; - - - - for (sp = 0; sp < max_angular_steps; sp++) - { - unsigned int minidx_bias12 = 55; - unsigned int maxidx_bias12 = 0; - - float errval = 0.0f; - - float rcp_stepsize = angular_steppings[sp]; - float offset = offsets[sp]; - - float scaled_offset = rcp_stepsize * offset; - - - for (i = 0; i < samplecount - 1; i += 2) - { - float wt1 = sample_weights[i]; - float wt2 = sample_weights[i + 1]; - if32 p1, p2; - float sval1 = (samples[i] * rcp_stepsize) - scaled_offset; - float sval2 = (samples[i + 1] * rcp_stepsize) - scaled_offset; - p1.f = sval1 + 12582912.0f; // FP representation abuse to avoid floor() and float->int conversion - p2.f = sval2 + 12582912.0f; // FP representation abuse to avoid floor() and float->int conversion - float isval1 = p1.f - 12582912.0f; - float isval2 = p2.f - 12582912.0f; - float dif1 = sval1 - isval1; - float dif2 = sval2 - isval2; - - errval += (dif1 * wt1) * dif1; - errval += (dif2 * wt2) * dif2; - - // table lookups that really perform a minmax function. - unsigned int idx1_bias12 = idxtab[p1.u & 0xFF]; - unsigned int idx2_bias12 = idxtab[p2.u & 0xFF]; - - if (idx1_bias12 < minidx_bias12) - minidx_bias12 = idx1_bias12; - if (idx1_bias12 > maxidx_bias12) - maxidx_bias12 = idx1_bias12; - if (idx2_bias12 < minidx_bias12) - minidx_bias12 = idx2_bias12; - if (idx2_bias12 > maxidx_bias12) - maxidx_bias12 = idx2_bias12; - - error_from_forcing_weight_either_way[idx1_bias12] += wt1; - error_from_forcing_weight_down[idx1_bias12] += (dif1 * wt1); - - error_from_forcing_weight_either_way[idx2_bias12] += wt2; - error_from_forcing_weight_down[idx2_bias12] += (dif2 * wt2); - } - - if (samplecount & 1) - { - i = samplecount - 1; - float wt = sample_weights[i]; - if32 p; - float sval = (samples[i] * rcp_stepsize) - scaled_offset; - p.f = sval + 12582912.0f; // FP representation abuse to avoid floor() and float->int conversion - float isval = p.f - 12582912.0f; - float dif = sval - isval; - - errval += (dif * wt) * dif; - - unsigned int idx_bias12 = idxtab[p.u & 0xFF]; - - if (idx_bias12 < minidx_bias12) - minidx_bias12 = idx_bias12; - if (idx_bias12 > maxidx_bias12) - maxidx_bias12 = idx_bias12; - - error_from_forcing_weight_either_way[idx_bias12] += wt; - error_from_forcing_weight_down[idx_bias12] += dif * wt; - } - - - lowest_weight[sp] = (int)minidx_bias12 - 12; - highest_weight[sp] = (int)maxidx_bias12 - 12; - error[sp] = errval; - - // the cut_(lowest/highest)_weight_error indicate the error that results from - // forcing samples that should have had the (lowest/highest) weight value - // one step (up/down). - cut_low_weight_error[sp] = error_from_forcing_weight_either_way[minidx_bias12] - 2.0f * error_from_forcing_weight_down[minidx_bias12]; - cut_high_weight_error[sp] = error_from_forcing_weight_either_way[maxidx_bias12] + 2.0f * error_from_forcing_weight_down[maxidx_bias12]; - - // clear out the error-from-forcing values we actually used in this pass - // so that these are clean for the next pass. - unsigned int ui; - for (ui = minidx_bias12 & ~0x3; ui <= maxidx_bias12; ui += 4) - { - error_from_forcing_weight_either_way[ui] = 0; - error_from_forcing_weight_down[ui] = 0; - error_from_forcing_weight_either_way[ui + 1] = 0; - error_from_forcing_weight_down[ui + 1] = 0; - error_from_forcing_weight_either_way[ui + 2] = 0; - error_from_forcing_weight_down[ui + 2] = 0; - error_from_forcing_weight_either_way[ui + 3] = 0; - error_from_forcing_weight_down[ui + 3] = 0; - } - } - - - for (sp = 0; sp < max_angular_steps; sp++) - { - float errscale = stepsizes_sqr[sp]; - error[sp] *= errscale; - cut_low_weight_error[sp] *= errscale; - cut_high_weight_error[sp] *= errscale; - } -} - - - -// main function for running the angular algorithm. - - -void compute_angular_endpoints_for_quantization_levels(int samplecount, const float *samples, const float *sample_weights, int max_quantization_level, float low_value[12], float high_value[12]) -{ - int i; - - - max_quantization_level++; // Temporarily increase level - needs refinement - - static const int quantization_steps_for_level[13] = { 2, 3, 4, 5, 6, 8, 10, 12, 16, 20, 24, 33, 36 }; - int max_quantization_steps = quantization_steps_for_level[max_quantization_level]; - - float offsets[ANGULAR_STEPS]; - - int max_angular_steps = max_angular_steps_needed_for_quant_level[max_quantization_level]; - - compute_angular_offsets(samplecount, samples, sample_weights, max_angular_steps, offsets); - - - // the +4 offsets are to allow for vectorization within compute_lowest_and_highest_weight(). - int8_t lowest_weight[ANGULAR_STEPS + 4]; - int8_t highest_weight[ANGULAR_STEPS + 4]; - float error[ANGULAR_STEPS + 4]; - - float cut_low_weight_error[ANGULAR_STEPS + 4]; - float cut_high_weight_error[ANGULAR_STEPS + 4]; - - compute_lowest_and_highest_weight(samplecount, samples, sample_weights, max_angular_steps, offsets, lowest_weight, highest_weight, error, cut_low_weight_error, cut_high_weight_error); - - - #ifdef DEBUG_PRINT_DIAGNOSTICS - if (print_diagnostics) - { - printf("%s : max-angular-steps=%d \n", __func__, max_angular_steps); - printf("Samplecount=%d, max_quantization_level=%d\n", samplecount, max_quantization_level); - for (i = 0; i < samplecount; i++) - printf("Sample %d : %f (weight %f)\n", i, samples[i], sample_weights[i]); - - for (i = 0; i < max_angular_steps; i++) - { - printf("%d: offset=%f error=%f lowest=%d highest=%d cl=%f ch=%f\n", i, offsets[i], error[i], lowest_weight[i], highest_weight[i], cut_low_weight_error[i], cut_high_weight_error[i]); - } - printf("\n"); - } - #endif - - // for each quantization level, find the best error terms. - float best_errors[40]; - int best_scale[40]; - uint8_t cut_low_weight[40]; - - for (i = 0; i < (max_quantization_steps + 4); i++) - { - best_errors[i] = 1e30f; - best_scale[i] = -1; // Indicates no solution found - cut_low_weight[i] = 0; - } - - - - for (i = 0; i < max_angular_steps; i++) - { - int samplecount = highest_weight[i] - lowest_weight[i] + 1; - if (samplecount >= (max_quantization_steps + 4)) - { - continue; - } - if (samplecount < 2) - samplecount = 2; - - if (best_errors[samplecount] > error[i]) - { - best_errors[samplecount] = error[i]; - best_scale[samplecount] = i; - cut_low_weight[samplecount] = 0; - } - - float error_cut_low = error[i] + cut_low_weight_error[i]; - float error_cut_high = error[i] + cut_high_weight_error[i]; - float error_cut_low_high = error[i] + cut_low_weight_error[i] + cut_high_weight_error[i]; - - if (best_errors[samplecount - 1] > error_cut_low) - { - best_errors[samplecount - 1] = error_cut_low; - best_scale[samplecount - 1] = i; - cut_low_weight[samplecount - 1] = 1; - } - - if (best_errors[samplecount - 1] > error_cut_high) - { - best_errors[samplecount - 1] = error_cut_high; - best_scale[samplecount - 1] = i; - cut_low_weight[samplecount - 1] = 0; - } - - if (best_errors[samplecount - 2] > error_cut_low_high) - { - best_errors[samplecount - 2] = error_cut_low_high; - best_scale[samplecount - 2] = i; - cut_low_weight[samplecount - 2] = 1; - } - - } - - // if we got a better error-value for a low sample count than for a high one, - // use the low sample count error value for the higher sample count as well. - for (i = 3; i <= max_quantization_steps; i++) - { - if (best_errors[i] > best_errors[i - 1]) - { - best_errors[i] = best_errors[i - 1]; - best_scale[i] = best_scale[i - 1]; - cut_low_weight[i] = cut_low_weight[i - 1]; - } - } - - - max_quantization_level--; // Decrease level again (see corresponding ++, above) - - static const int ql_weights[12] = { 2, 3, 4, 5, 6, 8, 10, 12, 16, 20, 24, 33 }; - for (i = 0; i <= max_quantization_level; i++) - { - int q = ql_weights[i]; - int bsi = best_scale[q]; - - // Did we find anything? - if(bsi < 0) - { - printf("ERROR: Unable to find an encoding within the specified error limits. Please revise the error limit values and try again.\n"); - exit(1); - } - - float stepsize = stepsizes[bsi]; - int lwi = lowest_weight[bsi] + cut_low_weight[q]; - int hwi = lwi + q - 1; - float offset = offsets[bsi]; - - low_value[i] = offset + lwi * stepsize; - high_value[i] = offset + hwi * stepsize; - } - -} - - -// helper functions that will compute ideal angular-endpoints -// for a given set of weights and a given block size descriptors - -void compute_angular_endpoints_1plane(float mode_cutoff, const block_size_descriptor * bsd, - const float *decimated_quantized_weights, const float *decimated_weights, - float low_value[MAX_WEIGHT_MODES], float high_value[MAX_WEIGHT_MODES]) -{ - int i; - float low_values[MAX_DECIMATION_MODES][12]; - float high_values[MAX_DECIMATION_MODES][12]; - - for (i = 0; i < MAX_DECIMATION_MODES; i++) - { - int samplecount = bsd->decimation_mode_samples[i]; - int quant_mode = bsd->decimation_mode_maxprec_1plane[i]; - float percentile = bsd->decimation_mode_percentile[i]; - int permit_encode = bsd->permit_encode[i]; - if (permit_encode == 0 || samplecount < 1 || quant_mode < 0 || percentile > mode_cutoff) - continue; - - - compute_angular_endpoints_for_quantization_levels(samplecount, - decimated_quantized_weights + i * MAX_WEIGHTS_PER_BLOCK, - decimated_weights + i * MAX_WEIGHTS_PER_BLOCK, quant_mode, low_values[i], high_values[i]); - } - - for (i = 0; i < MAX_WEIGHT_MODES; i++) - { - if (bsd->block_modes[i].is_dual_plane != 0 || bsd->block_modes[i].percentile > mode_cutoff) - continue; - int quant_mode = bsd->block_modes[i].quantization_mode; - int decim_mode = bsd->block_modes[i].decimation_mode; - - low_value[i] = low_values[decim_mode][quant_mode]; - high_value[i] = high_values[decim_mode][quant_mode]; - } - -} - - - -void compute_angular_endpoints_2planes(float mode_cutoff, - const block_size_descriptor * bsd, - const float *decimated_quantized_weights, - const float *decimated_weights, - float low_value1[MAX_WEIGHT_MODES], float high_value1[MAX_WEIGHT_MODES], float low_value2[MAX_WEIGHT_MODES], float high_value2[MAX_WEIGHT_MODES]) -{ - int i; - float low_values1[MAX_DECIMATION_MODES][12]; - float high_values1[MAX_DECIMATION_MODES][12]; - float low_values2[MAX_DECIMATION_MODES][12]; - float high_values2[MAX_DECIMATION_MODES][12]; - - for (i = 0; i < MAX_DECIMATION_MODES; i++) - { - int samplecount = bsd->decimation_mode_samples[i]; - int quant_mode = bsd->decimation_mode_maxprec_2planes[i]; - float percentile = bsd->decimation_mode_percentile[i]; - int permit_encode = bsd->permit_encode[i]; - if (permit_encode == 0 || samplecount < 1 || quant_mode < 0 || percentile > mode_cutoff) - continue; - - compute_angular_endpoints_for_quantization_levels(samplecount, - decimated_quantized_weights + 2 * i * MAX_WEIGHTS_PER_BLOCK, - decimated_weights + 2 * i * MAX_WEIGHTS_PER_BLOCK, quant_mode, low_values1[i], high_values1[i]); - - compute_angular_endpoints_for_quantization_levels(samplecount, - decimated_quantized_weights + (2 * i + 1) * MAX_WEIGHTS_PER_BLOCK, - decimated_weights + (2 * i + 1) * MAX_WEIGHTS_PER_BLOCK, quant_mode, low_values2[i], high_values2[i]); - - } - - for (i = 0; i < MAX_WEIGHT_MODES; i++) - { - if (bsd->block_modes[i].is_dual_plane != 1 || bsd->block_modes[i].percentile > mode_cutoff) - continue; - int quant_mode = bsd->block_modes[i].quantization_mode; - int decim_mode = bsd->block_modes[i].decimation_mode; - - low_value1[i] = low_values1[decim_mode][quant_mode]; - high_value1[i] = high_values1[decim_mode][quant_mode]; - low_value2[i] = low_values2[decim_mode][quant_mode]; - high_value2[i] = high_values2[decim_mode][quant_mode]; - } -} |