相关疑难解决方法(0)

签名饱和添加64位整数?

我正在寻找一些用于签名饱和64位加法的C代码,它使用gcc优化器编译为高效的X86-64代码.便携式代码是理想的,尽管如果需要可以使用asm解决方案.

static const int64 kint64max = 0x7fffffffffffffffll;
static const int64 kint64min = 0x8000000000000000ll;

int64 signed_saturated_add(int64 x, int64 y) {
  bool x_is_negative = (x & kint64min) != 0;
  bool y_is_negative = (y & kint64min) != 0;
  int64 sum = x+y;
  bool sum_is_negative = (sum & kint64min) != 0;
  if (x_is_negative != y_is_negative) return sum;  // can't overflow
  if (x_is_negative && !sum_is_negative) return kint64min;
  if (!x_is_negative && sum_is_negative) return kint64max;
  return sum;
}
Run Code Online (Sandbox Code Playgroud)

写入的函数产生具有多个分支的相当长的汇编输出.有关优化的提示吗?看起来它应该只用一个带有一些CMOV指令的ADD来实现,但我对这些东西有点生疏.

c optimization x86-64 addition saturation-arithmetic

11
推荐指数
4
解决办法
1919
查看次数

饱和地添加了两个签名的Java"long"值

怎么能一个增加两个long,因此如果结果溢出,然后它被钳范围在Java中值Long.MIN_VALUE.. Long.MAX_VALUE

对于添加ints,可以执行long精度算术并将结果转换回int,例如:

int saturatedAdd(int x, int y) {
  long sum = (long) x + (long) y;
  long clampedSum = Math.max((long) Integer.MIN_VALUE,
                             Math.min(sum, (long) Integer.MAX_VALUE));
  return (int) clampedSum;
}
Run Code Online (Sandbox Code Playgroud)

要么

import com.google.common.primitives.Ints;

int saturatedAdd(int x, int y) {
  long sum = (long) x + (long) y;
  return Ints.saturatedCast(sum);
}
Run Code Online (Sandbox Code Playgroud)

但是在long没有较大的原始类型可以保持中间(非夹紧)总和的情况下.

由于这是Java,我不能使用内联汇编(特别是SSE的饱和添加指令).

它可以使用BigInteger例如

static final BigInteger bigMin = BigInteger.valueOf(Long.MIN_VALUE);
static final BigInteger bigMax = BigInteger.valueOf(Long.MAX_VALUE);

long …
Run Code Online (Sandbox Code Playgroud)

java math signal-processing bit-manipulation integer-overflow

9
推荐指数
2
解决办法
4413
查看次数

一般来说,如何防止C语言中发生整数溢出?

一般来说,如何防止C编程语言中发生整数溢出?我的意思是,有什么功能可以防止吗?最后,整数溢出是否会让我像缓冲区溢出等那样被黑客攻击?

c integer-overflow

7
推荐指数
2
解决办法
2万
查看次数

如何在C语言中检测包装计数器和大负值之间的差异

为我的愚蠢道歉,因为这是我在这个论坛上的第一篇文章.我试图通过以下代码检测包装无符号32位计数器和大负跳转之间的区别,但编译器给我错误:

错误:由于数据类型的范围有限,比较始终为真[-Werror = type-limits]

这是我的代码片段:

#define MAX_BACKWARD_JUMP -4294959295 //UINT_MAX - 8000
#define MIN_BACKWARD_JUMP -3600
#define MAX_FORWARD_JUMP   4800000

signed int rtpDelta; //Signed 32-bit
unsigned int currRTPTs, prevRTPTs; //unsigned 32-bit

rtpDelta = currRTPTs - prevRTPTs;

  if ((rtpDelta > MAX_BACKWARD_JUMP && rtpDelta < MIN_BACKWARD_JUMP) 
        || (rtpDelta > MAX_FORWARD_JUMP))
        {
          printf("Delta in Timestamps too large\n",rtpDelta);
        }
Run Code Online (Sandbox Code Playgroud)

这里的想法是在RTP时间戳中捕获无效的大型Deltas.我们有一个当前的TimeStamp和一个从对等RTP客户端接收的前一个Timestamp.RTP时间戳的无效值的边界限制是-4294959295 <rtpDelta <-3600,如果Delta小于-3600且大于-4294959295,它应该抛出错误,因为更接近UMAX_INT的值将被视为翻转.我在这做错了什么?

c c++ x86 32-bit rtp

5
推荐指数
2
解决办法
1671
查看次数