作为规范示例,考虑三角函数的参数减少问题,如计算xmod2π作为计算sin(x)的第一步.这种问题很难,因为你不能只使用fmod,因为y(在例子中为2π)不具有代表性.
我提出了一个简单的解决方案,适用于任意值y,而不仅仅是2π,我很好奇它是如何比较(性能)与典型的参数减少算法.
基本思想是将一个包含2 n mod y 值的表存储在log2(y)范围内的每个值n到最大可能的浮点指数,然后使用模运算的线性,将此表中的值相加在x的值中设置的位.它相当于N个分支和最多N个加法,其中N是浮点类型中的尾数位数.结果不一定小于y,但是它受N*y的限制,并且可以再次应用该过程以给出由log2(N)*y限定的结果,或者fmod可以简单地在此处使用具有最小误差的结果.
这可以改善吗?并且典型的三角参数约简算法是否适用于任意y或仅适用于2π?
我有一个对象的链接列表,每个对象包含一个32位整数(可证明少于2 32个这样的对象),我想有效地选择一个不在列表中的整数,而不使用任何额外的存储(所以将它们复制到一个数组,排序数组,并选择不在数组中的最小值将不是一个选项).但是,列表元素的结构定义在我的控制之下,因此我可以(在合理范围内)为每个元素添加额外的存储,作为解决问题的一部分.例如,我可以添加一组额外的prev/next指针并对列表进行合并排序.这是最好的解决方案吗?或者有更简单或更有效的方法吗?
以char字节为单位的整数类型(或任何类型)的大小很容易计算为sizeof(type).一个常见的习惯用法是乘以CHAR_BIT找到该类型占用的位数,但是在使用填充位的实现中,这将不等于值位的宽度.更糟糕的是,代码如下:
x>>CHAR_BIT*sizeof(type)-1
Run Code Online (Sandbox Code Playgroud)
如果CHAR_BIT*sizeof(type)大于实际宽度,实际上可能有未定义的行为type.
为简单起见,我们假设我们的类型是无符号的.那么宽度type是ceil(log2((type)-1).有没有办法将此值计算为常量表达式?
所有文档(在标准中)都fenv.h相当混乱,但我对feholdexcept浮点异常的"不停模式"的概念特别困惑.据我所知,在任何IEEE浮点实现中,默认情况下异常都是非信令/"不停止",并且fenv.h接口似乎无法启用信令模式,除非它是默认模式.feholdexcept除非在非IEEE系统或具有非标准扩展的系统上设置信令异常掩码,否则整个概念是无用的?
以下代码是否调用未定义的行为(由于别名冲突或其他原因)?
int foo(int (*a)[10], int (*b)[5])
{
(*a)[5]++;
return (*b)[0];
}
int x[10];
foo(&x, (int (*)[5])&x[5]);
Run Code Online (Sandbox Code Playgroud)
需要注意的是使用普通的相应的代码int *,而不是指针到数组类型将是完全合法的,因为a与b将指针相同类型并且因此允许别名彼此.
编辑:有趣的结果,如果这实际上是一个别名违规,是它似乎是一个hackish但有效的方式来获得restrictC99之前的语义.如:
void some_func(int *aa, int *bb)
{
int (*a)[1] = (void *)aa;
int (*b)[2] = (void *)bb;
/* Now **a and **b can be assumed by the compiler not to alias */
}
Run Code Online (Sandbox Code Playgroud)
假设您需要访问每个地址的实际数组,您可以使用SIZE_MAX-1和SIZE_MAX-2等作为不同的大小.
例如,此代码是有效的,还是通过违反别名规则来调用未定义的行为?
int x;
struct s { int i; } y;
x = 1;
y = *(struct s *)&x;
printf("%d\n", y.i);
Run Code Online (Sandbox Code Playgroud)
我的兴趣在于使用基于此的技术来开发用于执行别名读取的可移植方法.
更新:这是预期的用例,有点不同,但当且仅当上述内容有效时才有效:
static inline uint32_t read32(const unsigned char *p)
{
struct a { char r[4]; };
union b { struct a r; uint32_t x; } tmp;
tmp.r = *(struct a *)p;
return tmp.x;
}
Run Code Online (Sandbox Code Playgroud)
GCC根据需要将其编译为单个32位负载,并且它似乎避免了如果p实际指向除其他类型之外可能发生的混叠问题char.换句话说,它似乎是GNU C __attribute__((__may_alias__))属性的可移植替代品.但我不确定它是否真的定义明确......
是否有主要的C/C++实现,其中longjmp函数"展开",即它与自动存储对象的析构函数__attribute__((__cleanup__(...))),POSIX线程取消处理程序等交互,而不仅仅是恢复由setjmp?保存的寄存器上下文?我对使用此属性的POSIX实现的存在(或不存在)特别感兴趣,但C/C++通常也很有趣.
对于赏金,我正在寻找符合POSIX或至少类似POSIX的系统,而不是已经提到过的Windows.
我知道有一些实现memcpy,它们以相反的顺序复制内存以优化某些处理器.曾经有一个错误" mp3 flash网站上的奇怪声音 "与之相关.嗯,这是一个有趣的故事,但我的问题是另一个功能.
我想知道,memset世界上有一个函数,从最后开始填充缓冲区.很明显,理论上没有什么能阻止这样的函数实现.但我完全感兴趣的是,这个功能是在某个地方某人的实践中完成的.我将特别感谢库中具有这种功能的链接.
PS我明白,就应用程序编程而言,缓冲区是按升序还是降序填充完全没有区别.但是,重要的是要找出是否存在任何"反向"功能实现.我需要它写一篇文章.
我正在寻找一个5元素排序的排序网络实现,但由于我在SO上找不到一个好的参考,我想要求为所有小的n值排序网络,至少n = 3通过n = 6但更高的值也会很好.一个好的答案至少应该将它们列为"交换"(对2个元素进行排序)操作的序列,但是在低阶排序网络方面看到递归分解也可能会很好.
对于我的应用程序,我实际上只关心5个元素的中位数,而不是实际按顺序排列.也就是说,只要中位数在正确的位置结束,结果中可能未指定其他4个元素的顺序.可以使用与排序网络相关的方法来计算交换数量少于执行完整排序的中位数吗?如果是这样,我的问题(对于n = 5)和其他情况的这种解决方案也会得到一个很好的答案.
(注意:我已经标记了这个问题C,因为C是我使用的语言,我怀疑跟随C标签的人有很好的答案,但我真的不在乎答案实际上是用C编写而不是伪代码只要符合上述标准,它就可以很容易地转换成C语言.)