diff intercom/gsm/add.c @ 2:13be24d74cd2

import intercom-0.4.1
author Peter Meerwald <pmeerw@cosy.sbg.ac.at>
date Fri, 25 Jun 2010 09:57:52 +0200
parents
children
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/intercom/gsm/add.c	Fri Jun 25 09:57:52 2010 +0200
@@ -0,0 +1,256 @@
+/*
+ * Copyright 1992 by Jutta Degener and Carsten Bormann, Technische
+ * Universitaet Berlin.  See the accompanying file "COPYRIGHT" for
+ * details.  THERE IS ABSOLUTELY NO WARRANTY FOR THIS SOFTWARE.
+ */
+
+/* $Header: /home/kbs/jutta/src/gsm/gsm-1.0/src/RCS/add.c,v 1.2 1993/01/29 18:23:15 jutta Exp $ */
+
+/*
+ *  See private.h for the more commonly used macro versions.
+ */
+
+#include	<stdio.h>
+#include	<assert.h>
+
+#include	"private.h"
+#include	"gsm.h"
+#include	"proto.h"
+
+#define	saturate(x) 	\
+	((x) < MIN_WORD ? MIN_WORD : (x) > MAX_WORD ? MAX_WORD: (x))
+
+word gsm_add P2((a, b), word a, word b)
+{
+  longword sum = (longword) a + (longword) b;
+  return saturate(sum);
+}
+
+word gsm_sub P2((a, b), word a, word b)
+{
+  longword diff = (longword) a - (longword) b;
+  return saturate(diff);
+}
+
+word gsm_mult P2((a, b), word a, word b)
+{
+  if (a == MIN_WORD && b == MIN_WORD)
+    return MAX_WORD;
+  else
+    return (word) (SASR((longword) a * (longword) b, 15));
+}
+
+word gsm_mult_r P2((a, b), word a, word b)
+{
+  if (b == MIN_WORD && a == MIN_WORD)
+    return MAX_WORD;
+  else {
+    longword prod = (longword) a * (longword) b + 16384;
+    prod >>= 15;
+    return prod & 0xFFFF;
+  }
+}
+
+word gsm_abs P1((a), word a)
+{
+  return a < 0 ? (a == MIN_WORD ? MAX_WORD : -a) : a;
+}
+
+longword gsm_L_mult P2((a, b), word a, word b)
+{
+  assert(a != MIN_WORD || b != MIN_WORD);
+  return ((longword) a * (longword) b) << 1;
+}
+
+longword gsm_L_add P2((a, b), longword a, longword b)
+{
+  if (a < 0) {
+    if (b >= 0)
+      return a + b;
+    else {
+      ulongword A = (ulongword) - (a + 1) + (ulongword) - (b + 1);
+      return A >=
+        (ulongword) MAX_LONGWORD ? MIN_LONGWORD : -(longword) A - 2;
+    }
+  } else if (b <= 0)
+    return a + b;
+  else {
+    ulongword A = (ulongword) a + (ulongword) b;
+    return A > (ulongword) MAX_LONGWORD ? MAX_LONGWORD : A;
+  }
+}
+
+longword gsm_L_sub P2((a, b), longword a, longword b)
+{
+  if (a >= 0) {
+    if (b >= 0)
+      return a - b;
+    else {
+      /* a>=0, b<0 */
+
+      ulongword A = (ulongword) a + -(b + 1);
+      return A >= (ulongword) MAX_LONGWORD ? MAX_LONGWORD : (A + 1);
+    }
+  } else if (b <= 0)
+    return a - b;
+  else {
+    /* a<0, b>0 */
+
+    ulongword A = (ulongword) - (a + 1) + b;
+    return A >= (ulongword) MAX_LONGWORD ? MIN_LONGWORD : -A - 1;
+  }
+}
+
+static unsigned char bitoff[256] = {
+  8, 7, 6, 6, 5, 5, 5, 5, 4, 4, 4, 4, 4, 4, 4, 4,
+  3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+  2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+  2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+};
+
+word gsm_norm P1((a), longword a)
+/*
+ * the number of left shifts needed to normalize the 32 bit
+ * variable L_var1 for positive values on the interval
+ *
+ * with minimum of
+ * minimum of 1073741824  (01000000000000000000000000000000) and
+ * maximum of 2147483647  (01111111111111111111111111111111)
+ *
+ *
+ * and for negative values on the interval with
+ * minimum of -2147483648 (-10000000000000000000000000000000) and
+ * maximum of -1073741824 ( -1000000000000000000000000000000).
+ *
+ * in order to normalize the result, the following
+ * operation must be done: L_norm_var1 = L_var1 << norm( L_var1 );
+ *
+ * (That's 'ffs', only from the left, not the right..)
+ */
+{
+  assert(a != 0);
+
+  if (a < 0) {
+    if (a <= (longword) - 1073741824)
+      return 0;
+    a = ~a;
+  }
+
+  return a & 0xffff0000
+    ? (a & 0xff000000 ? -1 + bitoff[(unsigned char) (0xFF & (a >> 24))]
+    : 7 + bitoff[(unsigned char) (0xFF & (a >> 16))])
+    : (a & 0xff00 ? 15 + bitoff[(unsigned char) (0xFF & (a >> 8))]
+    : 23 + bitoff[(unsigned char) (0xFF & a)]);
+}
+
+longword gsm_L_asl P2((a, n), longword a, int n)
+{
+  if (n >= 32)
+    return 0;
+  if (n <= -32)
+    return -(a < 0);
+  if (n < 0)
+    return gsm_asr(a, -n);
+  return a << n;
+}
+
+word gsm_asl P2((a, n), word a, int n)
+{
+  if (n >= 16)
+    return 0;
+  if (n <= -16)
+    return -(a < 0);
+  if (n < 0)
+    return gsm_asr(a, -n);
+  return a << n;
+}
+
+longword gsm_L_asr P2((a, n), longword a, int n)
+{
+  if (n >= 32)
+    return -(a < 0);
+  if (n <= -32)
+    return 0;
+  if (n < 0)
+    return a << -n;
+
+#	ifdef	SASR
+  return a >> n;
+#	else
+  if (a >= 0)
+    return a >> n;
+  else
+    return -(longword) (-(ulongword) a >> n);
+#	endif
+}
+
+word gsm_asr P2((a, n), word a, int n)
+{
+  if (n >= 16)
+    return -(a < 0);
+  if (n <= -16)
+    return 0;
+  if (n < 0)
+    return a << -n;
+
+#	ifdef	SASR
+  return a >> n;
+#	else
+  if (a >= 0)
+    return a >> n;
+  else
+    return -(word) (-(uword) a >> n);
+#	endif
+}
+
+/* 
+ *  (From p. 46, end of section 4.2.5)
+ *
+ *  NOTE: The following lines gives [sic] one correct implementation
+ *  	  of the div(num, denum) arithmetic operation.  Compute div
+ *        which is the integer division of num by denum: with denum
+ *	  >= num > 0
+ */
+
+word gsm_div P2((num, denum), word num, word denum)
+{
+  longword L_num = num;
+  longword L_denum = denum;
+  word div = 0;
+  int k = 15;
+
+  /* The parameter num sometimes becomes zero.
+   * Although this is explicitly guarded against in 4.2.5,
+   * we assume that the result should then be zero as well.
+   */
+
+  /* assert(num != 0); */
+
+  assert(num >= 0 && denum >= num);
+  if (num == 0)
+    return 0;
+
+  while (k--) {
+    div <<= 1;
+    L_num <<= 1;
+
+    if (L_num >= L_denum) {
+      L_num -= L_denum;
+      div++;
+    }
+  }
+
+  return div;
+}

Repositories maintained by Peter Meerwald, pmeerw@pmeerw.net.