求平方根下取整,对于gcc type __uint128_t。

~45.5ns/op on i7-7700k@4.35G,即typical <200cyc/op。

Together with u128gen&timing&validation.

#include <cmath>
#include <cstdio>
#include <random>
#include <chrono>
typedef __uint128_t u128;
typedef unsigned long long u64;
const int count=10000000;
u64 sqrt_approx(u64 x){
u64 approx=sqrt(double(x));
return (approx+x/approx)>>1;
}
u64 sqrt(u64 x){
u64 approx=sqrt(double(x));
u64 apt=(approx+x/approx)>>1;
approx=apt*apt;
if(approx>x)return apt-1;
if(x-approx>=2*apt-1)return apt+1;
return apt;
}
u128 sqrt(u128 r){
if(!(r>>64))return sqrt(u64(r));
int cnt=(((64-__builtin_clzll(u64(r>>64)))+1)|1)^1;
u128 approx=u128(sqrt_approx(u64(r>>cnt)))<<(cnt/2);
approx=(approx+r/approx)>>1;
u128 apt=u128(u64(approx))*u128(u64(approx));
// if(r-apt>=2*approx-1)return approx+1;
return approx-((r-apt)>>127);
}
u128 rand_arr[count],root_arr[count]; typedef void(*func)(); void Time(const char*str,func fn,int multi=count){
using hrc=std::chrono::high_resolution_clock;
hrc::time_point start=hrc::now();
fn();
hrc::time_point stop=hrc::now();
hrc::duration dur=stop-start;
printf("%s Finished in %llu us . \n",str,std::chrono::duration_cast<std::chrono::microseconds>(dur).count());
if(multi)
printf("Average %.3lfns per op.\n",double(std::chrono::duration_cast<std::chrono::nanoseconds>(dur).count())/multi);
} void Root(){
for(int i=0;i<count;++i)
root_arr[i]=sqrt(rand_arr[i]);
} std::mt19937_64 rng; void Gen(){
for(int i=0;i<count;++i)
rand_arr[i]=(u128(rng())<<64)|rng();
} int Validate(){
for(int i=0;i<count;++i){
u128 ax=root_arr[i];
u128 bx=(ax+1)*(ax+1);
ax=ax*ax;
if(ax>rand_arr[i])
return i+1;
if(bx<=rand_arr[i])
return i+1;
}return 0;
} char pp[300];
#define spp(...) (sprintf(pp,##__VA_ARGS__),pp)
#define hexo(x) (spp("0x%llx%016llx",u64(x>>64),u64(x))) int main(){
printf("Count=%d\n",count);
Time("Generation",Gen);
Time("Square root",Root);
int val=Validate();
printf("Validation %s\n",val?spp("Fail at %d",val):"Passed");
if(val){
--val;
printf("Rand %s\n",hexo(rand_arr[val]));
printf("Root %s\n",hexo(root_arr[val]));
}
return 0;
}

sqrti128的更多相关文章

随机推荐

  1. Hadoop学习(一) Hadoop是什么

    Hadoop是什么? Hadoop是一个开发和运行处理大规模数据的软件平台,是Appach的一个用Java语言实现开源软件框架,实现在大量计算机组成的集群中对海量数据进行分布式计算. Hadoop框架 ...

  2. 2019js面试题前端必问点小视频

    其实市面上的面试题有很多,但是大部分都是总结的blog居多,有时候说明一个事物也许口述几分钟就可以搞定,但是看帖子可能要分析半天 所以我就出一部分前端js必考的小视频,不管我们什么时候面试基本都绕不过 ...

  3. cloudera manager服务迁移(scm数据库在postgresql上,其他amon,rman,oozie,metastore等在mysql上)

    公司线上大数据集群,之前用的是公有云主机,现在换成了自己idc机房机器,需要服务迁移,已下为测试: 1.备份原postgresql数据库: pg_dump -U scm scm > scm.sq ...

  4. Ubantu E325 错误的解决办法

    这个错误是由于未正确关闭文本编辑器导致的: 图一 解决办法:退出后输入 sudo vim /etc/hosts 图二 直接输入 D 即可! 注意:退出文本编辑器的正确方式是:ESC键 + :wq. 我 ...

  5. PRO*C 函数事例 1 -- 数据库连接、事务处理

    1.程序结构        每一个Pro*C程序都包括两部分:(1)应用程序首部:(2)应用程序体        应用程序首部定义了ORACLE数据库的有关变量, 为在C语言中操纵ORACLE数据库做 ...

  6. 剁了xp,醉了win7

    装完win7,安装各种软件完毕,重启,然并卵.  cpu,内存飙升!! svchost.exe这个进程内存发疯了一样往上飙升 从 几十兆  到占用1个多G, 纳尼, 总共物理内存才2G. ╮(╯▽╰) ...

  7. LINUX网络相关命令(转)

    网络连通性 Ping:发送一个 ICMP 回声请求消息给主机,一直持续到到你按下 Ctrl+C .Ping 表示一个包通过 ICMP 从你的机器发送出去,然后在IP层得到回应.Ping 可以检测你与另 ...

  8. 【C#】 语法糖

    [C#] 语法糖 一, 扩展方法 1. 对某个类功能上的扩展 2. 特点: 使用方便,可以在不修改原代码的基础上进行扩展. 参照 linq,linq 就是一系列的扩展方法 3. 语法: 非泛型静态类, ...

  9. rails 中 preload、includes、Eager load、Joins 的区别

    Rails 提供了四种不同加载关联数据的方法.下面就来介绍一下. 一.Preload Preload 是以附加一条查询语句来加载关联数据的 User.preload(:posts).to_a # =& ...

  10. 【廖雪峰老师python教程】——map/reduce

    Map[单个操作对不同单一对象重复进行] map()函数接收两个参数,一个是函数,一个是Iterable,map将传入的函数依次作用到序列的每个元素,并把结果作为新的Iterator返回. 返回结果注 ...