From oleg@nrcbsa.bio.nrc.ca Thu May 23 08:51:47 1991
Return-Path: <oleg@nrcbsa.bio.nrc.ca>
Received: from nrcnet0.nrc.ca by CS.UTK.EDU with SMTP (5.61++/2.5.1s-UTK)
	id AA26030; Thu, 23 May 91 08:51:40 -0400
Message-Id: <9105231251.AA28680@ nrcbsa.bio.nrc.ca>
Date: Thu, 23 May 91 08:51:14 EDT
From: Dr. Oleg Keselyov <oleg@nrcbsa.bio.nrc.ca>
To: dongarra@cs.utk.edu
Subject: vector.shar
Status: RO

#--------------------------------CUT HERE-------------------------------------
#! /bin/sh
#
# This is a shell archive. Save this into a file, edit it
# and delete all lines above this comment.  Then give this
# file to sh by executing the command 'sh file'. The files
# will be extracted into the current directory owned by
# you with default permissions.

# The arcive contains low and intermediate Level functions to manage vectors
# in C.
# In fact, the vector declaration as a special structure and
# a wide set of procedures to handle it define a class (in
# the sence of C++ or SMALLTALK) but it is still a common C.
# Features: high reliability and error-checking, the user can
# operate on single elements of the vector in the customary C
# manner, or he may wish to handle the vector as a whole 
# (as an atomary object) with high-effective functions 
# (that can clear the vector, assign vectors or obtain their
# scalar product, find the vector norm(s), etc.).

#			The contents of the archive
#
# Header file
#	vector.h	Define the package
#
# Source code for vector implementation
# 	vec_base.c	Basic vector primitives, constructors, destructors
#	vec_norm.c	Computing vector norms and the scalar product
#	vec_serv.c	Comparison and Input/Output functions
#
# Package verification
#	vvector.c	Test driver
#	vvector.dat	Verification protocol

