4 * This source code is part of
8 * GROningen MAchine for Chemical Simulations
12 * Copyright (c) 1991-2001
13 * BIOSON Research Institute, Dept. of Biophysical Chemistry
14 * University of Groningen, The Netherlands
16 * This program is free software; you can redistribute it and/or
17 * modify it under the terms of the GNU General Public License
18 * as published by the Free Software Foundation; either version 2
19 * of the License, or (at your option) any later version.
21 * If you want to redistribute modifications, please consider that
22 * scientific software is very special. Version control is crucial -
23 * bugs must be traceable. We will be happy to consider code for
24 * inclusion in the official distribution, but derived work must not
25 * be called official GROMACS. Details are found in the README & COPYING
26 * files - if they are missing, get the official version at www.gromacs.org.
28 * To help us fund GROMACS development, we humbly ask that you cite
29 * the papers on the package - you can find them in the top README file.
31 * Do check out http://www.gromacs.org , or mail us at gromacs@gromacs.org .
34 * Giving Russians Opium May Alter Current Situation
40 static char *SRCID_vec_h = "$Id$";
46 #ident "@(#) vec.h 1.8 12/16/92"
47 #endif /* HAVE_IDENT */
50 collection of in-line ready operations:
52 lookup-table optimized scalar operations:
54 void vecinvsqrt(real in[],real out[],int n)
56 void vecrecip(real in[],real out[],int n)
60 void rvec_add(const rvec a,const rvec b,rvec c) c = a + b
61 void rvec_inc(rvec a,rvec b) a += b
62 void rvec_sub(const rvec a,const rvec b,rvec c) c = a - b
63 void rvec_dec(rvec a,rvec b) a -= b
64 void copy_rvec(const rvec a,rvec b) b = a (reals)
65 void copy_ivec(const ivec a,ivec b) b = a (integers)
66 void ivec_sub(const ivec a,const ivec b,ivec c) c = a - b
67 void svmul(real a,rvec v1,rvec v2) v2 = a * v1
68 void clear_rvec(rvec a) a = 0
69 void clear_rvecs(int n,rvec v[])
70 real iprod(rvec a,rvec b) = a . b (inner product)
71 real iiprod(ivec a,ivec b) = a . b (integers)
72 real norm2(rvec a) = | a |^2 ( = x*y*z )
73 real norm(rvec a) = | a |
74 void oprod(rvec a,rvec b,rvec c) c = a x b (outer product)
75 void dprod(rvec a,rvec b,rvec c) c = a * b (direct product)
76 real cos_angle(rvec a,rvec b)
77 real cos_angle_no_table(rvec a,rvec b)
78 real distance2(rvec v1, rvec v2) = | v2 - v1 |^2
79 void unitv(rvec src,rvec dest) dest = src / |src|
80 void unitv_no_table(rvec src,rvec dest) dest = src / |src|
82 matrix (3x3) operations:
83 void copy_mat(matrix a,matrix b) b = a
84 void clear_mat(matrix a) a = 0
85 void mmul(matrix a,matrix b,matrix dest) dest = a . b
86 void transpose(matrix src,matrix dest) dest = src*
87 void tmmul(matrix a,matrix b,matrix dest) dest = a* . b
88 void mtmul(matrix a,matrix b,matrix dest) dest = a . b*
89 real det(matrix a) = det(a)
90 void m_add(matrix a,matrix b,matrix dest) dest = a + b
91 void m_sub(matrix a,matrix b,matrix dest) dest = a - b
92 void msmul(matrix m1,real r1,matrix dest) dest = r1 * m1
93 void m_inv(matrix src,matrix dest) dest = src^-1
94 void mvmul(matrix a,rvec src,rvec dest) dest = a . src
95 real trace(matrix m) = trace(m)
102 #include "typedefs.h"
103 #include "sysstuff.h"
108 #define EXP_LSB 0x00800000
109 #define EXP_MASK 0x7f800000
111 #define FRACT_MASK 0x007fffff
112 #define FRACT_SIZE 11 /* significant part of fraction */
113 #define FRACT_SHIFT (EXP_SHIFT-FRACT_SIZE)
114 #define EXP_ADDR(val) (((val)&EXP_MASK)>>EXP_SHIFT)
115 #define FRACT_ADDR(val) (((val)&(FRACT_MASK|EXP_LSB))>>FRACT_SHIFT)
117 #define PR_VEC(a) a[XX],a[YY],a[ZZ]
120 extern const unsigned int cinvsqrtexptab[];
121 extern const unsigned int cinvsqrtfracttab[];
124 #ifdef SOFTWARE_RECIP
125 extern const unsigned int crecipexptab[];
126 extern const unsigned int crecipfracttab[];
136 #ifdef SOFTWARE_INVSQRT
137 static inline real invsqrt(float x)
140 const real three=3.0;
141 t_convert result,bit_pattern;
142 unsigned int exp,fract;
150 exp = EXP_ADDR(bit_pattern.bval);
151 fract = FRACT_ADDR(bit_pattern.bval);
152 result.bval=cinvsqrtexptab[exp] | cinvsqrtfracttab[fract];
155 y=(half*lu*(three-((x*lu)*lu)));
157 y2=(half*y*(three-((x*y)*y)));
159 return y2; /* 10 Flops */
161 return y; /* 5 Flops */
165 #endif /* gmx_invsqrt */
168 #define invsqrt(x) (1.0f/sqrt(x))
173 static inline void vecinvsqrt(real in[],real out[],int n)
177 const real three=3.0;
178 t_convert result,bit_pattern;
179 unsigned int exp,fract;
184 #endif /* INVSQRT_DONE */
189 if(cpu_capabilities & X86_3DNOW_SUPPORT)
190 vecinvsqrt_3dnow(in,out,n);
194 if((cpu_capabilities & X86_SSE_SUPPORT) && !((unsigned long int)in & 0x1f) && !((unsigned long int)out & 0x1f)) /* SSE data must be cache aligned */
195 vecinvsqrt_sse(in,out,n);
197 #endif /* no x86 optimizations */
198 #endif /* not double */
203 exp = EXP_ADDR(bit_pattern.bval);
204 fract = FRACT_ADDR(bit_pattern.bval);
205 result.bval=cinvsqrtexptab[exp] | cinvsqrtfracttab[fract];
209 y=(half*lu*(three-((x*lu)*lu)));
210 out[i]=(half*y*(three-((x*y)*y)));
212 out[i]=(half*lu*(three-((x*lu)*lu)));
215 #else /* no gmx invsqrt */
217 out[i]=1.0f/sqrt(in[i]);
218 #endif /* INVSQRT_DONE */
221 #ifdef SOFTWARE_RECIP
222 static inline real recip(float x)
225 t_convert result,bit_pattern;
226 unsigned int exp,fract;
234 exp = EXP_ADDR(bit_pattern.bval);
235 fract = FRACT_ADDR(bit_pattern.bval);
236 result.bval=crecipexptab[exp] | crecipfracttab[fract];
243 return y2; /* 6 Flops */
245 return y; /* 3 Flops */
251 static inline void vecrecip(real in[],real out[],int n)
253 #ifdef SOFTWARE_RECIP
255 t_convert result,bit_pattern;
256 unsigned int exp,fract;
261 #endif /* SOFTWARE_RECIP */
266 if(cpu_capabilities & X86_3DNOW_SUPPORT)
267 vecrecip_3dnow(in,out,n);
271 if((cpu_capabilities & X86_SSE_SUPPORT) && !((unsigned long int)in & 0x1f) && !((unsigned long int)out & 0x1f)) /* SSE data must be cache aligned */
272 vecrecip_sse(in,out,n);
274 #endif /* no x86 optimizations */
275 #endif /* not double */
276 #ifdef SOFTWARE_RECIP
280 exp = EXP_ADDR(bit_pattern.bval);
281 fract = FRACT_ADDR(bit_pattern.bval);
282 result.bval=crecipexptab[exp] | crecipfracttab[fract];
289 out[i]=lu*(two-x*lu);
292 #else /* No gmx recip */
295 #endif /* SOFTWARE_RECIP */
298 static inline real sqr(real x)
303 static inline void rvec_add(const rvec a,const rvec b,rvec c)
316 static inline void rvec_inc(rvec a,rvec b)
329 static inline void rvec_sub(const rvec a,const rvec b,rvec c)
342 static inline void rvec_dec(rvec a,rvec b)
355 static inline void copy_rvec(const rvec a,rvec b)
362 static inline void copy_ivec(const ivec a,ivec b)
369 static inline void ivec_sub(const ivec a,const ivec b,ivec c)
382 static inline void copy_mat(matrix a,matrix b)
384 copy_rvec(a[XX],b[XX]);
385 copy_rvec(a[YY],b[YY]);
386 copy_rvec(a[ZZ],b[ZZ]);
389 static inline void svmul(real a,rvec v1,rvec v2)
396 static inline real distance2(rvec v1, rvec v2)
398 return sqr(v2[XX]-v1[XX]) + sqr(v2[YY]-v1[YY]) + sqr(v2[ZZ]-v1[ZZ]);
401 static inline void clear_rvec(rvec a)
403 /* The ibm compiler has problems with inlining this
404 * when we use a const real variable
411 static inline void clear_rvecs(int n,rvec v[])
419 static inline void clear_mat(matrix a)
423 a[XX][XX]=a[XX][YY]=a[XX][ZZ]=nul;
424 a[YY][XX]=a[YY][YY]=a[YY][ZZ]=nul;
425 a[ZZ][XX]=a[ZZ][YY]=a[ZZ][ZZ]=nul;
428 static inline real iprod(rvec a,rvec b)
430 return (a[XX]*b[XX]+a[YY]*b[YY]+a[ZZ]*b[ZZ]);
433 static inline real iiprod(ivec a,ivec b)
435 return (a[XX]*b[XX]+a[YY]*b[YY]+a[ZZ]*b[ZZ]);
438 static inline real norm2(rvec a)
440 return a[XX]*a[XX]+a[YY]*a[YY]+a[ZZ]*a[ZZ];
443 static inline real norm(rvec a)
445 return sqrt(a[XX]*a[XX]+a[YY]*a[YY]+a[ZZ]*a[ZZ]);
448 static inline real cos_angle(rvec a,rvec b)
451 * ax*bx + ay*by + az*bz
452 * cos-vec (a,b) = ---------------------
457 double aa,bb,ip,ipa,ipb; /* For accuracy these must be double! */
460 for(m=0; (m<DIM); m++) { /* 18 */
467 cos=ip*invsqrt(ipa*ipb); /* 7 */
477 static inline real cos_angle_no_table(rvec a,rvec b)
479 /* This version does not need the invsqrt lookup table */
482 double aa,bb,ip,ipa,ipb; /* For accuracy these must be double! */
485 for(m=0; (m<DIM); m++) { /* 18 */
492 cos=ip/sqrt(ipa*ipb); /* 12 */
502 static inline void oprod(rvec a,rvec b,rvec c)
504 c[XX]=a[YY]*b[ZZ]-a[ZZ]*b[YY];
505 c[YY]=a[ZZ]*b[XX]-a[XX]*b[ZZ];
506 c[ZZ]=a[XX]*b[YY]-a[YY]*b[XX];
509 static inline void mmul(matrix a,matrix b,matrix dest)
511 dest[XX][XX]=a[XX][XX]*b[XX][XX]+a[XX][YY]*b[YY][XX]+a[XX][ZZ]*b[ZZ][XX];
512 dest[YY][XX]=a[YY][XX]*b[XX][XX]+a[YY][YY]*b[YY][XX]+a[YY][ZZ]*b[ZZ][XX];
513 dest[ZZ][XX]=a[ZZ][XX]*b[XX][XX]+a[ZZ][YY]*b[YY][XX]+a[ZZ][ZZ]*b[ZZ][XX];
514 dest[XX][YY]=a[XX][XX]*b[XX][YY]+a[XX][YY]*b[YY][YY]+a[XX][ZZ]*b[ZZ][YY];
515 dest[YY][YY]=a[YY][XX]*b[XX][YY]+a[YY][YY]*b[YY][YY]+a[YY][ZZ]*b[ZZ][YY];
516 dest[ZZ][YY]=a[ZZ][XX]*b[XX][YY]+a[ZZ][YY]*b[YY][YY]+a[ZZ][ZZ]*b[ZZ][YY];
517 dest[XX][ZZ]=a[XX][XX]*b[XX][ZZ]+a[XX][YY]*b[YY][ZZ]+a[XX][ZZ]*b[ZZ][ZZ];
518 dest[YY][ZZ]=a[YY][XX]*b[XX][ZZ]+a[YY][YY]*b[YY][ZZ]+a[YY][ZZ]*b[ZZ][ZZ];
519 dest[ZZ][ZZ]=a[ZZ][XX]*b[XX][ZZ]+a[ZZ][YY]*b[YY][ZZ]+a[ZZ][ZZ]*b[ZZ][ZZ];
522 static inline void transpose(matrix src,matrix dest)
524 dest[XX][XX]=src[XX][XX];
525 dest[YY][XX]=src[XX][YY];
526 dest[ZZ][XX]=src[XX][ZZ];
527 dest[XX][YY]=src[YY][XX];
528 dest[YY][YY]=src[YY][YY];
529 dest[ZZ][YY]=src[YY][ZZ];
530 dest[XX][ZZ]=src[ZZ][XX];
531 dest[YY][ZZ]=src[ZZ][YY];
532 dest[ZZ][ZZ]=src[ZZ][ZZ];
535 static inline void tmmul(matrix a,matrix b,matrix dest)
537 /* Computes dest=mmul(transpose(a),b,dest) - used in do_pr_pcoupl */
538 dest[XX][XX]=a[XX][XX]*b[XX][XX]+a[YY][XX]*b[YY][XX]+a[ZZ][XX]*b[ZZ][XX];
539 dest[XX][YY]=a[XX][XX]*b[XX][YY]+a[YY][XX]*b[YY][YY]+a[ZZ][XX]*b[ZZ][YY];
540 dest[XX][ZZ]=a[XX][XX]*b[XX][ZZ]+a[YY][XX]*b[YY][ZZ]+a[ZZ][XX]*b[ZZ][ZZ];
541 dest[YY][XX]=a[XX][YY]*b[XX][XX]+a[YY][YY]*b[YY][XX]+a[ZZ][YY]*b[ZZ][XX];
542 dest[YY][YY]=a[XX][YY]*b[XX][YY]+a[YY][YY]*b[YY][YY]+a[ZZ][YY]*b[ZZ][YY];
543 dest[YY][ZZ]=a[XX][YY]*b[XX][ZZ]+a[YY][YY]*b[YY][ZZ]+a[ZZ][YY]*b[ZZ][ZZ];
544 dest[ZZ][XX]=a[XX][ZZ]*b[XX][XX]+a[YY][ZZ]*b[YY][XX]+a[ZZ][ZZ]*b[ZZ][XX];
545 dest[ZZ][YY]=a[XX][ZZ]*b[XX][YY]+a[YY][ZZ]*b[YY][YY]+a[ZZ][ZZ]*b[ZZ][YY];
546 dest[ZZ][ZZ]=a[XX][ZZ]*b[XX][ZZ]+a[YY][ZZ]*b[YY][ZZ]+a[ZZ][ZZ]*b[ZZ][ZZ];
549 static inline void mtmul(matrix a,matrix b,matrix dest)
551 /* Computes dest=mmul(a,transpose(b),dest) - used in do_pr_pcoupl */
552 dest[XX][XX]=a[XX][XX]*b[XX][XX]+a[XX][YY]*b[XX][YY]+a[XX][ZZ]*b[XX][ZZ];
553 dest[XX][YY]=a[XX][XX]*b[YY][XX]+a[XX][YY]*b[YY][YY]+a[XX][ZZ]*b[YY][ZZ];
554 dest[XX][ZZ]=a[XX][XX]*b[ZZ][XX]+a[XX][YY]*b[ZZ][YY]+a[XX][ZZ]*b[ZZ][ZZ];
555 dest[YY][XX]=a[YY][XX]*b[XX][XX]+a[YY][YY]*b[XX][YY]+a[YY][ZZ]*b[XX][ZZ];
556 dest[YY][YY]=a[YY][XX]*b[YY][XX]+a[YY][YY]*b[YY][YY]+a[YY][ZZ]*b[YY][ZZ];
557 dest[YY][ZZ]=a[YY][XX]*b[ZZ][XX]+a[YY][YY]*b[ZZ][YY]+a[YY][ZZ]*b[ZZ][ZZ];
558 dest[ZZ][XX]=a[ZZ][XX]*b[XX][XX]+a[ZZ][YY]*b[XX][YY]+a[ZZ][ZZ]*b[XX][ZZ];
559 dest[ZZ][YY]=a[ZZ][XX]*b[YY][XX]+a[ZZ][YY]*b[YY][YY]+a[ZZ][ZZ]*b[YY][ZZ];
560 dest[ZZ][ZZ]=a[ZZ][XX]*b[ZZ][XX]+a[ZZ][YY]*b[ZZ][YY]+a[ZZ][ZZ]*b[ZZ][ZZ];
563 static inline real det(matrix a)
565 return ( a[XX][XX]*(a[YY][YY]*a[ZZ][ZZ]-a[ZZ][YY]*a[YY][ZZ])
566 -a[YY][XX]*(a[XX][YY]*a[ZZ][ZZ]-a[ZZ][YY]*a[XX][ZZ])
567 +a[ZZ][XX]*(a[XX][YY]*a[YY][ZZ]-a[YY][YY]*a[XX][ZZ]));
570 static inline void m_add(matrix a,matrix b,matrix dest)
572 dest[XX][XX]=a[XX][XX]+b[XX][XX];
573 dest[XX][YY]=a[XX][YY]+b[XX][YY];
574 dest[XX][ZZ]=a[XX][ZZ]+b[XX][ZZ];
575 dest[YY][XX]=a[YY][XX]+b[YY][XX];
576 dest[YY][YY]=a[YY][YY]+b[YY][YY];
577 dest[YY][ZZ]=a[YY][ZZ]+b[YY][ZZ];
578 dest[ZZ][XX]=a[ZZ][XX]+b[ZZ][XX];
579 dest[ZZ][YY]=a[ZZ][YY]+b[ZZ][YY];
580 dest[ZZ][ZZ]=a[ZZ][ZZ]+b[ZZ][ZZ];
583 static inline void m_sub(matrix a,matrix b,matrix dest)
585 dest[XX][XX]=a[XX][XX]-b[XX][XX];
586 dest[XX][YY]=a[XX][YY]-b[XX][YY];
587 dest[XX][ZZ]=a[XX][ZZ]-b[XX][ZZ];
588 dest[YY][XX]=a[YY][XX]-b[YY][XX];
589 dest[YY][YY]=a[YY][YY]-b[YY][YY];
590 dest[YY][ZZ]=a[YY][ZZ]-b[YY][ZZ];
591 dest[ZZ][XX]=a[ZZ][XX]-b[ZZ][XX];
592 dest[ZZ][YY]=a[ZZ][YY]-b[ZZ][YY];
593 dest[ZZ][ZZ]=a[ZZ][ZZ]-b[ZZ][ZZ];
596 static inline void msmul(matrix m1,real r1,matrix dest)
598 dest[XX][XX]=r1*m1[XX][XX];
599 dest[XX][YY]=r1*m1[XX][YY];
600 dest[XX][ZZ]=r1*m1[XX][ZZ];
601 dest[YY][XX]=r1*m1[YY][XX];
602 dest[YY][YY]=r1*m1[YY][YY];
603 dest[YY][ZZ]=r1*m1[YY][ZZ];
604 dest[ZZ][XX]=r1*m1[ZZ][XX];
605 dest[ZZ][YY]=r1*m1[ZZ][YY];
606 dest[ZZ][ZZ]=r1*m1[ZZ][ZZ];
609 static inline void m_inv(matrix src,matrix dest)
611 const real smallreal = 1.0e-18;
612 const real largereal = 1.0e18;
619 if ((fc <= smallreal) || (fc >= largereal))
620 fatal_error(0,"Determinant = %f",1.0/c);
622 dest[XX][XX]= c*(src[YY][YY]*src[ZZ][ZZ]-src[ZZ][YY]*src[YY][ZZ]);
623 dest[XX][YY]=-c*(src[XX][YY]*src[ZZ][ZZ]-src[ZZ][YY]*src[XX][ZZ]);
624 dest[XX][ZZ]= c*(src[XX][YY]*src[YY][ZZ]-src[YY][YY]*src[XX][ZZ]);
625 dest[YY][XX]=-c*(src[YY][XX]*src[ZZ][ZZ]-src[ZZ][XX]*src[YY][ZZ]);
626 dest[YY][YY]= c*(src[XX][XX]*src[ZZ][ZZ]-src[ZZ][XX]*src[XX][ZZ]);
627 dest[YY][ZZ]=-c*(src[XX][XX]*src[YY][ZZ]-src[YY][XX]*src[XX][ZZ]);
628 dest[ZZ][XX]= c*(src[YY][XX]*src[ZZ][YY]-src[ZZ][XX]*src[YY][YY]);
629 dest[ZZ][YY]=-c*(src[XX][XX]*src[ZZ][YY]-src[ZZ][XX]*src[XX][YY]);
630 dest[ZZ][ZZ]= c*(src[XX][XX]*src[YY][YY]-src[YY][XX]*src[XX][YY]);
633 static inline void mvmul(matrix a,rvec src,rvec dest)
635 dest[XX]=a[XX][XX]*src[XX]+a[XX][YY]*src[YY]+a[XX][ZZ]*src[ZZ];
636 dest[YY]=a[YY][XX]*src[XX]+a[YY][YY]*src[YY]+a[YY][ZZ]*src[ZZ];
637 dest[ZZ]=a[ZZ][XX]*src[XX]+a[ZZ][YY]*src[YY]+a[ZZ][ZZ]*src[ZZ];
640 static inline void unitv(rvec src,rvec dest)
644 linv=invsqrt(norm2(src));
645 dest[XX]=linv*src[XX];
646 dest[YY]=linv*src[YY];
647 dest[ZZ]=linv*src[ZZ];
650 static inline void unitv_no_table(rvec src,rvec dest)
654 linv=1.0/sqrt(norm2(src));
655 dest[XX]=linv*src[XX];
656 dest[YY]=linv*src[YY];
657 dest[ZZ]=linv*src[ZZ];
660 static inline real trace(matrix m)
662 return (m[XX][XX]+m[YY][YY]+m[ZZ][ZZ]);
665 static inline real _divide(real a,real b,char *file,int line)
668 fatal_error(0,"Dividing by zero, file %s, line %d",file,line);
672 static inline int _mod(int a,int b,char *file,int line)
675 fatal_error(0,"Modulo zero, file %s, line %d",file,line);
679 #define divide(a,b) _divide((a),(b),__FILE__,__LINE__)
680 #define mod(a,b) _mod((a),(b),__FILE__,__LINE__)