void vhatg_c ( ConstSpiceDouble * v1, SpiceInt ndim, SpiceDouble * vout ) /* -Brief_I/O VARIABLE I/O DESCRIPTION -------- --- -------------------------------------------------- v1 I Vector to be normalized. ndim I Dimension of v1 (and also vout). vout O Unit vector v1 / |v1|. If v1 = 0, vout will also be zero. vout can overwrite v1. -Detailed_Input v1 This is any double precision vector of arbitrary dimension. This routine will detect if is V1 the zero vector, and will not attempt to divide by zero. ndim is the dimension of V1 (and also VOUT). -Detailed_Output vout contains the unit vector in the direction of v1. If v1 represents the zero vector, then vout will also be the zero vector. vout may overwrite v1. -Parameters None. -Particulars vhatg_c determines the magnitude of V1 and then divides each component of V1 by the magnitude. This process is highly stable over the whole range of multi-dimensional vectors. -Examples The following table shows how selected v1 maps to vout. v1 ndim vout ----------------------------------------------------------------- (5, 12, 0, 0) 4 (5/13, 12/13, 0, 0) (1e-7, 2D-e, 2e-7) 3 (1/3, 2/3, 2/3) -Restrictions The relative number of cases whereby floating point overflow may occur is negligible. Thus, no error recovery or reporting scheme is incorporated into this subroutine. -Exceptions Error free. -Files None. -Author_and_Institution N.J. Bachman (JPL) W.M. Owen (JPL) -Literature_References None. -Version -CSPICE Version 1.0.0, 13-JUL-1999 (NJB) (WMO) -Index_Entries unitize a n-dimensional vector -& */ { /* Begin vhatg_c */ /* Local variables */ SpiceDouble vmag; SpiceInt i; /* Obtain the magnitude of v1. */ vmag = vnormg_c ( v1, ndim ); /* If vmag is nonzero, then normalize. Note that this process is numerically stable: overflow could only happen if vmag were small, but this could only happen if each component of v1 were small. In fact, the magnitude of any vector is never less than the magnitude of any component. */ if ( vmag > 0.0 ) { for ( i = 0; i < ndim; i++ ) { vout[i] = v1[i] / vmag; } } else { for ( i = 0; i < ndim; i++ ) { vout[i] = 0.; } } } /* End vhatg_c */
SpiceDouble vrelg_c ( ConstSpiceDouble * v1, ConstSpiceDouble * v2, SpiceInt ndim ) /* -Brief_I/O Variable I/O Description -------- --- -------------------------------------------------- v1,v2 I Input vectors. ndim I Dimension of v1 and v2. -Detailed_Input v1, v2 are two vectors for which the relative difference is to be computed. ndim is the dimension of v1 and v2. -Detailed_Output vrelg_c is the relative difference between v1 and v2. It is defined as: || v1 - v2 || vrelg_c = ---------------------- max ( ||v1||, ||v2|| ) where || x || indicates the euclidean norm of the vector x ( ||x|| = sqrt( x . x ) ). vrelg_c assumes values in the range [0,2]. If both v1 and v2 are zero vectors then vrelg_c is defined to be zero. -Parameters None. -Exceptions Error free. If both v1 and v2 are zero vectors then vrelg_c is defined to be zero. -Files None. -Particulars This function computes the relative difference between two vectors of general dimension as defined above. The function vrel_c may be used to find the relative difference for two 3-dimensional vectors. -Examples This example determines if the state of Jupiter, with respect to Voyager 2, for a set of times is the same for two different ephemeris files. Instead of insisting on absolute equality between the state vectors, the program will check if the relative difference between the vectors is greater than a fixed tolerance. #include "SpiceUsr.h" . . . /. The NAIF code for Jupiter is 599 and for Voyager 2 is -32. Set the tolerance to be 0.0005. ./ #define NUM 500 #define JUP 599 #define VG2 -32 #define TOL .0005 /. Local variables ./ SpiceDouble state1 [6][NUM]; SpiceDouble state2 [6][NUM]; SpiceDouble et [NUM]; SpiceDouble lt; SpiceDouble diff; SpiceInt i; . . . /. Load the first SPK file. ./ furnsh_c ( "VG2_SOURCE_1.BSP" ); /. Find the states for each time in the array ET. This example assumes that the SPK file can provide states for all of the times in the array. ./ for ( i = 0; i < NUM; i++ ) { spkez_c ( JUP, et[i], "J2000", "lt", VG2, state1[1][i], < ); } /. Unload the first file and load the second one. ./ unload_c ( "VG2_SOURCE_1.BSP" ); furnsh_c ( "VG2_SOURCE_2.BSP" ); /. Find the states from the new file. ./ for ( i = 0; i < NUM; i++ ) { spkez_c ( JUP, et[i], "J2000", "lt", VG2, state2[1][i], < ); } /. Now compare the two state vectors for each time. ./ for ( i = 0; i < NUM; i++ ) { diff = vrelg_c ( state1[1][i], state2[1][i], 6 ); if ( diff > TOL ) { ... } -Restrictions None. -Literature_References None. -Author_and_Institution J.M. Lynch (JPL) E.D. Wright (JPL) -Version -CSPICE Version 1.1.0, 28-AUG-2001 (NJB) Include interface macro definition file SpiceZim.h. Made some minor updates and corrections in the code example. -CSPICE Version 1.0.0, 6-JUL-1999 -Index_Entries relative difference of n-dimensional vectors -& */ { /* Begin vrelg_c */ /* Local variables */ SpiceDouble nunorm; SpiceDouble denorm; /* If the vectors are both zero or equivalent, return 0. */ nunorm = vdistg_c ( v1, v2, ndim ); if ( nunorm == 0. ) { return 0.; } else { denorm = MaxVal( vnormg_c( v1, ndim ), vnormg_c( v2, ndim ) ); return ( nunorm/denorm ); } } /* End vrelg_c */
SpiceDouble vsepg_c ( ConstSpiceDouble * v1, ConstSpiceDouble * v2, SpiceInt ndim ) /* -Brief_I/O VARIABLE I/O DESCRIPTION -------- --- -------------------------------------------------- v1 I First vector. v2 I Second vector. ndim I The number of elements in v1 and v2. -Detailed_Input v1 is any double precision vector of arbitrary dimension. v2 is also a double precision vector of arbitrary dimension. v1 or v2 or both may be the zero vector. ndim is the dimension of the both of the input vectors v1 and v2. -Detailed_Output vsepg_c the angle between v1 and v2 expressed in radians. vsepg_c is strictly non-negative. For input vectors of four or more dimensions, the angle is defined as the generalization of the definition for three dimensions. If either v1 or v2 is the zero vector, then vsepg_c is defined to be 0 radians. -Parameters None. -Particulars In four or more dimensions this angle does not have a physically realizable interpretation. However, the angle is defined as the generalization of the following definition which is valid in three or two dimensions: In the plane, it is a simple matter to calculate the angle between two vectors once the two vectors have been made to be unit length. Then, since the two vectors form the two equal sides of an isosceles triangle, the length of the third side is given by the expression length = 2.0 * sine ( vsepg/2.0 ) The length is given by the magnitude of the difference of the two unit vectors length = norm ( u1 - u2 ) Once the length is found, the value of vsepg_c may be calculated by inverting the first expression given above as vsepg_c = 2.0 * arcsine ( length/2.0 ) This expression becomes increasingly unstable when vsepg_c gets larger than pi/2 or 90 degrees. In this situation (which is easily detected by determining the sign of the dot product of v1 and v2) the supplementary angle is calculated first and then vsepg_c is given by vsepg_c = pi - SUPPLEMENTARY_ANGLE -Examples The following table gives sample values for v1, v2 and vsepg_c implied by the inputs. v1 v2 ndim vsepg_c ----------------------------------------------------------------- (1, 0, 0, 0) (1, 0, 0, 0) 4 0.0 (1, 0, 0) (0, 1, 0) 3 pi/2 (=1.71...) (3, 0) (-5, 0) 2 pi (=3.14...) -Restrictions The user is required to insure that the input vectors will not cause floating point overflow upon calculation of the vector dot product since no error detection or correction code is implemented. In practice, this is not a significant restriction. -Exceptions Error free. -Files None -Author_and_Institution C.A. Curzon (JPL) K.R. Gehringer (JPL) H.A. Neilan (JPL) W.L. Taber (JPL) E.D. Wright (JPL) -Literature_References None -Version -CSPICE Version 1.0.0, 29-JUN-1999 -Index_Entries angular separation of n-dimensional vectors -& */ { /* Begin vsepg_c */ /* Local variables */ SpiceDouble mag1; SpiceDouble mag2; SpiceDouble mag_dif; SpiceDouble r1; SpiceDouble r2; SpiceInt i; mag1 = vnormg_c( v1, ndim); mag2 = vnormg_c( v2, ndim); /* If either v1 or v2 have magnitude zero, the separation is 0. */ if ( ( mag1 == 0.) || ( mag2 == 0.) ) { return 0; } if ( vdotg_c( v1, v2, ndim ) < 0. ) { r1 = 1./mag1; r2 = 1./mag2; mag_dif = 0.; for ( i = 0; i < ndim; i++ ) { mag_dif += pow( ( v1[i]*r1 - v2[i]*r2 ), 2); } mag_dif = sqrt(mag_dif); return ( 2. * asin (0.5 * mag_dif) ); } else if ( vdotg_c (v1, v2, ndim) > 0. ) { r1 = 1./mag1; r2 = 1./mag2; mag_dif = 0.; for ( i = 0; i < ndim; i++ ) { mag_dif += pow( ( v1[i]*r1 + v2[i]*r2 ), 2); } mag_dif = sqrt(mag_dif); return ( pi_c() - 2. * asin (0.5 * mag_dif) ); } return ( halfpi_c()); } /* End vsepg_c */
void unormg_c ( ConstSpiceDouble * v1, SpiceInt ndim, SpiceDouble * vout, SpiceDouble * vmag ) /* -Brief_I/O VARIABLE I/O DESCRIPTION -------- --- -------------------------------------------------- v1 I Vector to be normalized. ndim I Dimension of v1 (and also vout). vout O Unit vector v1 / |v1|. If v1 = 0, vout will also be zero. vout can overwrite v1. vmag O Magnitude of v1, that is, |v1|. -Detailed_Input v1 This variable may contain any vector of arbitrary dimension, including the zero vector. ndim This is the dimension of v1 and vout. -Detailed_Output vout This variable contains the unit vector in the direction of v1. If v1 is the zero vector, then vout will also be the zero vector. vmag This is the magnitude of v1. -Parameters None. -Particulars unormg_c references a function called vnormg_c (which itself is numerically stable) to calculate the norm of the input vector v1. If the norm is equal to zero, then each component of the output vector vout is set to zero. Otherwise, vout is calculated by dividing v1 by the norm. No error detection or correction is implemented. -Examples The following table shows how selected v1 implies vout and mag. v1 ndim vout mag ----------------------------------------------------------------- (5, 12) 2 (5/13, 12/13) 13 (1D-7, 2D-7, 2D-7) 3 (1/3, 2/3, 2/3) 3D-7 -Restrictions No error checking is implemented in this subroutine to guard against numeric overflow. -Exceptions 1) If ndim is not physically realistic, greater than zero, a BADDIMENSION error is flagged. -Files None. -Author_and_Institution W.M. Owen (JPL) W.L. Taber (JPL) E.D. Wright (JPL) -Literature_References None. -Version -CSPICE Version 1.1.0, 22-OCT-1998 (NJB) Made input vector const. Converted check-in style to discovery. -CSPICE Version 1.0.0, 31-MAR-1998 (EDW) -Index_Entries n-dimensional unit vector and norm -& */ { /* Begin unormg_c */ /* Local variables */ SpiceInt i; /* Use discovery check-in. */ /* Check ndim is cool. Dimension is positive definite. */ if ( ndim <= 0 ) { chkin_c ( "unormg_c" ); SpiceError ( "Vector dimension less than or equal to zero", "BADDIMENSION" ); chkout_c ( "unormg_c" ); return; } /* Get the magnitude of the vector. */ *vmag = vnormg_c ( v1, ndim ); /* If vmag is nonzero, then normalize. Note that this process is numerically stable: overflow could only happen if vmag were small, but this could only happen if each component of v1 were also small. In fact, the magnitude of any vector is never less than the magnitude of any component. */ if ( *vmag > 0. ) { for ( i = 0; i < ndim; i++ ) { vout[i] = v1[i]/ (*vmag); } } else { for ( i = 0; i < ndim ; i++ ); { vout[i] = 0.; } } } /* End unormg_c */