function c = outer(a, b, idA, idB)
%OUTER Vector outer product.
% This function exploits the MULTIPROD engine (MATLAB Central, file
% #8773), which enables multiple products and array expansion (AX).
%
% When A and B are vectors (e.g. P1, 1P, or 11P arrays):
%
% C = OUTER(A, B) returns their outer product. A and B may have
% different lengths P and Q. If A and B are both column vectors, C is
% a PQ matrix, and OUTER(A, B) is the same as CONJ(A) * B'.
% Otherwise, C is a multi-dimensional array containing a single PxQ
% matrix (e.g. a 1PQ array, if A and B are row vectors; see below).
% C = OUTER(A(:), B(:)) guarantees that C is a matrix.
%
% More generally, when A and B are arrays of any size containing one or
% more vectors:
%
% C = OUTER(A, B) is equivalent to C = OUTER(A, B, IDA, IDB), where
% IDA and IDB are the first non-singleton dimensions of A and B,
% respectively.
%
% C = OUTER(A, B, DIM) is equivalent to C = OUTER(A, B, IDA, IDB),
% where IDA = IDB = DIM.
%
% C = OUTER(A, B, IDA, IDB) returns the outer products between the
% vectors contained in A along dimension IDA and those contained in B
% along dimension IDB. These vectors may have different lengths
% P = SIZE(A,IDA) and Q = SIZE(B,IDB). A and B are viewed as "block
% arrays". IDA and IDB are referred to as their "internal dimensions"
% (IDs). For instance, a 562 array may be viewed as an array
% containing twelve 5-element blocks. In this case, its size is
% denoted by (5)62, and its ID is 1. Since AX is enabled, the
% "external dimensions" of A and B may have different size, and IDA
% may not coincide with IDB (see MULTIPROD).
%
% C = OUTER(A, B, IDA, IDB) just calls the instruction
% C = MULTIPROD(CONJ(A), B, [IDA 0], [0 IDB]), which turns the
% vectors found in CONJ(A) and B into P1 and 1Q matrices,
% respectively, then multiplies them obtaining PQ matrices.
%
% Input and output format (see MULTIPROD, syntax 4c):
% Array Block size Internal dimension(s)
% ------------------------------------------------------
% A P (1-D) IDA
% B Q (1-D) IDB
% C PQ (2-D) MAX([IDA IDA+1], [IDB IDB+1])
% ------------------------------------------------------
%
% Examples:
% If A is ......... a (5)62 array of vectors,
% and B is ......... a (3)62 array of vectors,
% C = OUTER(A, B) is a (53)62 array of matrices.
%
% A single vector B multiplies thirty vectors contained in A:
% If A is ............... a 56(2) array of 30 vectors,
% and B is ............... a (3)1 vector,
% C = OUTER(A, B, 3, 1) is a 56(23) array of 30 matrices.
%
% See also DOT2, CROSS2, CROSSDIV, MAGN, UNIT, PROJECTION, REJECTION,
% MULTIPROD, TESTOUTER.
% $ Version: 2.0 $
% CODE by: Paolo de Leva (IUSM, Rome, IT) 2009 Feb 1
% COMMENTS by: Code author 2009 Feb 12
% OUTPUT tested by: Code author 2009 Feb 12
% -------------------------------------------------------------------------
% Allow 2 to 4 input arguments
error( nargchk(2, 4, nargin) );
% Setting IDA and/or IDB
switch nargin
case 2
idA0 = find(size(a)>1, 1, 'first'); % First non-singleton dim.
idB0 = find(size(b)>1, 1, 'first'); % ([] if the array is a scalar)
idA = max([idA0, 1]); % IDA = 1 if A is empty or a scalar
idB = max([idB0, 1]);
case 3
idB = idA;
end
c = multiprod(conj(a), b, [idA 0], [0 idB]);