home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
OS/2 Shareware BBS: 22 gnu
/
22-gnu.zip
/
mesch12a.zip
/
vecop.c
< prev
next >
Wrap
C/C++ Source or Header
|
1994-01-13
|
14KB
|
598 lines
/**************************************************************************
**
** Copyright (C) 1993 David E. Steward & Zbigniew Leyk, all rights reserved.
**
** Meschach Library
**
** This Meschach Library is provided "as is" without any express
** or implied warranty of any kind with respect to this software.
** In particular the authors shall not be liable for any direct,
** indirect, special, incidental or consequential damages arising
** in any way from use of the software.
**
** Everyone is granted permission to copy, modify and redistribute this
** Meschach Library, provided:
** 1. All copies contain this copyright notice.
** 2. All modified copies shall carry a notice stating who
** made the last modification and the date of such modification.
** 3. No charge is made for this software or works derived from it.
** This clause shall not be construed as constraining other software
** distributed on the same medium as this software, nor is a
** distribution fee considered a charge.
**
***************************************************************************/
/* vecop.c 1.3 8/18/87 */
#include <stdio.h>
#include "matrix.h"
static char rcsid[] = "$Id: vecop.c,v 1.3 1994/01/13 04:29:06 des Exp $";
/* _in_prod -- inner product of two vectors from i0 downwards */
double _in_prod(a,b,i0)
VEC *a,*b;
u_int i0;
{
u_int limit;
/* Real *a_v, *b_v; */
/* register Real sum; */
if ( a==(VEC *)NULL || b==(VEC *)NULL )
error(E_NULL,"_in_prod");
limit = min(a->dim,b->dim);
if ( i0 > limit )
error(E_BOUNDS,"_in_prod");
return __ip__(&(a->ve[i0]),&(b->ve[i0]),(int)(limit-i0));
/*****************************************
a_v = &(a->ve[i0]); b_v = &(b->ve[i0]);
for ( i=i0; i<limit; i++ )
sum += a_v[i]*b_v[i];
sum += (*a_v++)*(*b_v++);
return (double)sum;
******************************************/
}
/* sv_mlt -- scalar-vector multiply -- may be in-situ */
VEC *sv_mlt(scalar,vector,out)
double scalar;
VEC *vector,*out;
{
/* u_int dim, i; */
/* Real *out_ve, *vec_ve; */
if ( vector==(VEC *)NULL )
error(E_NULL,"sv_mlt");
if ( out==(VEC *)NULL || out->dim != vector->dim )
out = v_resize(out,vector->dim);
if ( scalar == 0.0 )
return v_zero(out);
if ( scalar == 1.0 )
return v_copy(vector,out);
__smlt__(vector->ve,(double)scalar,out->ve,(int)(vector->dim));
/**************************************************
dim = vector->dim;
out_ve = out->ve; vec_ve = vector->ve;
for ( i=0; i<dim; i++ )
out->ve[i] = scalar*vector->ve[i];
(*out_ve++) = scalar*(*vec_ve++);
**************************************************/
return (out);
}
/* v_add -- vector addition -- may be in-situ */
VEC *v_add(vec1,vec2,out)
VEC *vec1,*vec2,*out;
{
u_int dim;
/* Real *out_ve, *vec1_ve, *vec2_ve; */
if ( vec1==(VEC *)NULL || vec2==(VEC *)NULL )
error(E_NULL,"v_add");
if ( vec1->dim != vec2->dim )
error(E_SIZES,"v_add");
if ( out==(VEC *)NULL || out->dim != vec1->dim )
out = v_resize(out,vec1->dim);
dim = vec1->dim;
__add__(vec1->ve,vec2->ve,out->ve,(int)dim);
/************************************************************
out_ve = out->ve; vec1_ve = vec1->ve; vec2_ve = vec2->ve;
for ( i=0; i<dim; i++ )
out->ve[i] = vec1->ve[i]+vec2->ve[i];
(*out_ve++) = (*vec1_ve++) + (*vec2_ve++);
************************************************************/
return (out);
}
/* v_mltadd -- scalar/vector multiplication and addition
-- out = v1 + scale.v2 */
VEC *v_mltadd(v1,v2,scale,out)
VEC *v1,*v2,*out;
double scale;
{
/* register u_int dim, i; */
/* Real *out_ve, *v1_ve, *v2_ve; */
if ( v1==(VEC *)NULL || v2==(VEC *)NULL )
error(E_NULL,"v_mltadd");
if ( v1->dim != v2->dim )
error(E_SIZES,"v_mltadd");
if ( scale == 0.0 )
return v_copy(v1,out);
if ( scale == 1.0 )
return v_add(v1,v2,out);
if ( v2 != out )
{
tracecatch(out = v_copy(v1,out),"v_mltadd");
/* dim = v1->dim; */
__mltadd__(out->ve,v2->ve,scale,(int)(v1->dim));
}
else
{
tracecatch(out = sv_mlt(scale,v2,out),"v_mltadd");
out = v_add(v1,out,out);
}
/************************************************************
out_ve = out->ve; v1_ve = v1->ve; v2_ve = v2->ve;
for ( i=0; i < dim ; i++ )
out->ve[i] = v1->ve[i] + scale*v2->ve[i];
(*out_ve++) = (*v1_ve++) + scale*(*v2_ve++);
************************************************************/
return (out);
}
/* v_sub -- vector subtraction -- may be in-situ */
VEC *v_sub(vec1,vec2,out)
VEC *vec1,*vec2,*out;
{
/* u_int i, dim; */
/* Real *out_ve, *vec1_ve, *vec2_ve; */
if ( vec1==(VEC *)NULL || vec2==(VEC *)NULL )
error(E_NULL,"v_sub");
if ( vec1->dim != vec2->dim )
error(E_SIZES,"v_sub");
if ( out==(VEC *)NULL || out->dim != vec1->dim )
out = v_resize(out,vec1->dim);
__sub__(vec1->ve,vec2->ve,out->ve,(int)(vec1->dim));
/************************************************************
dim = vec1->dim;
out_ve = out->ve; vec1_ve = vec1->ve; vec2_ve = vec2->ve;
for ( i=0; i<dim; i++ )
out->ve[i] = vec1->ve[i]-vec2->ve[i];
(*out_ve++) = (*vec1_ve++) - (*vec2_ve++);
************************************************************/
return (out);
}
/* v_map -- maps function f over components of x: out[i] = f(x[i])
-- _v_map sets out[i] = f(x[i],params) */
VEC *v_map(f,x,out)
double (*f)();
VEC *x, *out;
{
Real *x_ve, *out_ve;
int i, dim;
if ( ! x || ! f )
error(E_NULL,"v_map");
if ( ! out || out->dim != x->dim )
out = v_resize(out,x->dim);
dim = x->dim; x_ve = x->ve; out_ve = out->ve;
for ( i = 0; i < dim; i++ )
*out_ve++ = (*f)(*x_ve++);
return out;
}
VEC *_v_map(f,params,x,out)
double (*f)();
VEC *x, *out;
void *params;
{
Real *x_ve, *out_ve;
int i, dim;
if ( ! x || ! f )
error(E_NULL,"_v_map");
if ( ! out || out->dim != x->dim )
out = v_resize(out,x->dim);
dim = x->dim; x_ve = x->ve; out_ve = out->ve;
for ( i = 0; i < dim; i++ )
*out_ve++ = (*f)(params,*x_ve++);
return out;
}
/* v_lincomb -- returns sum_i a[i].v[i], a[i] real, v[i] vectors */
VEC *v_lincomb(n,v,a,out)
int n; /* number of a's and v's */
Real a[];
VEC *v[], *out;
{
int i;
if ( ! a || ! v )
error(E_NULL,"v_lincomb");
if ( n <= 0 )
return VNULL;
for ( i = 1; i < n; i++ )
if ( out == v[i] )
error(E_INSITU,"v_lincomb");
out = sv_mlt(a[0],v[0],out);
for ( i = 1; i < n; i++ )
{
if ( ! v[i] )
error(E_NULL,"v_lincomb");
if ( v[i]->dim != out->dim )
error(E_SIZES,"v_lincomb");
out = v_mltadd(out,v[i],a[i],out);
}
return out;
}
#ifdef ANSI_C
/* v_linlist -- linear combinations taken from a list of arguments;
calling:
v_linlist(out,v1,a1,v2,a2,...,vn,an,NULL);
where vi are vectors (VEC *) and ai are numbers (double)
*/
VEC *v_linlist(VEC *out,VEC *v1,double a1,...)
{
va_list ap;
VEC *par;
double a_par;
if ( ! v1 )
return VNULL;
va_start(ap, a1);
out = sv_mlt(a1,v1,out);
while (par = va_arg(ap,VEC *)) { /* NULL ends the list*/
a_par = va_arg(ap,double);
if (a_par == 0.0) continue;
if ( out == par )
error(E_INSITU,"v_linlist");
if ( out->dim != par->dim )
error(E_SIZES,"v_linlist");
if (a_par == 1.0)
out = v_add(out,par,out);
else if (a_par == -1.0)
out = v_sub(out,par,out);
else
out = v_mltadd(out,par,a_par,out);
}
va_end(ap);
return out;
}
#elif VARARGS
/* v_linlist -- linear combinations taken from a list of arguments;
calling:
v_linlist(out,v1,a1,v2,a2,...,vn,an,NULL);
where vi are vectors (VEC *) and ai are numbers (double)
*/
VEC *v_linlist(va_alist) va_dcl
{
va_list ap;
VEC *par, *out;
double a_par;
va_start(ap);
out = va_arg(ap,VEC *);
par = va_arg(ap,VEC *);
if ( ! par ) {
va_end(ap);
return VNULL;
}
a_par = va_arg(ap,double);
out = sv_mlt(a_par,par,out);
while (par = va_arg(ap,VEC *)) { /* NULL ends the list*/
a_par = va_arg(ap,double);
if (a_par == 0.0) continue;
if ( out == par )
error(E_INSITU,"v_linlist");
if ( out->dim != par->dim )
error(E_SIZES,"v_linlist");
if (a_par == 1.0)
out = v_add(out,par,out);
else if (a_par == -1.0)
out = v_sub(out,par,out);
else
out = v_mltadd(out,par,a_par,out);
}
va_end(ap);
return out;
}
#endif
/* v_star -- computes componentwise (Hadamard) product of x1 and x2
-- result out is returned */
VEC *v_star(x1, x2, out)
VEC *x1, *x2, *out;
{
int i;
if ( ! x1 || ! x2 )
error(E_NULL,"v_star");
if ( x1->dim != x2->dim )
error(E_SIZES,"v_star");
out = v_resize(out,x1->dim);
for ( i = 0; i < x1->dim; i++ )
out->ve[i] = x1->ve[i] * x2->ve[i];
return out;
}
/* v_slash -- computes componentwise ratio of x2 and x1
-- out[i] = x2[i] / x1[i]
-- if x1[i] == 0 for some i, then raise E_SING error
-- result out is returned */
VEC *v_slash(x1, x2, out)
VEC *x1, *x2, *out;
{
int i;
Real tmp;
if ( ! x1 || ! x2 )
error(E_NULL,"v_slash");
if ( x1->dim != x2->dim )
error(E_SIZES,"v_slash");
out = v_resize(out,x1->dim);
for ( i = 0; i < x1->dim; i++ )
{
tmp = x1->ve[i];
if ( tmp == 0.0 )
error(E_SING,"v_slash");
out->ve[i] = x2->ve[i] / tmp;
}
return out;
}
/* v_min -- computes minimum component of x, which is returned
-- also sets min_idx to the index of this minimum */
double v_min(x, min_idx)
VEC *x;
int *min_idx;
{
int i, i_min;
Real min_val, tmp;
if ( ! x )
error(E_NULL,"v_min");
if ( x->dim <= 0 )
error(E_SIZES,"v_min");
i_min = 0;
min_val = x->ve[0];
for ( i = 1; i < x->dim; i++ )
{
tmp = x->ve[i];
if ( tmp < min_val )
{
min_val = tmp;
i_min = i;
}
}
if ( min_idx != NULL )
*min_idx = i_min;
return min_val;
}
/* v_max -- computes maximum component of x, which is returned
-- also sets max_idx to the index of this maximum */
double v_max(x, max_idx)
VEC *x;
int *max_idx;
{
int i, i_max;
Real max_val, tmp;
if ( ! x )
error(E_NULL,"v_max");
if ( x->dim <= 0 )
error(E_SIZES,"v_max");
i_max = 0;
max_val = x->ve[0];
for ( i = 1; i < x->dim; i++ )
{
tmp = x->ve[i];
if ( tmp > max_val )
{
max_val = tmp;
i_max = i;
}
}
if ( max_idx != NULL )
*max_idx = i_max;
return max_val;
}
#define MAX_STACK 60
/* v_sort -- sorts vector x, and generates permutation that gives the order
of the components; x = [1.3, 3.7, 0.5] -> [0.5, 1.3, 3.7] and
the permutation is order = [2, 0, 1].
-- if order is NULL on entry then it is ignored
-- the sorted vector x is returned */
VEC *v_sort(x, order)
VEC *x;
PERM *order;
{
Real *x_ve, tmp, v;
/* int *order_pe; */
int dim, i, j, l, r, tmp_i;
int stack[MAX_STACK], sp;
if ( ! x )
error(E_NULL,"v_sort");
if ( order != PNULL && order->size != x->dim )
order = px_resize(order, x->dim);
x_ve = x->ve;
dim = x->dim;
if ( order != PNULL )
px_ident(order);
if ( dim <= 1 )
return x;
/* using quicksort algorithm in Sedgewick,
"Algorithms in C", Ch. 9, pp. 118--122 (1990) */
sp = 0;
l = 0; r = dim-1; v = x_ve[0];
for ( ; ; )
{
while ( r > l )
{
/* "i = partition(x_ve,l,r);" */
v = x_ve[r];
i = l-1;
j = r;
for ( ; ; )
{
while ( x_ve[++i] < v )
;
while ( x_ve[--j] > v )
;
if ( i >= j ) break;
tmp = x_ve[i];
x_ve[i] = x_ve[j];
x_ve[j] = tmp;
if ( order != PNULL )
{
tmp_i = order->pe[i];
order->pe[i] = order->pe[j];
order->pe[j] = tmp_i;
}
}
tmp = x_ve[i];
x_ve[i] = x_ve[r];
x_ve[r] = tmp;
if ( order != PNULL )
{
tmp_i = order->pe[i];
order->pe[i] = order->pe[r];
order->pe[r] = tmp_i;
}
if ( i-l > r-i )
{ stack[sp++] = l; stack[sp++] = i-1; l = i+1; }
else
{ stack[sp++] = i+1; stack[sp++] = r; r = i-1; }
}
/* recursion elimination */
if ( sp == 0 )
break;
r = stack[--sp];
l = stack[--sp];
}
return x;
}
/* v_sum -- returns sum of entries of a vector */
double v_sum(x)
VEC *x;
{
int i;
Real sum;
if ( ! x )
error(E_NULL,"v_sum");
sum = 0.0;
for ( i = 0; i < x->dim; i++ )
sum += x->ve[i];
return sum;
}
/* v_conv -- computes convolution product of two vectors */
VEC *v_conv(x1, x2, out)
VEC *x1, *x2, *out;
{
int i;
if ( ! x1 || ! x2 )
error(E_NULL,"v_conv");
if ( x1 == out || x2 == out )
error(E_INSITU,"v_conv");
if ( x1->dim == 0 || x2->dim == 0 )
return out = v_resize(out,0);
out = v_resize(out,x1->dim + x2->dim - 1);
v_zero(out);
for ( i = 0; i < x1->dim; i++ )
__mltadd__(&(out->ve[i]),x2->ve,x1->ve[i],x2->dim);
return out;
}
/* v_pconv -- computes a periodic convolution product
-- the period is the dimension of x2 */
VEC *v_pconv(x1, x2, out)
VEC *x1, *x2, *out;
{
int i;
if ( ! x1 || ! x2 )
error(E_NULL,"v_pconv");
if ( x1 == out || x2 == out )
error(E_INSITU,"v_pconv");
out = v_resize(out,x2->dim);
if ( x2->dim == 0 )
return out;
v_zero(out);
for ( i = 0; i < x1->dim; i++ )
{
__mltadd__(&(out->ve[i]),x2->ve,x1->ve[i],x2->dim - i);
if ( i > 0 )
__mltadd__(out->ve,&(x2->ve[x2->dim - i]),x1->ve[i],i);
}
return out;
}