From 5a0ff887b2bdb6d3643b85a7f7042ae20a30e8ab Mon Sep 17 00:00:00 2001 From: Mattias Andrée Date: Sat, 6 Dec 2025 16:24:06 +0100 Subject: Use libj2 for double-max precision integers MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Mattias Andrée --- libquanta_vquantise_wu.c | 135 ++++++++++++++++++++++++----------------------- 1 file changed, 68 insertions(+), 67 deletions(-) (limited to 'libquanta_vquantise_wu.c') diff --git a/libquanta_vquantise_wu.c b/libquanta_vquantise_wu.c index d148c96..25a4ad2 100644 --- a/libquanta_vquantise_wu.c +++ b/libquanta_vquantise_wu.c @@ -1,5 +1,6 @@ /* See LICENSE file for copyright and license details. */ #include "common.h" +#include /* TODO limitation: 32 values per channel, limits palette size */ #define WORKING_BITS 5U @@ -10,10 +11,10 @@ struct channel_data { size_t subindex_multiplier; size_t colour_shift_down; size_t colour_shift_up; - struct bigint *histogram; - struct bigint whole; - struct bigint half; - struct bigint base; + struct libj2_j2u *histogram; + struct libj2_j2u whole; + struct libj2_j2u half; + struct libj2_j2u base; long double max; size_t cut; int has_cut; @@ -68,7 +69,7 @@ compute_histogram(struct libquanta_image *image, struct histogram *histogram, st v <<= channels[ch].colour_shift_up; v += 1U; index += v * channels[ch].subindex_multiplier; - bigint_add_small(&channels[ch].histogram[index], v); + libj2_j2u_add_ju(&channels[ch].histogram[index], v); } histogram[index].occurrences += 1U; histogram[index].square_sum += square_subsum; @@ -79,37 +80,37 @@ compute_histogram(struct libquanta_image *image, struct histogram *histogram, st static void -moments_bigint_(size_t channel, const struct channel_data *channels, size_t nchannels, - struct bigint *out, const struct bigint *in, size_t index) +moments_j2u_(size_t channel, const struct channel_data *channels, size_t nchannels, + struct libj2_j2u *out, const struct libj2_j2u *in, size_t index) { size_t i, mul; if (!nchannels) { if (in != out) memcpy(&out[index], &in[index], sizeof(*in)); - bigint_add_big(&out[index], &out[index - channels[channel].subindex_multiplier]); + libj2_j2u_add_j2u(&out[index], &out[index - channels[channel].subindex_multiplier]); return; } mul = channels[--nchannels].subindex_multiplier; for (i = 0; i++ < (1U << WORKING_BITS);) - moments_bigint_(channel, channels, nchannels, out, in, index + i * mul); + moments_j2u_(channel, channels, nchannels, out, in, index + i * mul); } static void -moments_bigint(size_t channel, struct channel_data *channels, size_t nchannels, struct bigint *buf, size_t bufsize) +moments_j2u(size_t channel, struct channel_data *channels, size_t nchannels, struct libj2_j2u *buf, size_t bufsize) { - struct bigint *in = channels[channel].histogram; + struct libj2_j2u *in = channels[channel].histogram; size_t i; memset(buf, 0, bufsize); for (i = nchannels; i-- > 1U;) { - moments_bigint_(i, channels, nchannels, buf, in, 0); + moments_j2u_(i, channels, nchannels, buf, in, 0); in = buf; } - moments_bigint_(0, channels, nchannels, channels[channel].histogram, in, 0); + moments_j2u_(0, channels, nchannels, channels[channel].histogram, in, 0); } static void @@ -153,12 +154,12 @@ compute_cumulative_moments(struct histogram *histogram, struct channel_data *cha void *buf; size_t i, bufsize; - bufsize = bufelems * sizeof(struct bigint); + bufsize = bufelems * sizeof(struct libj2_j2u); buf = malloc(bufsize); if (!buf) return -1; for (i = 0; i < nchannels; i++) - moments_bigint(i, channels, nchannels, buf, bufsize); + moments_j2u(i, channels, nchannels, buf, bufsize); free(buf); bufsize = bufelems * sizeof(struct histogram); @@ -244,38 +245,38 @@ volume_over_occurrences(const struct cube *cube, const struct histogram *data, c static void -volume_over_bigints_(const struct cube *cube, const struct bigint *data, const struct channel_data *channels, size_t nchannels, - size_t index, int use_addition, struct bigint *result) +volume_over_j2us_(const struct cube *cube, const struct libj2_j2u *data, const struct channel_data *channels, size_t nchannels, + size_t index, int use_addition, struct libj2_j2u *result) { size_t ch; if (!nchannels) { if (use_addition) - bigint_add_big(result, &data[index]); + libj2_j2u_add_j2u(result, &data[index]); else - bigint_sub_big(result, &data[index]); + libj2_j2u_sub_j2u(result, &data[index]); return; } ch = nchannels - 1U; - volume_over_bigints_(cube, data, channels, ch, - index + cube->bounds[ch].max * channels[ch].subindex_multiplier, - use_addition ^ 1, result); + volume_over_j2us_(cube, data, channels, ch, + index + cube->bounds[ch].max * channels[ch].subindex_multiplier, + use_addition ^ 1, result); - volume_over_bigints_(cube, data, channels, ch, - index + cube->bounds[ch].min * channels[ch].subindex_multiplier, - use_addition, result); + volume_over_j2us_(cube, data, channels, ch, + index + cube->bounds[ch].min * channels[ch].subindex_multiplier, + use_addition, result); } static void -volume_over_bigints(const struct cube *cube, const struct bigint *data, const struct channel_data *channels, size_t nchannels, - struct bigint *result) +volume_over_j2us(const struct cube *cube, const struct libj2_j2u *data, const struct channel_data *channels, size_t nchannels, + struct libj2_j2u *result) { int use_addition = (int)(~nchannels & 1U); result->high = 0; result->low = 0; - volume_over_bigints_(cube, data, channels, nchannels, 0, use_addition, result); + volume_over_j2us_(cube, data, channels, nchannels, 0, use_addition, result); } @@ -320,41 +321,41 @@ bottom_over_occurrences(const struct cube *cube, size_t channel, const struct hi static void -bottom_over_bigints_(const struct cube *cube, size_t channel, const struct bigint *data, const struct channel_data *channels, - size_t nchannels, size_t index, int use_addition, struct bigint *result) +bottom_over_j2us_(const struct cube *cube, size_t channel, const struct libj2_j2u *data, const struct channel_data *channels, + size_t nchannels, size_t index, int use_addition, struct libj2_j2u *result) { size_t ch; if (!nchannels) { if (use_addition) - bigint_add_big(result, &data[index]); + libj2_j2u_add_j2u(result, &data[index]); else - bigint_sub_big(result, &data[index]); + libj2_j2u_sub_j2u(result, &data[index]); return; } ch = nchannels - 1U; - bottom_over_bigints_(cube, channel, data, channels, ch, - index + cube->bounds[ch].min * channels[ch].subindex_multiplier, - use_addition, result); + bottom_over_j2us_(cube, channel, data, channels, ch, + index + cube->bounds[ch].min * channels[ch].subindex_multiplier, + use_addition, result); if (ch == channel) return; - bottom_over_bigints_(cube, channel, data, channels, ch, - index + cube->bounds[ch].max * channels[ch].subindex_multiplier, - use_addition ^ 1, result); + bottom_over_j2us_(cube, channel, data, channels, ch, + index + cube->bounds[ch].max * channels[ch].subindex_multiplier, + use_addition ^ 1, result); } static void -bottom_over_bigints(const struct cube *cube, size_t channel, const struct bigint *data, const struct channel_data *channels, - size_t nchannels, struct bigint *result) +bottom_over_j2us(const struct cube *cube, size_t channel, const struct libj2_j2u *data, const struct channel_data *channels, + size_t nchannels, struct libj2_j2u *result) { int use_addition = (int)(~nchannels & 1U); result->high = 0; result->low = 0; - bottom_over_bigints_(cube, channel, data, channels, nchannels, 0, use_addition, result); + bottom_over_j2us_(cube, channel, data, channels, nchannels, 0, use_addition, result); } @@ -403,45 +404,45 @@ top_over_occurrences(const struct cube *cube, size_t channel, size_t position, c static void -top_over_bigints_(const struct cube *cube, size_t channel, size_t position, const struct bigint *data, - const struct channel_data *channels, size_t nchannels, size_t index, int use_addition, struct bigint *result) +top_over_j2us_(const struct cube *cube, size_t channel, size_t position, const struct libj2_j2u *data, + const struct channel_data *channels, size_t nchannels, size_t index, int use_addition, struct libj2_j2u *result) { size_t ch; if (!nchannels) { if (use_addition) - bigint_add_big(result, &data[index]); + libj2_j2u_add_j2u(result, &data[index]); else - bigint_sub_big(result, &data[index]); + libj2_j2u_sub_j2u(result, &data[index]); return; } ch = nchannels - 1U; if (ch == channel) { - top_over_bigints_(cube, channel, position, data, channels, ch, - index + position * channels[ch].subindex_multiplier, - use_addition ^ 1, result); + top_over_j2us_(cube, channel, position, data, channels, ch, + index + position * channels[ch].subindex_multiplier, + use_addition ^ 1, result); } else { - top_over_bigints_(cube, channel, position, data, channels, ch, - index + cube->bounds[ch].min * channels[ch].subindex_multiplier, - use_addition, result); + top_over_j2us_(cube, channel, position, data, channels, ch, + index + cube->bounds[ch].min * channels[ch].subindex_multiplier, + use_addition, result); - top_over_bigints_(cube, channel, position, data, channels, ch, - index + cube->bounds[ch].max * channels[ch].subindex_multiplier, - use_addition ^ 1, result); + top_over_j2us_(cube, channel, position, data, channels, ch, + index + cube->bounds[ch].max * channels[ch].subindex_multiplier, + use_addition ^ 1, result); } } static void -top_over_bigints(const struct cube *cube, size_t channel, size_t position, const struct bigint *data, - const struct channel_data *channels, size_t nchannels, struct bigint *result) +top_over_j2us(const struct cube *cube, size_t channel, size_t position, const struct libj2_j2u *data, + const struct channel_data *channels, size_t nchannels, struct libj2_j2u *result) { int use_addition = (int)(~nchannels & 1U); result->high = 0; result->low = 0; - top_over_bigints_(cube, channel, position, data, channels, nchannels, 0, use_addition, result); + top_over_j2us_(cube, channel, position, data, channels, nchannels, 0, use_addition, result); } @@ -460,7 +461,7 @@ maximise(const struct cube *cube, size_t channel, const struct histogram *histog channels[channel].has_cut = 0; for (i = 0; i < nchannels; i++) - bottom_over_bigints(cube, channel, channels[i].histogram, channels, nchannels, &channels[i].base); + bottom_over_j2us(cube, channel, channels[i].histogram, channels, nchannels, &channels[i].base); base_weight = bottom_over_occurrences(cube, channel, histogram, channels, nchannels); first = cube->bounds[channel].min + 1U; @@ -473,8 +474,8 @@ maximise(const struct cube *cube, size_t channel, const struct histogram *histog temp = 0; for (i = 0; i < nchannels; i++) { - top_over_bigints(cube, channel, pos, channels[i].histogram, channels, nchannels, &channels[i].half); - bigint_add_big(&channels[i].half, &channels[i].base); + top_over_j2us(cube, channel, pos, channels[i].histogram, channels, nchannels, &channels[i].half); + libj2_j2u_add_j2u(&channels[i].half, &channels[i].base); v = (long double)channels[i].half.high; v = ldexpl(v, 8 * sizeof(channels[i].half.low)); @@ -489,7 +490,7 @@ maximise(const struct cube *cube, size_t channel, const struct histogram *histog temp2 = 0; for (i = 0; i < nchannels; i++) { - bigint_rsub_big(&channels[i].half, &channels[i].whole); /* half = whole - half */ + libj2_j2u_rsub_j2u(&channels[i].half, &channels[i].whole); /* half = whole - half */ v = (long double)channels[i].half.high; v = ldexpl(v, 8 * sizeof(channels[i].half.low)); @@ -515,7 +516,7 @@ cut(struct cube *cube1, struct cube *cube2, const struct histogram *histogram, s long double max_max; for (i = 0; i < nchannels; i++) - volume_over_bigints(cube1, channels[i].histogram, channels, nchannels, &channels[i].whole); + volume_over_j2us(cube1, channels[i].histogram, channels, nchannels, &channels[i].whole); whole_weight = volume_over_occurrences(cube1, histogram, channels, nchannels); for (i = 0; i < nchannels; i++) @@ -556,13 +557,13 @@ variance(const struct cube *cube, const struct histogram *histogram, const struc { uintmax_t weight; long double w, x, y = 0; - struct bigint v; + struct libj2_j2u v; size_t i; x = volume_over_square_sums(cube, histogram, channels, nchannels); for (i = 0; i < nchannels; i++) { - volume_over_bigints(cube, channels[i].histogram, channels, nchannels, &v); + volume_over_j2us(cube, channels[i].histogram, channels, nchannels, &v); w = (long double)v.high; w = ldexpl(w, 8 * sizeof(v.low)); w += (long double)v.low; @@ -658,7 +659,7 @@ libquanta_vquantise_wu(struct libquanta_palette *palette, va_list args) struct libquanta_image *ret = NULL; size_t size, image_size, *tag = NULL; uintmax_t weight, mean; - struct bigint sum; + struct libj2_j2u sum; struct cube **cubes = NULL; size_t cube_size; size_t ncolours_used; @@ -767,8 +768,8 @@ libquanta_vquantise_wu(struct libquanta_palette *palette, va_list args) if (!weight) continue; for (j = 0; j < nchannels; j++) { - volume_over_bigints(cubes[i], channels[j].histogram, channels, nchannels, &sum); - mean = bigint_div_small(&sum, weight); + volume_over_j2us(cubes[i], channels[j].histogram, channels, nchannels, &sum); + mean = libj2_j2u_div_ju_return(&sum, weight); if (channels[j].ch->bits_out < channels[j].ch->bits_in) mean >>= channels[j].ch->bits_in - channels[j].ch->bits_out; palette->palette[n * nchannels + j] = (uint64_t)mean; -- cgit v1.2.3-70-g09d2