echo 'x - vector.h'
sed 's/^X//' << '________This_Is_The_END________' > vector.h
X/*
X ************************************************************************
X *			  VECTOR of floats
X * 		Description of data and operations
X */
X
X#ifndef V$elem_type
X
X#define V$elem_type float
X
Xtypedef struct {		/* 	Vector structure		*/
X	short int valid;		/* Validation code		*/
X	short int ident;		/* Identification		*/
X	int upb;			/* Upper bound value		*/
X	int lwb;			/* Lower bound value		*/
X	V$elem_type * ptr; 		/* Ptr to the vector body	*/
X		}
X*VECTOR, _VECTOR;
X
X#define _V$validation_code	23567	/* VECTOR->valid contents	*/
X
X				/* Vector identification codes		*/
X#define _V$id_dynamic	1		/* Storage was obtained via malloc*/
X
X/*
X *-----------------------------------------------------------------------
X *     			Allocation routines
X */
X				/* Defining a not-dynamical vector	*/
X#define	Vector(name,lwb,upb) V$elem_type _$_name [(upb)-(lwb)+1]; \
X		VECTOR name = &{_V$validation_code, 0, (upb), (lwb), _$_name}
X
XVECTOR V_new(			/* Create a new dynamic vector		*/
X	const int lwb,			/* Lower bound 			*/
X	const int upb			/* Upper bound 			*/
X	    );
X
XVECTOR V_build(			/* Build a vector and assign init val	*/
X	const int lwb,			/* Lower bound 			*/
X	const int upb,			/* Upper bound 			*/
X	...				/* DOUBLE numbers - values of 	*/
X					/* vector components		*/
X					/* List must contain an extra   */
X					/* argument - string "END"	*/
X	    );
X
X
Xvoid   V_free(			/* Delete a vector and free its storage	*/
X	VECTOR v			/* Dynamic vector to be freed	*/
X	     );
X
X				/* Assure that two vectors are compatible*/
X#define	V_are_compatible(v1,v2) {if( v1->lwb != v2->lwb || v1->upb != v2->upb )\
X	_error("Vectors [%d:%d] and [%d:%d] are incompatible.\nFile %s, line \
X	%d\n",v1->lwb,v1->upb, v2->lwb,v2->upb, __FILE__, __LINE__);}
X
X
X/*
X *-----------------------------------------------------------------------
X *     		       	 Access to VECTOR fields
X */
X				/* Assure the vector having been initialized*/
X#define V_verify(v) if( v->valid != _V$validation_code ) \
X	_error("Illegal vector.\nFile %s, line %d\n",__FILE__,__LINE__)
X
X#define V_lwb(v) v->lwb			/* Lower vector bound		*/
X#define V_upb(v) v->upb			/* Upper vector bound		*/
X#define V_no_elems(v) (v->upb-v->lwb+1) /* No. of vector elements	*/
X
X                 		/* Get ptr to the vector body		*/
XV$elem_type * V_body(
X	const VECTOR v 			/* Vector under operation	*/
X		    );
X#define V_pointer(ptr,v) V$elem_type *ptr = V_body(v)
X
X				/* Get ptr to a vector element		*/
XV$elem_type * V_elem(
X	const VECTOR v,			/* Vector under operation	*/
X	const int i    			/* Index			*/
X		    );
X
X/*
X *-----------------------------------------------------------------------
X *     		       	 	Assignments
X */
X
Xvoid V_assign(			/* Assign vector to vector		*/
X	VECTOR dest,			/* Destination vector		*/
X	const VECTOR source       	/* Source vector		*/
X	     );
X
Xvoid V_clear(			/* Clear the entire vector (fill with 0)*/
X	VECTOR v			/* Vector being operated	*/
X	    );
X
Xvoid V_setto(			/* Set all vector elements to a given val*/
X	VECTOR v,			/* Vector being operated	*/
X	const double val        	/* Value to be set		*/
X	    );
X
X/*
X *-----------------------------------------------------------------------
X *     		  	  Compute vector norms
X */
X
Xdouble V_1_norm(		/* 1. vector norm = SUM[ |vector[i]| ]	*/
X	const VECTOR v    	   	/* Vector under operation	*/
X	       );	
X
Xdouble V_2_norm(		/* 2. vector norm = MAX[ |vector[i]| ]	*/
X	const VECTOR v		       	/* Vector under operation	*/
X	       );	
X
Xdouble V_e2_norm(		/* Square of the Euclid norm =         	*/
X	const VECTOR v		    	/* SUM[ vector[i]^2 ]    	*/
X	       );	
X
Xdouble V_diff_e2_norm(		/* Square of the Euclid norm for       	*/
X	const VECTOR v1,  	  	/* the difference of 2 vectors 	*/
X	const VECTOR v2	
X	       );	
X
X
X
X/*
X *-----------------------------------------------------------------------
X *     		       	   Vector arithmetics
X */
X
Xdouble V_scalar_prod( 		/* Scalar product of two vectors      	*/
X	const VECTOR v1, 
X	const VECTOR v2
X	       );	
X
X
Xvoid V_op2(			/* Vector arithmetics: 	binary operations*/
X	VECTOR dest,			/* Destination			*/
X	char   sign
X	  );
X
X/*
X *-----------------------------------------------------------------------
X *     		       	  Service functions
X */
X
Xvoid V_compare(			/* Compare two vectors			*/
X	const VECTOR v1,   		/* Vectors to be compared      	*/
X	const VECTOR v2,   
X	const char * message		/* Explanation message		*/
X	      );	
X
Xvoid V_print(  			/* Print a vector     			*/
X	const VECTOR v,    		/* Vector to be printed       	*/
X	const char * title  		/* Explanation message		*/
X	      );	
X
XVECTOR V_read(   		/* Read a vector from stdin		*/
X	const char * title		/* File is assumed to contain	*/
X	      );	               	/* title, counter, and elements */
X
X#endif
________This_Is_The_END________
if test `wc -l < vector.h` -ne 161; then
echo 'shar: vector.h was damaged during transit (should have had 161 lines)'
fi


