source: src/SingleVector.cpp@ 72e7fa

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 72e7fa was 72e7fa, checked in by Tillmann Crueger <crueger@…>, 15 years ago

Started work on the VectorComposites

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