source: src/SingleVector.cpp@ 273382

Action_Thermostats Add_AtomRandomPerturbation Add_FitFragmentPartialChargesAction Add_RotateAroundBondAction Add_SelectAtomByNameAction Added_ParseSaveFragmentResults AddingActions_SaveParseParticleParameters Adding_Graph_to_ChangeBondActions Adding_MD_integration_tests Adding_ParticleName_to_Atom Adding_StructOpt_integration_tests AtomFragments Automaking_mpqc_open AutomationFragmentation_failures Candidate_v1.5.4 Candidate_v1.6.0 Candidate_v1.6.1 ChangeBugEmailaddress ChangingTestPorts ChemicalSpaceEvaluator CombiningParticlePotentialParsing Combining_Subpackages Debian_Package_split Debian_package_split_molecuildergui_only Disabling_MemDebug Docu_Python_wait EmpiricalPotential_contain_HomologyGraph EmpiricalPotential_contain_HomologyGraph_documentation Enable_parallel_make_install Enhance_userguide Enhanced_StructuralOptimization Enhanced_StructuralOptimization_continued Example_ManyWaysToTranslateAtom Exclude_Hydrogens_annealWithBondGraph FitPartialCharges_GlobalError Fix_BoundInBox_CenterInBox_MoleculeActions Fix_ChargeSampling_PBC Fix_ChronosMutex Fix_FitPartialCharges Fix_FitPotential_needs_atomicnumbers Fix_ForceAnnealing Fix_IndependentFragmentGrids Fix_ParseParticles Fix_ParseParticles_split_forward_backward_Actions Fix_PopActions Fix_QtFragmentList_sorted_selection Fix_Restrictedkeyset_FragmentMolecule Fix_StatusMsg Fix_StepWorldTime_single_argument Fix_Verbose_Codepatterns Fix_fitting_potentials Fixes ForceAnnealing_goodresults ForceAnnealing_oldresults ForceAnnealing_tocheck ForceAnnealing_with_BondGraph ForceAnnealing_with_BondGraph_continued ForceAnnealing_with_BondGraph_continued_betteresults ForceAnnealing_with_BondGraph_contraction-expansion FragmentAction_writes_AtomFragments FragmentMolecule_checks_bonddegrees GeometryObjects Gui_Fixes Gui_displays_atomic_force_velocity ImplicitCharges IndependentFragmentGrids IndependentFragmentGrids_IndividualZeroInstances IndependentFragmentGrids_IntegrationTest IndependentFragmentGrids_Sole_NN_Calculation JobMarket_RobustOnKillsSegFaults JobMarket_StableWorkerPool JobMarket_unresolvable_hostname_fix MoreRobust_FragmentAutomation ODR_violation_mpqc_open PartialCharges_OrthogonalSummation PdbParser_setsAtomName PythonUI_with_named_parameters QtGui_reactivate_TimeChanged_changes Recreated_GuiChecks Rewrite_FitPartialCharges RotateToPrincipalAxisSystem_UndoRedo SaturateAtoms_findBestMatching SaturateAtoms_singleDegree StoppableMakroAction Subpackage_CodePatterns Subpackage_JobMarket Subpackage_LinearAlgebra Subpackage_levmar Subpackage_mpqc_open Subpackage_vmg Switchable_LogView ThirdParty_MPQC_rebuilt_buildsystem TrajectoryDependenant_MaxOrder TremoloParser_IncreasedPrecision TremoloParser_MultipleTimesteps TremoloParser_setsAtomName Ubuntu_1604_changes stable
Last change on this file since 273382 was 273382, checked in by Tillmann Crueger <crueger@…>, 15 years ago

Prepared interface of Vector Class for transition to VectorComposites

  • Property mode set to 100644