echo 'x - vec_base.c'
sed 's/^X//' << '________This_Is_The_END________' > vec_base.c
X/*
X ************************************************************************
X *			  VECTOR of floats
X * 			  Base operations
X */
X
X#include "vector.h"
X
X#include "assert.h"
X#include <stdlib.h>
X#include <malloc.h>
X
X/*
X *			Create a dynamic vector
X *
X */
X
XVECTOR V_new(lwb,upb)
Xconst int lwb, upb;
X{
X  register int no_elements = upb - lwb + 1;
X  register VECTOR v;
X
X  assure(no_elements>0,"V_new: lwb > upb");
X  assure((v = (VECTOR)malloc(sizeof(_VECTOR))) != (VECTOR)0, 
X				"V_new: no memory");
X  
X  v->valid = _V$validation_code;
X  v->ident = _V$id_dynamic;
X  v->lwb = lwb;
X  v->upb = upb;
X  assure((v->ptr = (V$elem_type *)malloc(no_elements*sizeof(V$elem_type))
X         ) != NULL, 
X	 "V_new: no memory");
X  return v;
X}
X
X
X#include <stdarg.h>
X
X			/* Build a vector and assign init values	*/
X			/* The arg list must contain an extra argument- */
X			/* string "END"					*/
XVECTOR V_build(
X	const int lwb,			/* Lower bound 			*/
X	const int upb,			/* Upper bound 			*/
X	...
X)
X{
X  va_list args;
X  VECTOR v = V_new(lwb,upb);
X  register int i;
X
X  va_start(args,upb);			/* Init 'args' to the beginning of */
X					/* the variable length list of args*/
X  for(i=lwb; i<=upb; i++)
X     *V_elem(v,i) = (double)va_arg(args,double);
X  assure( strcmp((char *)va_arg(args,char *),"END") == 0, 
X		"V_build: argument list should be terminated by \"END\" ");
X  return v;
X}
X
X
X/*
X *			Free a dynamic vector
X *
X */
X
Xvoid V_free(v)
XVECTOR v;
X{
X  assure( v->valid == _V$validation_code && 
X	  (v->ident & _V$id_dynamic == _V$id_dynamic),
X	  "V_free: invalid dynamic vector to free" );
X  free( v->ptr );
X  v->valid = 0; v->lwb = 0; v->upb = -1;
X  free(v);
X}
X
X
X/*
X *		        Get ptr to the VECTOR body
X *
X */
X
XV$elem_type * V_body(v)
Xconst VECTOR v;
X{
X  assure( v->valid == _V$validation_code, "V_body: invalid VECTOR ptr");
X  assure( v->upb >= v->lwb, "V_body: VECTOR must have been corrupted");
X  return v->ptr;
X}
X
X
X/*
X *		    Get ptr to the specified VECTOR element
X *
X */
X
XV$elem_type * V_elem(v,i)
Xconst VECTOR v;   				/* Vector under operation */
Xconst int i;                                    /* Index of the req. elem */
X{
X  assure( v->valid == _V$validation_code, "V_elem: invalid VECTOR ptr");
X  if( i>V_upb(v) || i<V_lwb(v) )
X    _error("V_elem: index %d is out of range [%d:%d]",i,V_lwb(v),V_upb(v));
X  return v->ptr + (i-V_lwb(v));
X}
X
X
X/*
X *=======================================================================
X *			   VECTOR assignments
X */
X
X
X/*
X *		      Clear all the vector elements
X *
X */
X
Xvoid V_clear(v)
XVECTOR v;   	      
X{
X  register int i;
X  register V$elem_type *p = V_body(v);
X
X  for(i=V_no_elems(v); --i >=0;)
X     *p++ = 0;
X}
X
X
X/*
X *		   Set all the vector elements to a given value
X *
X */
X
Xvoid V_setto(v,val)
XVECTOR v;   			   
Xconst double val;                          
X{
X  register int i;
X  register V$elem_type *p = V_body(v);
X
X  for(i=V_no_elems(v); --i >= 0;)
X     *p++ = val;
X}
X
X/*
X *		       Assign one vector to another
X *
X */
X
Xvoid V_assign(dest,src)
XVECTOR dest;   					/* Destination		*/
Xconst VECTOR src;                               /* Source		*/
X{
X  register int i;
X  register V$elem_type *p = V_body(dest);
X  register V$elem_type *q = V_body(src);
X
X  V_are_compatible(dest,src);
X
X  for(i=V_no_elems(src); --i >= 0;)
X     (*p++) = (*q++);
X
X}
________This_Is_The_END________
if test `wc -l < vec_base.c` -ne 167; then
echo 'shar: vec_base.c was damaged during transit (should have had 167 lines)'
fi


