3 * This source code is part of
7 * GROningen MAchine for Chemical Simulations
10 * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
11 * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
12 * Copyright (c) 2001-2004, The GROMACS development team,
13 * check out http://www.gromacs.org for more information.
15 * This program is free software; you can redistribute it and/or
16 * modify it under the terms of the GNU General Public License
17 * as published by the Free Software Foundation; either version 2
18 * of the License, or (at your option) any later version.
20 * If you want to redistribute modifications, please consider that
21 * scientific software is very special. Version control is crucial -
22 * bugs must be traceable. We will be happy to consider code for
23 * inclusion in the official distribution, but derived work must not
24 * be called official GROMACS. Details are found in the README & COPYING
25 * files - if they are missing, get the official version at www.gromacs.org.
27 * To help us fund GROMACS development, we humbly ask that you cite
28 * the papers on the package - you can find them in the top README file.
30 * For more info, check our website at http://www.gromacs.org
33 * Gromacs Runs On Most of All Computer Systems
41 #define gmx_inline inline
44 #define gmx_inline __inline
52 collection of in-line ready operations:
54 lookup-table optimized scalar operations:
55 real gmx_invsqrt(real x)
56 void vecinvsqrt(real in[],real out[],int n)
57 void vecrecip(real in[],real out[],int n)
62 void rvec_add(const rvec a,const rvec b,rvec c) c = a + b
63 void dvec_add(const dvec a,const dvec b,dvec c) c = a + b
64 void ivec_add(const ivec a,const ivec b,ivec c) c = a + b
65 void rvec_inc(rvec a,const rvec b) a += b
66 void dvec_inc(dvec a,const dvec b) a += b
67 void ivec_inc(ivec a,const ivec b) a += b
68 void rvec_sub(const rvec a,const rvec b,rvec c) c = a - b
69 void dvec_sub(const dvec a,const dvec b,dvec c) c = a - b
70 void rvec_dec(rvec a,rvec b) a -= b
71 void copy_rvec(const rvec a,rvec b) b = a (reals)
72 void copy_dvec(const dvec a,dvec b) b = a (reals)
73 void copy_ivec(const ivec a,ivec b) b = a (integers)
74 void ivec_sub(const ivec a,const ivec b,ivec c) c = a - b
75 void svmul(real a,rvec v1,rvec v2) v2 = a * v1
76 void dsvmul(double a,dvec v1,dvec v2) v2 = a * v1
77 void clear_rvec(rvec a) a = 0
78 void clear_dvec(dvec a) a = 0
79 void clear_ivec(rvec a) a = 0
80 void clear_rvecs(int n,rvec v[])
81 real iprod(rvec a,rvec b) = a . b (inner product)
82 double diprod(dvec a,dvec b) = a . b (inner product)
83 real iiprod(ivec a,ivec b) = a . b (integers)
84 real norm2(rvec a) = | a |^2 ( = x*y*z )
85 double dnorm2(dvec a) = | a |^2 ( = x*y*z )
86 real norm(rvec a) = | a |
87 double dnorm(dvec a) = | a |
88 void cprod(rvec a,rvec b,rvec c) c = a x b (cross product)
89 void dprod(rvec a,rvec b,rvec c) c = a x b (cross product)
90 void dprod(rvec a,rvec b,rvec c) c = a * b (direct product)
91 real cos_angle(rvec a,rvec b)
92 real cos_angle_no_table(rvec a,rvec b)
93 real distance2(rvec v1, rvec v2) = | v2 - v1 |^2
94 void unitv(rvec src,rvec dest) dest = src / |src|
95 void unitv_no_table(rvec src,rvec dest) dest = src / |src|
97 matrix (3x3) operations:
98 ! indicates that dest should not be the same as a, b or src
99 the _ur0 varieties work on matrices that have only zeros
100 in the upper right part, such as box matrices, these varieties
101 could produce less rounding errors, not due to the operations themselves,
102 but because the compiler can easier recombine the operations
103 void copy_mat(matrix a,matrix b) b = a
104 void clear_mat(matrix a) a = 0
105 void mmul(matrix a,matrix b,matrix dest) ! dest = a . b
106 void mmul_ur0(matrix a,matrix b,matrix dest) dest = a . b
107 void transpose(matrix src,matrix dest) ! dest = src*
108 void tmmul(matrix a,matrix b,matrix dest) ! dest = a* . b
109 void mtmul(matrix a,matrix b,matrix dest) ! dest = a . b*
110 real det(matrix a) = det(a)
111 void m_add(matrix a,matrix b,matrix dest) dest = a + b
112 void m_sub(matrix a,matrix b,matrix dest) dest = a - b
113 void msmul(matrix m1,real r1,matrix dest) dest = r1 * m1
114 void m_inv_ur0(matrix src,matrix dest) dest = src^-1
115 void m_inv(matrix src,matrix dest) ! dest = src^-1
116 void mvmul(matrix a,rvec src,rvec dest) ! dest = a . src
117 void mvmul_ur0(matrix a,rvec src,rvec dest) dest = a . src
118 void tmvmul_ur0(matrix a,rvec src,rvec dest) dest = a* . src
119 real trace(matrix m) = trace(m)
122 #include "types/simple.h"
124 #include "typedefs.h"
125 #include "sysstuff.h"
127 #include "gmx_fatal.h"
128 #include "mpelogging.h"
131 #define EXP_LSB 0x00800000
132 #define EXP_MASK 0x7f800000
134 #define FRACT_MASK 0x007fffff
135 #define FRACT_SIZE 11 /* significant part of fraction */
136 #define FRACT_SHIFT (EXP_SHIFT-FRACT_SIZE)
137 #define EXP_ADDR(val) (((val)&EXP_MASK)>>EXP_SHIFT)
138 #define FRACT_ADDR(val) (((val)&(FRACT_MASK|EXP_LSB))>>FRACT_SHIFT)
140 #define PR_VEC(a) a[XX],a[YY],a[ZZ]
142 #ifdef GMX_SOFTWARE_INVSQRT
143 extern const unsigned int * gmx_invsqrt_exptab
;
144 extern const unsigned int * gmx_invsqrt_fracttab
;
155 #ifdef GMX_SOFTWARE_INVSQRT
156 static real
gmx_invsqrt(real x
)
159 const real three
=3.0;
160 t_convert result
,bit_pattern
;
161 unsigned int exp
,fract
;
169 exp
= EXP_ADDR(bit_pattern
.bval
);
170 fract
= FRACT_ADDR(bit_pattern
.bval
);
171 result
.bval
=gmx_invsqrt_exptab
[exp
] | gmx_invsqrt_fracttab
[fract
];
174 y
=(half
*lu
*(three
-((x
*lu
)*lu
)));
176 y2
=(half
*y
*(three
-((x
*y
)*y
)));
178 return y2
; /* 10 Flops */
180 return y
; /* 5 Flops */
184 #endif /* gmx_invsqrt */
186 #ifdef GMX_POWERPC_SQRT
187 static real
gmx_invsqrt(real x
)
190 const real three
=3.0;
191 t_convert result
,bit_pattern
;
192 unsigned int exp
,fract
;
199 lu
= __frsqrte((double)x
);
201 y
=(half
*lu
*(three
-((x
*lu
)*lu
)));
203 #if (GMX_POWERPC_SQRT==2)
204 /* Extra iteration required */
205 y
=(half
*y
*(three
-((x
*y
)*y
)));
209 y2
=(half
*y
*(three
-((x
*y
)*y
)));
211 return y2
; /* 10 Flops */
213 return y
; /* 5 Flops */
217 #endif /* powerpc_invsqrt */
221 #define gmx_invsqrt(x) (1.0f/sqrt(x))
228 static real
sqr(real x
)
233 static inline double dsqr(double x
)
238 extern void vecinvsqrt(real in
[],real out
[],int n
);
239 /* Perform out[i]=1.0/sqrt(in[i]) for n elements */
242 extern void vecrecip(real in
[],real out
[],int n
);
243 /* Perform out[i]=1.0/(in[i]) for n elements */
245 /* Note: If you need a fast version of vecinvsqrt
246 * and/or vecrecip, call detectcpu() and run the SSE/3DNow/SSE2/Altivec
247 * versions if your hardware supports it.
249 * To use those routines, your memory HAS TO BE CACHE-ALIGNED.
250 * Start by allocating 31 bytes more than you need, put
251 * this in a temp variable (e.g. _buf, so you can free it later), and
252 * create your aligned array buf with
254 * buf=(real *) ( ( (unsigned long int)_buf + 31 ) & (~0x1f) );
258 static inline void rvec_add(const rvec a
,const rvec b
,rvec c
)
271 static inline void dvec_add(const dvec a
,const dvec b
,dvec c
)
284 static inline void ivec_add(const ivec a
,const ivec b
,ivec c
)
297 static inline void rvec_inc(rvec a
,const rvec b
)
310 static inline void dvec_inc(dvec a
,const dvec b
)
323 static inline void rvec_sub(const rvec a
,const rvec b
,rvec c
)
336 static inline void dvec_sub(const dvec a
,const dvec b
,dvec c
)
349 static inline void rvec_dec(rvec a
,const rvec b
)
362 static inline void copy_rvec(const rvec a
,rvec b
)
369 static inline void copy_dvec(const dvec a
,dvec b
)
376 static inline void copy_ivec(const ivec a
,ivec b
)
383 static inline void ivec_sub(const ivec a
,const ivec b
,ivec c
)
396 static inline void copy_mat(matrix a
,matrix b
)
398 copy_rvec(a
[XX
],b
[XX
]);
399 copy_rvec(a
[YY
],b
[YY
]);
400 copy_rvec(a
[ZZ
],b
[ZZ
]);
403 static inline void svmul(real a
,const rvec v1
,rvec v2
)
410 static inline void dsvmul(double a
,const dvec v1
,dvec v2
)
417 static inline real
distance2(const rvec v1
,const rvec v2
)
419 return sqr(v2
[XX
]-v1
[XX
]) + sqr(v2
[YY
]-v1
[YY
]) + sqr(v2
[ZZ
]-v1
[ZZ
]);
422 static inline void clear_rvec(rvec a
)
424 /* The ibm compiler has problems with inlining this
425 * when we use a const real variable
432 static inline void clear_dvec(dvec a
)
434 /* The ibm compiler has problems with inlining this
435 * when we use a const real variable
442 static inline void clear_ivec(ivec a
)
449 static inline void clear_rvecs(int n
,rvec v
[])
451 /* memset(v[0],0,DIM*n*sizeof(v[0][0])); */
454 GMX_MPE_LOG(ev_clear_rvecs_start
);
459 GMX_MPE_LOG(ev_clear_rvecs_finish
);
462 static inline void clear_mat(matrix a
)
464 /* memset(a[0],0,DIM*DIM*sizeof(a[0][0])); */
468 a
[XX
][XX
]=a
[XX
][YY
]=a
[XX
][ZZ
]=nul
;
469 a
[YY
][XX
]=a
[YY
][YY
]=a
[YY
][ZZ
]=nul
;
470 a
[ZZ
][XX
]=a
[ZZ
][YY
]=a
[ZZ
][ZZ
]=nul
;
473 static inline real
iprod(const rvec a
,const rvec b
)
475 return (a
[XX
]*b
[XX
]+a
[YY
]*b
[YY
]+a
[ZZ
]*b
[ZZ
]);
478 static inline double diprod(const dvec a
,const dvec b
)
480 return (a
[XX
]*b
[XX
]+a
[YY
]*b
[YY
]+a
[ZZ
]*b
[ZZ
]);
483 static inline int iiprod(const ivec a
,const ivec b
)
485 return (a
[XX
]*b
[XX
]+a
[YY
]*b
[YY
]+a
[ZZ
]*b
[ZZ
]);
488 static inline real
norm2(const rvec a
)
490 return a
[XX
]*a
[XX
]+a
[YY
]*a
[YY
]+a
[ZZ
]*a
[ZZ
];
493 static inline double dnorm2(const dvec a
)
495 return a
[XX
]*a
[XX
]+a
[YY
]*a
[YY
]+a
[ZZ
]*a
[ZZ
];
498 static inline real
norm(const rvec a
)
500 return (real
)sqrt(a
[XX
]*a
[XX
]+a
[YY
]*a
[YY
]+a
[ZZ
]*a
[ZZ
]);
503 static inline double dnorm(const dvec a
)
505 return sqrt(a
[XX
]*a
[XX
]+a
[YY
]*a
[YY
]+a
[ZZ
]*a
[ZZ
]);
508 static inline real
cos_angle(const rvec a
,const rvec b
)
511 * ax*bx + ay*by + az*bz
512 * cos-vec (a,b) = ---------------------
517 double aa
,bb
,ip
,ipa
,ipb
,ipab
; /* For accuracy these must be double! */
520 for(m
=0; (m
<DIM
); m
++) { /* 18 */
529 cosval
= ip
*gmx_invsqrt(ipab
); /* 7 */
541 static inline real
cos_angle_no_table(const rvec a
,const rvec b
)
543 /* This version does not need the invsqrt lookup table */
546 double aa
,bb
,ip
,ipa
,ipb
; /* For accuracy these must be double! */
549 for(m
=0; (m
<DIM
); m
++) { /* 18 */
556 cosval
=ip
/sqrt(ipa
*ipb
); /* 12 */
566 static inline void cprod(const rvec a
,const rvec b
,rvec c
)
568 c
[XX
]=a
[YY
]*b
[ZZ
]-a
[ZZ
]*b
[YY
];
569 c
[YY
]=a
[ZZ
]*b
[XX
]-a
[XX
]*b
[ZZ
];
570 c
[ZZ
]=a
[XX
]*b
[YY
]-a
[YY
]*b
[XX
];
573 static inline void dcprod(const dvec a
,const dvec b
,dvec c
)
575 c
[XX
]=a
[YY
]*b
[ZZ
]-a
[ZZ
]*b
[YY
];
576 c
[YY
]=a
[ZZ
]*b
[XX
]-a
[XX
]*b
[ZZ
];
577 c
[ZZ
]=a
[XX
]*b
[YY
]-a
[YY
]*b
[XX
];
580 static inline void mmul_ur0(matrix a
,matrix b
,matrix dest
)
582 dest
[XX
][XX
]=a
[XX
][XX
]*b
[XX
][XX
];
585 dest
[YY
][XX
]=a
[YY
][XX
]*b
[XX
][XX
]+a
[YY
][YY
]*b
[YY
][XX
];
586 dest
[YY
][YY
]= a
[YY
][YY
]*b
[YY
][YY
];
588 dest
[ZZ
][XX
]=a
[ZZ
][XX
]*b
[XX
][XX
]+a
[ZZ
][YY
]*b
[YY
][XX
]+a
[ZZ
][ZZ
]*b
[ZZ
][XX
];
589 dest
[ZZ
][YY
]= a
[ZZ
][YY
]*b
[YY
][YY
]+a
[ZZ
][ZZ
]*b
[ZZ
][YY
];
590 dest
[ZZ
][ZZ
]= a
[ZZ
][ZZ
]*b
[ZZ
][ZZ
];
593 static inline void mmul(matrix a
,matrix b
,matrix dest
)
595 dest
[XX
][XX
]=a
[XX
][XX
]*b
[XX
][XX
]+a
[XX
][YY
]*b
[YY
][XX
]+a
[XX
][ZZ
]*b
[ZZ
][XX
];
596 dest
[YY
][XX
]=a
[YY
][XX
]*b
[XX
][XX
]+a
[YY
][YY
]*b
[YY
][XX
]+a
[YY
][ZZ
]*b
[ZZ
][XX
];
597 dest
[ZZ
][XX
]=a
[ZZ
][XX
]*b
[XX
][XX
]+a
[ZZ
][YY
]*b
[YY
][XX
]+a
[ZZ
][ZZ
]*b
[ZZ
][XX
];
598 dest
[XX
][YY
]=a
[XX
][XX
]*b
[XX
][YY
]+a
[XX
][YY
]*b
[YY
][YY
]+a
[XX
][ZZ
]*b
[ZZ
][YY
];
599 dest
[YY
][YY
]=a
[YY
][XX
]*b
[XX
][YY
]+a
[YY
][YY
]*b
[YY
][YY
]+a
[YY
][ZZ
]*b
[ZZ
][YY
];
600 dest
[ZZ
][YY
]=a
[ZZ
][XX
]*b
[XX
][YY
]+a
[ZZ
][YY
]*b
[YY
][YY
]+a
[ZZ
][ZZ
]*b
[ZZ
][YY
];
601 dest
[XX
][ZZ
]=a
[XX
][XX
]*b
[XX
][ZZ
]+a
[XX
][YY
]*b
[YY
][ZZ
]+a
[XX
][ZZ
]*b
[ZZ
][ZZ
];
602 dest
[YY
][ZZ
]=a
[YY
][XX
]*b
[XX
][ZZ
]+a
[YY
][YY
]*b
[YY
][ZZ
]+a
[YY
][ZZ
]*b
[ZZ
][ZZ
];
603 dest
[ZZ
][ZZ
]=a
[ZZ
][XX
]*b
[XX
][ZZ
]+a
[ZZ
][YY
]*b
[YY
][ZZ
]+a
[ZZ
][ZZ
]*b
[ZZ
][ZZ
];
606 static inline void transpose(matrix src
,matrix dest
)
608 dest
[XX
][XX
]=src
[XX
][XX
];
609 dest
[YY
][XX
]=src
[XX
][YY
];
610 dest
[ZZ
][XX
]=src
[XX
][ZZ
];
611 dest
[XX
][YY
]=src
[YY
][XX
];
612 dest
[YY
][YY
]=src
[YY
][YY
];
613 dest
[ZZ
][YY
]=src
[YY
][ZZ
];
614 dest
[XX
][ZZ
]=src
[ZZ
][XX
];
615 dest
[YY
][ZZ
]=src
[ZZ
][YY
];
616 dest
[ZZ
][ZZ
]=src
[ZZ
][ZZ
];
619 static inline void tmmul(matrix a
,matrix b
,matrix dest
)
621 /* Computes dest=mmul(transpose(a),b,dest) - used in do_pr_pcoupl */
622 dest
[XX
][XX
]=a
[XX
][XX
]*b
[XX
][XX
]+a
[YY
][XX
]*b
[YY
][XX
]+a
[ZZ
][XX
]*b
[ZZ
][XX
];
623 dest
[XX
][YY
]=a
[XX
][XX
]*b
[XX
][YY
]+a
[YY
][XX
]*b
[YY
][YY
]+a
[ZZ
][XX
]*b
[ZZ
][YY
];
624 dest
[XX
][ZZ
]=a
[XX
][XX
]*b
[XX
][ZZ
]+a
[YY
][XX
]*b
[YY
][ZZ
]+a
[ZZ
][XX
]*b
[ZZ
][ZZ
];
625 dest
[YY
][XX
]=a
[XX
][YY
]*b
[XX
][XX
]+a
[YY
][YY
]*b
[YY
][XX
]+a
[ZZ
][YY
]*b
[ZZ
][XX
];
626 dest
[YY
][YY
]=a
[XX
][YY
]*b
[XX
][YY
]+a
[YY
][YY
]*b
[YY
][YY
]+a
[ZZ
][YY
]*b
[ZZ
][YY
];
627 dest
[YY
][ZZ
]=a
[XX
][YY
]*b
[XX
][ZZ
]+a
[YY
][YY
]*b
[YY
][ZZ
]+a
[ZZ
][YY
]*b
[ZZ
][ZZ
];
628 dest
[ZZ
][XX
]=a
[XX
][ZZ
]*b
[XX
][XX
]+a
[YY
][ZZ
]*b
[YY
][XX
]+a
[ZZ
][ZZ
]*b
[ZZ
][XX
];
629 dest
[ZZ
][YY
]=a
[XX
][ZZ
]*b
[XX
][YY
]+a
[YY
][ZZ
]*b
[YY
][YY
]+a
[ZZ
][ZZ
]*b
[ZZ
][YY
];
630 dest
[ZZ
][ZZ
]=a
[XX
][ZZ
]*b
[XX
][ZZ
]+a
[YY
][ZZ
]*b
[YY
][ZZ
]+a
[ZZ
][ZZ
]*b
[ZZ
][ZZ
];
633 static inline void mtmul(matrix a
,matrix b
,matrix dest
)
635 /* Computes dest=mmul(a,transpose(b),dest) - used in do_pr_pcoupl */
636 dest
[XX
][XX
]=a
[XX
][XX
]*b
[XX
][XX
]+a
[XX
][YY
]*b
[XX
][YY
]+a
[XX
][ZZ
]*b
[XX
][ZZ
];
637 dest
[XX
][YY
]=a
[XX
][XX
]*b
[YY
][XX
]+a
[XX
][YY
]*b
[YY
][YY
]+a
[XX
][ZZ
]*b
[YY
][ZZ
];
638 dest
[XX
][ZZ
]=a
[XX
][XX
]*b
[ZZ
][XX
]+a
[XX
][YY
]*b
[ZZ
][YY
]+a
[XX
][ZZ
]*b
[ZZ
][ZZ
];
639 dest
[YY
][XX
]=a
[YY
][XX
]*b
[XX
][XX
]+a
[YY
][YY
]*b
[XX
][YY
]+a
[YY
][ZZ
]*b
[XX
][ZZ
];
640 dest
[YY
][YY
]=a
[YY
][XX
]*b
[YY
][XX
]+a
[YY
][YY
]*b
[YY
][YY
]+a
[YY
][ZZ
]*b
[YY
][ZZ
];
641 dest
[YY
][ZZ
]=a
[YY
][XX
]*b
[ZZ
][XX
]+a
[YY
][YY
]*b
[ZZ
][YY
]+a
[YY
][ZZ
]*b
[ZZ
][ZZ
];
642 dest
[ZZ
][XX
]=a
[ZZ
][XX
]*b
[XX
][XX
]+a
[ZZ
][YY
]*b
[XX
][YY
]+a
[ZZ
][ZZ
]*b
[XX
][ZZ
];
643 dest
[ZZ
][YY
]=a
[ZZ
][XX
]*b
[YY
][XX
]+a
[ZZ
][YY
]*b
[YY
][YY
]+a
[ZZ
][ZZ
]*b
[YY
][ZZ
];
644 dest
[ZZ
][ZZ
]=a
[ZZ
][XX
]*b
[ZZ
][XX
]+a
[ZZ
][YY
]*b
[ZZ
][YY
]+a
[ZZ
][ZZ
]*b
[ZZ
][ZZ
];
647 static inline real
det(matrix a
)
649 return ( a
[XX
][XX
]*(a
[YY
][YY
]*a
[ZZ
][ZZ
]-a
[ZZ
][YY
]*a
[YY
][ZZ
])
650 -a
[YY
][XX
]*(a
[XX
][YY
]*a
[ZZ
][ZZ
]-a
[ZZ
][YY
]*a
[XX
][ZZ
])
651 +a
[ZZ
][XX
]*(a
[XX
][YY
]*a
[YY
][ZZ
]-a
[YY
][YY
]*a
[XX
][ZZ
]));
654 static inline void m_add(matrix a
,matrix b
,matrix dest
)
656 dest
[XX
][XX
]=a
[XX
][XX
]+b
[XX
][XX
];
657 dest
[XX
][YY
]=a
[XX
][YY
]+b
[XX
][YY
];
658 dest
[XX
][ZZ
]=a
[XX
][ZZ
]+b
[XX
][ZZ
];
659 dest
[YY
][XX
]=a
[YY
][XX
]+b
[YY
][XX
];
660 dest
[YY
][YY
]=a
[YY
][YY
]+b
[YY
][YY
];
661 dest
[YY
][ZZ
]=a
[YY
][ZZ
]+b
[YY
][ZZ
];
662 dest
[ZZ
][XX
]=a
[ZZ
][XX
]+b
[ZZ
][XX
];
663 dest
[ZZ
][YY
]=a
[ZZ
][YY
]+b
[ZZ
][YY
];
664 dest
[ZZ
][ZZ
]=a
[ZZ
][ZZ
]+b
[ZZ
][ZZ
];
667 static inline void m_sub(matrix a
,matrix b
,matrix dest
)
669 dest
[XX
][XX
]=a
[XX
][XX
]-b
[XX
][XX
];
670 dest
[XX
][YY
]=a
[XX
][YY
]-b
[XX
][YY
];
671 dest
[XX
][ZZ
]=a
[XX
][ZZ
]-b
[XX
][ZZ
];
672 dest
[YY
][XX
]=a
[YY
][XX
]-b
[YY
][XX
];
673 dest
[YY
][YY
]=a
[YY
][YY
]-b
[YY
][YY
];
674 dest
[YY
][ZZ
]=a
[YY
][ZZ
]-b
[YY
][ZZ
];
675 dest
[ZZ
][XX
]=a
[ZZ
][XX
]-b
[ZZ
][XX
];
676 dest
[ZZ
][YY
]=a
[ZZ
][YY
]-b
[ZZ
][YY
];
677 dest
[ZZ
][ZZ
]=a
[ZZ
][ZZ
]-b
[ZZ
][ZZ
];
680 static inline void msmul(matrix m1
,real r1
,matrix dest
)
682 dest
[XX
][XX
]=r1
*m1
[XX
][XX
];
683 dest
[XX
][YY
]=r1
*m1
[XX
][YY
];
684 dest
[XX
][ZZ
]=r1
*m1
[XX
][ZZ
];
685 dest
[YY
][XX
]=r1
*m1
[YY
][XX
];
686 dest
[YY
][YY
]=r1
*m1
[YY
][YY
];
687 dest
[YY
][ZZ
]=r1
*m1
[YY
][ZZ
];
688 dest
[ZZ
][XX
]=r1
*m1
[ZZ
][XX
];
689 dest
[ZZ
][YY
]=r1
*m1
[ZZ
][YY
];
690 dest
[ZZ
][ZZ
]=r1
*m1
[ZZ
][ZZ
];
693 static inline void m_inv_ur0(matrix src
,matrix dest
)
695 double tmp
= src
[XX
][XX
]*src
[YY
][YY
]*src
[ZZ
][ZZ
];
696 if (fabs(tmp
) <= 100*GMX_REAL_MIN
)
697 gmx_fatal(FARGS
,"Can not invert matrix, determinant is zero");
699 dest
[XX
][XX
] = 1/src
[XX
][XX
];
700 dest
[YY
][YY
] = 1/src
[YY
][YY
];
701 dest
[ZZ
][ZZ
] = 1/src
[ZZ
][ZZ
];
702 dest
[ZZ
][XX
] = (src
[YY
][XX
]*src
[ZZ
][YY
]*dest
[YY
][YY
]
703 - src
[ZZ
][XX
])*dest
[XX
][XX
]*dest
[ZZ
][ZZ
];
704 dest
[YY
][XX
] = -src
[YY
][XX
]*dest
[XX
][XX
]*dest
[YY
][YY
];
705 dest
[ZZ
][YY
] = -src
[ZZ
][YY
]*dest
[YY
][YY
]*dest
[ZZ
][ZZ
];
711 static inline void m_inv(matrix src
,matrix dest
)
713 const real smallreal
= (real
)1.0e-24;
714 const real largereal
= (real
)1.0e24
;
721 if ((fc
<= smallreal
) || (fc
>= largereal
))
722 gmx_fatal(FARGS
,"Can not invert matrix, determinant = %e",deter
);
724 dest
[XX
][XX
]= c
*(src
[YY
][YY
]*src
[ZZ
][ZZ
]-src
[ZZ
][YY
]*src
[YY
][ZZ
]);
725 dest
[XX
][YY
]=-c
*(src
[XX
][YY
]*src
[ZZ
][ZZ
]-src
[ZZ
][YY
]*src
[XX
][ZZ
]);
726 dest
[XX
][ZZ
]= c
*(src
[XX
][YY
]*src
[YY
][ZZ
]-src
[YY
][YY
]*src
[XX
][ZZ
]);
727 dest
[YY
][XX
]=-c
*(src
[YY
][XX
]*src
[ZZ
][ZZ
]-src
[ZZ
][XX
]*src
[YY
][ZZ
]);
728 dest
[YY
][YY
]= c
*(src
[XX
][XX
]*src
[ZZ
][ZZ
]-src
[ZZ
][XX
]*src
[XX
][ZZ
]);
729 dest
[YY
][ZZ
]=-c
*(src
[XX
][XX
]*src
[YY
][ZZ
]-src
[YY
][XX
]*src
[XX
][ZZ
]);
730 dest
[ZZ
][XX
]= c
*(src
[YY
][XX
]*src
[ZZ
][YY
]-src
[ZZ
][XX
]*src
[YY
][YY
]);
731 dest
[ZZ
][YY
]=-c
*(src
[XX
][XX
]*src
[ZZ
][YY
]-src
[ZZ
][XX
]*src
[XX
][YY
]);
732 dest
[ZZ
][ZZ
]= c
*(src
[XX
][XX
]*src
[YY
][YY
]-src
[YY
][XX
]*src
[XX
][YY
]);
735 static inline void mvmul(matrix a
,const rvec src
,rvec dest
)
737 dest
[XX
]=a
[XX
][XX
]*src
[XX
]+a
[XX
][YY
]*src
[YY
]+a
[XX
][ZZ
]*src
[ZZ
];
738 dest
[YY
]=a
[YY
][XX
]*src
[XX
]+a
[YY
][YY
]*src
[YY
]+a
[YY
][ZZ
]*src
[ZZ
];
739 dest
[ZZ
]=a
[ZZ
][XX
]*src
[XX
]+a
[ZZ
][YY
]*src
[YY
]+a
[ZZ
][ZZ
]*src
[ZZ
];
742 static inline void mvmul_ur0(matrix a
,const rvec src
,rvec dest
)
744 dest
[ZZ
]=a
[ZZ
][XX
]*src
[XX
]+a
[ZZ
][YY
]*src
[YY
]+a
[ZZ
][ZZ
]*src
[ZZ
];
745 dest
[YY
]=a
[YY
][XX
]*src
[XX
]+a
[YY
][YY
];
746 dest
[XX
]=a
[XX
][XX
]*src
[XX
];
749 static inline void tmvmul_ur0(matrix a
,const rvec src
,rvec dest
)
751 dest
[XX
]=a
[XX
][XX
]*src
[XX
]+a
[YY
][XX
]*src
[YY
]+a
[ZZ
][XX
]*src
[ZZ
];
752 dest
[YY
]= a
[YY
][YY
]*src
[YY
]+a
[ZZ
][YY
]*src
[ZZ
];
753 dest
[ZZ
]= a
[ZZ
][ZZ
]*src
[ZZ
];
756 static inline void unitv(const rvec src
,rvec dest
)
760 linv
=gmx_invsqrt(norm2(src
));
761 dest
[XX
]=linv
*src
[XX
];
762 dest
[YY
]=linv
*src
[YY
];
763 dest
[ZZ
]=linv
*src
[ZZ
];
766 static inline void unitv_no_table(const rvec src
,rvec dest
)
770 linv
=1.0/sqrt(norm2(src
));
771 dest
[XX
]=linv
*src
[XX
];
772 dest
[YY
]=linv
*src
[YY
];
773 dest
[ZZ
]=linv
*src
[ZZ
];
776 static void calc_lll(rvec box
,rvec lll
)
778 lll
[XX
] = 2.0*M_PI
/box
[XX
];
779 lll
[YY
] = 2.0*M_PI
/box
[YY
];
780 lll
[ZZ
] = 2.0*M_PI
/box
[ZZ
];
783 static inline real
trace(matrix m
)
785 return (m
[XX
][XX
]+m
[YY
][YY
]+m
[ZZ
][ZZ
]);
788 static inline real
_divide(real a
,real b
,const char *file
,int line
)
790 if (fabs(b
) <= GMX_REAL_MIN
)
791 gmx_fatal(FARGS
,"Dividing by zero, file %s, line %d",file
,line
);
795 static inline int _mod(int a
,int b
,char *file
,int line
)
798 gmx_fatal(FARGS
,"Modulo zero, file %s, line %d",file
,line
);
802 /* Operations on multidimensional rvecs, used e.g. in edsam.c */
803 static void m_rveccopy(int dim
, rvec
*a
, rvec
*b
)
808 for (i
=0; i
<dim
; i
++)
809 copy_rvec(a
[i
],b
[i
]);
812 /*computer matrix vectors from base vectors and angles */
813 static void matrix_convert(matrix box
, rvec vec
, rvec angle
)
815 svmul(DEG2RAD
,angle
,angle
);
816 box
[XX
][XX
] = vec
[XX
];
817 box
[YY
][XX
] = vec
[YY
]*cos(angle
[ZZ
]);
818 box
[YY
][YY
] = vec
[YY
]*sin(angle
[ZZ
]);
819 box
[ZZ
][XX
] = vec
[ZZ
]*cos(angle
[YY
]);
820 box
[ZZ
][YY
] = vec
[ZZ
]
821 *(cos(angle
[XX
])-cos(angle
[YY
])*cos(angle
[ZZ
]))/sin(angle
[ZZ
]);
822 box
[ZZ
][ZZ
] = sqrt(sqr(vec
[ZZ
])
823 -box
[ZZ
][XX
]*box
[ZZ
][XX
]-box
[ZZ
][YY
]*box
[ZZ
][YY
]);
826 #define divide(a,b) _divide((a),(b),__FILE__,__LINE__)
827 #define mod(a,b) _mod((a),(b),__FILE__,__LINE__)