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