now compiles with new add.c

compiles, but not tested
This commit is contained in:
John Cupitt 2011-04-02 16:39:20 +01:00
parent 370641d25b
commit ce03da8c71
6 changed files with 160 additions and 94 deletions

View File

@ -27,6 +27,7 @@ libarithmetic_la_SOURCES = \
math.c \
arithmetic.c \
binary.c \
add.c \
power.c \
round.c

View File

@ -34,7 +34,7 @@
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif /*HAVE_CONFIG_H*/
#include <vips8/intl.h>
#include <vips/intl.h>
#include <stdio.h>
#include <stdlib.h>
@ -73,33 +73,33 @@ typedef VipsBinaryClass VipsAddClass;
G_DEFINE_TYPE( VipsAdd, vips_add, VIPS_TYPE_BINARY );
#define LOOP( IN, OUT ) { \
IN *p1 = (IN *) in[0]; \
IN *p2 = (IN *) in[1]; \
IN *p1 = (IN *) left; \
IN *p2 = (IN *) right; \
OUT *q = (OUT *) out; \
\
for( x = 0; x < sz; x++ ) \
q[x] = p1[x] + p2[x]; \
}
static VipsVector *add_vectors[VIPS_FORMAT_LAST] = { NULL };
static void
add_buffer( PEL **in, PEL *out, int width, IMAGE *im )
add_buffer( VipsBinary *binary, PEL *out, PEL *left, PEL *right, int width )
{
VipsArithmeticClass *class = VIPS_ARITHMETIC_GET_CLASS( binary );
VipsImage *im = binary->left_processed;
/* Complex just doubles the size.
*/
const int sz = width * im->Bands *
(vips_bandfmt_iscomplex( im->BandFmt ) ? 2 : 1);
(vips_band_format_iscomplex( im->BandFmt ) ? 2 : 1);
if( vips_vector_get_enabled() &&
add_vectors[im->BandFmt] ) {
VipsVector *vector = add_vectors[im->BandFmt];
VipsVector *v;
if( (v = vips_arithmetic_get_vector( class, im->BandFmt )) ) {
VipsExecutor ex;
vips_executor_set_program( &ex, vector, sz );
vips_executor_set_array( &ex, vector->s[0], in[0] );
vips_executor_set_array( &ex, vector->s[1], in[1] );
vips_executor_set_program( &ex, v, sz );
vips_executor_set_array( &ex, v->s[0], left );
vips_executor_set_array( &ex, v->s[1], right );
vips_executor_set_destination( &ex, out );
vips_executor_run( &ex );
@ -151,47 +151,6 @@ add_buffer( PEL **in, PEL *out, int width, IMAGE *im )
#define D IM_BANDFMT_DOUBLE
#define DX IM_BANDFMT_DPCOMPLEX
VipsVector *
im__init_program( VipsVector *vectors[IM_BANDFMT_LAST],
VipsBandFmt format_table[IM_BANDFMT_LAST], VipsBandFmt fmt )
{
int isize = im__sizeof_bandfmt[fmt];
int osize = im__sizeof_bandfmt[format_table[fmt]];
VipsVector *v;
v = vips_vector_new( "binary arith", osize );
vips_vector_source_name( v, "s1", isize );
vips_vector_source_name( v, "s2", isize );
vips_vector_temporary( v, "t1", osize );
vips_vector_temporary( v, "t2", osize );
vectors[fmt] = v;
return( v );
}
void
im__compile_programs( VipsVector *vectors[IM_BANDFMT_LAST] )
{
int fmt;
for( fmt = 0; fmt < IM_BANDFMT_LAST; fmt++ ) {
if( vectors[fmt] &&
!vips_vector_compile( vectors[fmt] ) )
IM_FREEF( vips_vector_free, vectors[fmt] );
}
#ifdef DEBUG
printf( "im__compile_programs: " );
for( fmt = 0; fmt < IM_BANDFMT_LAST; fmt++ )
if( vectors[fmt] )
printf( "%s ", im_BandFmt2char( fmt ) );
printf( "\n" );
#endif /*DEBUG*/
}
/* Type promotion for addition. Sign and value preserving. Make sure these
* match the case statement in add_buffer() above.
*/
@ -201,32 +160,30 @@ static int bandfmt_add[10] = {
};
static void
build_programs( void )
vips_add_class_init( VipsAddClass *class )
{
static gboolean done = FALSE;
VipsArithmeticClass *aclass = VIPS_ARITHMETIC_CLASS( class );
VipsBinaryClass *bclass = VIPS_BINARY_CLASS( class );
VipsVector *v;
if( done )
return;
done = TRUE;
vips_arithmetic_set_format_table( aclass, bandfmt_add );
v = im__init_program( add_vectors, bandfmt_add, IM_BANDFMT_UCHAR );
v = vips_arithmetic_get_program( aclass, VIPS_FORMAT_UCHAR );
vips_vector_asm2( v, "convubw", "t1", "s1" );
vips_vector_asm2( v, "convubw", "t2", "s2" );
vips_vector_asm3( v, "addw", "d1", "t1", "t2" );
v = im__init_program( add_vectors, bandfmt_add, IM_BANDFMT_CHAR );
v = vips_arithmetic_get_program( aclass, VIPS_FORMAT_CHAR );
vips_vector_asm2( v, "convsbw", "t1", "s1" );
vips_vector_asm2( v, "convsbw", "t2", "s2" );
vips_vector_asm3( v, "addw", "d1", "t1", "t2" );
v = im__init_program( add_vectors, bandfmt_add, IM_BANDFMT_USHORT );
v = vips_arithmetic_get_program( aclass, VIPS_FORMAT_USHORT );
vips_vector_asm2( v, "convuwl", "t1", "s1" );
vips_vector_asm2( v, "convuwl", "t2", "s2" );
vips_vector_asm3( v, "addl", "d1", "t1", "t2" );
v = im__init_program( add_vectors, bandfmt_add, IM_BANDFMT_SHORT );
v = vips_arithmetic_get_program( aclass, VIPS_FORMAT_SHORT );
vips_vector_asm2( v, "convswl", "t1", "s1" );
vips_vector_asm2( v, "convswl", "t2", "s2" );
vips_vector_asm3( v, "addl", "d1", "t1", "t2" );
@ -237,14 +194,20 @@ build_programs( void )
float/double/complex are not handled well
v = im__init_program( add_vectors, IM_BANDFMT_UINT );
v = vips_arithmetic_get_vector( aclass, VIPS_FORMAT_UINT );
vips_vector_asm3( v, "addl", "d1", "s1", "s2" );
v = im__init_program( add_vectors, IM_BANDFMT_INT );
v = vips_arithmetic_get_vector( aclass, VIPS_FORMAT_INT );
vips_vector_asm3( v, "addl", "d1", "s1", "s2" );
*/
im__compile_programs( add_vectors );
vips_arithmetic_compile( aclass );
bclass->process_line = add_buffer;
}
static void
vips_add_init( VipsAdd *add )
{
}

View File

@ -43,7 +43,7 @@
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif /*HAVE_CONFIG_H*/
#include <vips8/intl.h>
#include <vips/intl.h>
#include <stdio.h>
#include <stdlib.h>
@ -69,8 +69,6 @@ G_DEFINE_ABSTRACT_TYPE( VipsArithmetic, vips_arithmetic, VIPS_TYPE_OPERATION );
static int
vips_arithmetic_build( VipsObject *object )
{
VipsArithmetic *arithmetic = VIPS_ARITHMETIC (object);
if( VIPS_OBJECT_CLASS( vips_arithmetic_parent_class )->build( object ) )
return( -1 );
@ -110,6 +108,85 @@ vips_arithmetic_init( VipsArithmetic *arithmetic )
{
}
void
vips_arithmetic_set_format_table( VipsArithmeticClass *class,
VipsBandFormat *format_table )
{
int i;
g_assert( !class->format_table );
class->format_table = format_table;
for( i = 0; i < VIPS_FORMAT_LAST; i++ ) {
int isize = vips_format_sizeof( i );
int osize = vips_format_sizeof( (int) format_table[i] );
VipsVector *v;
v = vips_vector_new( "arithmetic", osize );
vips_vector_source_name( v, "s1", isize );
vips_vector_source_name( v, "s2", isize );
vips_vector_temporary( v, "t1", osize );
vips_vector_temporary( v, "t2", osize );
class->vectors[i] = v;
}
}
/* Get the stub for this program ... use _get_vector() to get the compiled
* code.
*/
VipsVector *
vips_arithmetic_get_program( VipsArithmeticClass *class, VipsBandFormat fmt )
{
g_assert( (int) fmt >= 0 && (int) fmt < VIPS_FORMAT_LAST );
g_assert( !class->vector_program[fmt] );
class->vector_program[fmt] = TRUE;
return( class->vectors[fmt] );
}
/* Get the compiled code for this type, if available.
*/
VipsVector *
vips_arithmetic_get_vector( VipsArithmeticClass *class, VipsBandFormat fmt )
{
g_assert( fmt >= 0 && fmt < VIPS_FORMAT_LAST );
if( !vips_vector_get_enabled() ||
!class->vector_program[fmt] )
return( NULL );
return( class->vectors[fmt] );
}
void
vips_arithmetic_compile( VipsArithmeticClass *class )
{
int i;
g_assert( class->format_table );
for( i = 0; i < VIPS_FORMAT_LAST; i++ )
if( class->vector_program[i] &&
!vips_vector_compile( class->vectors[i] ) )
/* If compilation fails, turn off the vector for this
* type.
*/
class->vector_program[i] = FALSE;
#ifdef DEBUG
printf( "vips_arithmetic_compile: " );
for( i = 0; i < IM_BANDFMT_LAST; i++ )
if( class->vector_program[i] )
printf( "%s ", VIPS_ENUM_NICK( VIPS_TYPE_FORMAT, i ) );
printf( "\n" );
#endif /*DEBUG*/
}
/* Called from iofuncs to init all operations in this dir. Use a plugin system
* instead?
*/
@ -120,3 +197,4 @@ vips_arithmetic_operation_init( void )
vips_add_get_type();
}

View File

@ -34,6 +34,8 @@
extern "C" {
#endif /*__cplusplus*/
#include <vips/vector.h>
#define VIPS_TYPE_ARITHMETIC (vips_arithmetic_get_type())
#define VIPS_ARITHMETIC( obj ) \
(G_TYPE_CHECK_INSTANCE_CAST( (obj), \
@ -56,19 +58,35 @@ typedef struct _VipsArithmetic {
*/
VipsImage *output;
/* For each input format, what output format. Used for arithmetic
* too, since we cast inputs to match.
*/
VipsFormat *cast_table;
} VipsArithmetic;
typedef struct _VipsArithmeticClass {
VipsOperationClass parent_class;
/* For each input format, what output format. Used for arithmetic
* too, since we cast inputs to match.
*/
VipsBandFormat *format_table;
/* A vector program for each input type.
*/
VipsVector *vectors[VIPS_FORMAT_LAST];
/* ... and if we've set a program for this format.
*/
gboolean vector_program[VIPS_FORMAT_LAST];
} VipsArithmeticClass;
GType vips_arithmetic_get_type( void );
void vips_arithmetic_set_format_table( VipsArithmeticClass *klass,
VipsBandFormat *format_table );
VipsVector *vips_arithmetic_get_vector( VipsArithmeticClass *klass,
VipsBandFormat fmt );
void vips_arithmetic_compile( VipsArithmeticClass *klass );
VipsVector *vips_arithmetic_get_program( VipsArithmeticClass *klass,
VipsBandFormat fmt );
#ifdef __cplusplus
}
#endif /*__cplusplus*/

View File

@ -34,7 +34,7 @@
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif /*HAVE_CONFIG_H*/
#include <vips8/intl.h>
#include <vips/intl.h>
#include <stdio.h>
#include <stdlib.h>
@ -75,7 +75,7 @@ G_DEFINE_ABSTRACT_TYPE( VipsBinary, vips_binary, VIPS_TYPE_ARITHMETIC );
/* For two integer types, the "largest", ie. one which can represent the
* full range of both.
*/
static VipsFormat format_largest[6][6] = {
static VipsBandFormat format_largest[6][6] = {
/* UC C US S UI I */
/* UC */ { UC, S, US, S, UI, I },
/* C */ { S, C, I, S, I, I },
@ -87,11 +87,11 @@ static VipsFormat format_largest[6][6] = {
/* For two formats, find one which can represent the full range of both.
*/
static VipsFormat
vips_format_common( VipsFormat a, VipsFormat b )
static VipsBandFormat
vips_format_common( VipsBandFormat a, VipsBandFormat b )
{
if( vips_format_iscomplex( a ) ||
vips_format_iscomplex( b ) ) {
if( vips_band_format_iscomplex( a ) ||
vips_band_format_iscomplex( b ) ) {
if( a == VIPS_FORMAT_DPCOMPLEX ||
b == VIPS_FORMAT_DPCOMPLEX )
return( VIPS_FORMAT_DPCOMPLEX );
@ -99,8 +99,8 @@ vips_format_common( VipsFormat a, VipsFormat b )
return( VIPS_FORMAT_COMPLEX );
}
else if( vips_format_isfloat( a ) ||
vips_format_isfloat( b ) ) {
else if( vips_band_format_isfloat( a ) ||
vips_band_format_isfloat( b ) ) {
if( a == VIPS_FORMAT_DOUBLE ||
b == VIPS_FORMAT_DOUBLE )
return( VIPS_FORMAT_DOUBLE );
@ -115,13 +115,13 @@ int
vips__formatalike_vec( VipsImage **in, VipsImage **out, int n )
{
int i;
VipsFormat format;
VipsBandFormat format;
g_assert( n >= 1 );
format = in[0]->BandFmt;
for( i = 1; i < n; i++ )
fmt = vips_format_common( format, in[i]->BandFmt );
format = vips_format_common( format, in[i]->BandFmt );
for( i = 0; i < n; i++ )
if( im_clip2fmt( in[i], out[i], format ) )
@ -219,6 +219,7 @@ vips_binary_process_region( VipsRegion *or, void *seq, void *a, void *b )
{
VipsRegion **ir = (VipsRegion **) seq;
VipsBinary *binary = VIPS_BINARY( b );
VipsBinaryClass *class = VIPS_BINARY_GET_CLASS( binary );
PEL *p[MAX_INPUT_IMAGES], *q;
int i, y;
@ -237,7 +238,7 @@ vips_binary_process_region( VipsRegion *or, void *seq, void *a, void *b )
for( y = 0; y < or->valid.height; y++ ) {
/* Bizarre double-cast stops a bogus gcc 4.1 compiler warning.
*/
binary->process_line( binary, q, p[0], p[1], or->valid.width );
class->process_line( binary, q, p[0], p[1], or->valid.width );
for( i = 0; ir[i]; i++ )
p[i] += VIPS_REGION_LSKIP( ir[i] );
@ -253,6 +254,7 @@ vips_binary_build( VipsObject *object )
VipsObjectClass *class = VIPS_OBJECT_GET_CLASS( object );
const char *domain = class->description;
VipsArithmetic *arithmetic = VIPS_ARITHMETIC( object );
VipsArithmeticClass *aclass = VIPS_ARITHMETIC_GET_CLASS( arithmetic );
VipsBinary *binary = VIPS_BINARY( object );
VipsImage *t[5];
@ -284,15 +286,15 @@ vips_binary_build( VipsObject *object )
/* Hint demand style. Being a buffer processor, we are happiest with
* thin strips.
*/
if( vips_demand_hint_array( binary->output,
if( vips_demand_hint_array( arithmetic->output,
VIPS_DEMAND_STYLE_THINSTRIP, t + 2 ) ||
vips_image_copy_fields_array( binary->output, t + 2 ) )
vips_image_copy_fields_array( arithmetic->output, t + 2 ) )
return( -1 );
binary->output->Bands = t[2]->Bands;
binary->output->BandFmt = arithmetic->cast_table[t[2]->BandFmt];
arithmetic->output->Bands = t[2]->Bands;
arithmetic->output->BandFmt = aclass->format_table[t[2]->BandFmt];
if( vips_image_generate( binary->output,
if( vips_image_generate( arithmetic->output,
vips_start_many, vips_binary_process_region,
vips_stop_many,
t + 2, binary ) )

View File

@ -46,8 +46,9 @@ extern "C" {
#define VIPS_BINARY_GET_CLASS( obj ) \
(G_TYPE_INSTANCE_GET_CLASS( (obj), VIPS_TYPE_BINARY, VipsBinaryClass ))
typedef void (*VipsBinaryProcessFn)( VipsBinary *binary,
void *out, void *left, void *right, int width );
struct _VipsBinary;
typedef void (*VipsBinaryProcessFn)( struct _VipsBinary *binary,
PEL *out, PEL *left, PEL *right, int width );
typedef struct _VipsBinary {
VipsArithmetic parent_instance;
@ -66,9 +67,8 @@ typedef struct _VipsBinary {
VipsImage *left_processed;
VipsImage *right_processed;
/* The line processor, plus some client data.
/* Some client data for the line processor, if it wants it.
*/
VipsBinaryProcessFn process_line;
void *a;
void *b;
} VipsBinary;
@ -76,6 +76,10 @@ typedef struct _VipsBinary {
typedef struct _VipsBinaryClass {
VipsArithmeticClass parent_class;
/* The line processor.
*/
VipsBinaryProcessFn process_line;
} VipsBinaryClass;
GType vips_binary_get_type( void );