m3core/src/Csupport/Common/hand.c
/* Copyright (C) 1992, Digital Equipment Corporation */
/* All rights reserved. */
/* See the file COPYRIGHT for a full description. */
/* */
/* Last modified on Thu Feb 1 09:36:52 PST 1996 by heydon */
/* modified on Tue Jan 10 15:48:28 PST 1995 by kalsow */
/* modified on Tue Feb 11 15:18:40 PST 1992 by muller */
#ifdef _MSC_VER
#pragma warning(disable:4255) /* () changed to (void) */
#pragma warning(disable:4505) /* unused static function removed */
#pragma warning(disable:4711) /* automatic inlining */
#endif
#include "m3core.h"
#if __GNUC__ >= 4
#ifdef __APPLE__
#pragma GCC visibility push(default)
#else
#pragma GCC visibility push(protected)
#endif
#endif
#ifdef __cplusplus
extern "C"
{
#endif
#if !defined(_MSC_VER) && !defined(__stdcall)
#define __stdcall /* nothing */
#endif
/* return positive form of a negative value, avoiding overflow */
/* T should be an unsigned type */
#define M3_POS(T, a) (((T)-((a) + 1)) + 1)
#ifndef _WIN32
#define m3_div64 m3_divL
#define m3_mod64 m3_modL
#endif
#ifndef _WIN32
INTEGER
__stdcall
m3_div(INTEGER b, INTEGER a)
{
typedef INTEGER ST; /* signed type */
typedef WORD_T UT; /* unsigned type */
int aneg = (a < 0);
int bneg = (b < 0);
if (aneg == bneg || a == 0 || b == 0)
return (a / b);
else
{
/* round negative result down by rounding positive result up
unsigned math is much better defined, see gcc -Wstrict-overflow=4 */
UT ua = (aneg ? M3_POS(UT, a) : (UT)a);
UT ub = (bneg ? M3_POS(UT, b) : (UT)b);
return -(ST)((ua + ub - 1) / ub);
}
}
INTEGER
__stdcall
m3_mod(INTEGER b, INTEGER a)
{
typedef INTEGER ST; /* signed type */
typedef WORD_T UT; /* unsigned type */
int aneg = (a < 0);
int bneg = (b < 0);
if (aneg == bneg || a == 0 || b == 0)
return (a % b);
else
{
UT ua = (aneg ? M3_POS(UT, a) : (UT)a);
UT ub = (bneg ? M3_POS(UT, b) : (UT)b);
a = (ST)(ub - 1 - (ua + ub - 1) % ub);
return (bneg ? -a : a);
}
}
#endif
INT64
__stdcall
m3_div64(INT64 b, INT64 a)
{
typedef INT64 ST; /* signed type */
typedef UINT64 UT; /* unsigned type */
int aneg = (a < 0);
int bneg = (b < 0);
if (aneg == bneg || a == 0 || b == 0)
return (a / b);
else
{
/* round negative result down by rounding positive result up
unsigned math is much better defined, see gcc -Wstrict-overflow=4 */
UT ua = (aneg ? M3_POS(UT, a) : (UT)a);
UT ub = (bneg ? M3_POS(UT, b) : (UT)b);
return -(ST)((ua + ub - 1) / ub);
}
}
INT64
__stdcall
m3_mod64(INT64 b, INT64 a)
{
typedef INT64 ST; /* signed type */
typedef UINT64 UT; /* unsigned type */
int aneg = (a < 0);
int bneg = (b < 0);
if (aneg == bneg || a == 0 || b == 0)
return (a % b);
else
{
UT ua = (aneg ? M3_POS(UT, a) : (UT)a);
UT ub = (bneg ? M3_POS(UT, b) : (UT)b);
a = (ST)(ub - 1 - (ua + ub - 1) % ub);
return (bneg ? -a : a);
}
}
#define SET_GRAIN (sizeof(WORD_T) * 8)
WORD_T
__stdcall
set_member(WORD_T elt, WORD_T* set)
{
WORD_T const word = elt / SET_GRAIN;
WORD_T const bit = elt % SET_GRAIN;
return (set[word] & (((WORD_T)1) << bit)) != 0;
}
void
__stdcall
set_union(WORD_T n_bits, WORD_T* c, WORD_T* b, WORD_T* a)
{
WORD_T const n_words = n_bits / SET_GRAIN;
WORD_T i;
for (i = 0; i < n_words; i++)
a[i] = b[i] | c[i];
}
void
__stdcall
set_intersection(WORD_T n_bits, WORD_T* c, WORD_T* b, WORD_T* a)
{
WORD_T const n_words = n_bits / SET_GRAIN;
WORD_T i;
for (i = 0; i < n_words; i++)
a[i] = b[i] & c[i];
}
void
__stdcall
set_difference(WORD_T n_bits, WORD_T* c, WORD_T* b, WORD_T* a)
{
WORD_T const n_words = n_bits / SET_GRAIN;
WORD_T i;
for (i = 0; i < n_words; i++)
a[i] = b[i] & (~ c[i]);
}
void
__stdcall
set_sym_difference(WORD_T n_bits, WORD_T* c, WORD_T* b, WORD_T* a)
{
WORD_T const n_words = n_bits / SET_GRAIN;
WORD_T i;
for (i = 0; i < n_words; i++)
a[i] = b[i] ^ c[i];
}
WORD_T
__stdcall
set_eq(WORD_T n_bits, WORD_T* b, WORD_T* a)
/* never used by current backend */
{
return (memcmp(a, b, n_bits / 8) == 0);
}
WORD_T
__stdcall
set_ne(WORD_T n_bits, WORD_T* b, WORD_T* a)
/* never used by current backend */
{
return (memcmp(a, b, n_bits / 8) != 0);
}
WORD_T
__stdcall
set_le(WORD_T n_bits, WORD_T* b, WORD_T* a)
{
WORD_T const n_words = n_bits / SET_GRAIN;
WORD_T i;
for (i = 0; i < n_words; i++) {
if (a[i] & (~ b[i])) return 0;
}
return 1;
}
WORD_T
__stdcall
set_lt(WORD_T n_bits, WORD_T* b, WORD_T* a)
{
WORD_T const n_words = n_bits / SET_GRAIN;
WORD_T i;
WORD_T eq = 0;
for (i = 0; i < n_words; i++) {
if (a[i] & (~ b[i])) return 0;
eq |= (a[i] ^ b[i]);
}
return (eq != 0);
}
WORD_T
__stdcall
set_ge(WORD_T n_bits, WORD_T* b, WORD_T* a)
{
return set_le(n_bits, a, b);
}
WORD_T
__stdcall
set_gt(WORD_T n_bits, WORD_T* b, WORD_T* a)
{
return set_lt(n_bits, a, b);
}
#define HIGH_BITS(a) ((~(WORD_T)0) << (a))
#define LOW_BITS(a) ((~(WORD_T)0) >> (SET_GRAIN - (a) - 1))
void
__stdcall
set_range(WORD_T b, WORD_T a, WORD_T* s)
{
if (a >= b) {
/* no bits to set */
} else {
WORD_T const a_word = a / SET_GRAIN;
WORD_T const b_word = b / SET_GRAIN;
WORD_T i;
WORD_T const high_bits = HIGH_BITS(a % SET_GRAIN);
WORD_T const low_bits = LOW_BITS(b % SET_GRAIN);
if (a_word == b_word) {
s[a_word] |= (high_bits & low_bits);
} else {
s[a_word] |= high_bits;
for (i = a_word + 1; i < b_word; ++i)
s[i] = ~(WORD_T)0;
s[b_word] |= low_bits;
}
}
}
void
__stdcall
set_singleton(WORD_T a, WORD_T* s)
{
WORD_T a_word = a / SET_GRAIN;
WORD_T a_bit = a % SET_GRAIN;
s[a_word] |= (((WORD_T)1) << a_bit);
}
#ifdef _WIN32
UINT64 _rotl64(UINT64 value, int shift);
UINT64 _rotr64(UINT64 value, int shift);
#pragma intrinsic(_rotl64)
#pragma intrinsic(_rotr64)
UINT64
__stdcall
m3_rotate_left64(UINT64 a, int b) { return _rotl64(a, b); }
UINT64
__stdcall
m3_rotate_right64(UINT64 a, int b) { return _rotr64(a, b); }
UINT64
__stdcall
m3_rotate64(UINT64 a, int b)
{
b &= 63;
if (b > 0)
a = _rotl64(a, b);
else if (b < 0)
a = _rotr64(a, -b);
return a;
}
#endif /* WIN32 */
#ifdef __cplusplus
} /* extern "C" */
#endif