alibOuter
Outer (tensor) product generalized to any binary operator. The routine applies an operator to each pair (x,y), where x is from one array and y is from a second array. If for example the operator is multiplication and arrays are x and y, the elements of the result are x[i]*y[j] where j varies fastest. This essentially two-dimensional operation has a general multidimensional interpretation: If x and y are interpreted as m-dimensional and n-dimensional, respectively, the result is interpreted as the (m+n)-dimensional tensor product of x and y, where the first m dimensions are from x and the last n dimensions are from y. The PV-WAVE API for this routine is the undocumented TENSORT function which is used like z=TENSORT(f,x,y), where f is a string designating a PV-WAVE binary operator and where x and y are arrays of the same data-type. TENSORT is the row-major equivalent of the column-major PV-WAVE TENSOR functions, and the possible values of f are the suffixes on the names of the TENSOR functions.
Prototypes
void alibOuterb( void (*f)(), wvlong m, wvlong n, UCHAR *p, UCHAR *q, wvlong *k, UCHAR *r, UCHAR *s )
void alibOuters( void (*f)(), wvlong m, wvlong n, short *p, short *q, wvlong *k, short *r, UCHAR *s )
void alibOuteri( void (*f)(), wvlong m, wvlong n, int *p, int *q, wvlong *k, int *r, UCHAR *s )
void alibOuterl( void (*f)(), wvlong m, wvlong n, wvlong *p, wvlong *q, wvlong *k, wvlong *r, UCHAR *s )
void alibOuterf( void (*f)(), wvlong m, wvlong n, float *p, float *q, wvlong *k, float *r, UCHAR *s )
void alibOuterd( void (*f)(), wvlong m, wvlong n, double *p, double *q, wvlong *k, double *r, UCHAR *s )
void alibOuterc( void (*f)(), wvlong m, wvlong n, COMPLEX *p, COMPLEX *q, wvlong *k, COMPLEX *r, UCHAR *s )
void alibOuterz( void (*f)(), wvlong m, wvlong n, DCOMPLEX *p, DCOMPLEX *q, wvlong *k, DCOMPLEX *r, UCHAR *s )
Parameters
(*f)() — (Input) The name of one of the following functions:
where the asterisk represents the letter-code for a supported data-type.
m — (Input) The number of elements in the first array operand.
n — (Input) The number of elements in the second array operand.
*p — (Input) The m-element source array. A scalar p[i] is the first operand in each call to f(), i = 0, ..., m–1.
*q — (Input) NULL if f is alibPowI*, and otherwise, q is the n-element source array used as the second operand in each call to f().
*k — (Input) NULL if f is not alibPowI*, and otherwise, k is the n-element source array used as the second operand in each call to f().
*r — (Input/Output) NULL if f is one of alibEq*, alibNe*, alibLe*, alibGe*, alibLt*, or alibGt*. Otherwise r is an mn-element destination array, and on return r[n*i+j]=p[i]@q[j], where @ is the operation connected with f().
*s — (Input/Output) NULL if f is not one of alibEq*, alibNe*, alibLe*, alibGe*, alibLt*, or alibGt*. Otherwise s is an mn-element destination array, and on return s[n*i+j]=p[i]@q[j], where @ is the operation connected with f().
Example
Besides demonstrating each of the three basic ways to call this routine, this example also demonstrates how to interpret results for multi-dimensional input arrays (see
RWalib Introduction.), and how to use the routine to generate index arrays for matrix subdiagonals, superdiagonals, and full/strict lower/upper-triangles.
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include "alib.h"
void main() {
/* input and output arrays for the examples */
UCHAR lb[16];
wvlong l[24], l0[6], l1[4];
float f[24], f0[6];
/* make up some data for the input arrays */
alibinit( NULL, NULL, NULL, NULL );
alibIndexl( 6, 0, 1, l0 );
alibIndexf( 6, 0, 1, f0 );
alibIndexl( 4, 1, 1, l1 );
printf( "\n\n show 4-element vector f0 and 3-element vector l1" );
alibPrintArrayf( 1, 1, 1, 4, f0, NULL );
alibPrintArrayl( 1, 1, 1, 3, l1, NULL );
printf( "\n\n show the matrix of the values f0[i] to integer power l1[j]" );
alibOuterf( alibPowIf, 4, 3, f0, NULL, l1, f, NULL );
alibPrintArrayf( 1, 1, 4, 3, f, NULL );
printf( "\n\n show 4-element vectors l0 and l1" );
alibPrintArrayl( 1, 1, 1, 4, l0, "%4lld" );
alibPrintArrayl( 1, 1, 1, 4, l1, "%4lld" );
printf( "\n\n show the matrix of the values l0[i] == l1[j]" );
alibOuterl( alibEql, 4, 4, l0, l1, NULL, NULL, lb );
alibPrintArrayb( 1, 1, 4, 4, lb, NULL );
printf( "\n\n this procedure also yields indices of the subdiagonal" );
alibFindb( 3, lb, l );
alibPrintArrayl( 1, 1, 1, 3, l, "%4lld" );
printf( "\n\n interchange l0 and l1 to get indices of the superdiagonal" );
alibOuterl( alibEql, 4, 4, l1, l0, NULL, NULL, lb );
alibFindb( 3, lb, l );
alibPrintArrayl( 1, 1, 1, 3, l, "%4lld" );
printf( "\n\n similar procedure finds indices of lower-triangular matrix" );
alibOuterl( alibGel, 4, 4, l0, l0, NULL, NULL, lb );
alibFindb( 10, lb, l );
alibPrintArrayb( 1, 1, 4, 4, lb, NULL );
alibPrintArrayl( 1, 1, 1, 10, l, "%4lld" );
printf( "\n\n or finds indices of strictly lower-triangular matrix" );
alibOuterl( alibGtl, 4, 4, l0, l0, NULL, NULL, lb );
alibFindb( 6, lb, l );
alibPrintArrayb( 1, 1, 4, 4, lb, NULL );
alibPrintArrayl( 1, 1, 1, 6, l, "%4lld" );
printf( "\n\n or finds indices of upper-triangular matrix" );
alibOuterl( alibLel, 4, 4, l0, l0, NULL, NULL, lb );
alibFindb( 10, lb, l );
alibPrintArrayb( 1, 1, 4, 4, lb, NULL );
alibPrintArrayl( 1, 1, 1, 10, l, "%4lld" );
printf( "\n\n or finds indices of strictly upper-triangular matrix" );
alibOuterl( alibLtl, 4, 4, l0, l0, NULL, NULL, lb );
alibFindb( 6, lb, l );
alibPrintArrayb( 1, 1, 4, 4, lb, NULL );
alibPrintArrayl( 1, 1, 1, 6, l, "%4lld" );
printf( "\n\n show (2,3) array l0 and 4-element vector l1" );
alibPrintArrayl( 1, 1, 2, 3, l0, "%4lld" );
alibPrintArrayl( 1, 1, 1, 4, l1, "%4lld" );
printf( "\n\n show outer (tensor) product of 2d array l0 and 1d array l1" );
alibOuterl( alibMultl, 6, 4, l0, l1, NULL, l, NULL );
alibPrintArrayl( 1, 2, 3, 4, l, "%4lld" );
printf( "\n\n show (2,2) arrays l0 and l1" );
alibPrintArrayl( 1, 1, 2, 2, l0, "%4lld" );
alibPrintArrayl( 1, 1, 2, 2, l1, "%4lld" );
printf( "\n\n show 4d result of tensor product of 2d arrays l0 and l1" );
alibOuterl( alibMultl, 4, 4, l0, l1, NULL, l, NULL );
alibPrintArrayl( 2, 2, 2, 2, l, "%4lld" );
}
Output:
show 4-element vector f0 and 3-element vector l1
0.000e+00 1.000e+00 2.000e+00 3.000e+00
1 2 3
show the matrix of the values f0[i] to integer power l1[j]
0.000e+00 0.000e+00 0.000e+00
1.000e+00 1.000e+00 1.000e+00
2.000e+00 4.000e+00 8.000e+00
3.000e+00 9.000e+00 2.700e+01
show 4-element vectors l0 and l1
0 1 2 3
1 2 3 4
show the matrix of the values l0[i] == l1[j]
0 0 0 0
1 0 0 0
0 1 0 0
0 0 1 0
this procedure also yields indices of the subdiagonal
4 9 14
interchange l0 and l1 to get indices of the superdiagonal
1 6 11
similar procedure finds indices of lower-triangular matrix
1 0 0 0
1 1 0 0
1 1 1 0
1 1 1 1
0 4 5 8 9 10 12 13 14 15
or finds indices of strictly lower-triangular matrix
0 0 0 0
1 0 0 0
1 1 0 0
1 1 1 0
4 8 9 12 13 14
or finds indices of upper-triangular matrix
1 1 1 1
0 1 1 1
0 0 1 1
0 0 0 1
0 1 2 3 5 6 7 10 11 15
or finds indices of strictly upper-triangular matrix
0 1 1 1
0 0 1 1
0 0 0 1
0 0 0 0
1 2 3 6 7 11
show (2,3) array l0 and 4-element vector l1
0 1 2
3 4 5
1 2 3 4
show outer (tensor) product of 2d array l0 and 1d array l1
0 0 0 0
1 2 3 4
2 4 6 8
3 6 9 12
4 8 12 16
5 10 15 20
show (2,2) arrays l0 and l1
0 1
2 3
1 2
3 4
show 4d result of tensor product of 2d arrays l0 and l1
0 0
0 0
1 2
3 4
2 4
6 8
3 6
9 12
Version 2017.0
Copyright © 2017, Rogue Wave Software, Inc. All Rights Reserved.