OpenFPM  5.2.0
Project that contain the implementation of distributed structures
pcp_unit_test_helpfunctions.h
1 #include <math.h>
2 // This is a collection of helpfunctions that were used to run convergence tests and benchmarks for the ellipse/ellipsoid
3 // in the particle closest point draft. Computing the theoretical closest points and distances from a given query point
4 // is done using the first four functions which were adopted from David Eberly "Distance from a Point to an Ellipse, an
5 // Ellipsoid, or a Hyperellipsoid", 2013.
6 //
7 // Created by lschulze
8 double GetRoot (double r0, double z0, double z1, double g)
9  {
10  const int maxIter = 100;
11  double n0 = r0*z0;
12  double s0 = z1 - 1;
13  double s1 = ( g < 0 ? 0 : sqrt(n0*n0+z1*z1) - 1 ) ;
14  double s = 0;
15  for ( int i = 0; i < maxIter; ++i ){
16  if (i == (maxIter - 1)) std::cout<<"distance point ellipse algorithm did not converge."<<std::endl;
17  s = ( s0 + s1 ) / 2 ;
18  if ( s == s0 || s == s1 ) {break; }
19  double ratio0 = n0 /( s + r0 );
20  double ratio1 = z1 /( s + 1 );
21  g = ratio0*ratio0 + ratio1*ratio1 - 1 ;
22  if (g > 0) {s0 = s;} else if (g < 0) {s1 = s ;} else {break ;}
23  }
24  return s;
25  }
26 
27 double GetRoot(double r0, double r1, double z0, double z1, double z2, double g)
28 {
29  const int maxIter = 100;
30  double n0 = r0*z0;
31  double n1 = r1*z1;
32  double s0 = z2 - 1;
33  double s1 = (g < 0 ? 0 : sqrt(n0*n0 + n1*n1 + z2*z2) - 1) ;
34  double s = s;
35  for(int i = 0 ; i < maxIter ; ++i )
36  {
37  if (i == (maxIter - 1)) std::cout<<"distance point ellipse algorithm did not converge."<<std::endl;
38  s = ( s0 + s1 ) / 2 ;
39  if ( s == s0 || s == s1 ) {break; }
40  double ratio0 = n0 / ( s + r0 );
41  double ratio1 = n1 / ( s + r1 );
42  double ratio2 = z2 / ( s + 1 );
43  g = ratio0*ratio0 + ratio1*ratio1 +ratio2*ratio2 - 1;
44  if ( g > 0 ) { s0 = s ;}
45  else if ( g < 0 ) { s1 = s ; }
46  else {break;}
47  }
48  return (s);
49 }
50 
51 double DistancePointEllipse(double e0, double e1, double y0, double y1, double& x0, double& x1)
52  {
53  double distance;
54  if ( y1 > 0){
55  if ( y0 > 0){
56  double z0 = y0 / e0;
57  double z1 = y1 / e1;
58  double g = z0*z0+z1*z1 - 1;
59  if ( g != 0){
60  double r0 = (e0/e1)*(e0/e1);
61  double sbar = GetRoot(r0 , z0 , z1 , g);
62  x0 = r0 * y0 /( sbar + r0 );
63  x1 = y1 /( sbar + 1 );
64  distance = sqrt( (x0-y0)*(x0-y0) + (x1-y1)*(x1-y1) );
65  }else{
66  x0 = y0;
67  x1 = y1;
68  distance = 0;
69  }
70  }
71  else // y0 == 0
72  {x0 = 0 ; x1 = e1 ; distance = abs( y1 - e1 );}
73  }else{ // y1 == 0
74  double numer0 = e0*y0 , denom0 = e0*e0 - e1*e1;
75  if ( numer0 < denom0 ){
76  double xde0 = numer0/denom0;
77  x0 = e0*xde0 ; x1 = e1*sqrt(1 - xde0*xde0 );
78  distance = sqrt( (x0-y0)*(x0-y0) + x1*x1 );
79  }else{
80  x0 = e0;
81  x1 = 0;
82  distance = abs( y0 - e0 );
83  }
84  }
85  return distance;
86  }
87 
88 double DistancePointEllipsoid(double e0, double e1, double e2, double y0, double y1, double y2, double& x0, double& x1, double& x2)
89 {
90  double distance;
91  if( y2 > 0 )
92  {
93  if( y1 > 0 )
94  {
95  if( y0 > 0 )
96  {
97  double z0 = y0 / e0;
98  double z1 = y1 / e1;
99  double z2 = y2 / e2;
100  double g = z0*z0 + z1*z1 + z2*z2 - 1 ;
101  if( g != 0 )
102  {
103  double r0 = (e0/e2)*(e0/e2);
104  double r1 = (e1/e2)*(e1/e2);
105  double sbar = GetRoot ( r0 , r1 , z0 , z1 , z2 , g );
106  x0 = r0 *y0 / ( sbar + r0 );
107  x1 = r1 *y1 / ( sbar + r1 );
108  x2 = y2 / ( sbar + 1 );
109  distance = sqrt( (x0 - y0)*(x0 - y0) + (x1 - y1)*(x1 - y1) + (x2 - y2)*(x2 - y2));
110  }
111  else
112  {
113  x0 = y0;
114  x1 = y1;
115  x2 = y2;
116  distance = 0;
117  }
118  }
119  else // y0 == 0
120  {
121  x0 = 0;
122  distance = DistancePointEllipse( e1 , e2 , y1 , y2, x1, x2);
123  }
124  }
125  else // y1 == 0
126  {
127  if( y0 > 0 )
128  {
129  x1 = 0;
130  distance = DistancePointEllipse( e0 , e2 , y0 , y2, x0, x2);
131  }
132  else // y0 == 0
133  {
134  x0 = 0;
135  x1 = 0;
136  x2 = e2;
137  distance = abs(y2 - e2);
138  }
139  }
140  }
141  else // y2 == 0
142  {
143  double denom0 = e0*e0 - e2*e2;
144  double denom1 = e1*e1 - e2*e2;
145  double numer0 = e0*y0;
146  double numer1 = e1*y1;
147  bool computed = false;
148  if((numer0 < denom0) && (numer1 < denom1))
149  {
150  double xde0 = numer0/denom0;
151  double xde1 = numer1/denom1 ;
152  double xde0sqr = xde0 *xde0;
153  double xde1sqr = xde1 * xde1 ;
154  double discr = 1 - xde0sqr - xde1sqr;
155  if( discr > 0 )
156  {
157  x0 = e0*xde0;
158  x1 = e1*xde1;
159  x2 = e2*sqrt(discr);
160  distance = sqrt((x0 - y0)*(x0 - y0) + (x1 - y1)*(x1 - y1) + x2*x2);
161  computed = true;
162  }
163  }
164  if( !computed )
165  {
166  x2 = 0;
167  distance = DistancePointEllipse(e0 , e1 , y0 , y1, x0, x1);
168  }
169  }
170  return distance;
171 }
172 
173 constexpr unsigned int factorial(unsigned int x)
174 {
175  unsigned int fact = 1;
176  for(int i = 1; i < (x + 1); i++) fact = fact*i;
177  return(fact);
178 }
179 constexpr unsigned int minter_lp_degree_one_num_coeffs(unsigned int dims, unsigned int poly_degree)
180 {
181  return(factorial(dims + poly_degree)/(factorial(dims)*factorial(poly_degree)));
182 }
183 
184 int return_sign(double phi)
185 {
186  if (phi > 0) return 1;
187  if (phi < 0) return -1;
188  return 0;
189 }
190 
191 double randMinusOneToOne()
192 {
193  double temp = rand() / (RAND_MAX + 1.0);
194  //std::cout<<(2.0*temp - 1.0)<<std::endl;
195  return(2.0*temp - 1.0);
196 }