aboutsummaryrefslogtreecommitdiffstats
path: root/libquanta_vquantise_wu.c
diff options
context:
space:
mode:
authorMattias Andrée <m@maandree.se>2025-12-06 16:24:06 +0100
committerMattias Andrée <m@maandree.se>2025-12-06 16:24:06 +0100
commit5a0ff887b2bdb6d3643b85a7f7042ae20a30e8ab (patch)
tree2c4e3765c62bcd022479a62151b1f0d7278ff773 /libquanta_vquantise_wu.c
parentRefine implementation of Wu's Colour Quantiser (diff)
downloadlibquanta-5a0ff887b2bdb6d3643b85a7f7042ae20a30e8ab.tar.gz
libquanta-5a0ff887b2bdb6d3643b85a7f7042ae20a30e8ab.tar.bz2
libquanta-5a0ff887b2bdb6d3643b85a7f7042ae20a30e8ab.tar.xz
Use libj2 for double-max precision integersHEADmaster
Signed-off-by: Mattias Andrée <m@maandree.se>
Diffstat (limited to 'libquanta_vquantise_wu.c')
-rw-r--r--libquanta_vquantise_wu.c135
1 files changed, 68 insertions, 67 deletions
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 <libj2.h>
/* 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;