moab
|
00001 #ifndef FINDPTFUNCS_H 00002 #define FINDPTFUNCS_H 00003 00004 #include "float.h" 00005 #include "math.h" 00006 00007 /*====================================================== 00008 / from types.h 00009 /====================================================== 00010 */ 00011 00012 /* integer type to use for everything */ 00013 #if defined(USE_LONG) 00014 # define INTEGER long 00015 #elif defined(USE_LONG_LONG) 00016 # define INTEGER long long 00017 #elif defined(USE_SHORT) 00018 # define INTEGER short 00019 #else 00020 # define INTEGER int 00021 #endif 00022 00023 /* when defined, use the given type for global indices instead of INTEGER */ 00024 #if defined(USE_GLOBAL_LONG_LONG) 00025 # define GLOBAL_INT long long 00026 #elif defined(USE_GLOBAL_LONG) 00027 # define GLOBAL_INT long 00028 #else 00029 # define GLOBAL_INT long 00030 #endif 00031 00032 /* floating point type to use for everything */ 00033 #if defined(USE_FLOAT) 00034 typedef float real; 00035 # define floorr floorf 00036 # define ceilr ceilf 00037 # define sqrtr sqrtf 00038 # define fabsr fabsf 00039 # define cosr cosf 00040 # define sinr sinf 00041 # define EPS (128*FLT_EPSILON) 00042 # define PI 3.1415926535897932384626433832795028841971693993751058209749445923F 00043 #elif defined(USE_LONG_DOUBLE) 00044 typedef long double real; 00045 # define floorr floorl 00046 # define ceilr ceill 00047 # define sqrtr sqrtl 00048 # define fabsr fabsl 00049 # define cosr cosl 00050 # define sinr sinl 00051 # define EPS (128*LDBL_EPSILON) 00052 # define PI 3.1415926535897932384626433832795028841971693993751058209749445923L 00053 #else 00054 typedef double real; 00055 # define floorr floor 00056 # define ceilr ceil 00057 # define sqrtr sqrt 00058 # define fabsr fabs 00059 # define cosr cos 00060 # define sinr sin 00061 # define EPS (128*DBL_EPSILON) 00062 # define PI 3.1415926535897932384626433832795028841971693993751058209749445923 00063 #endif 00064 00065 /* apparently uint and ulong can be defined already in standard headers */ 00066 #define uint uint_ 00067 #define ulong ulong_ 00068 #define sint sint_ 00069 #define slong slong_ 00070 00071 typedef signed INTEGER sint; 00072 typedef unsigned INTEGER uint; 00073 #undef INTEGER 00074 00075 #ifdef GLOBAL_INT 00076 typedef signed GLOBAL_INT slong; 00077 typedef unsigned GLOBAL_INT ulong; 00078 #else 00079 typedef sint slong; 00080 typedef uint ulong; 00081 #endif 00082 00083 /*====================================================== 00084 / from poly.h 00085 /====================================================== 00086 */ 00087 00088 /* 00089 For brevity's sake, some names have been shortened 00090 Quadrature rules 00091 Gauss -> Gauss-Legendre quadrature (open) 00092 Lobatto -> Gauss-Lobatto-Legendre quadrature (closed at both ends) 00093 Polynomial bases 00094 Legendre -> Legendre basis 00095 Gauss -> Lagrangian basis using Gauss quadrature nodes 00096 Lobatto -> Lagrangian basis using Lobatto quadrature nodes 00097 */ 00098 00099 /*-------------------------------------------------------------------------- 00100 Legendre Polynomial Matrix Computation 00101 (compute P_i(x_j) for i = 0, ..., n and a given set of x) 00102 --------------------------------------------------------------------------*/ 00103 00104 /* precondition: n >= 1 00105 inner index is x index (0 ... m-1); 00106 outer index is Legendre polynomial number (0 ... n) 00107 */ 00108 void legendre_matrix(const real *x, int m, real *P, int n); 00109 00110 /* precondition: n >= 1 00111 inner index is Legendre polynomial number (0 ... n) 00112 outer index is x index (0 ... m-1); 00113 */ 00114 void legendre_matrix_t(const real *x, int m, real *P, int n); 00115 00116 /* precondition: n >= 1 00117 compute P_i(x) with i = 0 ... n 00118 */ 00119 void legendre_row(real x, real *P, int n); 00120 00121 00122 /*-------------------------------------------------------------------------- 00123 Quadrature Nodes and Weights Calculation 00124 00125 call the _nodes function before calling the _weights function 00126 --------------------------------------------------------------------------*/ 00127 00128 void gauss_nodes(real *z, int n); /* n nodes (order = 2n-1) */ 00129 void lobatto_nodes(real *z, int n); /* n nodes (order = 2n-3) */ 00130 00131 void gauss_weights(const real *z, real *w, int n); 00132 void lobatto_weights(const real *z, real *w, int n); 00133 00134 /*-------------------------------------------------------------------------- 00135 Lagrangian to Legendre Change-of-basis Matrix 00136 --------------------------------------------------------------------------*/ 00137 00138 /* precondition: n >= 2 00139 given the Gauss quadrature rule (z,w,n), compute the square matrix J 00140 for transforming from the Gauss basis to the Legendre basis: 00141 00142 u_legendre(i) = sum_j J(i,j) u_gauss(j) 00143 00144 computes J = .5 (2i+1) w P (z ) 00145 ij j i j 00146 00147 in column major format (inner index is i, the Legendre index) 00148 */ 00149 void gauss_to_legendre(const real *z, const real *w, int n, real *J); 00150 00151 /* precondition: n >= 2 00152 same as above, but 00153 in row major format (inner index is j, the Gauss index) 00154 */ 00155 void gauss_to_legendre_t(const real *z, const real *w, int n, real *J); 00156 00157 /* precondition: n >= 3 00158 given the Lobatto quadrature rule (z,w,n), compute the square matrix J 00159 for transforming from the Lobatto basis to the Legendre basis: 00160 00161 u_legendre(i) = sum_j J(i,j) u_lobatto(j) 00162 00163 in column major format (inner index is i, the Legendre index) 00164 */ 00165 void lobatto_to_legendre(const real *z, const real *w, int n, real *J); 00166 00167 /*-------------------------------------------------------------------------- 00168 Lagrangian basis function evaluation 00169 --------------------------------------------------------------------------*/ 00170 00171 /* given the Lagrangian nodes (z,n) and evaluation points (x,m) 00172 evaluate all Lagrangian basis functions at all points x 00173 00174 inner index of output J is the basis function index (row-major format) 00175 provide work array with space for 4*n doubles 00176 */ 00177 void lagrange_weights(const real *z, unsigned n, 00178 const real *x, unsigned m, 00179 real *J, real *work); 00180 00181 /* given the Lagrangian nodes (z,n) and evaluation points (x,m) 00182 evaluate all Lagrangian basis functions and their derivatives 00183 00184 inner index of outputs J,D is the basis function index (row-major format) 00185 provide work array with space for 6*n doubles 00186 */ 00187 void lagrange_weights_deriv(const real *z, unsigned n, 00188 const real *x, unsigned m, 00189 real *J, real *D, real *work); 00190 00191 /*-------------------------------------------------------------------------- 00192 Speedy Lagrangian Interpolation 00193 00194 Usage: 00195 00196 lagrange_data p; 00197 lagrange_setup(&p,z,n); * setup for nodes z[0 ... n-1] * 00198 00199 the weights 00200 p->J [0 ... n-1] interpolation weights 00201 p->D [0 ... n-1] 1st derivative weights 00202 p->D2[0 ... n-1] 2nd derivative weights 00203 are computed for a given x with: 00204 lagrange_0(p,x); * compute p->J * 00205 lagrange_1(p,x); * compute p->J, p->D * 00206 lagrange_2(p,x); * compute p->J, p->D, p->D2 * 00207 lagrange_2u(p); * compute p->D2 after call of lagrange_1(p,x); * 00208 These functions use the z array supplied to setup 00209 (that pointer should not be freed between calls) 00210 Weights for x=z[0] and x=z[n-1] are computed during setup; access as: 00211 p->J_z0, etc. and p->J_zn, etc. 00212 00213 lagrange_free(&p); * deallocate memory allocated by setup * 00214 --------------------------------------------------------------------------*/ 00215 00216 typedef struct { 00217 unsigned n; /* number of Lagrange nodes */ 00218 const real *z; /* Lagrange nodes (user-supplied) */ 00219 real *J, *D, *D2; /* weights for 0th,1st,2nd derivatives */ 00220 real *J_z0, *D_z0, *D2_z0; /* ditto at z[0] (computed at setup) */ 00221 real *J_zn, *D_zn, *D2_zn; /* ditto at z[n-1] (computed at setup) */ 00222 real *w, *d, *u0, *v0, *u1, *v1, *u2, *v2; /* work data */ 00223 } lagrange_data; 00224 00225 void lagrange_setup(lagrange_data *p, const real *z, unsigned n); 00226 void lagrange_free(lagrange_data *p); 00227 00228 void lagrange_0(lagrange_data *p, real x) ; 00229 void lagrange_1(lagrange_data *p, real x) ; 00230 void lagrange_2(lagrange_data *p, real x) ; 00231 void lagrange_2u(lagrange_data *p) ; 00232 00233 /*====================================================== 00234 / from tensor.h 00235 /====================================================== 00236 */ 00237 00238 /*-------------------------------------------------------------------------- 00239 1-,2-,3-d Tensor Application 00240 00241 the 3d case: 00242 tensor_f3(R,mr,nr, S,ms,ns, T,mt,nt, u,v, work1,work2) 00243 gives v = [ R (x) S (x) T ] u 00244 where R is mr x nr, S is ms x ns, T is mt x nt, 00245 each in row- or column-major format according to f := r | c 00246 u is nr x ns x nt in column-major format (inner index is r) 00247 v is mr x ms x mt in column-major format (inner index is r) 00248 --------------------------------------------------------------------------*/ 00249 00250 void tensor_c1(const real *R, unsigned mr, unsigned nr, 00251 const real *u, real *v); 00252 void tensor_r1(const real *R, unsigned mr, unsigned nr, 00253 const real *u, real *v); 00254 00255 /* work holds mr*ns reals */ 00256 void tensor_c2(const real *R, unsigned mr, unsigned nr, 00257 const real *S, unsigned ms, unsigned ns, 00258 const real *u, real *v, real *work); 00259 void tensor_r2(const real *R, unsigned mr, unsigned nr, 00260 const real *S, unsigned ms, unsigned ns, 00261 const real *u, real *v, real *work); 00262 00263 /* work1 holds mr*ns*nt reals, 00264 work2 holds mr*ms*nt reals */ 00265 void tensor_c3(const real *R, unsigned mr, unsigned nr, 00266 const real *S, unsigned ms, unsigned ns, 00267 const real *T, unsigned mt, unsigned nt, 00268 const real *u, real *v, real *work1, real *work2); 00269 void tensor_r3(const real *R, unsigned mr, unsigned nr, 00270 const real *S, unsigned ms, unsigned ns, 00271 const real *T, unsigned mt, unsigned nt, 00272 const real *u, real *v, real *work1, real *work2); 00273 00274 /*-------------------------------------------------------------------------- 00275 1-,2-,3-d Tensor Application of Row Vectors (for Interpolation) 00276 00277 the 3d case: 00278 v = tensor_i3(Jr,nr, Js,ns, Jt,nt, u, work) 00279 same effect as tensor_r3(Jr,1,nr, Js,1,ns, Jt,1,nt, u,&v, work1,work2): 00280 gives v = [ Jr (x) Js (x) Jt ] u 00281 where Jr, Js, Jt are row vectors (interpolation weights) 00282 u is nr x ns x nt in column-major format (inner index is r) 00283 v is a scalar 00284 --------------------------------------------------------------------------*/ 00285 00286 real tensor_i1(const real *Jr, unsigned nr, const real *u); 00287 00288 /* work holds ns reals */ 00289 real tensor_i2(const real *Jr, unsigned nr, 00290 const real *Js, unsigned ns, 00291 const real *u, real *work); 00292 00293 /* work holds ns*nt + nt reals */ 00294 real tensor_i3(const real *Jr, unsigned nr, 00295 const real *Js, unsigned ns, 00296 const real *Jt, unsigned nt, 00297 const real *u, real *work); 00298 00299 /*-------------------------------------------------------------------------- 00300 1-,2-,3-d Tensor Application of Row Vectors 00301 for simultaneous Interpolation and Gradient computation 00302 00303 the 3d case: 00304 v = tensor_ig3(Jr,Dr,nr, Js,Ds,ns, Jt,Dt,nt, u,g, work) 00305 gives v = [ Jr (x) Js (x) Jt ] u 00306 g_0 = [ Dr (x) Js (x) Jt ] u 00307 g_1 = [ Jr (x) Ds (x) Jt ] u 00308 g_2 = [ Jr (x) Js (x) Dt ] u 00309 where Jr,Dr,Js,Ds,Jt,Dt are row vectors 00310 (interpolation & derivative weights) 00311 u is nr x ns x nt in column-major format (inner index is r) 00312 v is a scalar, g is an array of 3 reals 00313 --------------------------------------------------------------------------*/ 00314 00315 real tensor_ig1(const real *Jr, const real *Dr, unsigned nr, 00316 const real *u, real *g); 00317 00318 /* work holds 2*ns reals */ 00319 real tensor_ig2(const real *Jr, const real *Dr, unsigned nr, 00320 const real *Js, const real *Ds, unsigned ns, 00321 const real *u, real *g, real *work); 00322 00323 /* work holds 2*ns*nt + 3*ns reals */ 00324 real tensor_ig3(const real *Jr, const real *Dr, unsigned nr, 00325 const real *Js, const real *Ds, unsigned ns, 00326 const real *Jt, const real *Dt, unsigned nt, 00327 const real *u, real *g, real *work); 00328 00329 /*====================================================== 00330 / from findpt.h 00331 /====================================================== 00332 */ 00333 00334 typedef struct { 00335 real x[2], A[4], axis_bnd[4]; 00336 } obbox_2; 00337 00338 typedef struct { 00339 real x[3], A[9], axis_bnd[6]; 00340 } obbox_3; 00341 00342 typedef struct { 00343 unsigned hash_n; 00344 real bnd[4]; /* bounds for all elements */ 00345 real fac[2]; /* fac[i] = hash_n / (bnd[2*i+1]-bnd[2*i]) */ 00346 obbox_2 *obb; /* obb[nel] -- bounding box info for each element */ 00347 uint *offset; /* hash table -- for cell i,j: 00348 uint index = j*hash_n+i, 00349 b = offset[index ], 00350 e = offset[index+1]; 00351 elements in cell are 00352 offset[b], offset[b+1], ..., offset[e-1] */ 00353 unsigned max; /* maximum # of elements in any cell */ 00354 } hash_data_2; 00355 00356 typedef struct { 00357 unsigned hash_n; 00358 real bnd[6]; /* bounds for all elements */ 00359 real fac[3]; /* fac[i] = hash_n / (bnd[2*i+1]-bnd[2*i]) */ 00360 obbox_3 *obb; /* obb[nel] -- bounding box info for each element */ 00361 uint *offset; /* hash table -- for cell i,j,k: 00362 uint index = (k*hash_n+j)*hash_n+i, 00363 b = offset[index ], 00364 e = offset[index+1]; 00365 elements in cell are 00366 offset[b], offset[b+1], ..., offset[e-1] */ 00367 unsigned max; /* maximum # of elements in any cell */ 00368 } hash_data_3; 00369 00370 typedef struct { 00371 uint el; 00372 real r[3]; 00373 real dist; 00374 } findpt_listel; 00375 00376 typedef struct { 00377 unsigned constraints; 00378 unsigned de, d1; 00379 real *x[2], *fd1[2]; 00380 } opt_edge_data_2; 00381 00382 typedef struct { 00383 unsigned constraints; 00384 real x[2], jac[4]; 00385 } opt_point_data_2; 00386 00387 typedef struct { 00388 lagrange_data *ld; 00389 unsigned size[3]; 00390 const real *elx[2]; 00391 opt_edge_data_2 ed; 00392 opt_point_data_2 pd; 00393 real *work; 00394 real x[2], jac[4]; 00395 } opt_data_2; 00396 00397 typedef struct { 00398 const real *xw[2]; /* geometry data */ 00399 real *z[2]; /* lobatto nodes */ 00400 lagrange_data ld[2]; /* interpolation, derivative weights & data */ 00401 unsigned nptel; /* nodes per element */ 00402 hash_data_2 *hash; /* geometric hashing data */ 00403 findpt_listel *list, **sorted, **end; 00404 /* pre-allocated list of elements to 00405 check (found by hashing), and 00406 pre-allocated list of pointers into 00407 the first list for sorting */ 00408 opt_data_2 *od; /* data for the optimization algorithm */ 00409 real *od_work; 00410 } findpt_data_2; 00411 00412 typedef struct { 00413 unsigned constraints; 00414 unsigned dn, d1, d2; 00415 real *x[3], *fdn[3]; 00416 } opt_face_data_3; 00417 00418 typedef struct { 00419 unsigned constraints; 00420 unsigned de, d1, d2; 00421 real *x[3], *fd1[3], *fd2[3]; 00422 } opt_edge_data_3; 00423 00424 typedef struct { 00425 unsigned constraints; 00426 real x[3], jac[9]; 00427 } opt_point_data_3; 00428 00429 typedef struct { 00430 lagrange_data *ld; 00431 unsigned size[4]; 00432 const real *elx[3]; 00433 opt_face_data_3 fd; 00434 opt_edge_data_3 ed; 00435 opt_point_data_3 pd; 00436 real *work; 00437 real x[3], jac[9]; 00438 } opt_data_3; 00439 00440 typedef struct { 00441 const real *xw[3]; /* geometry data */ 00442 real *z[3]; /* lobatto nodes */ 00443 lagrange_data ld[3]; /* interpolation, derivative weights & data */ 00444 unsigned nptel; /* nodes per element */ 00445 hash_data_3 *hash; /* geometric hashing data */ 00446 findpt_listel *list, **sorted, **end; 00447 /* pre-allocated list of elements to 00448 check (found by hashing), and 00449 pre-allocated list of pointers into 00450 the first list for sorting */ 00451 opt_data_3 *od; /* data for the optimization algorithm */ 00452 real *od_work; 00453 } findpt_data_3; 00454 00455 findpt_data_2 *findpt_setup_2( 00456 const real *const xw[2], const unsigned n[2], uint nel, 00457 uint max_hash_size, real bbox_tol); 00458 findpt_data_3 *findpt_setup_3( 00459 const real *const xw[3], const unsigned n[3], uint nel, 00460 uint max_hash_size, real bbox_tol); 00461 00462 void findpt_free_2(findpt_data_2 *p); 00463 void findpt_free_3(findpt_data_3 *p); 00464 00465 const real *findpt_allbnd_2(const findpt_data_2 *p); 00466 const real *findpt_allbnd_3(const findpt_data_3 *p); 00467 00468 typedef int (*findpt_func)(void *, const real *, int, uint *, real *, real *); 00469 int findpt_2(findpt_data_2 *p, const real x[2], int guess, 00470 uint *el, real r[2], real *dist); 00471 int findpt_3(findpt_data_3 *p, const real x[3], int guess, 00472 uint *el, real r[3], real *dist); 00473 00474 void findpt_weights_2(findpt_data_2 *p, const real r[2]); 00475 00476 void findpt_weights_3(findpt_data_3 *p, const real r[3]); 00477 00478 double findpt_eval_2(findpt_data_2 *p, const real *u); 00479 00480 double findpt_eval_3(findpt_data_3 *p, const real *u); 00481 00482 /*====================================================== 00483 / from extrafindpt.h 00484 /====================================================== 00485 */ 00486 00487 void opt_alloc_3(opt_data_3 *p, lagrange_data *ld); 00488 void opt_free_3(opt_data_3 *p); 00489 double opt_findpt_3(opt_data_3 *p, const real *const elx[3], 00490 const real xstar[3], real r[3], unsigned *constr); 00491 void opt_vol_set_intp_3(opt_data_3 *p, const real r[3]); 00492 00493 /* for 2d spectralQuad */ 00494 /*-------------------------------------------------------------------------- 00495 00496 2 - D 00497 00498 --------------------------------------------------------------------------*/ 00499 00500 void opt_alloc_2(opt_data_2 *p, lagrange_data *ld); 00501 void opt_free_2(opt_data_2 *p); 00502 double opt_findpt_2(opt_data_2 *p, const real *const elx[2], 00503 const real xstar[2], real r[2], unsigned *constr); 00504 00505 extern const unsigned opt_no_constraints_2; 00506 extern const unsigned opt_no_constraints_3; 00507 00508 /*====================================================== 00509 / from errmem.h 00510 /====================================================== 00511 */ 00512 00513 /* requires: 00514 <stdlib.h> for malloc, calloc, realloc, free 00515 */ 00516 00517 /*-------------------------------------------------------------------------- 00518 Error Reporting 00519 Memory Allocation Wrappers to Catch Out-of-memory 00520 --------------------------------------------------------------------------*/ 00521 00522 /* #include "malloc.h" */ 00523 #include <stdlib.h> 00524 00525 #ifdef __GNUC__ 00526 void fail(const char *fmt, ...) __attribute__ ((noreturn)); 00527 #define MAYBE_UNUSED __attribute__ ((unused)) 00528 #else 00529 void fail(const char *fmt, ...); 00530 #define MAYBE_UNUSED 00531 #endif 00532 00533 #if 0 00534 {} 00535 #endif 00536 00537 static void *smalloc(size_t size, const char *file) MAYBE_UNUSED; 00538 static void *smalloc(size_t size, const char *file) 00539 { 00540 void *res = malloc(size); 00541 if(!res && size) fail("%s: allocation of %d bytes failed\n",file,(int)size); 00542 return res; 00543 } 00544 00545 static void *scalloc(size_t nmemb, size_t size, const char *file) MAYBE_UNUSED; 00546 static void *scalloc(size_t nmemb, size_t size, const char *file) 00547 { 00548 void *res = calloc(nmemb, size); 00549 if(!res && nmemb) 00550 fail("%s: allocation of %d bytes failed\n",file,(int)size*nmemb); 00551 return res; 00552 } 00553 00554 static void *srealloc(void *ptr, size_t size, const char *file) MAYBE_UNUSED; 00555 static void *srealloc(void *ptr, size_t size, const char *file) 00556 { 00557 void *res = realloc(ptr, size); 00558 if(!res && size) fail("%s: allocation of %d bytes failed\n",file,(int)size); 00559 return res; 00560 } 00561 00562 #define tmalloc(type, count) \ 00563 ((type*) smalloc((count)*sizeof(type),__FILE__) ) 00564 #define tcalloc(type, count) \ 00565 ((type*) scalloc((count),sizeof(type),__FILE__) ) 00566 #define trealloc(type, ptr, count) \ 00567 ((type*) srealloc((ptr),(count)*sizeof(type),__FILE__) ) 00568 /* 00569 typedef struct { size_t size; void *ptr; } buffer; 00570 00571 static void buffer_init_(buffer *b, size_t size, const char *file) MAYBE_UNUSED; 00572 static void buffer_init_(buffer *b, size_t size, const char *file) 00573 { 00574 b->size=size, b->ptr=smalloc(size,file); 00575 } 00576 static void buffer_reserve_(buffer *b, size_t min, const char *file) 00577 MAYBE_UNUSED; 00578 static void buffer_reserve_(buffer *b, size_t min, const char *file) 00579 { 00580 size_t size = b->size; 00581 if(size<min) { 00582 size+=size/2+1; 00583 if(size<min) size=min; 00584 b->ptr=srealloc(b->ptr,size,file); 00585 } 00586 } 00587 static void buffer_free(buffer *b) MAYBE_UNUSED; 00588 static void buffer_free(buffer *b) { free(b->ptr); } 00589 00590 #define buffer_init(b,size) buffer_init_(b,size,__FILE__) 00591 #define buffer_reserve(b,min) buffer_reserve_(b,min,__FILE__) 00592 */ 00593 00594 00595 /*====================================================== 00596 / from minmax.h 00597 /====================================================== 00598 */ 00599 00600 /*-------------------------------------------------------------------------- 00601 Min, Max, Norm 00602 --------------------------------------------------------------------------*/ 00603 00604 #ifdef __GNUC__ 00605 #define MAYBE_UNUSED __attribute__ ((unused)) 00606 #else 00607 #define MAYBE_UNUSED 00608 #endif 00609 00610 #define DECLMINMAX(type, prefix) \ 00611 static type prefix##min_2(type a, type b) MAYBE_UNUSED; \ 00612 static type prefix##min_2(type a, type b) { \ 00613 return b<a?b:a; \ 00614 } \ 00615 static type prefix##max_2(type a, type b) MAYBE_UNUSED; \ 00616 static type prefix##max_2(type a, type b) { \ 00617 return a>b?a:b; \ 00618 } \ 00619 static void prefix##minmax_2(type *min, type *max, type a, \ 00620 type b) MAYBE_UNUSED; \ 00621 static void prefix##minmax_2(type *min, type *max, type a, type b) { \ 00622 if(b<a) *min=b, *max=a; \ 00623 else *min=a, *max=b; \ 00624 } \ 00625 static type prefix##min_3(type a, type b, type c) MAYBE_UNUSED; \ 00626 static type prefix##min_3(type a, type b, type c) { \ 00627 return b<a?(c<b?c:b):(c<a?c:a); \ 00628 } \ 00629 static type prefix##max_3(type a, type b, type c) MAYBE_UNUSED; \ 00630 static type prefix##max_3(type a, type b, type c) { \ 00631 return a>b?(a>c?a:c):(b>c?b:c); \ 00632 } \ 00633 static void prefix##minmax_3(type *min, type *max, type a, type b, \ 00634 type c) MAYBE_UNUSED; \ 00635 static void prefix##minmax_3(type *min, type *max, type a, type b, \ 00636 type c) { \ 00637 if(b<a) *min=prefix##min_2(b,c), *max=prefix##max_2(a,c); \ 00638 else *min=prefix##min_2(a,c), *max=prefix##max_2(b,c); \ 00639 } 00640 00641 DECLMINMAX(int, i) 00642 DECLMINMAX(unsigned, u) 00643 DECLMINMAX(real, r) 00644 #undef DECLMINMAX 00645 00646 static real r1norm_1(real a) MAYBE_UNUSED; 00647 static real r1norm_1(real a) { 00648 return fabsr(a); 00649 } 00650 static real r1norm_2(real a, real b) MAYBE_UNUSED; 00651 static real r1norm_2(real a, real b) { 00652 return fabsr(a)+fabsr(b); 00653 } 00654 static real r1norm_3(real a, real b, real c) MAYBE_UNUSED; 00655 static real r1norm_3(real a, real b, real c) { 00656 return fabsr(a)+fabsr(b)+fabsr(c); 00657 } 00658 static real r2norm_1(real a) MAYBE_UNUSED; 00659 static real r2norm_1(real a) { 00660 return sqrtr(a*a); 00661 } 00662 static real r2norm_2(real a, real b) MAYBE_UNUSED; 00663 static real r2norm_2(real a, real b) { 00664 return sqrtr(a*a+b*b); 00665 } 00666 static real r2norm_3(real a, real b, real c) MAYBE_UNUSED; 00667 static real r2norm_3(real a, real b, real c) { 00668 return sqrtr(a*a+b*b+c*c); 00669 } 00670 00671 #endif 00672 00673