Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members

intutils.h

Go to the documentation of this file.
00001 /* -*- mode: C++; c-file-style: "stroustrup"; c-basic-offset: 4; indent-tabs-mode: nil; -*- */
00002 /*********************************************************************
00003  *
00004  * Filename : intutils.h (base)
00005  *
00006  * Utility functions for integers.
00007  *
00008  * This file is a part of the UPPAAL toolkit.
00009  * Copyright (c) 1995 - 2003, Uppsala University and Aalborg University.
00010  * All right reserved.
00011  *
00012  * $Id: intutils.h,v 1.13 2005/04/22 15:20:10 adavid Exp $
00013  *
00014  **********************************************************************/
00015 
00016 #ifndef INCLUDE_BASE_INTUTILS_H
00017 #define INCLUDE_BASE_INTUTILS_H
00018 
00019 #include <string.h>
00020 
00021 #ifdef __cplusplus
00022 extern "C" {
00023 #endif
00024 
00025 #include "base/inttypes.h"
00026 
00027 /** Unsigned 32-bit subtraction with borrow. 
00028  * Function that subtracts two unsigned 32-bit numbers. 
00029  * For x86-processors this function is implemented in assembler.
00030  * This saves around 50 instructions of which several are branches.
00031  * @param a: the first term.
00032  * @param b: the second term.
00033  * @param cp: pointer to carry/borrow. (in/out).
00034  *
00035  * @return the lower 32-bits of a - (b + *cp).
00036  * 
00037  * @pre:
00038  * - *cp is either 0 or 1.
00039  *
00040  * @post:
00041  * - *cp is 1 if borrow was necessary, 0 otherwise.
00042  */
00043 static inline
00044 uint32_t base_subu32(uint32_t a, uint32_t b, uint32_t *cp)
00045 {
00046 #if defined(__GNUG__) && defined(i386)
00047     uint32_t c = *cp;
00048     asm("rcrl %1        # Move borrow to carry flag.\n\t"
00049         "sbbl %2, %0    # Perform subtraction.\n\t"
00050         "rcll %1        # Move borrow from carry flag.\n\t" 
00051         : "=r" (a), "=r" (c) : "rm" (b), "0" (a), "1" (c) : "cc");
00052     *cp = c;
00053     return a;
00054 #else
00055     uint32_t c = *cp;   
00056     uint32_t v = (b + c);
00057     *cp = ((a < v) || (c > v) ? 1 : 0);
00058     return a - v;        
00059 #endif
00060 }
00061 
00062 
00063 /** Best compromise for copy:
00064  * - for Intel, it is better to define our
00065  *   own copy function for small copies
00066  *   memcpy is better for sizes over 120-150
00067  * - for Sun, memcpy is always worse.
00068  *
00069  * As the cost of a function call is negligible
00070  * we prefer to reduce code size by not inlining
00071  * the code.
00072  *
00073  * @param src: source
00074  * @param dst: destination
00075  * @param intSize: size in int to copy
00076  * @pre src and dst are int32_t[intsize].
00077  */
00078 void base_copySmall(void *dst, const void *src, size_t intSize);
00079 
00080 static inline
00081 void base_copyLarge(void *dst, const void *src, size_t intSize)
00082 {
00083 #if INTEL_ARCH
00084     memcpy(dst, src, intSize << 2);
00085 #else
00086     base_copySmall(dst, src, intSize);
00087 #endif
00088 }
00089 
00090 /** Try to choose best copy dynamically.
00091  */
00092 static inline
00093 void base_copyBest(void *dst, const void *src, size_t intSize)
00094 {
00095 #if INTEL_ARCH
00096     (intSize < 180 ? base_copySmall : base_copyLarge)(dst, src, intSize);
00097 #else
00098     base_copySmall(dst, src, intSize);
00099 #endif
00100 }
00101 
00102 
00103 /** Fill memory with a given value.
00104  * @param mem: memory to fill
00105  * @param intSize: size in int to fill
00106  * @param intValue: value to use to fill
00107  * @post int[0..intSize-1] at mem is filled with intValue
00108  */
00109 void base_fill(void *mem, size_t intSize, uint32_t intValue);
00110 
00111 
00112 /** Check if memory differs with a given value.
00113  * @param mem: memory to check
00114  * @param intSize: size in int to fill
00115  * @param intValue: value to check
00116  * @return 0 if mem[0..intSize-1] == intValue,
00117  * or !=0 otherwise.
00118  */
00119 uint32_t base_diff(const void *mem, size_t intSize, uint32_t intValue);
00120 
00121 
00122 /** Reset memory:
00123  * tests on Intel and Sun show that
00124  * memset is always slower on Sun and
00125  * it becomes faster than a custom function
00126  * on Intel after a threshold between 120 and 150
00127  * ints.
00128  * In practice reset is used for 2 very different
00129  * purposes:
00130  * - reset of small size for control vector or similar
00131  * - reset of large size for hash tables
00132  *
00133  * @param mem: memory to reset
00134  * @param intSize: size in int to reset
00135  * @pre mem is a int32_t[intSize]
00136  */
00137 static inline
00138 void base_resetSmall(void *mem, size_t intSize)
00139 {
00140     base_fill(mem, intSize, 0);
00141 }
00142 
00143 static inline
00144 void base_resetLarge(void *mem, size_t intSize)
00145 {
00146 #if INTEL_ARCH
00147     memset(mem, 0, intSize << 2);
00148 #else
00149     base_fill(mem, intSize, 0);
00150 #endif
00151 }
00152 
00153 /** Try to choose best reset dynamically.
00154  */
00155 static inline
00156 void base_resetBest(void *mem, size_t intSize)
00157 {
00158 #if INTEL_ARCH
00159     (intSize < 200 ? base_resetSmall : base_resetLarge)(mem, intSize);
00160 #else
00161     base_fill(mem, intSize, 0);
00162 #endif
00163 }
00164 
00165 
00166 /** Test equality. (optimistic implementation)
00167  * @param data1,data2: data to be compared.
00168  * @param intSize: size in int to compare.
00169  * @return TRUE if the contents are the same.
00170  * @pre data1 and data2 are of size int32_t[intSize]
00171  * null pointers are accepted as argument
00172  */
00173 BOOL base_areEqual(const void *data1, const void *data2, size_t intSize);
00174 
00175 
00176 /** @return abs(x) without a jump!
00177  * @param x: int to test.
00178  */
00179 static inline
00180 int32_t base_abs(int32_t x)
00181 {
00182     /* Algo:
00183      * - if x >= 0, sign == 0
00184      *   and (x^sign)+sign == x
00185      * - if x < 0, sign == 1
00186      *   and -sign = 0xffffffff
00187      *   x^-sign == ~x
00188      *   return ~x+1 == -x
00189      */
00190     uint32_t sign = ((uint32_t) x) >> 31;
00191     return (x ^ -sign) + sign;
00192 }
00193 
00194 
00195 /** @return (x < 0 ? ~x : x) without a jump!
00196  * @param x: int to test.
00197  */
00198 static inline
00199 int32_t base_absNot(int32_t x)
00200 {
00201     /* Algo: see base_abs
00202      */
00203     uint32_t sign = ((uint32_t) x) >> 31;
00204     return (x ^ -sign);
00205 }
00206 
00207 
00208 /** Quick sort: from lower to higher ints
00209  * @param values: values to sort
00210  * @param n: number of values
00211  * @pre values is a uint32_t[n]
00212  */
00213 void base_sort(uint32_t *values, size_t n);
00214 
00215 
00216 #ifdef __cplusplus
00217 }
00218 #endif
00219 
00220 #endif /* INCLUDE_BASE_INTUTILS_H */

Generated on Fri Jun 30 00:02:30 2006 for Module base by  doxygen 1.4.2