vfs: check userland buffers before reading them.
[haiku.git] / headers / libs / agg / agg_math.h
blob6d3ff1194b4ef221750d91b981db1e51b091591f
1 //----------------------------------------------------------------------------
2 // Anti-Grain Geometry - Version 2.4
3 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
4 //
5 // Permission to copy, use, modify, sell and distribute this software
6 // is granted provided this copyright notice appears in all copies.
7 // This software is provided "as is" without express or implied
8 // warranty, and with no claim as to its suitability for any purpose.
9 //
10 //----------------------------------------------------------------------------
11 // Contact: mcseem@antigrain.com
12 // mcseemagg@yahoo.com
13 // http://www.antigrain.com
14 //----------------------------------------------------------------------------
15 // Bessel function (besj) was adapted for use in AGG library by Andy Wilk
16 // Contact: castor.vulgaris@gmail.com
17 //----------------------------------------------------------------------------
19 #ifndef AGG_MATH_INCLUDED
20 #define AGG_MATH_INCLUDED
22 #include <math.h>
23 #include "agg_basics.h"
25 namespace agg
28 //------------------------------------------------------vertex_dist_epsilon
29 // Coinciding points maximal distance (Epsilon)
30 const double vertex_dist_epsilon = 1e-14;
32 //-----------------------------------------------------intersection_epsilon
33 // See calc_intersection
34 const double intersection_epsilon = 1.0e-30;
36 //------------------------------------------------------------cross_product
37 AGG_INLINE double cross_product(double x1, double y1,
38 double x2, double y2,
39 double x, double y)
41 return (x - x2) * (y2 - y1) - (y - y2) * (x2 - x1);
44 //--------------------------------------------------------point_in_triangle
45 AGG_INLINE bool point_in_triangle(double x1, double y1,
46 double x2, double y2,
47 double x3, double y3,
48 double x, double y)
50 bool cp1 = cross_product(x1, y1, x2, y2, x, y) < 0.0;
51 bool cp2 = cross_product(x2, y2, x3, y3, x, y) < 0.0;
52 bool cp3 = cross_product(x3, y3, x1, y1, x, y) < 0.0;
53 return cp1 == cp2 && cp2 == cp3 && cp3 == cp1;
56 //-----------------------------------------------------------calc_distance
57 AGG_INLINE double calc_distance(double x1, double y1, double x2, double y2)
59 double dx = x2-x1;
60 double dy = y2-y1;
61 return sqrt(dx * dx + dy * dy);
64 //--------------------------------------------------------calc_sq_distance
65 AGG_INLINE double calc_sq_distance(double x1, double y1, double x2, double y2)
67 double dx = x2-x1;
68 double dy = y2-y1;
69 return dx * dx + dy * dy;
72 //------------------------------------------------calc_line_point_distance
73 AGG_INLINE double calc_line_point_distance(double x1, double y1,
74 double x2, double y2,
75 double x, double y)
77 double dx = x2-x1;
78 double dy = y2-y1;
79 double d = sqrt(dx * dx + dy * dy);
80 if(d < vertex_dist_epsilon)
82 return calc_distance(x1, y1, x, y);
84 return ((x - x2) * dy - (y - y2) * dx) / d;
87 //-------------------------------------------------------calc_line_point_u
88 AGG_INLINE double calc_segment_point_u(double x1, double y1,
89 double x2, double y2,
90 double x, double y)
92 double dx = x2 - x1;
93 double dy = y2 - y1;
95 if(dx == 0 && dy == 0)
97 return 0;
100 double pdx = x - x1;
101 double pdy = y - y1;
103 return (pdx * dx + pdy * dy) / (dx * dx + dy * dy);
106 //---------------------------------------------calc_line_point_sq_distance
107 AGG_INLINE double calc_segment_point_sq_distance(double x1, double y1,
108 double x2, double y2,
109 double x, double y,
110 double u)
112 if(u <= 0)
114 return calc_sq_distance(x, y, x1, y1);
116 else
117 if(u >= 1)
119 return calc_sq_distance(x, y, x2, y2);
121 return calc_sq_distance(x, y, x1 + u * (x2 - x1), y1 + u * (y2 - y1));
124 //---------------------------------------------calc_line_point_sq_distance
125 AGG_INLINE double calc_segment_point_sq_distance(double x1, double y1,
126 double x2, double y2,
127 double x, double y)
129 return
130 calc_segment_point_sq_distance(
131 x1, y1, x2, y2, x, y,
132 calc_segment_point_u(x1, y1, x2, y2, x, y));
135 //-------------------------------------------------------calc_intersection
136 AGG_INLINE bool calc_intersection(double ax, double ay, double bx, double by,
137 double cx, double cy, double dx, double dy,
138 double* x, double* y)
140 double num = (ay-cy) * (dx-cx) - (ax-cx) * (dy-cy);
141 double den = (bx-ax) * (dy-cy) - (by-ay) * (dx-cx);
142 if(fabs(den) < intersection_epsilon) return false;
143 double r = num / den;
144 *x = ax + r * (bx-ax);
145 *y = ay + r * (by-ay);
146 return true;
149 //-----------------------------------------------------intersection_exists
150 AGG_INLINE bool intersection_exists(double x1, double y1, double x2, double y2,
151 double x3, double y3, double x4, double y4)
153 // It's less expensive but you can't control the
154 // boundary conditions: Less or LessEqual
155 double dx1 = x2 - x1;
156 double dy1 = y2 - y1;
157 double dx2 = x4 - x3;
158 double dy2 = y4 - y3;
159 return ((x3 - x2) * dy1 - (y3 - y2) * dx1 < 0.0) !=
160 ((x4 - x2) * dy1 - (y4 - y2) * dx1 < 0.0) &&
161 ((x1 - x4) * dy2 - (y1 - y4) * dx2 < 0.0) !=
162 ((x2 - x4) * dy2 - (y2 - y4) * dx2 < 0.0);
164 // It's is more expensive but more flexible
165 // in terms of boundary conditions.
166 //--------------------
167 //double den = (x2-x1) * (y4-y3) - (y2-y1) * (x4-x3);
168 //if(fabs(den) < intersection_epsilon) return false;
169 //double nom1 = (x4-x3) * (y1-y3) - (y4-y3) * (x1-x3);
170 //double nom2 = (x2-x1) * (y1-y3) - (y2-y1) * (x1-x3);
171 //double ua = nom1 / den;
172 //double ub = nom2 / den;
173 //return ua >= 0.0 && ua <= 1.0 && ub >= 0.0 && ub <= 1.0;
176 //--------------------------------------------------------calc_orthogonal
177 AGG_INLINE void calc_orthogonal(double thickness,
178 double x1, double y1,
179 double x2, double y2,
180 double* x, double* y)
182 double dx = x2 - x1;
183 double dy = y2 - y1;
184 double d = sqrt(dx*dx + dy*dy);
185 *x = thickness * dy / d;
186 *y = -thickness * dx / d;
189 //--------------------------------------------------------dilate_triangle
190 AGG_INLINE void dilate_triangle(double x1, double y1,
191 double x2, double y2,
192 double x3, double y3,
193 double *x, double* y,
194 double d)
196 double dx1=0.0;
197 double dy1=0.0;
198 double dx2=0.0;
199 double dy2=0.0;
200 double dx3=0.0;
201 double dy3=0.0;
202 double loc = cross_product(x1, y1, x2, y2, x3, y3);
203 if(fabs(loc) > intersection_epsilon)
205 if(cross_product(x1, y1, x2, y2, x3, y3) > 0.0)
207 d = -d;
209 calc_orthogonal(d, x1, y1, x2, y2, &dx1, &dy1);
210 calc_orthogonal(d, x2, y2, x3, y3, &dx2, &dy2);
211 calc_orthogonal(d, x3, y3, x1, y1, &dx3, &dy3);
213 *x++ = x1 + dx1; *y++ = y1 + dy1;
214 *x++ = x2 + dx1; *y++ = y2 + dy1;
215 *x++ = x2 + dx2; *y++ = y2 + dy2;
216 *x++ = x3 + dx2; *y++ = y3 + dy2;
217 *x++ = x3 + dx3; *y++ = y3 + dy3;
218 *x++ = x1 + dx3; *y++ = y1 + dy3;
221 //------------------------------------------------------calc_triangle_area
222 AGG_INLINE double calc_triangle_area(double x1, double y1,
223 double x2, double y2,
224 double x3, double y3)
226 return (x1*y2 - x2*y1 + x2*y3 - x3*y2 + x3*y1 - x1*y3) * 0.5;
229 //-------------------------------------------------------calc_polygon_area
230 template<class Storage> double calc_polygon_area(const Storage& st)
232 unsigned i;
233 double sum = 0.0;
234 double x = st[0].x;
235 double y = st[0].y;
236 double xs = x;
237 double ys = y;
239 for(i = 1; i < st.size(); i++)
241 const typename Storage::value_type& v = st[i];
242 sum += x * v.y - y * v.x;
243 x = v.x;
244 y = v.y;
246 return (sum + x * ys - y * xs) * 0.5;
249 //------------------------------------------------------------------------
250 // Tables for fast sqrt
251 extern int16u g_sqrt_table[1024];
252 extern int8 g_elder_bit_table[256];
255 //---------------------------------------------------------------fast_sqrt
256 //Fast integer Sqrt - really fast: no cycles, divisions or multiplications
257 #if defined(_MSC_VER)
258 #pragma warning(push)
259 #pragma warning(disable : 4035) //Disable warning "no return value"
260 #endif
261 AGG_INLINE unsigned fast_sqrt(unsigned val)
263 #if defined(_M_IX86) && defined(_MSC_VER) && !defined(AGG_NO_ASM)
264 //For Ix86 family processors this assembler code is used.
265 //The key command here is bsr - determination the number of the most
266 //significant bit of the value. For other processors
267 //(and maybe compilers) the pure C "#else" section is used.
268 __asm
270 mov ebx, val
271 mov edx, 11
272 bsr ecx, ebx
273 sub ecx, 9
274 jle less_than_9_bits
275 shr ecx, 1
276 adc ecx, 0
277 sub edx, ecx
278 shl ecx, 1
279 shr ebx, cl
280 less_than_9_bits:
281 xor eax, eax
282 mov ax, g_sqrt_table[ebx*2]
283 mov ecx, edx
284 shr eax, cl
286 #else
288 //This code is actually pure C and portable to most
289 //arcitectures including 64bit ones.
290 unsigned t = val;
291 int bit=0;
292 unsigned shift = 11;
294 //The following piece of code is just an emulation of the
295 //Ix86 assembler command "bsr" (see above). However on old
296 //Intels (like Intel MMX 233MHz) this code is about twice
297 //faster (sic!) then just one "bsr". On PIII and PIV the
298 //bsr is optimized quite well.
299 bit = t >> 24;
300 if(bit)
302 bit = g_elder_bit_table[bit] + 24;
304 else
306 bit = (t >> 16) & 0xFF;
307 if(bit)
309 bit = g_elder_bit_table[bit] + 16;
311 else
313 bit = (t >> 8) & 0xFF;
314 if(bit)
316 bit = g_elder_bit_table[bit] + 8;
318 else
320 bit = g_elder_bit_table[t];
325 //This is calculation sqrt itself.
326 bit -= 9;
327 if(bit > 0)
329 bit = (bit >> 1) + (bit & 1);
330 shift -= bit;
331 val >>= (bit << 1);
333 return g_sqrt_table[val] >> shift;
334 #endif
336 #if defined(_MSC_VER)
337 #pragma warning(pop)
338 #endif
343 //--------------------------------------------------------------------besj
344 // Function BESJ calculates Bessel function of first kind of order n
345 // Arguments:
346 // n - an integer (>=0), the order
347 // x - value at which the Bessel function is required
348 //--------------------
349 // C++ Mathematical Library
350 // Convereted from equivalent FORTRAN library
351 // Converetd by Gareth Walker for use by course 392 computational project
352 // All functions tested and yield the same results as the corresponding
353 // FORTRAN versions.
355 // If you have any problems using these functions please report them to
356 // M.Muldoon@UMIST.ac.uk
358 // Documentation available on the web
359 // http://www.ma.umist.ac.uk/mrm/Teaching/392/libs/392.html
360 // Version 1.0 8/98
361 // 29 October, 1999
362 //--------------------
363 // Adapted for use in AGG library by Andy Wilk (castor.vulgaris@gmail.com)
364 //------------------------------------------------------------------------
365 inline double besj(double x, int n)
367 if(n < 0)
369 return 0;
371 double d = 1E-6;
372 double b = 0;
373 if(fabs(x) <= d)
375 if(n != 0) return 0;
376 return 1;
378 double b1 = 0; // b1 is the value from the previous iteration
379 // Set up a starting order for recurrence
380 int m1 = (int)fabs(x) + 6;
381 if(fabs(x) > 5)
383 m1 = (int)(fabs(1.4 * x + 60 / x));
385 int m2 = (int)(n + 2 + fabs(x) / 4);
386 if (m1 > m2)
388 m2 = m1;
391 // Apply recurrence down from curent max order
392 for(;;)
394 double c3 = 0;
395 double c2 = 1E-30;
396 double c4 = 0;
397 int m8 = 1;
398 if (m2 / 2 * 2 == m2)
400 m8 = -1;
402 int imax = m2 - 2;
403 for (int i = 1; i <= imax; i++)
405 double c6 = 2 * (m2 - i) * c2 / x - c3;
406 c3 = c2;
407 c2 = c6;
408 if(m2 - i - 1 == n)
410 b = c6;
412 m8 = -1 * m8;
413 if (m8 > 0)
415 c4 = c4 + 2 * c6;
418 double c6 = 2 * c2 / x - c3;
419 if(n == 0)
421 b = c6;
423 c4 += c6;
424 b /= c4;
425 if(fabs(b - b1) < d)
427 return b;
429 b1 = b;
430 m2 += 3;
437 #endif