echo 'x - vec_norm.c'
sed 's/^X//' << '________This_Is_The_END________' > vec_norm.c
X/*
X ************************************************************************
X *			    VECTOR of floats
X * 		       Compute various vector norms
X *			  and the scalar product
X */
X
X#include "vector.h"
X
X#include "math.h"
X
X
Xdouble V_1_norm(v)		/* SUM[ |vi| ]				*/
Xconst VECTOR v;
X{
X  register int i;
X  register V$elem_type *p = V_body(v);
X  register double vi;
X  double sum = 0;
X
X  for(i=V_no_elems(v); --i >=0;)
X  {
X     vi = *p++;
X     sum += ( vi<0 ? -vi : vi );
X  }
X
X  return sum;
X}
X
X
Xdouble V_2_norm(v)		/* MAX[ |vi| ]				*/
Xconst VECTOR v;
X{
X  register int i;
X  register V$elem_type *p = V_body(v);
X  register double vi;
X  double max = -HUGE_VAL;
X
X  for(i=V_no_elems(v); --i >= 0;)
X  {
X     vi = *p++;
X     if( vi < 0 )
X       vi = -vi;
X     if( vi > max )
X       max = vi;
X  }
X
X  return max;
X}
X
X
Xdouble V_e2_norm(v)		/* SUM[ vi^2 ]				*/
Xconst VECTOR v;
X{
X  register int i;
X  register V$elem_type *p = V_body(v);
X  register double vi;
X  double sum = 0;
X
X  for(i=V_no_elems(v); --i >= 0;)
X  {
X     vi = *p++;
X     sum += vi*vi;
X  }
X
X  return sum;
X}
X
X
Xdouble V_diff_e2_norm(v1,v2)	/* SUM[ (v1i-v2i)^2 ]	   		*/
Xconst VECTOR v1,v2;
X{
X  register int i;
X  register V$elem_type *p = V_body(v1);
X  register V$elem_type *q = V_body(v2);
X  register double vi;
X  double sum = 0;
X
X  V_are_compatible(v1,v2);
X
X  for(i=V_no_elems(v1); --i >= 0;)
X  {
X     vi = (*p++) - (*q++);
X     sum += vi*vi;
X  }
X
X  return sum;
X}
X
X
Xdouble V_scalar_prod(v1,v2)	/* SUM[ v1i*v2i ]	   		*/
Xconst VECTOR v1,v2;
X{
X  register int i;
X  register V$elem_type *p = V_body(v1);
X  register V$elem_type *q = V_body(v2);
X  double sum = 0;
X
X  V_are_compatible(v1,v2);
X
X  for(i=V_no_elems(v1); --i >= 0;)
X     sum += (*p++) * (*q++);
X
X  return sum;
X}
________This_Is_The_END________
if test `wc -l < vec_norm.c` -ne 105; then
echo 'shar: vec_norm.c was damaged during transit (should have had 105 lines)'
fi


