NEURON
mymath.cpp
Go to the documentation of this file.
1 #ifndef __INTEL_LLVM_COMPILER
2 #ifdef __clang__
3 #pragma float_control(precise, on)
4 #endif
5 #pragma STDC FENV_ACCESS ON
6 #endif
7 
8 #include <../../nrnconf.h>
9 #include <InterViews/geometry.h>
10 #include "mymath.h"
11 #include "code.h"
12 #include "classreg.h"
13 #include "oc2iv.h"
14 #include <cmath>
15 #include <cstdio>
16 #include <cfenv>
17 
18 static double distance_to_line(void*) {
20  *getarg(1), *getarg(2), *getarg(3), *getarg(4), *getarg(5), *getarg(6));
21 }
22 
23 static double distance_to_line_segment(void*) {
25  *getarg(1), *getarg(2), *getarg(3), *getarg(4), *getarg(5), *getarg(6));
26 }
27 
28 static double inside(void*) {
30  return MyMath::inside(*getarg(1), *getarg(2), *getarg(3), *getarg(4), *getarg(5), *getarg(6));
31 }
32 
33 int nrn_feround(int);
34 // return last rounding mode and set to given mode if 1,2,3,4.
35 // order is FE_DOWNWARD, FE_TONEAREST, FE_TOWARDZERO, FE_UPWARD
36 static int round_mode[] = {FE_DOWNWARD, FE_TONEAREST, FE_TOWARDZERO, FE_UPWARD};
37 int nrn_feround(int mode) {
38  int oldmode = std::fegetround();
39  if (oldmode == FE_TONEAREST) {
40  oldmode = 2;
41  } else if (oldmode == FE_TOWARDZERO) {
42  oldmode = 3;
43  } else if (oldmode == FE_UPWARD) {
44  oldmode = 4;
45  } else if (oldmode == FE_DOWNWARD) {
46  oldmode = 1;
47  } else {
48  assert(0);
49  }
50  if (mode > 0 && mode < 5) {
51  nrn_assert(std::fesetround(round_mode[mode - 1]) == 0);
52  }
53  return oldmode;
54 }
55 
56 static double feround(void*) {
57  int arg = 0;
59  if (ifarg(1)) {
60  arg = (int) chkarg(1, 0, 4);
61  }
62  return (double) nrn_feround(arg);
63 }
64 
65 static Member_func members[] = {{"d2line", distance_to_line},
66  {"d2line_seg", distance_to_line_segment},
67  {"inside", inside},
68  {"feround", feround},
69  {nullptr, nullptr}};
70 
71 static void* cons(Object*) {
72  return NULL;
73 }
74 
75 static void destruct(void*) {}
76 
77 void GUIMath_reg() {
78  class2oc("GUIMath", cons, destruct, members, nullptr, nullptr);
79 }
80 
81 double MyMath::anint(double x) {
82  if (x < 0) {
83  return ceil(x - .5);
84  } else {
85  return floor(x + .5);
86  }
87 }
88 float MyMath::min(int count, const float* x) {
89  float m = x[0];
90  for (int i = 1; i < count; ++i) {
91  if (m > x[i]) {
92  m = x[i];
93  }
94  }
95  return m;
96 }
97 
98 float MyMath::max(int count, const float* x) {
99  float m = x[0];
100  for (int i = 1; i < count; ++i) {
101  if (m < x[i]) {
102  m = x[i];
103  }
104  }
105  return m;
106 }
107 
108 // within epsilon distance from the infinite line
109 
110 bool MyMath::near_line(Coord x, Coord y, Coord x1, Coord y1, Coord x2, Coord y2, float epsilon) {
111  // printf("near_line %g %g %g %g %g %g %g\n", x,y,x1,y1,x2,y2,epsilon);
112  if (eq(x, x1, epsilon) && eq(y, y1, epsilon)) {
113  return true;
114  }
115  if (eq(x1, x2, epsilon) && eq(y1, y2, epsilon)) {
116  return false;
117  }
118  Coord d, norm, norm2, dot;
119  Coord dx, dy, dx2, dy2;
120  dx = x - x1;
121  dy = y - y1;
122  dx2 = x2 - x1;
123  dy2 = y2 - y1;
124  // printf("%g %g %g %g\n", dx, dy, dx2, dy2);
125  norm2 = dx2 * dx2 + dy2 * dy2;
126  norm = dx * dx + dy * dy;
127  dot = dx * dx2 + dy * dy2;
128  d = norm - dot * dot / norm2;
129  // printf("near_line %g\n", d);
130  return d <= epsilon * epsilon;
131 }
132 
134  // printf("near_line %g %g %g %g %g %g %g\n", x,y,x1,y1,x2,y2,epsilon);
135  Coord d, norm, norm2, dot;
136  Coord dx, dy, dx2, dy2;
137  dx = x - x1;
138  dy = y - y1;
139  dx2 = x2 - x1;
140  dy2 = y2 - y1;
141  // printf("%g %g %g %g\n", dx, dy, dx2, dy2);
142  norm2 = dx2 * dx2 + dy2 * dy2;
143  norm = dx * dx + dy * dy;
144  dot = dx * dx2 + dy * dy2;
145  if (norm2 == 0) {
146  norm2 = 1.;
147  }
148  d = norm - dot * dot / norm2;
149  if (d < 0.) {
150  return 0.;
151  }
152  return sqrt(d);
153 }
154 
156  Coord norm, norm2, dot;
157  Coord dx, dy, dx2, dy2;
158  dx = x - x1;
159  dy = y - y1;
160  dx2 = x2 - x1;
161  dy2 = y2 - y1;
162  norm2 = dx2 * dx2 + dy2 * dy2;
163  norm = dx * dx + dy * dy;
164 
165  if (norm2 == 0) {
166  return sqrt(norm);
167  }
168  dot = dx * dx2 + dy * dy2;
169  if (dot < 0) {
170  return sqrt(norm);
171  } else if (dot > norm2) {
172  dx = x - x2;
173  dy = y - y2;
174  return sqrt(dx * dx + dy * dy);
175  } else {
176  dx = norm - dot * dot / norm2;
177  if (dx <= 0) {
178  return 0.;
179  }
180  return sqrt(dx);
181  }
182 }
183 
185  Coord y,
186  Coord x1,
187  Coord y1,
188  Coord x2,
189  Coord y2,
190  float epsilon) {
191  Coord l = x1, b = y1, r = x2, t = y2;
192  MyMath::minmax(l, r);
193  MyMath::minmax(b, t);
194  // printf("near_line_seg inside %d\n",inside(x, y, l-epsilon, b-epsilon, r+epsilon, t+epsilon));
195  // printf("near_line_seg near_line %d\n", near_line(x, y, l, b, r, t, epsilon));
196  return MyMath::inside(x, y, l - epsilon, b - epsilon, r + epsilon, t + epsilon) &&
197  MyMath::near_line(x, y, x1, y1, x2, y2, epsilon);
198 }
199 
200 void MyMath::round_range(Coord x1, Coord x2, double& y1, double& y2, int& ntic) {
201  double d = x2 - x1;
202  d = pow(10, floor(log10(d))) / 10;
203  y1 = d * MyMath::anint(x1 / d);
204  y2 = d * MyMath::anint(x2 / d);
205  int i = int((y2 - y1) / d + .5); // 10 < i < 100
206  // printf("%d %g\n", i, dx);
207  for (;;) {
208  if (i % 3 == 0) {
209  ntic = 3;
210  return;
211  } else if (i % 4 == 0) {
212  ntic = 4;
213  return;
214  } else if (i % 5 == 0) {
215  ntic = 5;
216  return;
217  }
218  y1 -= d;
219  y2 += d;
220  i += 2;
221  }
222 }
223 
224 void MyMath::round_range_down(Coord x1, Coord x2, double& y1, double& y2, int& ntic) {
225  double d = x2 - x1;
226  double e = pow(10, floor(log10(d))) / 10;
227  int i = int(d / e + .5);
228  if (i > 20) {
229  y1 = 5 * e * ceil(x1 / e / 5 - .01);
230  y2 = 5 * e * floor(x2 / e / 5 + .01);
231  } else {
232  y1 = e * ceil(x1 / e - .01);
233  y2 = e * floor(x2 / e + .01);
234  }
235  i = int((y2 - y1) / e + .5);
236  // printf("%d %g\n", i, e);
237  for (;;) {
238  if (i % 3 == 0) {
239  ntic = 3;
240  return;
241  } else if (i % 4 == 0) {
242  ntic = 4;
243  return;
244  } else if (i % 5 == 0) {
245  ntic = 5;
246  return;
247  }
248  y1 -= e;
249  ++i;
250  }
251 }
252 
253 double MyMath::round(float& x1, float& x2, int direction, int digits) {
254  double d;
255  if (x2 > x1) {
256  d = x2 - x1;
257  } else {
258  d = std::abs(x1);
259  }
260  double e = pow(10, floor(log10(d)) + 1 - digits);
261  switch (direction) {
262  case Expand:
263  x1 = e * floor(x1 / e);
264  x2 = e * ceil(x2 / e);
265  break;
266  case Contract:
267  x1 = e * ceil(x1 / e);
268  x2 = e * floor(x2 / e);
269  break;
270  case Lower:
271  x1 = e * floor(x1 / e);
272  x2 = e * floor(x2 / e);
273  break;
274  case Higher:
275  x1 = e * ceil(x1 / e);
276  x2 = e * ceil(x2 / e);
277  break;
278  }
279  return e;
280 }
281 
282 void MyMath::box(Requisition& req, Coord& x1, Coord& y1, Coord& x2, Coord& y2) {
283  Requirement& rx = req.x_requirement();
284  x1 = -rx.alignment() * rx.natural();
285  x2 = x1 + rx.natural();
286  Requirement& ry = req.y_requirement();
287  y1 = -ry.alignment() * ry.natural();
288  y2 = y1 + ry.natural();
289 }
290 
292  float d = sqrt(x * x + y * y);
293  if (d < 1e-6) {
294  perp[0] = 0.;
295  perp[1] = 1.;
296  return false;
297  }
298  perp[0] = y / d;
299  perp[1] = -x / d;
300  return true;
301 }
#define Coord
Definition: _defines.h:17
static bool near_line(Coord x, Coord y, Coord x1, Coord y1, Coord x2, Coord y2, float epsilon)
Definition: mymath.cpp:110
static void round_range_down(Coord x1, Coord x2, double &y1, double &y2, int &ntic)
Definition: mymath.cpp:224
static bool near_line_segment(Coord x, Coord y, Coord x1, Coord y1, Coord x2, Coord y2, float epsilon)
Definition: mymath.cpp:184
static float distance_to_line_segment(Coord x, Coord y, Coord x1, Coord y1, Coord x2, Coord y2)
Definition: mymath.cpp:155
static double anint(double)
Definition: mymath.cpp:81
static void minmax(Coord &min, Coord &max)
Definition: mymath.h:83
static bool unit_normal(Coord x, Coord y, Coord *perp)
Definition: mymath.cpp:291
static bool eq(T x, T y, T e)
Definition: mymath.h:63
static void round_range(Coord x1, Coord x2, double &y1, double &y2, int &ntic)
Definition: mymath.cpp:200
static float max(int count, const float *)
Definition: mymath.cpp:98
static bool inside(Coord x, Coord min, Coord max)
Definition: mymath.h:91
static void box(Requisition &, Coord &x1, Coord &y1, Coord &x2, Coord &y2)
Definition: mymath.cpp:282
static float min(int count, const float *)
Definition: mymath.cpp:88
static double round(float &x1, float &x2, int direction, int digits)
Definition: mymath.cpp:253
static float norm2(Coord x, Coord y)
Definition: mymath.h:36
static float distance_to_line(Coord x, Coord y, Coord x1, Coord y1, Coord x2, Coord y2)
Definition: mymath.cpp:133
@ Expand
Definition: mymath.h:48
@ Lower
Definition: mymath.h:48
@ Contract
Definition: mymath.h:48
@ Higher
Definition: mymath.h:48
void alignment(float)
Definition: geometry.h:237
void natural(Coord)
Definition: geometry.h:231
const Requirement & x_requirement() const
Definition: geometry.h:245
const Requirement & y_requirement() const
Definition: geometry.h:246
void class2oc(const char *, ctor_f *cons, dtor_f *destruct, Member_func *, Member_ret_obj_func *, Member_ret_str_func *)
Definition: hoc_oop.cpp:1631
HocReturnType hoc_return_type_code
Definition: code.cpp:42
#define i
Definition: md1redef.h:19
double chkarg(int, double low, double high)
Definition: code2.cpp:626
#define assert(ex)
Definition: hocassrt.h:24
#define getarg
Definition: hocdec.h:17
ceil
Definition: extdef.h:4
sqrt
Definition: extdef.h:3
floor
Definition: extdef.h:4
log10
Definition: extdef.h:4
pow
Definition: extdef.h:4
void GUIMath_reg()
Definition: mymath.cpp:77
static double inside(void *)
Definition: mymath.cpp:28
static Member_func members[]
Definition: mymath.cpp:65
static void * cons(Object *)
Definition: mymath.cpp:71
int nrn_feround(int)
Definition: mymath.cpp:37
static void destruct(void *)
Definition: mymath.cpp:75
static double distance_to_line_segment(void *)
Definition: mymath.cpp:23
static double distance_to_line(void *)
Definition: mymath.cpp:18
static double feround(void *)
Definition: mymath.cpp:56
static int round_mode[]
Definition: mymath.cpp:36
double norm(const Point3D &p1)
Definition: lfp.hpp:22
double dot(const Point3D &p1, const Point3D &p2)
Definition: lfp.hpp:18
#define nrn_assert(x)
assert()-like macro, independent of NDEBUG status
Definition: nrn_assert.h:33
int ifarg(int)
Definition: code.cpp:1607
#define NULL
Definition: spdefs.h:105
Definition: hocdec.h:173