1/*
2 * Copyright (C) by Argonne National Laboratory
3 *     See COPYRIGHT in top-level directory
4 */
5
6#ifndef YAKSA_H_INCLUDED
7#define YAKSA_H_INCLUDED
8
9/* Keep C++ compilers from getting confused */
10#if defined(__cplusplus)
11/* extern "C" { */
12#endif
13
14/* This is a public API header and should not include any internal
15 * headers */
16#include <stdio.h>
17#include <stdint.h>
18#include <sys/types.h>
19#include <sys/uio.h>
20
21
22/******************************************************************************/
23/* YAKSA TYPES */
24/******************************************************************************/
25
26/** @file yaksa.h */
27
28/*! \addtogroup yaksa-types Yaksa Builtin Datatypes
29 * @{
30 */
31
32/* The most significant 32 bits of the yaksa type are unused at this
33 * point.  They are kept for future potential use, for example to set
34 * a predefined bit or to store the size or alignment for predefined
35 * types inside the handle itself.  For now, only the least
36 * significant 32 bits are used to store the handle to the internal
37 * type object. */
38typedef uint64_t yaksa_type_t;
39
40/**
41 * \brief yaksa builtin datatypes
42 */
43/* generic */
44#define YAKSA_TYPE__NULL                              ((yaksa_type_t) 0)
45#define YAKSA_TYPE___BOOL                             ((yaksa_type_t) 1)
46
47/* char types */
48#define YAKSA_TYPE__CHAR                              ((yaksa_type_t) 2)
49#define YAKSA_TYPE__SIGNED_CHAR                       ((yaksa_type_t) 3)
50#define YAKSA_TYPE__UNSIGNED_CHAR                     ((yaksa_type_t) 4)
51#define YAKSA_TYPE__WCHAR_T                           ((yaksa_type_t) 5)
52
53/* int types */
54#define YAKSA_TYPE__INT8_T                            ((yaksa_type_t) 6)
55#define YAKSA_TYPE__INT16_T                           ((yaksa_type_t) 7)
56#define YAKSA_TYPE__INT32_T                           ((yaksa_type_t) 8)
57#define YAKSA_TYPE__INT64_T                           ((yaksa_type_t) 9)
58#define YAKSA_TYPE__UINT8_T                           ((yaksa_type_t) 10)
59#define YAKSA_TYPE__UINT16_T                          ((yaksa_type_t) 11)
60#define YAKSA_TYPE__UINT32_T                          ((yaksa_type_t) 12)
61#define YAKSA_TYPE__UINT64_T                          ((yaksa_type_t) 13)
62
63#define YAKSA_TYPE__INT                               ((yaksa_type_t) 14)
64#define YAKSA_TYPE__UNSIGNED                          ((yaksa_type_t) 15)
65#define YAKSA_TYPE__SHORT                             ((yaksa_type_t) 16)
66#define YAKSA_TYPE__UNSIGNED_SHORT                    ((yaksa_type_t) 17)
67#define YAKSA_TYPE__LONG                              ((yaksa_type_t) 18)
68#define YAKSA_TYPE__UNSIGNED_LONG                     ((yaksa_type_t) 19)
69#define YAKSA_TYPE__LONG_LONG                         ((yaksa_type_t) 20)
70#define YAKSA_TYPE__UNSIGNED_LONG_LONG                ((yaksa_type_t) 21)
71
72#define YAKSA_TYPE__INT_FAST8_T                       ((yaksa_type_t) 22)
73#define YAKSA_TYPE__INT_FAST16_T                      ((yaksa_type_t) 23)
74#define YAKSA_TYPE__INT_FAST32_T                      ((yaksa_type_t) 24)
75#define YAKSA_TYPE__INT_FAST64_T                      ((yaksa_type_t) 25)
76#define YAKSA_TYPE__UINT_FAST8_T                      ((yaksa_type_t) 26)
77#define YAKSA_TYPE__UINT_FAST16_T                     ((yaksa_type_t) 27)
78#define YAKSA_TYPE__UINT_FAST32_T                     ((yaksa_type_t) 28)
79#define YAKSA_TYPE__UINT_FAST64_T                     ((yaksa_type_t) 29)
80
81#define YAKSA_TYPE__INT_LEAST8_T                      ((yaksa_type_t) 30)
82#define YAKSA_TYPE__INT_LEAST16_T                     ((yaksa_type_t) 31)
83#define YAKSA_TYPE__INT_LEAST32_T                     ((yaksa_type_t) 32)
84#define YAKSA_TYPE__INT_LEAST64_T                     ((yaksa_type_t) 33)
85#define YAKSA_TYPE__UINT_LEAST8_T                     ((yaksa_type_t) 34)
86#define YAKSA_TYPE__UINT_LEAST16_T                    ((yaksa_type_t) 35)
87#define YAKSA_TYPE__UINT_LEAST32_T                    ((yaksa_type_t) 36)
88#define YAKSA_TYPE__UINT_LEAST64_T                    ((yaksa_type_t) 37)
89
90#define YAKSA_TYPE__BYTE                              ((yaksa_type_t) 38)
91#define YAKSA_TYPE__INTMAX_T                          ((yaksa_type_t) 39)
92#define YAKSA_TYPE__UINTMAX_T                         ((yaksa_type_t) 40)
93
94#define YAKSA_TYPE__SIZE_T                            ((yaksa_type_t) 41)
95
96/* pointer type */
97#define YAKSA_TYPE__INTPTR_T                          ((yaksa_type_t) 42)
98#define YAKSA_TYPE__UINTPTR_T                         ((yaksa_type_t) 43)
99#define YAKSA_TYPE__PTRDIFF_T                         ((yaksa_type_t) 44)
100
101/* float types */
102#define YAKSA_TYPE__FLOAT                             ((yaksa_type_t) 45)
103#define YAKSA_TYPE__DOUBLE                            ((yaksa_type_t) 46)
104#define YAKSA_TYPE__LONG_DOUBLE                       ((yaksa_type_t) 47)
105
106/* pair types */
107#define YAKSA_TYPE__C_COMPLEX                         ((yaksa_type_t) 48)
108#define YAKSA_TYPE__C_DOUBLE_COMPLEX                  ((yaksa_type_t) 49)
109#define YAKSA_TYPE__C_LONG_DOUBLE_COMPLEX             ((yaksa_type_t) 50)
110#define YAKSA_TYPE__FLOAT_INT                         ((yaksa_type_t) 51)
111#define YAKSA_TYPE__DOUBLE_INT                        ((yaksa_type_t) 52)
112#define YAKSA_TYPE__LONG_INT                          ((yaksa_type_t) 53)
113#define YAKSA_TYPE__2INT                              ((yaksa_type_t) 54)
114#define YAKSA_TYPE__SHORT_INT                         ((yaksa_type_t) 55)
115#define YAKSA_TYPE__LONG_DOUBLE_INT                   ((yaksa_type_t) 56)
116
117/*! @} */
118
119
120/*! \addtogroup yaksa-requests Yaksa predefined datatypes
121 * @{
122 */
123
124typedef uint64_t yaksa_request_t;
125
126/**
127 * \brief yaksa predefined requests
128 */
129#define YAKSA_REQUEST__NULL                           ((yaksa_request_t) 0)
130
131/*! @} */
132
133
134/*! \addtogroup yaksa-return-codes Yaksa return codes
135 * @{
136 */
137
138/******************************************************************************/
139/* YAKSA RETURN CODES */
140/******************************************************************************/
141/*! \brief the function completed successfully */
142#define YAKSA_SUCCESS          (0)
143/*! \brief yaksa ran out of memory */
144#define YAKSA_ERR__OUT_OF_MEM  (1)
145/*! \brief yaksa internal (undocumented) error */
146#define YAKSA_ERR__INTERNAL    (2)
147/*! \brief yaksa operation is not supported (only for development purposes) */
148#define YAKSA_ERR__NOT_SUPPORTED  (3)
149
150/*! @} */
151
152
153/*! \addtogroup yaksa-subarray-order Yaksa subarray order
154 * @{
155 */
156
157/******************************************************************************/
158/* YAKSA SUBARRAY DATA ORDER */
159/******************************************************************************/
160/**
161 * \brief yaksa subarray order
162 */
163typedef enum {
164    YAKSA_SUBARRAY_ORDER__C,
165    YAKSA_SUBARRAY_ORDER__FORTRAN
166} yaksa_subarray_order_e;
167
168/*! @} */
169
170
171/*! \addtogroup yaksa-info Yaksa info object
172 * @{
173 */
174
175/**
176 * \brief yaksa info object
177 */
178typedef void *yaksa_info_t;
179
180#define YAKSA_INFO_MAX_KEYLEN   (256)
181
182/*! @} */
183
184
185/*! \addtogroup yaksa-funcs Yaksa public functions
186 * @{
187 */
188
189/******************************************************************************/
190/* YAKSA PUBLIC FUNCTIONS */
191/******************************************************************************/
192/*!
193 * \brief creates an info object
194 *
195 * \param[out] info              Info object being created
196 */
197int yaksa_info_create(yaksa_info_t * info);
198
199/*!
200 * \brief frees the info object
201 *
202 * \param[in]  info              Info object being freed
203 */
204int yaksa_info_free(yaksa_info_t info);
205
206/*!
207 * \brief append a hint to the info object
208 *
209 * \param[in]  info              Info object
210 * \param[in]  key               Hint key
211 * \param[in]  val               Hint value
212 * \param[in]  vallen            Length of the hint value
213 */
214int yaksa_info_keyval_append(yaksa_info_t info, const char *key, const void *val,
215                             unsigned int vallen);
216
217/*!
218 * \brief initializes the yaksa library
219 */
220int yaksa_init(yaksa_info_t info);
221
222/*!
223 * \brief finalizes the yaksa library
224 */
225int yaksa_finalize(void);
226
227/*!
228 * \brief creates a vector layout
229 *
230 * \param[in]  count        Number of blocks in the vector
231 * \param[in]  blocklength  Length of each block
232 * \param[in]  stride       Increment from the start of one block to another
233 *                          (represented in terms of the count of the oldtype)
234 * \param[in]  oldtype      Base datatype forming each element in the vector
235 * \param[in]  info         Hint object
236 * \param[out] newtype      Final generated type
237 */
238int yaksa_type_create_vector(int count, int blocklength, int stride, yaksa_type_t oldtype,
239                             yaksa_info_t info, yaksa_type_t * newtype);
240
241/*!
242 * \brief creates a hvector layout
243 *
244 * \param[in]  count        Number of blocks in the vector
245 * \param[in]  blocklength  Length of each block
246 * \param[in]  stride       Increment from the start of one block to another
247 *                          (represented in bytes)
248 * \param[in]  oldtype      Base datatype forming each element in the vector
249 * \param[in]  info         Hint object
250 * \param[out] newtype      Final generated type
251 */
252int yaksa_type_create_hvector(int count, int blocklength, intptr_t stride, yaksa_type_t oldtype,
253                              yaksa_info_t info, yaksa_type_t * newtype);
254
255/*!
256 * \brief creates a contig layout
257 *
258 * \param[in]  count        Number of elements of the oldtype
259 * \param[in]  oldtype      Base datatype forming each element in the contig
260 * \param[in]  info         Hint object
261 * \param[out] newtype      Final generated type
262 */
263int yaksa_type_create_contig(int count, yaksa_type_t oldtype, yaksa_info_t info,
264                             yaksa_type_t * newtype);
265
266/*!
267 * \brief creates a copy of the oldtype
268 *
269 * \param[in]  oldtype      Base datatype being dup'ed
270 * \param[in]  info         Hint object
271 * \param[out] newtype      Final generated type
272 */
273int yaksa_type_create_dup(yaksa_type_t oldtype, yaksa_info_t info, yaksa_type_t * newtype);
274
275/*!
276 * \brief creates a block-indexed layout
277 *
278 * \param[in]  count                  Number of blocks in the new type
279 * \param[in]  blocklength            Length of each block
280 * \param[in]  array_of_displacements Starting offset to each block
281 *                                    (represented in terms of the count of the oldtype)
282 * \param[in]  oldtype                Base datatype forming each element in the new type
283 * \param[in]  info                   Hint object
284 * \param[out] newtype                Final generated type
285 */
286int yaksa_type_create_indexed_block(int count, int blocklength, const int *array_of_displacements,
287                                    yaksa_type_t oldtype, yaksa_info_t info,
288                                    yaksa_type_t * newtype);
289
290/*!
291 * \brief creates a block-hindexed layout
292 *
293 * \param[in]  count                  Number of blocks in the new type
294 * \param[in]  blocklength            Length of each block
295 * \param[in]  array_of_displacements Starting offset to each block
296 *                                    (represented in bytes)
297 * \param[in]  oldtype                Base datatype forming each element in the new type
298 * \param[in]  info                   Hint object
299 * \param[out] newtype                Final generated type
300 */
301int yaksa_type_create_hindexed_block(int count, int blocklength,
302                                     const intptr_t * array_of_displacements, yaksa_type_t oldtype,
303                                     yaksa_info_t info, yaksa_type_t * newtype);
304
305/*!
306 * \brief creates a indexed layout
307 *
308 * \param[in]  count                  Number of blocks in the new type
309 * \param[in]  array_of_blocklengths  Array of lengths of each block
310 * \param[in]  array_of_displacements Starting offset to each block
311 *                                    (represented in terms of the count of the oldtype)
312 * \param[in]  oldtype                Base datatype forming each element in the new type
313 * \param[in]  info                   Hint object
314 * \param[out] newtype                Final generated type
315 */
316int yaksa_type_create_indexed(int count, const int *array_of_blocklengths,
317                              const int *array_of_displacements, yaksa_type_t oldtype,
318                              yaksa_info_t info, yaksa_type_t * newtype);
319
320/*!
321 * \brief creates a hindexed layout
322 *
323 * \param[in]  count                  Number of blocks in the new type
324 * \param[in]  array_of_blocklengths  Array of lengths of each block
325 * \param[in]  array_of_displacements Starting offset to each block
326 *                                    (represented in bytes)
327 * \param[in]  oldtype                Base datatype forming each element in the new type
328 * \param[in]  info                   Hint object
329 * \param[out] newtype                Final generated type
330 */
331int yaksa_type_create_hindexed(int count, const int *array_of_blocklengths,
332                               const intptr_t * array_of_displacements, yaksa_type_t oldtype,
333                               yaksa_info_t info, yaksa_type_t * newtype);
334
335/*!
336 * \brief creates a resized layout with updated lower and extent
337 *
338 * \param[in]  oldtype                Base datatype forming each element in the new type
339 * \param[in]  lb                     New lower bound to use
340 * \param[in]  extent                 New extent to use
341 * \param[in]  info                   Hint object
342 * \param[out] newtype                Final generated type
343 */
344int yaksa_type_create_resized(yaksa_type_t oldtype, intptr_t lb, intptr_t extent,
345                              yaksa_info_t info, yaksa_type_t * newtype);
346
347/*!
348 * \brief creates a struct layout
349 *
350 * \param[in]  count                  Number of blocks in the new type
351 * \param[in]  array_of_blocklengths  Array of lengths of each block
352 * \param[in]  array_of_displacements Starting offset to each block
353 *                                    (represented in bytes)
354 * \param[in]  array_of_types         Array of base datatype forming each element in the new type
355 * \param[in]  info                   Hint object
356 * \param[out] newtype                Final generated type
357 */
358int yaksa_type_create_struct(int count, const int *array_of_blocklengths,
359                             const intptr_t * array_of_displacements,
360                             const yaksa_type_t * array_of_types, yaksa_info_t info,
361                             yaksa_type_t * newtype);
362
363/*!
364 * \brief creates a subarray layout
365 *
366 * \param[in]  ndims                  Number of dimensions in the array
367 * \param[in]  array_of_sizes         Dimension sizes for the entire array
368 * \param[in]  array_of_subsizes      Dimension sizes for the subarray
369 * \param[in]  array_of_starts        Start location ("corner representing the start") of the subarray
370 * \param[in]  order                  Data layout order (C or Fortran)
371 * \param[in]  oldtype                Base datatype forming each element in the new type
372 * \param[in]  info                   Hint object
373 * \param[out] newtype                Final generated type
374 */
375int yaksa_type_create_subarray(int ndims, const int *array_of_sizes, const int *array_of_subsizes,
376                               const int *array_of_starts, yaksa_subarray_order_e order,
377                               yaksa_type_t oldtype, yaksa_info_t info, yaksa_type_t * newtype);
378
379/*!
380 * \brief gets the size of (number of bytes in) the datatype
381 *
382 * \param[in]  type         The datatype whose size is being requested
383 * \param[out] size         The size of the datatype
384 */
385int yaksa_type_get_size(yaksa_type_t type, uintptr_t * size);
386
387/*!
388 * \brief gets the true extent (true span) of the datatype
389 *
390 * \param[in]  type         The datatype whose extent is being requested
391 * \param[out] lb           The lowerbound of the datatype
392 *                          (only used to calculate the extent; does
393 *                          not change where the buffer points to)
394 * \param[out] extent       The extent of the datatype
395 *                          (represents the distance between the
396 *                          lowest and highest points of the datatype,
397 *                          which can be larger than the size of the
398 *                          datatype, if the layout is noncontiguous)
399 */
400int yaksa_type_get_true_extent(yaksa_type_t type, intptr_t * lb, intptr_t * extent);
401
402/*!
403 * \brief gets the extent (span) of the datatype
404 *
405 * \param[in]  type         The datatype whose extent is being requested
406 * \param[out] lb           The lowerbound of the datatype
407 *                          (only used to calculate the extent; does
408 *                          not change where the buffer points to)
409 * \param[out] extent       The extent of the datatype
410 *                          (represents the distance between the
411 *                          lowest and highest points of the datatype.
412 *                          can be larger than the true extent of the
413 *                          datatype for subarrays or if the lb and ub
414 *                          values were modified by creating a resized
415 *                          datatype)
416 */
417int yaksa_type_get_extent(yaksa_type_t type, intptr_t * lb, intptr_t * extent);
418
419/*!
420 * \brief frees the datatype
421 *
422 * \param[in]  type         The datatype being freed
423 */
424int yaksa_type_free(yaksa_type_t type);
425
426/*!
427 * \brief tests to see if a request has completed
428 *
429 * \param[in]  request           The request object that needs to be tested
430 * \param[out] completed         Flag to tell the caller whether the request object has completed
431 */
432int yaksa_request_test(yaksa_request_t request, int *completed);
433
434/*!
435 * \brief waits till a request has completed
436 *
437 * \param[in]  request           The request object that needs to be waited up on
438 */
439int yaksa_request_wait(yaksa_request_t request);
440
441/*!
442 * \brief packs the data represented by the (incount, type) tuple into a contiguous buffer
443 *
444 * \param[in]  inbuf             Input buffer from which data is being packed
445 * \param[in]  incount           Number of elements of the datatype representing the layout
446 * \param[in]  type              Datatype representing the layout
447 * \param[in]  inoffset          Number of bytes to skip from the layout represented by the
448 *                               (incount, type) tuple
449 * \param[out] outbuf            Output buffer into which data is being packed
450 * \param[in]  max_pack_bytes    Maximum number of bytes that can be packed in the output buffer
451 * \param[out] actual_pack_bytes Actual number of bytes that were packed into the output buffer
452 * \param[in]  info              Hint object
453 * \param[out] request           Request handle associated with the operation
454 *                               (YAKSA_REQUEST__NULL if the request already completed)
455 */
456int yaksa_ipack(const void *inbuf, uintptr_t incount, yaksa_type_t type, uintptr_t inoffset,
457                void *outbuf, uintptr_t max_pack_bytes, uintptr_t * actual_pack_bytes,
458                yaksa_info_t info, yaksa_request_t * request);
459
460/*!
461 * \brief unpacks data from a contiguous buffer into a buffer represented by the (incount, type) tuple
462 *
463 * \param[in]  inbuf             Input buffer from which data is being unpacked
464 * \param[in]  insize            Number of bytes in the input buffer
465 * \param[out] outbuf            Output buffer into which data is being unpacked
466 * \param[in]  outcount          Number of elements of the datatype representing the layout
467 * \param[in]  type              Datatype representing the layout
468 * \param[in]  outoffset         Number of bytes to skip from the layout represented by the
469 *                               (incount, type) tuple
470 * \param[out] actual_unpack_bytes Actual number of bytes that were unpacked into the output buffer
471 * \param[in]  info              Hint object
472 * \param[out] request           Request handle associated with the operation
473 *                               (YAKSA_REQUEST__NULL if the request already completed)
474 */
475int yaksa_iunpack(const void *inbuf, uintptr_t insize, void *outbuf, uintptr_t outcount,
476                  yaksa_type_t type, uintptr_t outoffset, uintptr_t * actual_unpack_bytes,
477                  yaksa_info_t info, yaksa_request_t * request);
478
479/*!
480 * \brief gets the number of contiguous segments in the (count, type) tuple
481 *
482 * \param[in]  count             Number of elements of the datatype representing the layout
483 * \param[in]  type              Datatype representing the layout
484 * \param[out] iov_len           Number of contiguous segments in the (count, type) tuple
485 */
486int yaksa_iov_len(uintptr_t count, yaksa_type_t type, uintptr_t * iov_len);
487
488/*!
489 * \brief converts the (count, type) tuple into an I/O vector (array of base pointer/length structures)
490 *
491 * \param[in]  buf               Input buffer being used to create the iov
492 * \param[in]  count             Number of elements of the datatype representing the layout
493 * \param[in]  type              Datatype representing the layout
494 * \param[in]  iov_offset        Number of contiguous segments to skip
495 * \param[out] iov               The I/O vector that is being filled out
496 * \param[in]  max_iov_len       Maximum number of iov elements that can be added to the vector
497 * \param[out] actual_iov_len    Actual number of iov elements that were added to the vector
498 */
499int yaksa_iov(const char *buf, uintptr_t count, yaksa_type_t type, uintptr_t iov_offset,
500              struct iovec *iov, uintptr_t max_iov_len, uintptr_t * actual_iov_len);
501
502/*!
503 * \brief number of bytes that a flattened representation of the datatype would take
504 *
505 * \param[in]  type                Datatype to be flattened
506 * \param[out] flattened_type_size Number of bytes the flattened type would take
507 */
508int yaksa_flatten_size(yaksa_type_t type, uintptr_t * flattened_type_size);
509
510/*!
511 * \brief flattens the datatype into a form that can be sent to other processes in a multiprocess environment
512 *
513 * \param[in]  type                Datatype to be flattened
514 * \param[out] flattened_type      The flattened representation of the datatype
515 */
516int yaksa_flatten(yaksa_type_t type, void *flattened_type);
517
518/*!
519 * \brief unflattens the datatype into a full datatype
520 *
521 * \param[in]  type                Datatype generated from the flattened type
522 * \param[out] flattened_type      The flattened representation of the datatype
523 */
524int yaksa_unflatten(yaksa_type_t * type, const void *flattened_type);
525
526/*! @} */
527
528
529/*! \addtogroup yaksa-version Yaksa versioning information
530 * @{
531 */
532
533/******************************************************************************/
534/* YAKSA VERSION INFORMATION */
535/******************************************************************************/
536/* YAKSA_VERSION is the version string. YAKSA_NUMVERSION is the
537 * numeric version that can be used in numeric comparisons.
538 *
539 * YAKSA_VERSION uses the following format:
540 * Version: [MAJ].[MIN].[REV][EXT][EXT_NUMBER]
541 * Example: 1.0.7rc1 has
542 *          MAJ = 1
543 *          MIN = 0
544 *          REV = 7
545 *          EXT = rc
546 *          EXT_NUMBER = 1
547 *
548 * YAKSA_NUMVERSION will convert EXT to a format number:
549 *          ALPHA (a) = 0
550 *          BETA (b)  = 1
551 *          RC (rc)   = 2
552 *          PATCH (p) = 3
553 * Regular releases are treated as patch 0
554 *
555 * Numeric version will have 1 digit for MAJ, 2 digits for MIN, 2
556 * digits for REV, 1 digit for EXT and 2 digits for EXT_NUMBER. So,
557 * 1.0.7rc1 will have the numeric version 10007201.
558 */
559/*! \brief Yaksa library version (string format) */
560#define YAKSA_VERSION "@YAKSA_VERSION@"
561/*! \brief Yaksa library version (numerical format) */
562#define YAKSA_NUMVERSION @YAKSA_NUMVERSION@
563
564/*! \brief Yaksa alpha release (used to calculate the numeric version) */
565#define YAKSA_RELEASE_TYPE_ALPHA  0
566/*! \brief Yaksa beta release (used to calculate the numeric version) */
567#define YAKSA_RELEASE_TYPE_BETA   1
568/*! \brief Yaksa rc release (used to calculate the numeric version) */
569#define YAKSA_RELEASE_TYPE_RC     2
570/*! \brief Yaksa GA/patch release (used to calculate the numeric version) */
571#define YAKSA_RELEASE_TYPE_PATCH  3
572
573/*! \brief Macro to calculate the yaksa numeric version */
574#define YAKSA_CALC_VERSION(MAJOR, MINOR, REVISION, TYPE, PATCH) \
575    (((MAJOR) * 10000000) + ((MINOR) * 100000) + ((REVISION) * 1000) + ((TYPE) * 100) + (PATCH))
576
577/*! @} */
578
579#if defined(__cplusplus)
580/* } */
581#endif
582
583#endif /* YAKSA_H_INCLUDED */
584