echo 'x - vec_serv.c'
sed 's/^X//' << '________This_Is_The_END________' > vec_serv.c
X/*
X ************************************************************************
X *			    VECTOR of floats
X * 		   	 Some service functions
X */
X
X#include "vector.h"
X#include "math.h"
X#include <stdio.h>
X
X
X/*
X *	Compare two vectors
X */
X
Xvoid V_compare(v1,v2,msg)
Xconst VECTOR v1,v2;			/* Vectors to be compared	*/
Xconst char * msg;			/* Explanation message		*/
X{
X  double max_disc = -1;			/* Maximal discrepancy		*/
X  int index_max_disc;			/*    index for the corr. element*/
X  register int i;
X
X  printf("\n\nCompare two [%d:%d] vectors - %s\n",
X	  V_lwb(v1), V_upb(v1), msg);
X  V_are_compatible(v1,v2);
X
X  for(i=V_lwb(v1); i<=V_upb(v1); i++)
X  {
X    double delta = fabs( *V_elem(v1,i) - *V_elem(v2,i) );
X    if( delta > max_disc )
X    {
X	max_disc = delta;
X	index_max_disc = i;
X    }
X  }
X
X  printf("\nMaximal discrepancy    \t\t%g",max_disc);
X  printf("\n   reached at point no.\t\t%d",index_max_disc);
X  {
X    double v1i = *V_elem(v1,index_max_disc);
X    double v2i = *V_elem(v2,index_max_disc);
X    printf("\n Vector 1 at this point    \t\t%g",v1i);
X    printf("\n Vector 2 at this point    \t\t%g",v2i);
X    printf("\n Absolute error v2[i]-v1[i]\t\t%g",v2i-v1i);
X    printf("\n Relative error\t\t\t\t%g\n",
X		(v2i-v1i)/fmax(fabs(v2i+v1i)/2,1e-7) );
X  }
X  {
X    double v1n = sqrt( V_e2_norm(v1) );
X    double v2n = sqrt( V_e2_norm(v2) );
X    double vdn = sqrt( V_diff_e2_norm(v1,v2) );
X    printf("\n||v1||   \t\t\t%g",v1n);
X    printf("\n||v2||   \t\t\t%g",v2n);
X    printf("\n||v1-v2||\t\t\t\t%g",vdn);
X    printf("\n||v1-v2||/sqrt(||v1|| ||v2||)\t\t%g",
X           vdn/fmax( sqrt(v1n*v2n), 1e-7 )         );
X  }
X
X}
X
X
X 
X/*
X *	Print a vector
X */
X
Xvoid V_print(v,msg)
Xconst VECTOR v;				/* Vector to be printed		*/
Xconst char * msg;			/* Explanation message		*/
X{
X  const int elems_per_line = 10;	/* No. of elems per line	*/
X  extern const char _Minuses[];
X  register int i,j,k;
X
X  printf("\n\nvector [%d:%d] - %s\n\n",V_lwb(v),V_upb(v),msg);
X  for(i=V_lwb(v); i<=V_upb(v); i+=elems_per_line)
X  {
X    k = imin(i+elems_per_line-1,V_upb(v)); /* Index for the last elem at line*/
X    for(j=i; j<=k; j++)			/* Print indices		*/
X       printf("%6d\t",j);
X    printf("\n%s\n",_Minuses);
X    
X    for(j=i; j<=k; j++)			/* Print values 		*/
X       printf("%6g\t",*V_elem(v,j));
X    printf("\n\n");
X  }
X}
X  
________This_Is_The_END________
if test `wc -l < vec_serv.c` -ne 89; then
echo 'shar: vec_serv.c was damaged during transit (should have had 89 lines)'
fi


echo 'x - vvector.c'
sed 's/^X//' << '________This_Is_The_END________' > vvector.c
X/*		Test for VECTOR managing routines		*/
X
X#include "vector.h"
X
X
Xtest_alloc()			/* Vector allocating			*/
X{
X /* Vector(v1,1,20); */
X  VECTOR v1, v2, v3, v4;
X
X  printf("\n\n\tTest vector allocating\n");
X
X  v1 = V_new(1,20);
X  v2 = V_new(1,20);
X  v3 = V_new(0,19);
X  printf("\nv1 is declared as automatic [1:20] vector");
X  printf("\nv2[1:20] and v3[0:19] have been constructed dynamically");
X  V_are_compatible(v1,v2);
X  printf("\nv1 and v2 are compatible");
X  V_free(v2);
X  printf("\nv2 has been freed");
X
X  printf("\nv2 is builded with values (1,2,3,4,5)\n");
X  v2 = V_build(1,5,1.,2.,3.,4.,5.,"END");
X  V_print(v2,"vector created");
X
X  printf("\nInvalid call to V_build: V_build(1,5,1,2.,3.,4.,5.,\"END\")\n");
X  v2 = V_build(1,5,1,2.,3.,4.,5.,"END");
X
X/*
X  printf("\nAn attempt to compare v1 and v3");
X  V_are_compatible(v1,v3);
X  
X  printf("\nAn attempt to free automatic vector v1");
X  V_free(v1);
X */
X}
X
X
Xtest_base()			/* Test base vector operations		*/
X{
X  VECTOR v, v1, v2;
X  double norm;
X
X  printf("\n\nTest base VECTOR operations\n");
X
X  v = V_new(1,10);
X/*  v1 = V_new(2,10); */
X  v1 = V_new(1,10);
X  printf("\nCreated vectors v[%d:%d], v1[%d:%d]", 
X	V_lwb(v),V_upb(v),V_lwb(v1),V_upb(v1));
X
X  V_clear(v);
X  V_print(v,"v after clear");
X
X  V_setto(v1,4.2);
X  V_print(v1,"v1 after all elements are set to 4.2");
X
X  V_assign(v,v1);
X  V_print(v,"v after assignments v=v1");
X  V_print(v1,"v1 after assignments v=v1");
X
X  V_setto(v,-2);
X  *V_elem(v,2) = 4;
X  V_print(v,"v after been set to -2.0 and v[2]=4");
X  printf("\n1. norm of v	= %g",V_1_norm(v));
X  printf("\n2. norm of v	= %g",V_2_norm(v));
X  printf("\nE. norm of v ^2	= %g",V_e2_norm(v));
X  printf("\ncomputed via v*v	= %g",V_scalar_prod(v,v));
X  printf("\n||v-v1||^2		= %g",V_diff_e2_norm(v,v1));
X
X  printf("\n Scalar prod. v*v1	= %g",V_scalar_prod(v,v1));
X
X  V_compare(v,v1,"Compare v and v1");
X
X  printf("\nAn attempt to access 13. element of v1");
X  V_elem(v1,13);
X}
X
X
Xmain()
X{
X  test_alloc();
X  test_base();
X}
________This_Is_The_END________
if test `wc -l < vvector.c` -ne 85; then
echo 'shar: vvector.c was damaged during transit (should have had 85 lines)'
fi


