WCSLIB  4.25.1
tab.h
Go to the documentation of this file.
1 /*============================================================================
2 
3  WCSLIB 4.25 - an implementation of the FITS WCS standard.
4  Copyright (C) 1995-2015, Mark Calabretta
5 
6  This file is part of WCSLIB.
7 
8  WCSLIB is free software: you can redistribute it and/or modify it under the
9  terms of the GNU Lesser General Public License as published by the Free
10  Software Foundation, either version 3 of the License, or (at your option)
11  any later version.
12 
13  WCSLIB is distributed in the hope that it will be useful, but WITHOUT ANY
14  WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
15  FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for
16  more details.
17 
18  You should have received a copy of the GNU Lesser General Public License
19  along with WCSLIB. If not, see http://www.gnu.org/licenses.
20 
21  Direct correspondence concerning WCSLIB to mark@calabretta.id.au
22 
23  Author: Mark Calabretta, Australia Telescope National Facility, CSIRO.
24  http://www.atnf.csiro.au/people/Mark.Calabretta
25  $Id: tab.h,v 4.25.1.2 2015/01/06 01:01:06 mcalabre Exp mcalabre $
26 *=============================================================================
27 *
28 * WCSLIB 4.25 - C routines that implement tabular coordinate systems as
29 * defined by the FITS World Coordinate System (WCS) standard. Refer to
30 *
31 * "Representations of world coordinates in FITS",
32 * Greisen, E.W., & Calabretta, M.R. 2002, A&A, 395, 1061 (paper I)
33 *
34 * "Representations of spectral coordinates in FITS",
35 * Greisen, E.W., Calabretta, M.R., Valdes, F.G., & Allen, S.L.
36 * 2006, A&A, 446, 747 (Paper III)
37 *
38 * Refer to the README file provided with WCSLIB for an overview of the
39 * library.
40 *
41 *
42 * Summary of the tab routines
43 * ---------------------------
44 * These routines implement the part of the FITS WCS standard that deals with
45 * tabular coordinates, i.e. coordinates that are defined via a lookup table.
46 * They define methods to be used for computing tabular world coordinates from
47 * intermediate world coordinates (a linear transformation of image pixel
48 * coordinates), and vice versa. They are based on the tabprm struct which
49 * contains all information needed for the computations. The struct contains
50 * some members that must be set by the user, and others that are maintained
51 * by these routines, somewhat like a C++ class but with no encapsulation.
52 *
53 * tabini(), tabmem(), tabcpy(), and tabfree() are provided to manage the
54 * tabprm struct, and another, tabprt(), to print its contents.
55 *
56 * A setup routine, tabset(), computes intermediate values in the tabprm struct
57 * from parameters in it that were supplied by the user. The struct always
58 * needs to be set up by tabset() but it need not be called explicitly - refer
59 * to the explanation of tabprm::flag.
60 *
61 * tabx2s() and tabs2x() implement the WCS tabular coordinate transformations.
62 *
63 * Accuracy:
64 * ---------
65 * No warranty is given for the accuracy of these routines (refer to the
66 * copyright notice); intending users must satisfy for themselves their
67 * adequacy for the intended purpose. However, closure effectively to within
68 * double precision rounding error was demonstrated by test routine ttab.c
69 * which accompanies this software.
70 *
71 *
72 * tabini() - Default constructor for the tabprm struct
73 * ----------------------------------------------------
74 * tabini() allocates memory for arrays in a tabprm struct and sets all members
75 * of the struct to default values.
76 *
77 * PLEASE NOTE: every tabprm struct should be initialized by tabini(), possibly
78 * repeatedly. On the first invokation, and only the first invokation, the
79 * flag member of the tabprm struct must be set to -1 to initialize memory
80 * management, regardless of whether tabini() will actually be used to allocate
81 * memory.
82 *
83 * Given:
84 * alloc int If true, allocate memory unconditionally for arrays in
85 * the tabprm struct.
86 *
87 * If false, it is assumed that pointers to these arrays
88 * have been set by the user except if they are null
89 * pointers in which case memory will be allocated for
90 * them regardless. (In other words, setting alloc true
91 * saves having to initalize these pointers to zero.)
92 *
93 * M int The number of tabular coordinate axes.
94 *
95 * K const int[]
96 * Vector of length M whose elements (K_1, K_2,... K_M)
97 * record the lengths of the axes of the coordinate array
98 * and of each indexing vector. M and K[] are used to
99 * determine the length of the various tabprm arrays and
100 * therefore the amount of memory to allocate for them.
101 * Their values are copied into the tabprm struct.
102 *
103 * It is permissible to set K (i.e. the address of the
104 * array) to zero which has the same effect as setting
105 * each element of K[] to zero. In this case no memory
106 * will be allocated for the index vectors or coordinate
107 * array in the tabprm struct. These together with the
108 * K vector must be set separately before calling
109 * tabset().
110 *
111 * Given and returned:
112 * tab struct tabprm*
113 * Tabular transformation parameters. Note that, in
114 * order to initialize memory management tabprm::flag
115 * should be set to -1 when tab is initialized for the
116 * first time (memory leaks may result if it had already
117 * been initialized).
118 *
119 * Function return value:
120 * int Status return value:
121 * 0: Success.
122 * 1: Null tabprm pointer passed.
123 * 2: Memory allocation failed.
124 * 3: Invalid tabular parameters.
125 *
126 * For returns > 1, a detailed error message is set in
127 * tabprm::err if enabled, see wcserr_enable().
128 *
129 *
130 * tabmem() - Acquire tabular memory
131 * ---------------------------------
132 * tabmem() takes control of memory allocated by the user for arrays in the
133 * tabprm struct.
134 *
135 * Given and returned:
136 * tab struct tabprm*
137 * Tabular transformation parameters.
138 *
139 * Function return value:
140 * int Status return value:
141 * 0: Success.
142 * 1: Null tabprm pointer passed.
143 * 2: Memory allocation failed.
144 *
145 * For returns > 1, a detailed error message is set in
146 * tabprm::err if enabled, see wcserr_enable().
147 *
148 *
149 * tabcpy() - Copy routine for the tabprm struct
150 * ---------------------------------------------
151 * tabcpy() does a deep copy of one tabprm struct to another, using tabini() to
152 * allocate memory for its arrays if required. Only the "information to be
153 * provided" part of the struct is copied; a call to tabset() is required to
154 * set up the remainder.
155 *
156 * Given:
157 * alloc int If true, allocate memory unconditionally for arrays in
158 * the tabprm struct.
159 *
160 * If false, it is assumed that pointers to these arrays
161 * have been set by the user except if they are null
162 * pointers in which case memory will be allocated for
163 * them regardless. (In other words, setting alloc true
164 * saves having to initalize these pointers to zero.)
165 *
166 * tabsrc const struct tabprm*
167 * Struct to copy from.
168 *
169 * Given and returned:
170 * tabdst struct tabprm*
171 * Struct to copy to. tabprm::flag should be set to -1
172 * if tabdst was not previously initialized (memory leaks
173 * may result if it was previously initialized).
174 *
175 * Function return value:
176 * int Status return value:
177 * 0: Success.
178 * 1: Null tabprm pointer passed.
179 * 2: Memory allocation failed.
180 *
181 * For returns > 1, a detailed error message is set in
182 * tabprm::err (associated with tabdst) if enabled, see
183 * wcserr_enable().
184 *
185 *
186 * tabcmp() - Compare two tabprm structs for equality
187 * --------------------------------------------------
188 * tabcmp() compares two tabprm structs for equality.
189 *
190 * Given:
191 * cmp int A bit field controlling the strictness of the
192 * comparison. At present, this value must always be 0,
193 * indicating a strict comparison. In the future, other
194 * options may be added.
195 *
196 * tol double Tolerance for comparison of floating-point values.
197 * For example, for tol == 1e-6, all floating-point
198 * values in the structs must be equal to the first 6
199 * decimal places. A value of 0 implies exact equality.
200 *
201 * tab1 const struct tabprm*
202 * The first tabprm struct to compare.
203 *
204 * tab2 const struct tabprm*
205 * The second tabprm struct to compare.
206 *
207 * Returned:
208 * equal int* Non-zero when the given structs are equal.
209 *
210 * Function return value:
211 * int Status return value:
212 * 0: Success.
213 * 1: Null pointer passed.
214 *
215 *
216 * tabfree() - Destructor for the tabprm struct
217 * --------------------------------------------
218 * tabfree() frees memory allocated for the tabprm arrays by tabini().
219 * tabini() records the memory it allocates and tabfree() will only attempt to
220 * free this.
221 *
222 * PLEASE NOTE: tabfree() must not be invoked on a tabprm struct that was not
223 * initialized by tabini().
224 *
225 * Returned:
226 * tab struct tabprm*
227 * Coordinate transformation parameters.
228 *
229 * Function return value:
230 * int Status return value:
231 * 0: Success.
232 * 1: Null tabprm pointer passed.
233 *
234 *
235 * tabprt() - Print routine for the tabprm struct
236 * ----------------------------------------------
237 * tabprt() prints the contents of a tabprm struct using wcsprintf(). Mainly
238 * intended for diagnostic purposes.
239 *
240 * Given:
241 * tab const struct tabprm*
242 * Tabular transformation parameters.
243 *
244 * Function return value:
245 * int Status return value:
246 * 0: Success.
247 * 1: Null tabprm pointer passed.
248 *
249 *
250 * tabset() - Setup routine for the tabprm struct
251 * -----------------------------------------------
252 * tabset() allocates memory for work arrays in the tabprm struct and sets up
253 * the struct according to information supplied within it.
254 *
255 * Note that this routine need not be called directly; it will be invoked by
256 * tabx2s() and tabs2x() if tabprm::flag is anything other than a predefined
257 * magic value.
258 *
259 * Given and returned:
260 * tab struct tabprm*
261 * Tabular transformation parameters.
262 *
263 * Function return value:
264 * int Status return value:
265 * 0: Success.
266 * 1: Null tabprm pointer passed.
267 * 3: Invalid tabular parameters.
268 *
269 * For returns > 1, a detailed error message is set in
270 * tabprm::err if enabled, see wcserr_enable().
271 *
272 *
273 * tabx2s() - Pixel-to-world transformation
274 * ----------------------------------------
275 * tabx2s() transforms intermediate world coordinates to world coordinates
276 * using coordinate lookup.
277 *
278 * Given and returned:
279 * tab struct tabprm*
280 * Tabular transformation parameters.
281 *
282 * Given:
283 * ncoord,
284 * nelem int The number of coordinates, each of vector length
285 * nelem.
286 *
287 * x const double[ncoord][nelem]
288 * Array of intermediate world coordinates, SI units.
289 *
290 * Returned:
291 * world double[ncoord][nelem]
292 * Array of world coordinates, in SI units.
293 *
294 * stat int[ncoord]
295 * Status return value status for each coordinate:
296 * 0: Success.
297 * 1: Invalid intermediate world coordinate.
298 *
299 * Function return value:
300 * int Status return value:
301 * 0: Success.
302 * 1: Null tabprm pointer passed.
303 * 3: Invalid tabular parameters.
304 * 4: One or more of the x coordinates were invalid,
305 * as indicated by the stat vector.
306 *
307 * For returns > 1, a detailed error message is set in
308 * tabprm::err if enabled, see wcserr_enable().
309 *
310 *
311 * tabs2x() - World-to-pixel transformation
312 * ----------------------------------------
313 * tabs2x() transforms world coordinates to intermediate world coordinates.
314 *
315 * Given and returned:
316 * tab struct tabprm*
317 * Tabular transformation parameters.
318 *
319 * Given:
320 * ncoord,
321 * nelem int The number of coordinates, each of vector length
322 * nelem.
323 * world const double[ncoord][nelem]
324 * Array of world coordinates, in SI units.
325 *
326 * Returned:
327 * x double[ncoord][nelem]
328 * Array of intermediate world coordinates, SI units.
329 * stat int[ncoord]
330 * Status return value status for each vector element:
331 * 0: Success.
332 * 1: Invalid world coordinate.
333 *
334 * Function return value:
335 * int Status return value:
336 * 0: Success.
337 * 1: Null tabprm pointer passed.
338 * 3: Invalid tabular parameters.
339 * 5: One or more of the world coordinates were
340 * invalid, as indicated by the stat vector.
341 *
342 * For returns > 1, a detailed error message is set in
343 * tabprm::err if enabled, see wcserr_enable().
344 *
345 *
346 * tabprm struct - Tabular transformation parameters
347 * -------------------------------------------------
348 * The tabprm struct contains information required to transform tabular
349 * coordinates. It consists of certain members that must be set by the user
350 * ("given") and others that are set by the WCSLIB routines ("returned"). Some
351 * of the latter are supplied for informational purposes while others are for
352 * internal use only.
353 *
354 * int flag
355 * (Given and returned) This flag must be set to zero whenever any of the
356 * following tabprm structure members are set or changed:
357 *
358 * - tabprm::M (q.v., not normally set by the user),
359 * - tabprm::K (q.v., not normally set by the user),
360 * - tabprm::map,
361 * - tabprm::crval,
362 * - tabprm::index,
363 * - tabprm::coord.
364 *
365 * This signals the initialization routine, tabset(), to recompute the
366 * returned members of the tabprm struct. tabset() will reset flag to
367 * indicate that this has been done.
368 *
369 * PLEASE NOTE: flag should be set to -1 when tabini() is called for the
370 * first time for a particular tabprm struct in order to initialize memory
371 * management. It must ONLY be used on the first initialization otherwise
372 * memory leaks may result.
373 *
374 * int M
375 * (Given or returned) Number of tabular coordinate axes.
376 *
377 * If tabini() is used to initialize the tabprm struct (as would normally
378 * be the case) then it will set M from the value passed to it as a
379 * function argument. The user should not subsequently modify it.
380 *
381 * int *K
382 * (Given or returned) Pointer to the first element of a vector of length
383 * tabprm::M whose elements (K_1, K_2,... K_M) record the lengths of the
384 * axes of the coordinate array and of each indexing vector.
385 *
386 * If tabini() is used to initialize the tabprm struct (as would normally
387 * be the case) then it will set K from the array passed to it as a
388 * function argument. The user should not subsequently modify it.
389 *
390 * int *map
391 * (Given) Pointer to the first element of a vector of length tabprm::M
392 * that defines the association between axis m in the M-dimensional
393 * coordinate array (1 <= m <= M) and the indices of the intermediate world
394 * coordinate and world coordinate arrays, x[] and world[], in the argument
395 * lists for tabx2s() and tabs2x().
396 *
397 * When x[] and world[] contain the full complement of coordinate elements
398 * in image-order, as will usually be the case, then map[m-1] == i-1 for
399 * axis i in the N-dimensional image (1 <= i <= N). In terms of the FITS
400 * keywords
401 *
402 * map[PVi_3a - 1] == i - 1.
403 *
404 * However, a different association may result if x[], for example, only
405 * contains a (relevant) subset of intermediate world coordinate elements.
406 * For example, if M == 1 for an image with N > 1, it is possible to fill
407 * x[] with the relevant coordinate element with nelem set to 1. In this
408 * case map[0] = 0 regardless of the value of i.
409 *
410 * double *crval
411 * (Given) Pointer to the first element of a vector of length tabprm::M
412 * whose elements contain the index value for the reference pixel for each
413 * of the tabular coordinate axes.
414 *
415 * double **index
416 * (Given) Pointer to the first element of a vector of length tabprm::M of
417 * pointers to vectors of lengths (K_1, K_2,... K_M) of 0-relative indexes
418 * (see tabprm::K).
419 *
420 * The address of any or all of these index vectors may be set to zero,
421 * i.e.
422 *
423 = index[m] == 0;
424 *
425 * this is interpreted as default indexing, i.e.
426 *
427 = index[m][k] = k;
428 *
429 * double *coord
430 * (Given) Pointer to the first element of the tabular coordinate array,
431 * treated as though it were defined as
432 *
433 = double coord[K_M]...[K_2][K_1][M];
434 *
435 * (see tabprm::K) i.e. with the M dimension varying fastest so that the
436 * M elements of a coordinate vector are stored contiguously in memory.
437 *
438 * int nc
439 * (Returned) Total number of coordinate vectors in the coordinate array
440 * being the product K_1 * K_2 * ... * K_M (see tabprm::K).
441 *
442 * int padding
443 * (An unused variable inserted for alignment purposes only.)
444 *
445 * int *sense
446 * (Returned) Pointer to the first element of a vector of length tabprm::M
447 * whose elements indicate whether the corresponding indexing vector is
448 * monotonic increasing (+1), or decreasing (-1).
449 *
450 * int *p0
451 * (Returned) Pointer to the first element of a vector of length tabprm::M
452 * of interpolated indices into the coordinate array such that Upsilon_m,
453 * as defined in Paper III, is equal to (p0[m] + 1) + tabprm::delta[m].
454 *
455 * double *delta
456 * (Returned) Pointer to the first element of a vector of length tabprm::M
457 * of interpolated indices into the coordinate array such that Upsilon_m,
458 * as defined in Paper III, is equal to (tabprm::p0[m] + 1) + delta[m].
459 *
460 * double *extrema
461 * (Returned) Pointer to the first element of an array that records the
462 * minimum and maximum value of each element of the coordinate vector in
463 * each row of the coordinate array, treated as though it were defined as
464 *
465 = double extrema[K_M]...[K_2][2][M]
466 *
467 * (see tabprm::K). The minimum is recorded in the first element of the
468 * compressed K_1 dimension, then the maximum. This array is used by the
469 * inverse table lookup function, tabs2x(), to speed up table searches.
470 *
471 * struct wcserr *err
472 * (Returned) If enabled, when an error status is returned this struct
473 * contains detailed information about the error, see wcserr_enable().
474 *
475 * int m_flag
476 * (For internal use only.)
477 * int m_M
478 * (For internal use only.)
479 * int m_N
480 * (For internal use only.)
481 * int set_M
482 * (For internal use only.)
483 * int m_K
484 * (For internal use only.)
485 * int m_map
486 * (For internal use only.)
487 * int m_crval
488 * (For internal use only.)
489 * int m_index
490 * (For internal use only.)
491 * int m_indxs
492 * (For internal use only.)
493 * int m_coord
494 * (For internal use only.)
495 *
496 *
497 * Global variable: const char *tab_errmsg[] - Status return messages
498 * ------------------------------------------------------------------
499 * Error messages to match the status value returned from each function.
500 *
501 *===========================================================================*/
502 
503 #ifndef WCSLIB_TAB
504 #define WCSLIB_TAB
505 
506 #include "wcserr.h"
507 
508 #ifdef __cplusplus
509 extern "C" {
510 #endif
511 
512 
513 extern const char *tab_errmsg[];
514 
516  TABERR_SUCCESS = 0, /* Success. */
517  TABERR_NULL_POINTER = 1, /* Null tabprm pointer passed. */
518  TABERR_MEMORY = 2, /* Memory allocation failed. */
519  TABERR_BAD_PARAMS = 3, /* Invalid tabular parameters. */
520  TABERR_BAD_X = 4, /* One or more of the x coordinates were
521  invalid. */
522  TABERR_BAD_WORLD = 5 /* One or more of the world coordinates were
523  invalid. */
524 };
525 
526 struct tabprm {
527  /* Initialization flag (see the prologue above). */
528  /*------------------------------------------------------------------------*/
529  int flag; /* Set to zero to force initialization. */
530 
531  /* Parameters to be provided (see the prologue above). */
532  /*------------------------------------------------------------------------*/
533  int M; /* Number of tabular coordinate axes. */
534  int *K; /* Vector of length M whose elements */
535  /* (K_1, K_2,... K_M) record the lengths of */
536  /* the axes of the coordinate array and of */
537  /* each indexing vector. */
538  int *map; /* Vector of length M usually such that */
539  /* map[m-1] == i-1 for coordinate array */
540  /* axis m and image axis i (see above). */
541  double *crval; /* Vector of length M containing the index */
542  /* value for the reference pixel for each */
543  /* of the tabular coordinate axes. */
544  double **index; /* Vector of pointers to M indexing vectors */
545  /* of lengths (K_1, K_2,... K_M). */
546  double *coord; /* (1+M)-dimensional tabular coordinate */
547  /* array (see above). */
548 
549  /* Information derived from the parameters supplied. */
550  /*------------------------------------------------------------------------*/
551  int nc; /* Number of coordinate vectors (of length */
552  /* M) in the coordinate array. */
553  int padding; /* (Dummy inserted for alignment purposes.) */
554  int *sense; /* Vector of M flags that indicate whether */
555  /* the Mth indexing vector is monotonic */
556  /* increasing, or else decreasing. */
557  int *p0; /* Vector of M indices. */
558  double *delta; /* Vector of M increments. */
559  double *extrema; /* (1+M)-dimensional array of coordinate */
560  /* extrema. */
561 
562  /* Error handling */
563  /*------------------------------------------------------------------------*/
564  struct wcserr *err;
565 
566  /* Private - the remainder are for memory management. */
567  /*------------------------------------------------------------------------*/
568  int m_flag, m_M, m_N;
569  int set_M;
570  int *m_K, *m_map;
571  double *m_crval, **m_index, **m_indxs, *m_coord;
572 };
573 
574 /* Size of the tabprm struct in int units, used by the Fortran wrappers. */
575 #define TABLEN (sizeof(struct tabprm)/sizeof(int))
576 
577 
578 int tabini(int alloc, int M, const int K[], struct tabprm *tab);
579 
580 int tabmem(struct tabprm *tab);
581 
582 int tabcpy(int alloc, const struct tabprm *tabsrc, struct tabprm *tabdst);
583 
584 int tabcmp(int cmp, double tol, const struct tabprm *tab1,
585  const struct tabprm *tab2, int *equal);
586 
587 int tabfree(struct tabprm *tab);
588 
589 int tabprt(const struct tabprm *tab);
590 
591 int tabset(struct tabprm *tab);
592 
593 int tabx2s(struct tabprm *tab, int ncoord, int nelem, const double x[],
594  double world[], int stat[]);
595 
596 int tabs2x(struct tabprm *tab, int ncoord, int nelem, const double world[],
597  double x[], int stat[]);
598 
599 
600 /* Deprecated. */
601 #define tabini_errmsg tab_errmsg
602 #define tabcpy_errmsg tab_errmsg
603 #define tabfree_errmsg tab_errmsg
604 #define tabprt_errmsg tab_errmsg
605 #define tabset_errmsg tab_errmsg
606 #define tabx2s_errmsg tab_errmsg
607 #define tabs2x_errmsg tab_errmsg
608 
609 #ifdef __cplusplus
610 }
611 #endif
612 
613 #endif /* WCSLIB_TAB */
int tabfree(struct tabprm *tab)
Destructor for the tabprm struct.
Definition: tab.h:522
int set_M
Definition: tab.h:569
int tabini(int alloc, int M, const int K[], struct tabprm *tab)
Default constructor for the tabprm struct.
int tabset(struct tabprm *tab)
Setup routine for the tabprm struct.
Definition: tab.h:519
Error message handling.
Definition: wcserr.h:221
int m_flag
Definition: tab.h:568
double * m_crval
Definition: tab.h:571
int * map
Definition: tab.h:538
double * coord
Definition: tab.h:546
int tabcpy(int alloc, const struct tabprm *tabsrc, struct tabprm *tabdst)
Copy routine for the tabprm struct.
int * m_K
Definition: tab.h:570
int flag
Definition: tab.h:529
Definition: tab.h:516
const char * tab_errmsg[]
Status return messages.
double * delta
Definition: tab.h:558
Definition: tab.h:517
tab_errmsg_enum
Definition: tab.h:515
double ** m_index
Definition: tab.h:571
int tabprt(const struct tabprm *tab)
Print routine for the tabprm struct.
Definition: tab.h:518
int m_N
Definition: tab.h:568
int * m_map
Definition: tab.h:570
Definition: tab.h:520
double ** index
Definition: tab.h:544
double ** m_indxs
Definition: tab.h:571
int tabx2s(struct tabprm *tab, int ncoord, int nelem, const double x[], double world[], int stat[])
Pixel-to-world transformation.
int * sense
Definition: tab.h:554
int tabmem(struct tabprm *tab)
Acquire tabular memory.
Tabular transformation parameters.
Definition: tab.h:526
double * m_coord
Definition: tab.h:571
double * extrema
Definition: tab.h:559
int * K
Definition: tab.h:534
int padding
Definition: tab.h:553
struct wcserr * err
Definition: tab.h:564
int M
Definition: tab.h:533
double * crval
Definition: tab.h:541
int tabs2x(struct tabprm *tab, int ncoord, int nelem, const double world[], double x[], int stat[])
World-to-pixel transformation.
int * p0
Definition: tab.h:557
int tabcmp(int cmp, double tol, const struct tabprm *tab1, const struct tabprm *tab2, int *equal)
Compare two tabprm structs for equality.
int m_M
Definition: tab.h:568
int nc
Definition: tab.h:551