NEURON
mymath.cpp
Go to the documentation of this file.
1 #include <../../nrnconf.h>
2 #include <InterViews/geometry.h>
3 #include "mymath.h"
4 #include "classreg.h"
5 #include "oc2iv.h"
6 #include <math.h>
7 #include <stdio.h>
8 
9 extern int hoc_return_type_code;
10 
11 static double distance_to_line(void*) {
13  *getarg(1), *getarg(2), *getarg(3), *getarg(4), *getarg(5), *getarg(6));
14 }
15 
16 static double distance_to_line_segment(void*) {
18  *getarg(1), *getarg(2), *getarg(3), *getarg(4), *getarg(5), *getarg(6));
19 }
20 
21 static double inside(void*) {
22  hoc_return_type_code = 2; // boolean
23  return MyMath::inside(*getarg(1), *getarg(2), *getarg(3), *getarg(4), *getarg(5), *getarg(6));
24 }
25 
26 int nrn_feround(int);
27 // return last rounding mode and set to given mode if 1,2,3,4.
28 // order is FE_DOWNWARD, FE_TONEAREST, FE_TOWARDZERO, FE_UPWARD
29 #if defined(HAVE_FENV_H) && defined(HAVE_FESETROUND)
30 #include <fenv.h>
31 static int round_mode[] = {FE_DOWNWARD, FE_TONEAREST, FE_TOWARDZERO, FE_UPWARD};
32 #endif
33 int nrn_feround(int mode) {
34 #if defined(HAVE_FENV_H) && defined(HAVE_FESETROUND)
35  int oldmode = fegetround();
36  int m;
37  if (oldmode == FE_TONEAREST) {
38  oldmode = 2;
39  } else if (oldmode == FE_TOWARDZERO) {
40  oldmode = 3;
41  } else if (oldmode == FE_UPWARD) {
42  oldmode = 4;
43  } else if (oldmode == FE_DOWNWARD) {
44  oldmode = 1;
45  } else {
46  assert(0);
47  }
48  if (mode > 0 && mode < 5) {
49  nrn_assert(fesetround(round_mode[mode - 1]) == 0);
50  }
51  return oldmode;
52 #else
53  return 0;
54 #endif
55 }
56 
57 static double feround(void*) {
58  int arg = 0;
59  hoc_return_type_code = 1; // integer
60  if (ifarg(1)) {
61  arg = (int) chkarg(1, 0, 4);
62  }
63  return (double) nrn_feround(arg);
64 }
65 
66 static Member_func members[] = {"d2line",
68  "d2line_seg",
70  "inside",
71  inside,
72  "feround",
73  feround,
74  0,
75  0};
76 
77 static void* cons(Object*) {
78  return NULL;
79 }
80 
81 static void destruct(void*) {}
82 
83 void GUIMath_reg() {
84  class2oc("GUIMath", cons, destruct, members, NULL, NULL, NULL);
85 }
86 
87 double MyMath::anint(double x) {
88  if (x < 0) {
89  return ceil(x - .5);
90  } else {
91  return floor(x + .5);
92  }
93 }
94 float MyMath::min(int count, const float* x) {
95  float m = x[0];
96  for (int i = 1; i < count; ++i) {
97  if (m > x[i]) {
98  m = x[i];
99  }
100  }
101  return m;
102 }
103 
104 float MyMath::max(int count, const float* x) {
105  float m = x[0];
106  for (int i = 1; i < count; ++i) {
107  if (m < x[i]) {
108  m = x[i];
109  }
110  }
111  return m;
112 }
113 
114 // within epsilon distance from the infinite line
115 
116 bool MyMath::near_line(Coord x, Coord y, Coord x1, Coord y1, Coord x2, Coord y2, float epsilon) {
117  // printf("near_line %g %g %g %g %g %g %g\n", x,y,x1,y1,x2,y2,epsilon);
118  if (Math::equal(x, x1, epsilon) && Math::equal(y, y1, epsilon)) {
119  return true;
120  }
121  if (Math::equal(x1, x2, epsilon) && Math::equal(y1, y2, epsilon)) {
122  return false;
123  }
124  Coord d, norm, norm2, dot;
125  Coord dx, dy, dx2, dy2;
126  dx = x - x1;
127  dy = y - y1;
128  dx2 = x2 - x1;
129  dy2 = y2 - y1;
130  // printf("%g %g %g %g\n", dx, dy, dx2, dy2);
131  norm2 = dx2 * dx2 + dy2 * dy2;
132  norm = dx * dx + dy * dy;
133  dot = dx * dx2 + dy * dy2;
134  d = norm - dot * dot / norm2;
135  // printf("near_line %g\n", d);
136  if (d <= epsilon * epsilon) {
137  return true;
138  } else {
139  return false;
140  }
141 }
142 
144  // printf("near_line %g %g %g %g %g %g %g\n", x,y,x1,y1,x2,y2,epsilon);
145  Coord d, norm, norm2, dot;
146  Coord dx, dy, dx2, dy2;
147  dx = x - x1;
148  dy = y - y1;
149  dx2 = x2 - x1;
150  dy2 = y2 - y1;
151  // printf("%g %g %g %g\n", dx, dy, dx2, dy2);
152  norm2 = dx2 * dx2 + dy2 * dy2;
153  norm = dx * dx + dy * dy;
154  dot = dx * dx2 + dy * dy2;
155  if (norm2 == 0) {
156  norm2 = 1.;
157  }
158  d = norm - dot * dot / norm2;
159  if (d < 0.) {
160  return 0.;
161  }
162  return sqrt(d);
163 }
164 
166  Coord norm, norm2, dot;
167  Coord dx, dy, dx2, dy2;
168  dx = x - x1;
169  dy = y - y1;
170  dx2 = x2 - x1;
171  dy2 = y2 - y1;
172  norm2 = dx2 * dx2 + dy2 * dy2;
173  norm = dx * dx + dy * dy;
174 
175  if (norm2 == 0) {
176  return sqrt(norm);
177  }
178  dot = dx * dx2 + dy * dy2;
179  if (dot < 0) {
180  return sqrt(norm);
181  } else if (dot > norm2) {
182  dx = x - x2;
183  dy = y - y2;
184  return sqrt(dx * dx + dy * dy);
185  } else {
186  dx = norm - dot * dot / norm2;
187  if (dx <= 0) {
188  return 0.;
189  }
190  return sqrt(dx);
191  }
192 }
193 
195  Coord y,
196  Coord x1,
197  Coord y1,
198  Coord x2,
199  Coord y2,
200  float epsilon) {
201  Coord l = x1, b = y1, r = x2, t = y2;
202  MyMath::minmax(l, r);
203  MyMath::minmax(b, t);
204  // printf("near_line_seg inside %d\n",inside(x, y, l-epsilon, b-epsilon, r+epsilon, t+epsilon));
205  // printf("near_line_seg near_line %d\n", near_line(x, y, l, b, r, t, epsilon));
206  return MyMath::inside(x, y, l - epsilon, b - epsilon, r + epsilon, t + epsilon) &&
207  MyMath::near_line(x, y, x1, y1, x2, y2, epsilon);
208 }
209 
210 #if 0
211 void MyMath::round_range(Coord x1, Coord x2, double& y1, double& y2, int& ntic) {
212  double d = x2 - x1;
213  int e = 0;
214  while (d > 10) {
215  d /= 10.;
216  ++e;
217  }
218  while (d < 10) {
219  d *= 10.;
220  --e;
221  }
222 
223  if (d > 76.) {
224  d = 100.; ntic = 5;
225  }else if (d > 51.) {
226  d = 75.; ntic = 3;
227  }else if (d > 31.) {
228  d = 50.; ntic = 5;
229  }else if (d > 26.) {
230  d = 30.; ntic = 3;
231  }else if (d > 21.) {
232  d = 25.; ntic = 5;
233  }else if (d > 16) {
234  d = 20; ntic = 4;
235 #if 0
236  }else if (d > 11) {
237  d = 15; ntic = 3;
238  }else{
239  d = 10.; ntic = 5;
240  }
241 #else
242  }else{
243  int i = int(d);
244  d = double(i);
245  if (i > 6) {
246  if ((i%2) == 0) {
247  ntic = i/2;
248  }else if ((i%3) == 0) {
249  ntic = i/3;
250  } else {
251  i = i+1;
252  d = double(i);
253  ntic = i/2;
254  }
255  }else{
256  ntic = i;
257  }
258  }
259 #endif
260 
261  while (e > 0) {
262  d *= 10.;
263  --e;
264  }
265  while (e < 0) {
266  d /= 10.;
267  ++e;
268  }
269 
270  d /= double(ntic);
271  y1 = d*double(int(x1/d - .5));
272  y2 = d*double(int(x2/d + .5));
273  ntic = int((y2 - y1)/d + .5);
274 }
275 #else
276 void MyMath::round_range(Coord x1, Coord x2, double& y1, double& y2, int& ntic) {
277  double d = x2 - x1;
278  d = pow(10, floor(log10(d))) / 10;
279  y1 = d * MyMath::anint(x1 / d);
280  y2 = d * MyMath::anint(x2 / d);
281  int i = int((y2 - y1) / d + .5); // 10 < i < 100
282  // printf("%d %g\n", i, dx);
283  for (;;) {
284  if (i % 3 == 0) {
285  ntic = 3;
286  return;
287  } else if (i % 4 == 0) {
288  ntic = 4;
289  return;
290  } else if (i % 5 == 0) {
291  ntic = 5;
292  return;
293  }
294  y1 -= d;
295  y2 += d;
296  i += 2;
297  }
298 }
299 #endif
300 
301 void MyMath::round_range_down(Coord x1, Coord x2, double& y1, double& y2, int& ntic) {
302  double d = x2 - x1;
303  double e = pow(10, floor(log10(d))) / 10;
304  int i = int(d / e + .5);
305  if (i > 20) {
306  y1 = 5 * e * ceil(x1 / e / 5 - .01);
307  y2 = 5 * e * floor(x2 / e / 5 + .01);
308  } else {
309  y1 = e * ceil(x1 / e - .01);
310  y2 = e * floor(x2 / e + .01);
311  }
312  i = int((y2 - y1) / e + .5);
313  // printf("%d %g\n", i, e);
314  for (;;) {
315  if (i % 3 == 0) {
316  ntic = 3;
317  return;
318  } else if (i % 4 == 0) {
319  ntic = 4;
320  return;
321  } else if (i % 5 == 0) {
322  ntic = 5;
323  return;
324  }
325  y1 -= e;
326  ++i;
327  }
328 }
329 
330 double MyMath::round(float& x1, float& x2, int direction, int digits) {
331  double d;
332  if (x2 > x1) {
333  d = x2 - x1;
334  } else {
335  d = Math::abs(x1);
336  }
337  double e = pow(10, floor(log10(d)) + 1 - digits);
338  switch (direction) {
339  case Expand:
340  x1 = e * floor(x1 / e);
341  x2 = e * ceil(x2 / e);
342  break;
343  case Contract:
344  x1 = e * ceil(x1 / e);
345  x2 = e * floor(x2 / e);
346  break;
347  case Lower:
348  x1 = e * floor(x1 / e);
349  x2 = e * floor(x2 / e);
350  break;
351  case Higher:
352  x1 = e * ceil(x1 / e);
353  x2 = e * ceil(x2 / e);
354  break;
355  }
356  return e;
357 }
358 
359 void MyMath::box(Requisition& req, Coord& x1, Coord& y1, Coord& x2, Coord& y2) {
360  Requirement& rx = req.x_requirement();
361  x1 = -rx.alignment() * rx.natural();
362  x2 = x1 + rx.natural();
363  Requirement& ry = req.y_requirement();
364  y1 = -ry.alignment() * ry.natural();
365  y2 = y1 + ry.natural();
366 }
367 
369  float d;
370  d = sqrt(x * x + y * y);
371  if (d < 1e-6) {
372  perp[0] = 0.;
373  perp[1] = 1.;
374  return false;
375  }
376  perp[0] = y / d;
377  perp[1] = -x / d;
378  return true;
379 }
#define Coord
Definition: _defines.h:19
static bool equal(float x, float y, float e)
Definition: math.h:108
static int abs(int)
Definition: math.cpp:43
static bool near_line(Coord x, Coord y, Coord x1, Coord y1, Coord x2, Coord y2, float epsilon)
Definition: mymath.cpp:116
static void round_range_down(Coord x1, Coord x2, double &y1, double &y2, int &ntic)
Definition: mymath.cpp:301
@ Expand
Definition: mymath.h:52
@ Lower
Definition: mymath.h:52
@ Contract
Definition: mymath.h:52
@ Higher
Definition: mymath.h:52
static bool near_line_segment(Coord x, Coord y, Coord x1, Coord y1, Coord x2, Coord y2, float epsilon)
Definition: mymath.cpp:194
static float distance_to_line_segment(Coord x, Coord y, Coord x1, Coord y1, Coord x2, Coord y2)
Definition: mymath.cpp:165
static double anint(double)
Definition: mymath.cpp:87
static void minmax(Coord &min, Coord &max)
Definition: mymath.h:86
static bool unit_normal(Coord x, Coord y, Coord *perp)
Definition: mymath.cpp:368
static void round_range(Coord x1, Coord x2, double &y1, double &y2, int &ntic)
Definition: mymath.cpp:276
static float max(int count, const float *)
Definition: mymath.cpp:104
static bool inside(Coord x, Coord min, Coord max)
Definition: mymath.h:94
static void box(Requisition &, Coord &x1, Coord &y1, Coord &x2, Coord &y2)
Definition: mymath.cpp:359
static float min(int count, const float *)
Definition: mymath.cpp:94
static double round(float &x1, float &x2, int direction, int digits)
Definition: mymath.cpp:330
static float norm2(Coord x, Coord y)
Definition: mymath.h:40
static float distance_to_line(Coord x, Coord y, Coord x1, Coord y1, Coord x2, Coord y2)
Definition: mymath.cpp:143
void alignment(float)
Definition: geometry.h:241
void natural(Coord)
Definition: geometry.h:235
const Requirement & x_requirement() const
Definition: geometry.h:249
const Requirement & y_requirement() const
Definition: geometry.h:250
double t
Definition: cvodeobj.cpp:59
double chkarg(int, double low, double high)
Definition: code2.cpp:638
#define assert(ex)
Definition: hocassrt.h:32
#define getarg
Definition: hocdec.h:15
int ifarg(int)
Definition: code.cpp:1581
#define i
Definition: md1redef.h:12
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:83
static double inside(void *)
Definition: mymath.cpp:21
static Member_func members[]
Definition: mymath.cpp:66
static void * cons(Object *)
Definition: mymath.cpp:77
int nrn_feround(int)
Definition: mymath.cpp:33
static void destruct(void *)
Definition: mymath.cpp:81
int hoc_return_type_code
Definition: code.cpp:42
static double distance_to_line_segment(void *)
Definition: mymath.cpp:16
static double distance_to_line(void *)
Definition: mymath.cpp:11
static double feround(void *)
Definition: mymath.cpp:57
#define nrn_assert(ex)
Definition: nrnassrt.h:53
void class2oc(const char *, void *(*cons)(Object *), void(*destruct)(void *), Member_func *, int(*checkpoint)(void **), Member_ret_obj_func *, Member_ret_str_func *)
Definition: hoc_oop.cpp:1560
#define e
Definition: passive0.cpp:22
#define arg
Definition: redef.h:28
#define NULL
Definition: sptree.h:16
Definition: hocdec.h:227