echo 'x - vvector.dat'
sed 's/^X//' << '________This_Is_The_END________' > vvector.dat
X
X
X	Test vector allocating
X
Xv1 is declared as automatic [1:20] vector
Xv2[1:20] and v3[0:19] have been constructed dynamically
Xv1 and v2 are compatible
Xv2 has been freed
Xv2 is builded with values (1,2,3,4,5)
X
X
Xvector [1:5] - vector created
X
X     1	     2	     3	     4	     5	
X-------------------------------------------------------------------------------
X     1	     2	     3	     4	     5	
X
X
XInvalid call to V_build: V_build(1,5,1,2.,3.,4.,5.,"END")
X
X
XTest base VECTOR operations
X
XCreated vectors v[1:10], v1[1:10]
X
Xvector [1:10] - v after clear
X
X     1	     2	     3	     4	     5	     6	     7	     8	     9	    10	
X-------------------------------------------------------------------------------
X     0	     0	     0	     0	     0	     0	     0	     0	     0	     0	
X
X
X
Xvector [1:10] - v1 after all elements are set to 4.2
X
X     1	     2	     3	     4	     5	     6	     7	     8	     9	    10	
X-------------------------------------------------------------------------------
X   4.2	   4.2	   4.2	   4.2	   4.2	   4.2	   4.2	   4.2	   4.2	   4.2	
X
X
X
Xvector [1:10] - v after assignments v=v1
X
X     1	     2	     3	     4	     5	     6	     7	     8	     9	    10	
X-------------------------------------------------------------------------------
X   4.2	   4.2	   4.2	   4.2	   4.2	   4.2	   4.2	   4.2	   4.2	   4.2	
X
X
X
Xvector [1:10] - v1 after assignments v=v1
X
X     1	     2	     3	     4	     5	     6	     7	     8	     9	    10	
X-------------------------------------------------------------------------------
X   4.2	   4.2	   4.2	   4.2	   4.2	   4.2	   4.2	   4.2	   4.2	   4.2	
X
X
X
Xvector [1:10] - v after been set to -2.0 and v[2]=4
X
X     1	     2	     3	     4	     5	     6	     7	     8	     9	    10	
X-------------------------------------------------------------------------------
X    -2	     4	    -2	    -2	    -2	    -2	    -2	    -2	    -2	    -2	
X
X
X1. norm of v	= 22
X2. norm of v	= 4
XE. norm of v ^2	= 52
Xcomputed via v*v	= 52
X||v-v1||^2		= 346
X Scalar prod. v*v1	= -58.8
X
XCompare two [1:10] vectors - Compare v and v1
X
XMaximal discrepancy    		6.2
X   reached at point no.		1
X Vector 1 at this point    		-2
X Vector 2 at this point    		4.2
X Absolute error v2[i]-v1[i]		6.2
X Relative error				5.63636
X
X||v1||   			7.2111
X||v2||   			13.2816
X||v1-v2||				18.6011
X||v1-v2||/sqrt(||v1|| ||v2||)		1.9007
XAn attempt to access 13. element of v1
________This_Is_The_END________
if test `wc -l < vvector.dat` -ne 85; then
echo 'shar: vvector.dat was damaged during transit (should have had 85 lines)'
fi



