static void compute_lowest_and_highest_weight(
	unsigned int weight_count,
	const float* dec_weight_quant_uvalue,
	const float* dec_weight_quant_sig,
	unsigned int max_angular_steps,
	unsigned int max_quant_steps,
	const float* offsets,
	int* lowest_weight,
	int* weight_span,
	float* error,
	float* cut_low_weight_error,
	float* cut_high_weight_error
) {
	promise(weight_count > 0);
	promise(max_angular_steps > 0);

	vfloat rcp_stepsize = vfloat::lane_id() + vfloat(1.0f);

	// Arrays are ANGULAR_STEPS long, so always safe to run full vectors
	for (unsigned int sp = 0; sp < max_angular_steps; sp += ASTCENC_SIMD_WIDTH)
	{
		vfloat minidx(128.0f);
		vfloat maxidx(-128.0f);
		vfloat errval = vfloat::zero();
		vfloat cut_low_weight_err = vfloat::zero();
		vfloat cut_high_weight_err = vfloat::zero();
		vfloat offset = loada(&offsets[sp]);

		for (unsigned int j = 0; j < weight_count; ++j)
		{
			vfloat wt = load1(&dec_weight_quant_sig[j]);
			vfloat sval = load1(&dec_weight_quant_uvalue[j]) * rcp_stepsize - offset;
			vfloat svalrte = round(sval);
			vfloat dif = sval - svalrte;
			vfloat dwt = dif * wt;
			errval += dwt * dif;

			// Reset tracker on min hit
			vmask mask = svalrte < minidx;
			minidx = select(minidx, svalrte, mask);
			cut_low_weight_err = select(cut_low_weight_err, vfloat::zero(), mask);

			// Accumulate on min hit
			mask = svalrte == minidx;
			vfloat accum = cut_low_weight_err + wt - vfloat(2.0f) * dwt;
			cut_low_weight_err = select(cut_low_weight_err, accum, mask);

			// Reset tracker on max hit
			mask = svalrte > maxidx;
			maxidx = select(maxidx, svalrte, mask);
			cut_high_weight_err = select(cut_high_weight_err, vfloat::zero(), mask);

			// Accumulate on max hit
			mask = svalrte == maxidx;
			accum = cut_high_weight_err + wt + vfloat(2.0f) * dwt;
			cut_high_weight_err = select(cut_high_weight_err, accum, mask);
		}

		// Write out min weight and weight span; clamp span to a usable range
		vint span = float_to_int(maxidx - minidx + vfloat(1));
		span = min(span, vint(max_quant_steps + 3));
		span = max(span, vint(2));
		storea(float_to_int(minidx), &lowest_weight[sp]);
		storea(span, &weight_span[sp]);

		// The cut_(lowest/highest)_weight_error indicate the error that results from  forcing
		// samples that should have had the weight value one step (up/down).
		vfloat ssize = 1.0f / rcp_stepsize;
		vfloat errscale = ssize * ssize;
		storea(errval * errscale, &error[sp]);
		storea(cut_low_weight_err * errscale, &cut_low_weight_error[sp]);
		storea(cut_high_weight_err * errscale, &cut_high_weight_error[sp]);

		rcp_stepsize = rcp_stepsize + vfloat(ASTCENC_SIMD_WIDTH);
	}
}
static void compute_lowest_and_highest_weight(
	unsigned int weight_count,
	const float* dec_weight_quant_uvalue,
	const float* dec_weight_quant_sig,
	unsigned int max_angular_steps,
	unsigned int max_quant_steps,
	const float* offsets,
	int* lowest_weight,
	int* weight_span,
	float* error,
	float* cut_low_weight_error,
	float* cut_high_weight_error
) {
	promise(weight_count > 0);
	promise(max_angular_steps > 0);

	vfloat rcp_stepsize = vfloat::lane_id() + vfloat(1.0f);

	 
	for (unsigned int sp = 0; sp < max_angular_steps; sp += ASTCENC_SIMD_WIDTH)
	{
		vfloat minidx(128.0f);
		vfloat maxidx(-128.0f);
		vfloat errval = vfloat::zero();
		vfloat cut_low_weight_err = vfloat::zero();
		vfloat cut_high_weight_err = vfloat::zero();
		vfloat offset = loada(&offsets[sp]);

		for (unsigned int j = 0; j < weight_count; ++j)
		{
			vfloat wt = load1(&dec_weight_quant_sig[j]);
			vfloat sval = load1(&dec_weight_quant_uvalue[j]) * rcp_stepsize - offset;
			vfloat svalrte = round(sval);
			vfloat dif = sval - svalrte;
			vfloat dwt = dif * wt;
			errval += dwt * dif;

			 
			vmask mask = svalrte < minidx;
			minidx = select(minidx, svalrte, mask);
			cut_low_weight_err = select(cut_low_weight_err, vfloat::zero(), mask);

			 
			mask = svalrte == minidx;
			vfloat accum = cut_low_weight_err + wt - vfloat(2.0f) * dwt;
			cut_low_weight_err = select(cut_low_weight_err, accum, mask);

			 
			mask = svalrte > maxidx;
			maxidx = select(maxidx, svalrte, mask);
			cut_high_weight_err = select(cut_high_weight_err, vfloat::zero(), mask);

			 
			mask = svalrte == maxidx;
			accum = cut_high_weight_err + wt + vfloat(2.0f) * dwt;
			cut_high_weight_err = select(cut_high_weight_err, accum, mask);
		}

		 
		vint span = float_to_int(maxidx - minidx + vfloat(1));
		span = min(span, vint(max_quant_steps + 3));
		span = max(span, vint(2));
		storea(float_to_int(minidx), &lowest_weight[sp]);
		storea(span, &weight_span[sp]);

		 
		 
		vfloat ssize = 1.0f / rcp_stepsize;
		vfloat errscale = ssize * ssize;
		storea(errval * errscale, &error[sp]);
		storea(cut_low_weight_err * errscale, &cut_low_weight_error[sp]);
		storea(cut_high_weight_err * errscale, &cut_high_weight_error[sp]);

		rcp_stepsize = rcp_stepsize + vfloat(ASTCENC_SIMD_WIDTH);
	}
}