From 0b3ece5b42e15edbbd82c040f8eaabd0be1f97f5 Mon Sep 17 00:00:00 2001 From: John Cupitt Date: Wed, 21 Aug 2019 16:36:18 +0100 Subject: [PATCH] new constants code now passes all tests --- libvips/arithmetic/relational.c | 2 +- libvips/arithmetic/unaryconst.c | 27 ++++++++++++++++++++------- test/test-suite/helpers/helpers.py | 3 ++- test/test-suite/test_arithmetic.py | 11 +++++++---- 4 files changed, 30 insertions(+), 13 deletions(-) diff --git a/libvips/arithmetic/relational.c b/libvips/arithmetic/relational.c index 7d18e6ab..f2f8f817 100644 --- a/libvips/arithmetic/relational.c +++ b/libvips/arithmetic/relational.c @@ -499,7 +499,7 @@ vips_relational_const_buffer( VipsArithmetic *arithmetic, VipsImage *im = arithmetic->ready[0]; int bands = im->Bands; gboolean is_int = uconst->is_int && - vips_band_format_isint( im->BandFmt ); + vips_band_format_isint( im->BandFmt ); int i, x, b; diff --git a/libvips/arithmetic/unaryconst.c b/libvips/arithmetic/unaryconst.c index 133ede58..f098f169 100644 --- a/libvips/arithmetic/unaryconst.c +++ b/libvips/arithmetic/unaryconst.c @@ -2,6 +2,8 @@ * * 11/11/11 * - from arith_binary_const + * 21/8/19 + * - revise to fix out of range comparisons */ /* @@ -80,25 +82,36 @@ vips_unary_const_build( VipsObject *object ) * Some can use int constants as an optimisation, for example (x < * 12). It depends on the value though: obviously (x < 12.5) should * not use the int form. + * + * For complex images, we double the vector length and set the + * imaginary part to 0. */ if( uconst->c ) { + gboolean is_complex = + vips_band_format_iscomplex( unary->in->BandFmt ); + int step = is_complex ? 2 : 1; + int n = step * uconst->n; + double *c = (double *) uconst->c->data; + int i; - uconst->c_int = VIPS_ARRAY( object, uconst->n, int ); - uconst->c_double = VIPS_ARRAY( object, uconst->n, double ); + uconst->c_int = VIPS_ARRAY( object, n, int ); + uconst->c_double = VIPS_ARRAY( object, n, double ); if( !uconst->c_int || !uconst->c_double ) return( -1 ); + memset( uconst->c_int, 0, n * sizeof( int ) ); + memset( uconst->c_double, 0, n * sizeof( double ) ); - for( i = 0; i < uconst->n; i++ ) - uconst->c_double[i] = ((double *) uconst->c->data) - [VIPS_MIN( i, uconst->c->n - 1)]; + for( i = 0; i < n; i += step ) + uconst->c_double[i] = + c[VIPS_MIN( i / step, uconst->c->n - 1)]; - for( i = 0; i < uconst->n; i++ ) + for( i = 0; i < n; i += step ) uconst->c_int[i] = uconst->c_double[i]; uconst->is_int = TRUE; - for( i = 0; i < uconst->n; i++ ) + for( i = 0; i < n; i += step ) if( uconst->c_int[i] != uconst->c_double[i] ) { uconst->is_int = FALSE; break; diff --git a/test/test-suite/helpers/helpers.py b/test/test-suite/helpers/helpers.py index f254bd16..00d8caf6 100644 --- a/test/test-suite/helpers/helpers.py +++ b/test/test-suite/helpers/helpers.py @@ -1,5 +1,6 @@ # vim: set fileencoding=utf-8 : # test helpers + import os import tempfile import pytest @@ -174,7 +175,7 @@ def run_fn2(fn, x, y): # test a pair of things which can be lists for approx. equality def assert_almost_equal_objects(a, b, threshold=0.0001, msg=''): - # print 'assertAlmostEqualObjects %s = %s' % (a, b) + # print('assertAlmostEqualObjects %s = %s' % (a, b)) assert all([pytest.approx(x, abs=threshold) == y for x, y in zip_expand(a, b)]), msg diff --git a/test/test-suite/test_arithmetic.py b/test/test-suite/test_arithmetic.py index 8e6f3e46..eb3c15d8 100644 --- a/test/test-suite/test_arithmetic.py +++ b/test/test-suite/test_arithmetic.py @@ -1,4 +1,5 @@ # vim: set fileencoding=utf-8 : + import math import pytest @@ -10,14 +11,16 @@ from helpers import unsigned_formats, float_formats, noncomplex_formats, \ class TestArithmetic: def run_arith(self, fn, fmt=all_formats): - [run_image2(fn.__name__ + ' image', x.cast(y), x.cast(z), fn) + [run_image2('%s image %s %s %s' % (fn.__name__, x, y, z), + x.cast(y), x.cast(z), fn) for x in self.all_images for y in fmt for z in fmt] def run_arith_const(self, fn, fmt=all_formats): - [run_const(fn.__name__ + ' scalar', fn, x.cast(y), 2) + [run_const('%s scalar %s %s' % (fn.__name__, x, y), + fn, x.cast(y), 2) for x in self.all_images for y in fmt] - [run_const(fn.__name__ + ' vector', fn, self.colour.cast(y), - [1, 2, 3]) + [run_const('%s vector %s' % (fn.__name__, y), + fn, self.colour.cast(y), [1, 2, 3]) for y in fmt] # run a function on an image,