File size: 16.9 KB
Line 
1/** \file vector.cpp
2 *
3 * Function implementations for the class vector.
4 *
5 */
6
7
8#include "defs.hpp"
9#include "gslmatrix.hpp"
10#include "leastsquaremin.hpp"
11#include "memoryallocator.hpp"
12#include "SingleVector.hpp"
13#include "Helpers/fast_functions.hpp"
14#include "Helpers/Assert.hpp"
15#include "Plane.hpp"
16#include "Exceptions/LinearDependenceException.hpp"
17
18#include <gsl/gsl_linalg.h>
19#include <gsl/gsl_matrix.h>
20#include <gsl/gsl_permutation.h>
21#include <gsl/gsl_vector.h>
22
23/************************************ Functions for class vector ************************************/
24
25/** Constructor of class vector.
26 */
27SingleVector::SingleVector()
28{
29 x[0] = x[1] = x[2] = 0.;
30};
31
32/** Constructor of class vector.
33 */
34SingleVector::SingleVector(const double x1, const double x2, const double x3)
35{
36 x[0] = x1;
37 x[1] = x2;
38 x[2] = x3;
39};
40
41/**
42 * Copy constructor
43 */
44SingleVector::SingleVector(const Vector& src)
45{
46 x[0] = src[0];
47 x[1] = src[1];
48 x[2] = src[2];
49}
50
51/**
52 * Assignment operator
53 */
54Vector& SingleVector::operator=(const Vector& src){
55 // check for self assignment
56 if(&src!=this){
57 x[0] = src[0];
58 x[1] = src[1];
59 x[2] = src[2];
60 }
61 return *this;
62}
63
64/** Desctructor of class vector.
65 */
66SingleVector::~SingleVector() {};
67
68/** Calculates square of distance between this and another vector.
69 * \param *y array to second vector
70 * \return \f$| x - y |^2\f$
71 */
72double SingleVector::DistanceSquared(const Vector &y) const
73{
74 double res = 0.;
75 for (int i=NDIM;i--;)
76 res += (x[i]-y[i])*(x[i]-y[i]);
77 return (res);
78};
79
80/** Calculates distance between this and another vector.
81 * \param *y array to second vector
82 * \return \f$| x - y |\f$
83 */
84double SingleVector::Distance(const Vector &y) const
85{
86 double res = 0.;
87 for (int i=NDIM;i--;)
88 res += (x[i]-y[i])*(x[i]-y[i]);
89 return (sqrt(res));
90};
91
92/** Calculates distance between this and another vector in a periodic cell.
93 * \param *y array to second vector
94 * \param *cell_size 6-dimensional array with (xx, xy, yy, xz, yz, zz) entries specifying the periodic cell
95 * \return \f$| x - y |\f$
96 */
97double SingleVector::PeriodicDistance(const Vector &y, const double * const cell_size) const
98{
99 double res = Distance(y), tmp, matrix[NDIM*NDIM];
100 Vector Shiftedy, TranslationVector;
101 int N[NDIM];
102 matrix[0] = cell_size[0];
103 matrix[1] = cell_size[1];
104 matrix[2] = cell_size[3];
105 matrix[3] = cell_size[1];
106 matrix[4] = cell_size[2];
107 matrix[5] = cell_size[4];
108 matrix[6] = cell_size[3];
109 matrix[7] = cell_size[4];
110 matrix[8] = cell_size[5];
111 // in order to check the periodic distance, translate one of the vectors into each of the 27 neighbouring cells
112 for (N[0]=-1;N[0]<=1;N[0]++)
113 for (N[1]=-1;N[1]<=1;N[1]++)
114 for (N[2]=-1;N[2]<=1;N[2]++) {
115 // create the translation vector
116 TranslationVector.Zero();
117 for (int i=NDIM;i--;)
118 TranslationVector[i] = (double)N[i];
119 TranslationVector.MatrixMultiplication(matrix);
120 // add onto the original vector to compare with
121 Shiftedy = y + TranslationVector;
122 // get distance and compare with minimum so far
123 tmp = Distance(Shiftedy);
124 if (tmp < res) res = tmp;
125 }
126 return (res);
127};
128
129/** Calculates distance between this and another vector in a periodic cell.
130 * \param *y array to second vector
131 * \param *cell_size 6-dimensional array with (xx, xy, yy, xz, yz, zz) entries specifying the periodic cell
132 * \return \f$| x - y |^2\f$
133 */
134double SingleVector::PeriodicDistanceSquared(const Vector &y, const double * const cell_size) const
135{
136 double res = DistanceSquared(y), tmp, matrix[NDIM*NDIM];
137 Vector Shiftedy, TranslationVector;
138 int N[NDIM];
139 matrix[0] = cell_size[0];
140 matrix[1] = cell_size[1];
141 matrix[2] = cell_size[3];
142 matrix[3] = cell_size[1];
143 matrix[4] = cell_size[2];
144 matrix[5] = cell_size[4];
145 matrix[6] = cell_size[3];
146 matrix[7] = cell_size[4];
147 matrix[8] = cell_size[5];
148 // in order to check the periodic distance, translate one of the vectors into each of the 27 neighbouring cells
149 for (N[0]=-1;N[0]<=1;N[0]++)
150 for (N[1]=-1;N[1]<=1;N[1]++)
151 for (N[2]=-1;N[2]<=1;N[2]++) {
152 // create the translation vector
153 TranslationVector.Zero();
154 for (int i=NDIM;i--;)
155 TranslationVector[i] = (double)N[i];
156 TranslationVector.MatrixMultiplication(matrix);
157 // add onto the original vector to compare with
158 Shiftedy = y + TranslationVector;
159 // get distance and compare with minimum so far
160 tmp = DistanceSquared(Shiftedy);
161 if (tmp < res) res = tmp;
162 }
163 return (res);
164};
165
166/** Keeps the vector in a periodic cell, defined by the symmetric \a *matrix.
167 * \param *out ofstream for debugging messages
168 * Tries to translate a vector into each adjacent neighbouring cell.
169 */
170void SingleVector::KeepPeriodic(const double * const matrix)
171{
172// int N[NDIM];
173// bool flag = false;
174 //vector Shifted, TranslationVector;
175 Vector TestVector;
176// Log() << Verbose(1) << "Begin of KeepPeriodic." << endl;
177// Log() << Verbose(2) << "Vector is: ";
178// Output(out);
179// Log() << Verbose(0) << endl;
180 TestVector = *this;
181 TestVector.InverseMatrixMultiplication(matrix);
182 for(int i=NDIM;i--;) { // correct periodically
183 if (TestVector[i] < 0) { // get every coefficient into the interval [0,1)
184 TestVector[i] += ceil(TestVector[i]);
185 } else {
186 TestVector[i] -= floor(TestVector[i]);
187 }
188 }
189 TestVector.MatrixMultiplication(matrix);
190 CopyVector(TestVector);
191// Log() << Verbose(2) << "New corrected vector is: ";
192// Output(out);
193// Log() << Verbose(0) << endl;
194// Log() << Verbose(1) << "End of KeepPeriodic." << endl;
195};
196
197/** Calculates scalar product between this and another vector.
198 * \param *y array to second vector
199 * \return \f$\langle x, y \rangle\f$
200 */
201double SingleVector::ScalarProduct(const Vector &y) const
202{
203 double res = 0.;
204 for (int i=NDIM;i--;)
205 res += x[i]*y[i];
206 return (res);
207};
208
209
210/** Calculates VectorProduct between this and another vector.
211 * -# returns the Product in place of vector from which it was initiated
212 * -# ATTENTION: Only three dim.
213 * \param *y array to vector with which to calculate crossproduct
214 * \return \f$ x \times y \f&
215 */
216void SingleVector::VectorProduct(const Vector &y)
217{
218 Vector tmp;
219 tmp[0] = x[1]* (y[2]) - x[2]* (y[1]);
220 tmp[1] = x[2]* (y[0]) - x[0]* (y[2]);
221 tmp[2] = x[0]* (y[1]) - x[1]* (y[0]);
222 (*this) = tmp;
223};
224
225
226/** projects this vector onto plane defined by \a *y.
227 * \param *y normal vector of plane
228 * \return \f$\langle x, y \rangle\f$
229 */
230void SingleVector::ProjectOntoPlane(const Vector &y)
231{
232 Vector tmp;
233 tmp = y;
234 tmp.Normalize();
235 tmp.Scale(ScalarProduct(tmp));
236 *this -= tmp;
237};
238
239/** Calculates the minimum distance of this vector to the plane.
240 * \param *out output stream for debugging
241 * \param *PlaneNormal normal of plane
242 * \param *PlaneOffset offset of plane
243 * \return distance to plane
244 */
245double SingleVector::DistanceToPlane(const Vector &PlaneNormal, const Vector &PlaneOffset) const
246{
247 Vector temp;
248
249 // first create part that is orthonormal to PlaneNormal with withdraw
250 temp = (*this )- PlaneOffset;
251 temp.MakeNormalTo(PlaneNormal);
252 temp.Scale(-1.);
253 // then add connecting vector from plane to point
254 temp += (*this)-PlaneOffset;
255 double sign = temp.ScalarProduct(PlaneNormal);
256 if (fabs(sign) > MYEPSILON)
257 sign /= fabs(sign);
258 else
259 sign = 0.;
260
261 return (temp.Norm()*sign);
262};
263
264/** Calculates the projection of a vector onto another \a *y.
265 * \param *y array to second vector
266 */
267void SingleVector::ProjectIt(const Vector &y)
268{
269 Vector helper = y;
270 helper.Scale(-(ScalarProduct(y)));
271 AddVector(helper);
272};
273
274/** Calculates the projection of a vector onto another \a *y.
275 * \param *y array to second vector
276 * \return Vector
277 */
278Vector SingleVector::Projection(const Vector &y) const
279{
280 Vector helper = y;
281 helper.Scale((ScalarProduct(y)/y.NormSquared()));
282
283 return helper;
284};
285
286/** Calculates norm of this vector.
287 * \return \f$|x|\f$
288 */
289double SingleVector::Norm() const
290{
291 double res = 0.;
292 for (int i=NDIM;i--;)
293 res += this->x[i]*this->x[i];
294 return (sqrt(res));
295};
296
297/** Calculates squared norm of this vector.
298 * \return \f$|x|^2\f$
299 */
300double SingleVector::NormSquared() const
301{
302 return (ScalarProduct(*this));
303};
304
305/** Normalizes this vector.
306 */
307void SingleVector::Normalize()
308{
309 double res = 0.;
310 for (int i=NDIM;i--;)
311 res += this->x[i]*this->x[i];
312 if (fabs(res) > MYEPSILON)
313 res = 1./sqrt(res);
314 Scale(&res);
315};
316
317/** Zeros all components of this vector.
318 */
319void SingleVector::Zero()
320{
321 for (int i=NDIM;i--;)
322 this->x[i] = 0.;
323};
324
325/** Zeros all components of this vector.
326 */
327void SingleVector::One(const double one)
328{
329 for (int i=NDIM;i--;)
330 this->x[i] = one;
331};
332
333/** Initialises all components of this vector.
334 */
335void SingleVector::Init(const double x1, const double x2, const double x3)
336{
337 x[0] = x1;
338 x[1] = x2;
339 x[2] = x3;
340};
341
342/** Checks whether vector has all components zero.
343 * @return true - vector is zero, false - vector is not
344 */
345bool SingleVector::IsZero() const
346{
347 return (fabs(x[0])+fabs(x[1])+fabs(x[2]) < MYEPSILON);
348};
349
350/** Checks whether vector has length of 1.
351 * @return true - vector is normalized, false - vector is not
352 */
353bool SingleVector::IsOne() const
354{
355 return (fabs(Norm() - 1.) < MYEPSILON);
356};
357
358/** Checks whether vector is normal to \a *normal.
359 * @return true - vector is normalized, false - vector is not
360 */
361bool SingleVector::IsNormalTo(const Vector &normal) const
362{
363 if (ScalarProduct(normal) < MYEPSILON)
364 return true;
365 else
366 return false;
367};
368
369/** Checks whether vector is normal to \a *normal.
370 * @return true - vector is normalized, false - vector is not
371 */
372bool SingleVector::IsEqualTo(const Vector &a) const
373{
374 bool status = true;
375 for (int i=0;i<NDIM;i++) {
376 if (fabs(x[i] - a[i]) > MYEPSILON)
377 status = false;
378 }
379 return status;
380};
381
382/** Calculates the angle between this and another vector.
383 * \param *y array to second vector
384 * \return \f$\acos\bigl(frac{\langle x, y \rangle}{|x||y|}\bigr)\f$
385 */
386double SingleVector::Angle(const Vector &y) const
387{
388 double norm1 = Norm(), norm2 = y.Norm();
389 double angle = -1;
390 if ((fabs(norm1) > MYEPSILON) && (fabs(norm2) > MYEPSILON))
391 angle = this->ScalarProduct(y)/norm1/norm2;
392 // -1-MYEPSILON occured due to numerical imprecision, catch ...
393 //Log() << Verbose(2) << "INFO: acos(-1) = " << acos(-1) << ", acos(-1+MYEPSILON) = " << acos(-1+MYEPSILON) << ", acos(-1-MYEPSILON) = " << acos(-1-MYEPSILON) << "." << endl;
394 if (angle < -1)
395 angle = -1;
396 if (angle > 1)
397 angle = 1;
398 return acos(angle);
399};
400
401
402double& SingleVector::operator[](size_t i){
403 ASSERT(i<=NDIM && i>=0,"Vector Index out of Range");
404 return x[i];
405}
406
407const double& SingleVector::operator[](size_t i) const{
408 ASSERT(i<=NDIM && i>=0,"Vector Index out of Range");
409 return x[i];
410}
411
412double& SingleVector::at(size_t i){
413 return (*this)[i];
414}
415
416const double& SingleVector::at(size_t i) const{
417 return (*this)[i];
418}
419
420double* SingleVector::get(){
421 return x;
422}
423/** Scales each atom coordinate by an individual \a factor.
424 * \param *factor pointer to scaling factor
425 */
426void SingleVector::Scale(const double ** const factor)
427{
428 for (int i=NDIM;i--;)
429 x[i] *= (*factor)[i];
430};
431
432void SingleVector::Scale(const double * const factor)
433{
434 for (int i=NDIM;i--;)
435 x[i] *= *factor;
436};
437
438void SingleVector::Scale(const double factor)
439{
440 for (int i=NDIM;i--;)
441 x[i] *= factor;
442};
443
444/** Translate atom by given vector.
445 * \param trans[] translation vector.
446 */
447void SingleVector::Translate(const Vector &trans)
448{
449 for (int i=NDIM;i--;)
450 x[i] += trans[i];
451};
452
453/** Given a box by its matrix \a *M and its inverse *Minv the vector is made to point within that box.
454 * \param *M matrix of box
455 * \param *Minv inverse matrix
456 */
457void SingleVector::WrapPeriodically(const double * const M, const double * const Minv)
458{
459 MatrixMultiplication(Minv);
460 // truncate to [0,1] for each axis
461 for (int i=0;i<NDIM;i++) {
462 x[i] += 0.5; // set to center of box
463 while (x[i] >= 1.)
464 x[i] -= 1.;
465 while (x[i] < 0.)
466 x[i] += 1.;
467 }
468 MatrixMultiplication(M);
469};
470
471/** Do a matrix multiplication.
472 * \param *matrix NDIM_NDIM array
473 */
474void SingleVector::MatrixMultiplication(const double * const M)
475{
476 Vector C;
477 // do the matrix multiplication
478 C[0] = M[0]*x[0]+M[3]*x[1]+M[6]*x[2];
479 C[1] = M[1]*x[0]+M[4]*x[1]+M[7]*x[2];
480 C[2] = M[2]*x[0]+M[5]*x[1]+M[8]*x[2];
481
482 *this = C;
483};
484
485/** Do a matrix multiplication with the \a *A' inverse.
486 * \param *matrix NDIM_NDIM array
487 */
488bool SingleVector::InverseMatrixMultiplication(const double * const A)
489{
490 Vector C;
491 double B[NDIM*NDIM];
492 double detA = RDET3(A);
493 double detAReci;
494
495 // calculate the inverse B
496 if (fabs(detA) > MYEPSILON) {; // RDET3(A) yields precisely zero if A irregular
497 detAReci = 1./detA;
498 B[0] = detAReci*RDET2(A[4],A[5],A[7],A[8]); // A_11
499 B[1] = -detAReci*RDET2(A[1],A[2],A[7],A[8]); // A_12
500 B[2] = detAReci*RDET2(A[1],A[2],A[4],A[5]); // A_13
501 B[3] = -detAReci*RDET2(A[3],A[5],A[6],A[8]); // A_21
502 B[4] = detAReci*RDET2(A[0],A[2],A[6],A[8]); // A_22
503 B[5] = -detAReci*RDET2(A[0],A[2],A[3],A[5]); // A_23
504 B[6] = detAReci*RDET2(A[3],A[4],A[6],A[7]); // A_31
505 B[7] = -detAReci*RDET2(A[0],A[1],A[6],A[7]); // A_32
506 B[8] = detAReci*RDET2(A[0],A[1],A[3],A[4]); // A_33
507
508 // do the matrix multiplication
509 C[0] = B[0]*x[0]+B[3]*x[1]+B[6]*x[2];
510 C[1] = B[1]*x[0]+B[4]*x[1]+B[7]*x[2];
511 C[2] = B[2]*x[0]+B[5]*x[1]+B[8]*x[2];
512
513 *this = C;
514 return true;
515 } else {
516 return false;
517 }
518};
519
520
521/** Creates this vector as the b y *factors' components scaled linear combination of the given three.
522 * this vector = x1*factors[0] + x2* factors[1] + x3*factors[2]
523 * \param *x1 first vector
524 * \param *x2 second vector
525 * \param *x3 third vector
526 * \param *factors three-component vector with the factor for each given vector
527 */
528void SingleVector::LinearCombinationOfVectors(const Vector &x1, const Vector &x2, const Vector &x3, const double * const factors)
529{
530 for(int i=NDIM;i--;)
531 x[i] = factors[0]*x1[i] + factors[1]*x2[i] + factors[2]*x3[i];
532};
533
534/** Mirrors atom against a given plane.
535 * \param n[] normal vector of mirror plane.
536 */
537void SingleVector::Mirror(const Vector &n)
538{
539 double projection;
540 projection = ScalarProduct(n)/n.NormSquared(); // remove constancy from n (keep as logical one)
541 // withdraw projected vector twice from original one
542 for (int i=NDIM;i--;)
543 x[i] -= 2.*projection*n[i];
544};
545
546
547/** Calculates orthonormal vector to one given vector.
548 * Just subtracts the projection onto the given vector from this vector.
549 * The removed part of the vector is Vector::Projection()
550 * \param *x1 vector
551 * \return true - success, false - vector is zero
552 */
553bool SingleVector::MakeNormalTo(const Vector &y1)
554{
555 bool result = false;
556 double factor = y1.ScalarProduct(*this)/y1.NormSquared();
557 Vector x1;
558 x1 = factor * y1;
559 SubtractVector(x1);
560 for (int i=NDIM;i--;)
561 result = result || (fabs(x[i]) > MYEPSILON);
562
563 return result;
564};
565
566/** Creates this vector as one of the possible orthonormal ones to the given one.
567 * Just scan how many components of given *vector are unequal to zero and
568 * try to get the skp of both to be zero accordingly.
569 * \param *vector given vector
570 * \return true - success, false - failure (null vector given)
571 */
572bool SingleVector::GetOneNormalVector(const Vector &GivenVector)
573{
574 int Components[NDIM]; // contains indices of non-zero components
575 int Last = 0; // count the number of non-zero entries in vector
576 int j; // loop variables
577 double norm;
578
579 for (j=NDIM;j--;)
580 Components[j] = -1;
581 // find two components != 0
582 for (j=0;j<NDIM;j++)
583 if (fabs(GivenVector[j]) > MYEPSILON)
584 Components[Last++] = j;
585
586 switch(Last) {
587 case 3: // threecomponent system
588 case 2: // two component system
589 norm = sqrt(1./(GivenVector[Components[1]]*GivenVector[Components[1]]) + 1./(GivenVector[Components[0]]*GivenVector[Components[0]]));
590 x[Components[2]] = 0.;
591 // in skp both remaining parts shall become zero but with opposite sign and third is zero
592 x[Components[1]] = -1./GivenVector[Components[1]] / norm;
593 x[Components[0]] = 1./GivenVector[Components[0]] / norm;
594 return true;
595 break;
596 case 1: // one component system
597 // set sole non-zero component to 0, and one of the other zero component pendants to 1
598 x[(Components[0]+2)%NDIM] = 0.;
599 x[(Components[0]+1)%NDIM] = 1.;
600 x[Components[0]] = 0.;
601 return true;
602 break;
603 default:
604 return false;
605 }
606};
607
608/**
609 * Checks whether this vector is within the parallelepiped defined by the given three vectors and
610 * their offset.
611 *
612 * @param offest for the origin of the parallelepiped
613 * @param three vectors forming the matrix that defines the shape of the parallelpiped
614 */
615bool SingleVector::IsInParallelepiped(const Vector &offset, const double * const parallelepiped) const
616{
617 Vector a = (*this) - offset;
618 a.InverseMatrixMultiplication(parallelepiped);
619 bool isInside = true;
620
621 for (int i=NDIM;i--;)
622 isInside = isInside && ((a[i] <= 1) && (a[i] >= 0));
623
624 return isInside;
625}
Note: See TracBrowser for help on using the repository browser.