求平方根下取整,对于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. C语言实现二分查找

    二分查找优势:比顺序查找更有效率       特点:元素按顺序排列 #define _CRT_SECURE_NO_WARNINGS #include <stdio.h> #include ...

  2. ubuntu64位运行32位程序

    sudo dpkg --add-architecture i386 sudo apt install libc6:i386 转:https://blog.csdn.net/zoomdy/article ...

  3. java8lambda表达式初识

    一.函数式接口 只有一个 抽象方法 的 接口 叫函数式接口 /** * @auther hhh * @date 2018/12/24 22:20 * @description 函数式接口:只有 一个 ...

  4. 2018 ccpc final I. Cockroaches

    I. Cockroaches time limit per test6. s memory limit per test256 MB inputstandard input outputstandar ...

  5. 初步学习pg_control文件之六

    接前文:初步学习pg_control文件之五 ,DB_IN_ARCHIVE_RECOVERY何时出现? 看代码:如果recovery.conf文件存在,则返回 InArchiveRecovery = ...

  6. CDH,CM下载

    wget -c -r -nd -np -k -L -A rpm http://archive-primary.cloudera.com/cdh5/parcels/latest/ http://arch ...

  7. onenet基础通信套件返回+CIS ERROR: 50的问题解决

    1. 场景分析,主要问题就是有些操作返回+CIS ERROR: 50 2. 看了一下在AT+MIPLOBSERVERSP这个指令里面是没有返回+CIS ERROR: 50的错误类型的,所以应该是在解析 ...

  8. php杂记——1(基础知识与文件读写)

    1.变量前面需要加美元符号"$",常量则不需要: define('PRICE',100); echo PRICE; 2.用一个变量的值作为另一个变量的名称可以得到类似C中的指针变量 ...

  9. Mybatis快速入门指南

    简介 当下越来越多的企业项目架构中,在持久层部分,抛弃了Hibernate框架,而选用Mybatis框架取而代之,旨在更加深入细致的控制和数据库的交互. MyBatis 本是apache的一个开源项目 ...

  10. 跳出for循环break和continue的区别

    1.break 跳出for循环,结束for循环 如果有两层循环,break只能跳出一层循环 2.continue 跳出本次循环,继续下一条数据的循环