1 /* remainder.c
2  *
3  * 2/8/99 JC
4  *	- im_divide adapted to make im_remainder
5  * 8/5/02 JC
6  *	- im_remainderconst added
7  *	- im_remainderconst_vec added
8  * 27/9/04
9  *	- updated for 1 band $op n band image -> n band image case
10  * 26/2/07
11  * 	- oop, broken for _vec case :-(
12  * 14/5/08
13  * 	- better /0 test
14  * 27/8/08
15  * 	- revise upcasting system
16  * 	- add gtkdoc comments
17  * 23/6/10
18  * 	- constant ops clip to target range
19  * 12/11/11
20  * 	- redone as a class
21  */
22 
23 /*
24 
25     Copyright (C) 1991-2005 The National Gallery
26 
27     This library is free software; you can redistribute it and/or
28     modify it under the terms of the GNU Lesser General Public
29     License as published by the Free Software Foundation; either
30     version 2.1 of the License, or (at your option) any later version.
31 
32     This library is distributed in the hope that it will be useful,
33     but WITHOUT ANY WARRANTY; without even the implied warranty of
34     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
35     Lesser General Public License for more details.
36 
37     You should have received a copy of the GNU Lesser General Public
38     License along with this library; if not, write to the Free Software
39     Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
40     02110-1301  USA
41 
42  */
43 
44 /*
45 
46     These files are distributed with VIPS - http://www.vips.ecs.soton.ac.uk
47 
48  */
49 
50 /*
51 #define DEBUG
52  */
53 
54 #ifdef HAVE_CONFIG_H
55 #include <config.h>
56 #endif /*HAVE_CONFIG_H*/
57 #include <vips/intl.h>
58 
59 #include <stdio.h>
60 #include <stdlib.h>
61 #include <math.h>
62 
63 #include <vips/vips.h>
64 
65 #include "binary.h"
66 #include "unaryconst.h"
67 
68 typedef VipsBinary VipsRemainder;
69 typedef VipsBinaryClass VipsRemainderClass;
70 
71 G_DEFINE_TYPE( VipsRemainder, vips_remainder, VIPS_TYPE_BINARY );
72 
73 static int
vips_remainder_build(VipsObject * object)74 vips_remainder_build( VipsObject *object )
75 {
76 	VipsObjectClass *class = VIPS_OBJECT_GET_CLASS( object );
77 	VipsBinary *binary = (VipsBinary *) object;
78 
79 	if( binary->left &&
80 		vips_check_noncomplex( class->nickname, binary->left ) )
81 		return( -1 );
82 	if( binary->right &&
83 		vips_check_noncomplex( class->nickname, binary->right ) )
84 		return( -1 );
85 
86 	if( VIPS_OBJECT_CLASS( vips_remainder_parent_class )->build( object ) )
87 		return( -1 );
88 
89 	return( 0 );
90 }
91 
92 /* Integer remainder-after-division.
93  */
94 #define IREMAINDER( TYPE ) { \
95 	TYPE * restrict p1 = (TYPE *) in[0]; \
96 	TYPE * restrict p2 = (TYPE *) in[1]; \
97 	TYPE * restrict q = (TYPE *) out; \
98 	\
99 	for( x = 0; x < sz; x++ ) \
100 		q[x] = p2[x] ? p1[x] % p2[x] : -1; \
101 }
102 
103 /* Float remainder-after-division.
104  */
105 #define FREMAINDER( TYPE ) { \
106 	TYPE * restrict p1 = (TYPE *) in[0]; \
107 	TYPE * restrict p2 = (TYPE *) in[1]; \
108 	TYPE * restrict q = (TYPE *) out; \
109 	\
110 	for( x = 0; x < sz; x++ ) { \
111 		double a = p1[x]; \
112 		double b = p2[x]; \
113 		\
114 		q[x] = b ? a - b * VIPS_FLOOR (a / b) : -1; \
115 	} \
116 }
117 
118 static void
vips_remainder_buffer(VipsArithmetic * arithmetic,VipsPel * out,VipsPel ** in,int width)119 vips_remainder_buffer( VipsArithmetic *arithmetic,
120 	VipsPel *out, VipsPel **in, int width )
121 {
122 	VipsImage *im = arithmetic->ready[0];
123 	const int sz = width * vips_image_get_bands( im );
124 
125 	int x;
126 
127         switch( vips_image_get_format( im ) ) {
128         case VIPS_FORMAT_CHAR: 	IREMAINDER( signed char ); break;
129         case VIPS_FORMAT_UCHAR: IREMAINDER( unsigned char ); break;
130         case VIPS_FORMAT_SHORT: IREMAINDER( signed short ); break;
131         case VIPS_FORMAT_USHORT:IREMAINDER( unsigned short ); break;
132         case VIPS_FORMAT_INT: 	IREMAINDER( signed int ); break;
133         case VIPS_FORMAT_UINT: 	IREMAINDER( unsigned int ); break;
134         case VIPS_FORMAT_FLOAT: FREMAINDER( float ); break;
135         case VIPS_FORMAT_DOUBLE:FREMAINDER( double ); break;
136 
137         default:
138 		g_assert_not_reached();
139         }
140 }
141 
142 /* Save a bit of typing.
143  */
144 #define UC VIPS_FORMAT_UCHAR
145 #define C VIPS_FORMAT_CHAR
146 #define US VIPS_FORMAT_USHORT
147 #define S VIPS_FORMAT_SHORT
148 #define UI VIPS_FORMAT_UINT
149 #define I VIPS_FORMAT_INT
150 #define F VIPS_FORMAT_FLOAT
151 #define X VIPS_FORMAT_COMPLEX
152 #define D VIPS_FORMAT_DOUBLE
153 #define DX VIPS_FORMAT_DPCOMPLEX
154 
155 /* Type promotion for remainder. Keep in sync with remainder_buffer() above.
156  */
157 static int vips_remainder_format_table[10] = {
158 /* UC  C   US  S   UI  I  F  X  D  DX */
159    UC, C,  US, S,  UI, I, F, X, D, DX
160 };
161 
162 static void
vips_remainder_class_init(VipsRemainderClass * class)163 vips_remainder_class_init( VipsRemainderClass *class )
164 {
165 	GObjectClass *gobject_class = G_OBJECT_CLASS( class );
166 	VipsObjectClass *object_class = (VipsObjectClass *) class;
167 	VipsArithmeticClass *aclass = VIPS_ARITHMETIC_CLASS( class );
168 
169 	gobject_class->set_property = vips_object_set_property;
170 	gobject_class->get_property = vips_object_get_property;
171 
172 	object_class->nickname = "remainder";
173 	object_class->description =
174 		_( "remainder after integer division of two images" );
175 	object_class->build = vips_remainder_build;
176 
177 	aclass->process_line = vips_remainder_buffer;
178 
179 	vips_arithmetic_set_format_table( aclass,
180 		vips_remainder_format_table );
181 }
182 
183 static void
vips_remainder_init(VipsRemainder * remainder)184 vips_remainder_init( VipsRemainder *remainder )
185 {
186 }
187 
188 /**
189  * vips_remainder:
190  * @left: left-hand input #VipsImage
191  * @right: right-hand input #VipsImage
192  * @out: (out): output #VipsImage
193  * @...: %NULL-terminated list of optional named arguments
194  *
195  * This operation calculates @left % @right (remainder after integer division)
196  * and writes the result to @out. The images may have any
197  * non-complex format. For float formats, vips_remainder() calculates @in1 -
198  * @in2 * floor (@in1 / @in2).
199  *
200  * If the images differ in size, the smaller image is enlarged to match the
201  * larger by adding zero pixels along the bottom and right.
202  *
203  * If the number of bands differs, one of the images
204  * must have one band. In this case, an n-band image is formed from the
205  * one-band image by joining n copies of the one-band image together, and then
206  * the two n-band images are operated upon.
207  *
208  * The two input images are cast up to the smallest common format (see table
209  * Smallest common format in
210  * <link linkend="libvips-arithmetic">arithmetic</link>), and that format is the
211  * result type.
212  *
213  * See also: vips_remainder_const(), vips_divide(), vips_round().
214  *
215  * Returns: 0 on success, -1 on error
216  */
217 int
vips_remainder(VipsImage * left,VipsImage * right,VipsImage ** out,...)218 vips_remainder( VipsImage *left, VipsImage *right, VipsImage **out, ... )
219 {
220 	va_list ap;
221 	int result;
222 
223 	va_start( ap, out );
224 	result = vips_call_split( "remainder", ap, left, right, out );
225 	va_end( ap );
226 
227 	return( result );
228 }
229 
230 typedef VipsUnaryConst VipsRemainderConst;
231 typedef VipsUnaryConstClass VipsRemainderConstClass;
232 
233 G_DEFINE_TYPE( VipsRemainderConst,
234 	vips_remainder_const, VIPS_TYPE_UNARY_CONST );
235 
236 static int
vips_remainder_const_build(VipsObject * object)237 vips_remainder_const_build( VipsObject *object )
238 {
239 	VipsObjectClass *class = VIPS_OBJECT_GET_CLASS( object );
240 	VipsUnary *unary = (VipsUnary *) object;
241 
242 	if( unary->in &&
243 		vips_check_noncomplex( class->nickname, unary->in ) )
244 		return( -1 );
245 
246 	if( VIPS_OBJECT_CLASS( vips_remainder_const_parent_class )->
247 		build( object ) )
248 		return( -1 );
249 
250 	return( 0 );
251 }
252 
253 /* Integer remainder-after-divide, per-band constant.
254  */
255 #define IREMAINDERCONST( TYPE ) { \
256 	TYPE * restrict p = (TYPE *) in[0]; \
257 	TYPE * restrict q = (TYPE *) out; \
258 	int * restrict c = uconst->c_int; \
259 	\
260 	for( i = 0, x = 0; x < width; x++ ) \
261 		for( b = 0; b < bands; b++, i++ ) \
262 			q[i] = p[i] % c[b]; \
263 }
264 
265 /* Float remainder-after-divide, per-band constant.
266  */
267 #define FREMAINDERCONST( TYPE ) { \
268 	TYPE * restrict p = (TYPE *) in[0]; \
269 	TYPE * restrict q = (TYPE *) out; \
270 	int * restrict c = uconst->c_int; \
271 	\
272 	for( i = 0, x = 0; x < width; x++ ) \
273 		for( b = 0; b < bands; b++, i++ ) { \
274 			double left = p[i]; \
275 			double right = c[b]; \
276 			\
277 			q[i] = right ? \
278 				left - right * floor( left / right ) : \
279 				-1; \
280 		} \
281 }
282 
283 static void
vips_remainder_const_buffer(VipsArithmetic * arithmetic,VipsPel * out,VipsPel ** in,int width)284 vips_remainder_const_buffer( VipsArithmetic *arithmetic,
285 	VipsPel *out, VipsPel **in, int width )
286 {
287 	VipsUnaryConst *uconst = (VipsUnaryConst *) arithmetic;
288 	VipsImage *im = arithmetic->ready[0];
289 	int bands = im->Bands;
290 
291 	int i, x, b;
292 
293         switch( vips_image_get_format( im ) ) {
294         case VIPS_FORMAT_CHAR: 	IREMAINDERCONST( signed char ); break;
295         case VIPS_FORMAT_UCHAR: IREMAINDERCONST( unsigned char ); break;
296         case VIPS_FORMAT_SHORT: IREMAINDERCONST( signed short ); break;
297         case VIPS_FORMAT_USHORT:IREMAINDERCONST( unsigned short ); break;
298         case VIPS_FORMAT_INT: 	IREMAINDERCONST( signed int ); break;
299         case VIPS_FORMAT_UINT: 	IREMAINDERCONST( unsigned int ); break;
300         case VIPS_FORMAT_FLOAT: FREMAINDERCONST( float ); break;
301         case VIPS_FORMAT_DOUBLE:FREMAINDERCONST( double ); break;
302 
303         default:
304 		g_assert_not_reached();
305         }
306 }
307 
308 static void
vips_remainder_const_class_init(VipsRemainderConstClass * class)309 vips_remainder_const_class_init( VipsRemainderConstClass *class )
310 {
311 	GObjectClass *gobject_class = G_OBJECT_CLASS( class );
312 	VipsObjectClass *object_class = (VipsObjectClass *) class;
313 	VipsArithmeticClass *aclass = VIPS_ARITHMETIC_CLASS( class );
314 
315 	gobject_class->set_property = vips_object_set_property;
316 	gobject_class->get_property = vips_object_get_property;
317 
318 	object_class->nickname = "remainder_const";
319 	object_class->description =
320 		_( "remainder after integer division of an image "
321 		"and a constant" );
322 	object_class->build = vips_remainder_const_build;
323 
324 	aclass->process_line = vips_remainder_const_buffer;
325 
326 	vips_arithmetic_set_format_table( aclass, vips_remainder_format_table );
327 }
328 
329 static void
vips_remainder_const_init(VipsRemainderConst * remainder_const)330 vips_remainder_const_init( VipsRemainderConst *remainder_const )
331 {
332 }
333 
334 static int
vips_remainder_constv(VipsImage * in,VipsImage ** out,const double * c,int n,va_list ap)335 vips_remainder_constv( VipsImage *in, VipsImage **out,
336 	const double *c, int n, va_list ap )
337 {
338 	VipsArea *area_c;
339 	double *array;
340 	int result;
341 	int i;
342 
343 	area_c = vips_area_new_array( G_TYPE_DOUBLE, sizeof( double ), n );
344 	array = (double *) area_c->data;
345 	for( i = 0; i < n; i++ )
346 		array[i] = c[i];
347 
348 	result = vips_call_split( "remainder_const", ap, in, out, area_c );
349 
350 	vips_area_unref( area_c );
351 
352 	return( result );
353 }
354 
355 /**
356  * vips_remainder_const: (method)
357  * @in: input image
358  * @out: (out): output image
359  * @c: (array length=n): array of constants
360  * @n: number of constants in @c
361  * @...: %NULL-terminated list of optional named arguments
362  *
363  * This operation calculates @in % @c (remainder after division by an
364  * array of constants)
365  * and writes the result to @out.
366  * The image may have any
367  * non-complex format. For float formats, vips_remainder_const() calculates
368  * @in - @c * floor (@in / @c).
369  *
370  * If the array of constants has just one element, that constant is used for
371  * all image bands. If the array has more than one element and they have
372  * the same number of elements as there are bands in the image, then
373  * one array element is used for each band. If the arrays have more than one
374  * element and the image only has a single band, the result is a many-band
375  * image where each band corresponds to one array element.
376  *
377  * See also: vips_remainder(), vips_divide(), vips_round().
378  *
379  * Returns: 0 on success, -1 on error
380  */
381 int
vips_remainder_const(VipsImage * in,VipsImage ** out,const double * c,int n,...)382 vips_remainder_const( VipsImage *in, VipsImage **out,
383 	const double *c, int n, ... )
384 {
385 	va_list ap;
386 	int result;
387 
388 	va_start( ap, n );
389 	result = vips_remainder_constv( in, out, c, n, ap );
390 	va_end( ap );
391 
392 	return( result );
393 }
394 
395 /**
396  * vips_remainder_const1: (method)
397  * @in: input image
398  * @out: (out): output image
399  * @c: constant
400  * @...: %NULL-terminated list of optional named arguments
401  *
402  * This operation calculates @in % @c (remainder after division by a
403  * constant)
404  * and writes the result to @out.
405  * The image may have any
406  * non-complex format. For float formats, vips_remainder_const() calculates
407  * @in - @c * floor (@in / @c).
408  *
409  * If the array of constants has just one element, that constant is used for
410  * all image bands. If the array has more than one element and they have
411  * the same number of elements as there are bands in the image, then
412  * one array element is used for each band. If the arrays have more than one
413  * element and the image only has a single band, the result is a many-band
414  * image where each band corresponds to one array element.
415  *
416  * See also: vips_remainder(), vips_divide(), vips_round().
417  *
418  * Returns: 0 on success, -1 on error
419  */
420 int
vips_remainder_const1(VipsImage * in,VipsImage ** out,double c,...)421 vips_remainder_const1( VipsImage *in, VipsImage **out, double c, ... )
422 {
423 	va_list ap;
424 	int result;
425 
426 	va_start( ap, c );
427 	result = vips_remainder_constv( in, out, &c, 1, ap );
428 	va_end( ap );
429 
430 	return( result );
431 }
432 
433